next steps for closure iterators
This commit is contained in:
parent
85a5bfe605
commit
37229df7fc
28 changed files with 164 additions and 71 deletions
134
tests/showoff/tdrdobbs_examples.nim
Normal file
134
tests/showoff/tdrdobbs_examples.nim
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
discard """
|
||||
output: '''108
|
||||
11 -1 1936
|
||||
4.000000000000002-e001
|
||||
true
|
||||
truefalse'''
|
||||
"""
|
||||
|
||||
proc `++`(x: var int; y: int = 1; z: int = 0) =
|
||||
x = x + y + z
|
||||
|
||||
var g = 70
|
||||
++g
|
||||
g ++ 7
|
||||
g.`++`(10, 20)
|
||||
echo g
|
||||
|
||||
|
||||
#let lv = stdin.readline
|
||||
#var vv = stdin.readline
|
||||
#vv = "abc" # valid, reassignment allowed
|
||||
#lv = "abc" # fails at compile time
|
||||
|
||||
#proc square(x: int): int = x*x
|
||||
|
||||
template square(x: int): int =
|
||||
# ensure 'x' is only evaluated once:
|
||||
let y = x
|
||||
y * y
|
||||
|
||||
proc mostSignificantBit(n: int): int =
|
||||
# naive algorithm:
|
||||
var n = n
|
||||
while n != 0:
|
||||
n = n shr 1
|
||||
result += 1
|
||||
result -= 1
|
||||
|
||||
const msb3999 = mostSignificantBit(3999)
|
||||
|
||||
echo msb3999, " ", mostSignificantBit(0), " ", square(44)
|
||||
|
||||
proc filter[T](a: openarray[T], predicate: proc (x: T): bool): seq[T] =
|
||||
result = @[] # @[] constructs the empty seq
|
||||
for x in a:
|
||||
if predicate(x): result.add(x)
|
||||
|
||||
proc map[T, S](a: openarray[T], fn: proc (x: T): S): seq[S] =
|
||||
newSeq(result, a.len)
|
||||
for i in 0 .. <a.len: result[i] = fn(a[i])
|
||||
|
||||
|
||||
type
|
||||
FormulaKind = enum
|
||||
fkVar, ## element is a variable like 'X'
|
||||
fkLit, ## element is a literal like 0.1
|
||||
fkAdd, ## element is an addition operation
|
||||
fkMul, ## element is a multiplication operation
|
||||
fkExp ## element is an exponentiation operation
|
||||
|
||||
type
|
||||
Formula = ref object
|
||||
case kind: FormulaKind
|
||||
of fkVar: name: string
|
||||
of fkLit: value: float
|
||||
of fkAdd, fkMul, fkExp: left, right: Formula
|
||||
|
||||
from math import pow
|
||||
|
||||
proc evaluate(n: Formula, varToVal: proc (name: string): float): float =
|
||||
case n.kind
|
||||
of fkVar: varToVal(n.name)
|
||||
of fkLit: n.value
|
||||
of fkAdd: evaluate(n.left, varToVal) + evaluate(n.right, varToVal)
|
||||
of fkMul: evaluate(n.left, varToVal) * evaluate(n.right, varToVal)
|
||||
of fkExp: pow(evaluate(n.left, varToVal), evaluate(n.right, varToVal))
|
||||
|
||||
echo evaluate(Formula(kind: fkLit, value: 0.4), nil)
|
||||
|
||||
proc isPolyTerm(n: Formula): bool =
|
||||
n.kind == fkMul and n.left.kind == fkLit and (let e = n.right;
|
||||
e.kind == fkExp and e.left.kind == fkVar and e.right.kind == fkLit)
|
||||
|
||||
proc isPolynomial(n: Formula): bool =
|
||||
isPolyTerm(n) or
|
||||
(n.kind == fkAdd and isPolynomial(n.left) and isPolynomial(n.right))
|
||||
|
||||
let myFormula = Formula(kind: fkMul,
|
||||
left: Formula(kind: fkLit, value: 2.0),
|
||||
right: Formula(kind: fkExp,
|
||||
left: Formula(kind: fkVar, name: "x"),
|
||||
right: Formula(kind: fkLit, value: 5.0)))
|
||||
|
||||
echo isPolyTerm(myFormula)
|
||||
|
||||
proc pat2kind(pattern: string): FormulaKind =
|
||||
case pattern
|
||||
of "^": fkExp
|
||||
of "*": fkMul
|
||||
of "+": fkAdd
|
||||
of "x": fkVar
|
||||
of "c": fkLit
|
||||
else: fkVar # no error reporting for reasons of simplicity
|
||||
|
||||
import macros
|
||||
|
||||
proc matchAgainst(n, pattern: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
template `@`(current, field: expr): expr =
|
||||
newDotExpr(current, newIdentNode(astToStr(field)))
|
||||
|
||||
template `==@`(n, pattern: expr): expr =
|
||||
newCall("==", n@kind, newIdentNode($pat2kind($pattern.ident)))
|
||||
|
||||
case pattern.kind
|
||||
of CallNodes:
|
||||
result = newCall("and",
|
||||
n ==@ pattern[0],
|
||||
matchAgainst(n@left, pattern[1]))
|
||||
if pattern.len == 3:
|
||||
result = newCall("and", result.copy,
|
||||
matchAgainst(n@right, pattern[2]))
|
||||
of nnkIdent:
|
||||
result = n ==@ pattern
|
||||
of nnkPar:
|
||||
result = matchAgainst(n, pattern[0])
|
||||
else:
|
||||
error "invalid pattern"
|
||||
|
||||
macro `=~` (n: Formula, pattern: expr): bool =
|
||||
result = matchAgainst(n, pattern)
|
||||
|
||||
proc isPolyTerm2(n: Formula): bool = n =~ c * x^c
|
||||
|
||||
echo isPolyTerm2(myFormula), isPolyTerm2(Formula(kind: fkLit, value: 0.7))
|
||||
Loading…
Add table
Add a link
Reference in a new issue