From 37229df7fc044fe108d2f4d88f127141cabeb6a6 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 22 Jan 2014 17:32:38 +0100 Subject: next steps for closure iterators --- tests/block/tblock1.nim | 18 ----- tests/controlflow/tblock1.nim | 18 +++++ tests/controlflow/tnestif.nim | 24 ++++++ tests/ifstmt/tnestif.nim | 24 ------ tests/important/tdrdobbs_examples.nim | 134 ---------------------------------- tests/iter/tanoniter1.nim | 32 ++++++++ tests/iter/titer2.nim | 2 +- tests/metatype/tstaticparams.nim | 31 ++++++++ tests/object/tobjconstr.nim | 41 ----------- tests/object/tobjconstr2.nim | 22 ------ tests/object/tobjcov.nim | 17 ----- tests/object/tobject.nim | 15 ---- tests/object/tobject2.nim | 21 ------ tests/object/tobject3.nim | 28 ------- tests/object/toop.nim | 21 ------ tests/object/toop1.nim | 89 ---------------------- tests/objects/tobjconstr.nim | 41 +++++++++++ tests/objects/tobjconstr2.nim | 22 ++++++ tests/objects/tobjcov.nim | 17 +++++ tests/objects/tobject.nim | 15 ++++ tests/objects/tobject2.nim | 21 ++++++ tests/objects/tobject3.nim | 28 +++++++ tests/objects/tofopr.nim | 26 +++++++ tests/objects/toop.nim | 21 ++++++ tests/objects/toop1.nim | 89 ++++++++++++++++++++++ tests/operator/tofopr.nim | 26 ------- tests/operator/toprprec.nim | 39 ---------- tests/operator/tprecedence.nim | 11 --- tests/parser/toprprec.nim | 39 ++++++++++ tests/parser/tprecedence.nim | 11 +++ tests/showoff/tdrdobbs_examples.nim | 134 ++++++++++++++++++++++++++++++++++ tests/static/tstaticparams.nim | 31 -------- 32 files changed, 570 insertions(+), 538 deletions(-) delete mode 100644 tests/block/tblock1.nim create mode 100644 tests/controlflow/tblock1.nim create mode 100644 tests/controlflow/tnestif.nim delete mode 100644 tests/ifstmt/tnestif.nim delete mode 100644 tests/important/tdrdobbs_examples.nim create mode 100644 tests/iter/tanoniter1.nim create mode 100644 tests/metatype/tstaticparams.nim delete mode 100644 tests/object/tobjconstr.nim delete mode 100644 tests/object/tobjconstr2.nim delete mode 100644 tests/object/tobjcov.nim delete mode 100644 tests/object/tobject.nim delete mode 100644 tests/object/tobject2.nim delete mode 100644 tests/object/tobject3.nim delete mode 100644 tests/object/toop.nim delete mode 100644 tests/object/toop1.nim create mode 100644 tests/objects/tobjconstr.nim create mode 100644 tests/objects/tobjconstr2.nim create mode 100644 tests/objects/tobjcov.nim create mode 100644 tests/objects/tobject.nim create mode 100644 tests/objects/tobject2.nim create mode 100644 tests/objects/tobject3.nim create mode 100644 tests/objects/tofopr.nim create mode 100644 tests/objects/toop.nim create mode 100644 tests/objects/toop1.nim delete mode 100644 tests/operator/tofopr.nim delete mode 100644 tests/operator/toprprec.nim delete mode 100644 tests/operator/tprecedence.nim create mode 100644 tests/parser/toprprec.nim create mode 100644 tests/parser/tprecedence.nim create mode 100644 tests/showoff/tdrdobbs_examples.nim delete mode 100644 tests/static/tstaticparams.nim (limited to 'tests') diff --git a/tests/block/tblock1.nim b/tests/block/tblock1.nim deleted file mode 100644 index 5c41aaf82..000000000 --- a/tests/block/tblock1.nim +++ /dev/null @@ -1,18 +0,0 @@ -discard """ - file: "tblock1.nim" - line: 14 - errormsg: "undeclared identifier: \'ha\'" -""" -# check for forward label and -# for failure when label is not declared - -proc main = - block endLess: - write(stdout, "Muaahh!\N") - break endLess - - break ha #ERROR - -main() - - diff --git a/tests/controlflow/tblock1.nim b/tests/controlflow/tblock1.nim new file mode 100644 index 000000000..5c41aaf82 --- /dev/null +++ b/tests/controlflow/tblock1.nim @@ -0,0 +1,18 @@ +discard """ + file: "tblock1.nim" + line: 14 + errormsg: "undeclared identifier: \'ha\'" +""" +# check for forward label and +# for failure when label is not declared + +proc main = + block endLess: + write(stdout, "Muaahh!\N") + break endLess + + break ha #ERROR + +main() + + diff --git a/tests/controlflow/tnestif.nim b/tests/controlflow/tnestif.nim new file mode 100644 index 000000000..bfcd8751c --- /dev/null +++ b/tests/controlflow/tnestif.nim @@ -0,0 +1,24 @@ +discard """ + file: "tnestif.nim" + output: "i == 2" +""" +# test nested ifs + +var + x, y: int +x = 2 +if x == 0: + write(stdout, "i == 0") + if y == 0: + write(stdout, x) + else: + write(stdout, y) +elif x == 1: + write(stdout, "i == 1") +elif x == 2: + write(stdout, "i == 2") +else: + write(stdout, "looks like Python") +#OUT i == 2 + + diff --git a/tests/ifstmt/tnestif.nim b/tests/ifstmt/tnestif.nim deleted file mode 100644 index bfcd8751c..000000000 --- a/tests/ifstmt/tnestif.nim +++ /dev/null @@ -1,24 +0,0 @@ -discard """ - file: "tnestif.nim" - output: "i == 2" -""" -# test nested ifs - -var - x, y: int -x = 2 -if x == 0: - write(stdout, "i == 0") - if y == 0: - write(stdout, x) - else: - write(stdout, y) -elif x == 1: - write(stdout, "i == 1") -elif x == 2: - write(stdout, "i == 2") -else: - write(stdout, "looks like Python") -#OUT i == 2 - - diff --git a/tests/important/tdrdobbs_examples.nim b/tests/important/tdrdobbs_examples.nim deleted file mode 100644 index d1e0585d2..000000000 --- a/tests/important/tdrdobbs_examples.nim +++ /dev/null @@ -1,134 +0,0 @@ -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 .. 0: result.add(", ") - result.add($x) - result.add("]") - -proc main() = - for i in 1..10: - let d = TDummy(k: kindA, a: TArg(x: "abc", z: @[1,i,3]), empty: TEmpty()) - echo d[] - -main() - diff --git a/tests/object/tobjconstr2.nim b/tests/object/tobjconstr2.nim deleted file mode 100644 index cb47e146d..000000000 --- a/tests/object/tobjconstr2.nim +++ /dev/null @@ -1,22 +0,0 @@ -type TFoo{.exportc.} = object - x:int - -var s{.exportc.}: seq[TFoo] = @[] - -s.add TFoo(x: 42) - -echo s[0].x - - -# bug #563 -type - Foo = - object {.inheritable.} - x: int - - Bar = - object of Foo - y: int - -var a = Bar(y: 100, x: 200) # works -var b = Bar(x: 100, y: 200) # used to fail diff --git a/tests/object/tobjcov.nim b/tests/object/tobjcov.nim deleted file mode 100644 index fc44edf8e..000000000 --- a/tests/object/tobjcov.nim +++ /dev/null @@ -1,17 +0,0 @@ -# Covariance is not type safe: - -type - TA = object of TObject - a: int - TB = object of TA - b: array[0..5000_000, int] - -proc ap(x: var TA) = x.a = -1 -proc bp(x: var TB) = x.b[high(x.b)] = -1 - -# in Nimrod proc (x: TB) is compatible to proc (x: TA), -# but this is not type safe: -var f = cast[proc (x: var TA) {.nimcall.}](bp) -var a: TA -f(a) # bp expects a TB, but gets a TA - diff --git a/tests/object/tobject.nim b/tests/object/tobject.nim deleted file mode 100644 index 5fec84441..000000000 --- a/tests/object/tobject.nim +++ /dev/null @@ -1,15 +0,0 @@ -import unittest - -type Obj = object - foo: int - -proc makeObj(x: int): Obj = - result.foo = x - -suite "object basic methods": - test "it should convert an object to a string": - var obj = makeObj(1) - # Should be "obj: (foo: 1)" or similar. - check($obj == "(foo: 1)") - test "it should test equality based on fields": - check(makeObj(1) == makeObj(1)) diff --git a/tests/object/tobject2.nim b/tests/object/tobject2.nim deleted file mode 100644 index 0f1869695..000000000 --- a/tests/object/tobject2.nim +++ /dev/null @@ -1,21 +0,0 @@ -# Tests the object implementation - -type - TPoint2d {.inheritable.} = object - x, y: int - - TPoint3d = object of TPoint2d - z: int # added a field - -proc getPoint( p: var TPoint2d) = - {.breakpoint.} - writeln(stdout, p.x) - -var - p: TPoint3d - -TPoint2d(p).x = 34 -p.y = 98 -p.z = 343 - -getPoint(p) diff --git a/tests/object/tobject3.nim b/tests/object/tobject3.nim deleted file mode 100644 index 935e6ca8c..000000000 --- a/tests/object/tobject3.nim +++ /dev/null @@ -1,28 +0,0 @@ -type - TFoo = ref object of TObject - Data: int - TBar = ref object of TFoo - nil - TBar2 = ref object of TBar - d2: int - -template super(self: TBar): TFoo = self - -template super(self: TBar2): TBar = self - -proc Foo(self: TFoo) = - echo "TFoo" - -#proc Foo(self: TBar) = -# echo "TBar" -# Foo(super(self)) -# works when this code is uncommented - -proc Foo(self: TBar2) = - echo "TBar2" - Foo(super(self)) - -var b: TBar2 -new(b) - -Foo(b) diff --git a/tests/object/toop.nim b/tests/object/toop.nim deleted file mode 100644 index 0b42c2c22..000000000 --- a/tests/object/toop.nim +++ /dev/null @@ -1,21 +0,0 @@ -discard """ - output: "b" -""" - -type - TA = object of TObject - x, y: int - - TB = object of TA - z: int - - TC = object of TB - whatever: string - -proc p(a: var TA) = echo "a" -proc p(b: var TB) = echo "b" - -var c: TC - -p(c) - diff --git a/tests/object/toop1.nim b/tests/object/toop1.nim deleted file mode 100644 index 350799f51..000000000 --- a/tests/object/toop1.nim +++ /dev/null @@ -1,89 +0,0 @@ -discard """ - file: "toop1.nim" - output: "34[]o 5" -""" -# Test the stuff in the tutorial -import macros - -type - TFigure = object of TObject # abstract base class: - draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this - -proc init(f: var TFigure) = - f.draw = nil - -type - TCircle = object of TFigure - radius: int - -proc drawCircle(my: var TCircle) = stdout.writeln("o " & $my.radius) - -proc init(my: var TCircle) = - init(TFigure(my)) # call base constructor - my.radius = 5 - my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawCircle) - -type - TRectangle = object of TFigure - width, height: int - -proc drawRectangle(my: var TRectangle) = stdout.write("[]") - -proc init(my: var TRectangle) = - init(TFigure(my)) # call base constructor - my.width = 5 - my.height = 10 - my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle) - -macro `!` (n: expr): stmt {.immediate.} = - let n = callsite() - result = newNimNode(nnkCall, n) - var dot = newNimNode(nnkDotExpr, n) - dot.add(n[1]) # obj - if n[2].kind == nnkCall: - # transforms ``obj!method(arg1, arg2, ...)`` to - # ``(obj.method)(obj, arg1, arg2, ...)`` - dot.add(n[2][0]) # method - result.add(dot) - result.add(n[1]) # obj - for i in 1..n[2].len-1: - result.add(n[2][i]) - else: - # transforms ``obj!method`` to - # ``(obj.method)(obj)`` - dot.add(n[2]) # method - result.add(dot) - result.add(n[1]) # obj - -type - TSocket* = object of TObject - FHost: int # cannot be accessed from the outside of the module - # the `F` prefix is a convention to avoid clashes since - # the accessors are named `host` - -proc `host=`*(s: var TSocket, value: int) {.inline.} = - ## setter of hostAddr - s.FHost = value - -proc host*(s: TSocket): int {.inline.} = - ## getter of hostAddr - return s.FHost - -var - s: TSocket -s.host = 34 # same as `host=`(s, 34) -stdout.write(s.host) - -# now use these classes: -var - r: TRectangle - c: TCircle -init(r) -init(c) -r!draw -c!draw() - -#OUT 34[]o 5 - - - diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim new file mode 100644 index 000000000..3bd785728 --- /dev/null +++ b/tests/objects/tobjconstr.nim @@ -0,0 +1,41 @@ +discard """ + output: '''(k: kindA, a: (x: abc, z: [1, 1, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 2, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 3, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 4, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 5, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 6, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 7, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 8, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 9, 3]), empty: ()) +(k: kindA, a: (x: abc, z: [1, 10, 3]), empty: ())''' +""" + +type + TArg = object + x: string + z: seq[int] + TKind = enum kindXY, kindA + TEmpty = object + TDummy = ref object + case k: TKind + of kindXY: x, y: int + of kindA: + a: TArg + empty: TEmpty + +proc `$`[T](s: seq[T]): string = + # XXX why is that not in the stdlib? + result = "[" + for i, x in s: + if i > 0: result.add(", ") + result.add($x) + result.add("]") + +proc main() = + for i in 1..10: + let d = TDummy(k: kindA, a: TArg(x: "abc", z: @[1,i,3]), empty: TEmpty()) + echo d[] + +main() + diff --git a/tests/objects/tobjconstr2.nim b/tests/objects/tobjconstr2.nim new file mode 100644 index 000000000..cb47e146d --- /dev/null +++ b/tests/objects/tobjconstr2.nim @@ -0,0 +1,22 @@ +type TFoo{.exportc.} = object + x:int + +var s{.exportc.}: seq[TFoo] = @[] + +s.add TFoo(x: 42) + +echo s[0].x + + +# bug #563 +type + Foo = + object {.inheritable.} + x: int + + Bar = + object of Foo + y: int + +var a = Bar(y: 100, x: 200) # works +var b = Bar(x: 100, y: 200) # used to fail diff --git a/tests/objects/tobjcov.nim b/tests/objects/tobjcov.nim new file mode 100644 index 000000000..fc44edf8e --- /dev/null +++ b/tests/objects/tobjcov.nim @@ -0,0 +1,17 @@ +# Covariance is not type safe: + +type + TA = object of TObject + a: int + TB = object of TA + b: array[0..5000_000, int] + +proc ap(x: var TA) = x.a = -1 +proc bp(x: var TB) = x.b[high(x.b)] = -1 + +# in Nimrod proc (x: TB) is compatible to proc (x: TA), +# but this is not type safe: +var f = cast[proc (x: var TA) {.nimcall.}](bp) +var a: TA +f(a) # bp expects a TB, but gets a TA + diff --git a/tests/objects/tobject.nim b/tests/objects/tobject.nim new file mode 100644 index 000000000..5fec84441 --- /dev/null +++ b/tests/objects/tobject.nim @@ -0,0 +1,15 @@ +import unittest + +type Obj = object + foo: int + +proc makeObj(x: int): Obj = + result.foo = x + +suite "object basic methods": + test "it should convert an object to a string": + var obj = makeObj(1) + # Should be "obj: (foo: 1)" or similar. + check($obj == "(foo: 1)") + test "it should test equality based on fields": + check(makeObj(1) == makeObj(1)) diff --git a/tests/objects/tobject2.nim b/tests/objects/tobject2.nim new file mode 100644 index 000000000..0f1869695 --- /dev/null +++ b/tests/objects/tobject2.nim @@ -0,0 +1,21 @@ +# Tests the object implementation + +type + TPoint2d {.inheritable.} = object + x, y: int + + TPoint3d = object of TPoint2d + z: int # added a field + +proc getPoint( p: var TPoint2d) = + {.breakpoint.} + writeln(stdout, p.x) + +var + p: TPoint3d + +TPoint2d(p).x = 34 +p.y = 98 +p.z = 343 + +getPoint(p) diff --git a/tests/objects/tobject3.nim b/tests/objects/tobject3.nim new file mode 100644 index 000000000..935e6ca8c --- /dev/null +++ b/tests/objects/tobject3.nim @@ -0,0 +1,28 @@ +type + TFoo = ref object of TObject + Data: int + TBar = ref object of TFoo + nil + TBar2 = ref object of TBar + d2: int + +template super(self: TBar): TFoo = self + +template super(self: TBar2): TBar = self + +proc Foo(self: TFoo) = + echo "TFoo" + +#proc Foo(self: TBar) = +# echo "TBar" +# Foo(super(self)) +# works when this code is uncommented + +proc Foo(self: TBar2) = + echo "TBar2" + Foo(super(self)) + +var b: TBar2 +new(b) + +Foo(b) diff --git a/tests/objects/tofopr.nim b/tests/objects/tofopr.nim new file mode 100644 index 000000000..961d81bd3 --- /dev/null +++ b/tests/objects/tofopr.nim @@ -0,0 +1,26 @@ +discard """ + file: "tofopr.nim" + output: "falsetrue" +""" +# Test is operator + +type + TMyType = object {.inheritable.} + len: int + data: string + + TOtherType = object of TMyType + +proc p(x: TMyType): bool = + return x of TOtherType + +var + m: TMyType + n: TOtherType + +write(stdout, p(m)) +write(stdout, p(n)) + +#OUT falsetrue + + diff --git a/tests/objects/toop.nim b/tests/objects/toop.nim new file mode 100644 index 000000000..0b42c2c22 --- /dev/null +++ b/tests/objects/toop.nim @@ -0,0 +1,21 @@ +discard """ + output: "b" +""" + +type + TA = object of TObject + x, y: int + + TB = object of TA + z: int + + TC = object of TB + whatever: string + +proc p(a: var TA) = echo "a" +proc p(b: var TB) = echo "b" + +var c: TC + +p(c) + diff --git a/tests/objects/toop1.nim b/tests/objects/toop1.nim new file mode 100644 index 000000000..350799f51 --- /dev/null +++ b/tests/objects/toop1.nim @@ -0,0 +1,89 @@ +discard """ + file: "toop1.nim" + output: "34[]o 5" +""" +# Test the stuff in the tutorial +import macros + +type + TFigure = object of TObject # abstract base class: + draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this + +proc init(f: var TFigure) = + f.draw = nil + +type + TCircle = object of TFigure + radius: int + +proc drawCircle(my: var TCircle) = stdout.writeln("o " & $my.radius) + +proc init(my: var TCircle) = + init(TFigure(my)) # call base constructor + my.radius = 5 + my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawCircle) + +type + TRectangle = object of TFigure + width, height: int + +proc drawRectangle(my: var TRectangle) = stdout.write("[]") + +proc init(my: var TRectangle) = + init(TFigure(my)) # call base constructor + my.width = 5 + my.height = 10 + my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle) + +macro `!` (n: expr): stmt {.immediate.} = + let n = callsite() + result = newNimNode(nnkCall, n) + var dot = newNimNode(nnkDotExpr, n) + dot.add(n[1]) # obj + if n[2].kind == nnkCall: + # transforms ``obj!method(arg1, arg2, ...)`` to + # ``(obj.method)(obj, arg1, arg2, ...)`` + dot.add(n[2][0]) # method + result.add(dot) + result.add(n[1]) # obj + for i in 1..n[2].len-1: + result.add(n[2][i]) + else: + # transforms ``obj!method`` to + # ``(obj.method)(obj)`` + dot.add(n[2]) # method + result.add(dot) + result.add(n[1]) # obj + +type + TSocket* = object of TObject + FHost: int # cannot be accessed from the outside of the module + # the `F` prefix is a convention to avoid clashes since + # the accessors are named `host` + +proc `host=`*(s: var TSocket, value: int) {.inline.} = + ## setter of hostAddr + s.FHost = value + +proc host*(s: TSocket): int {.inline.} = + ## getter of hostAddr + return s.FHost + +var + s: TSocket +s.host = 34 # same as `host=`(s, 34) +stdout.write(s.host) + +# now use these classes: +var + r: TRectangle + c: TCircle +init(r) +init(c) +r!draw +c!draw() + +#OUT 34[]o 5 + + + diff --git a/tests/operator/tofopr.nim b/tests/operator/tofopr.nim deleted file mode 100644 index 961d81bd3..000000000 --- a/tests/operator/tofopr.nim +++ /dev/null @@ -1,26 +0,0 @@ -discard """ - file: "tofopr.nim" - output: "falsetrue" -""" -# Test is operator - -type - TMyType = object {.inheritable.} - len: int - data: string - - TOtherType = object of TMyType - -proc p(x: TMyType): bool = - return x of TOtherType - -var - m: TMyType - n: TOtherType - -write(stdout, p(m)) -write(stdout, p(n)) - -#OUT falsetrue - - diff --git a/tests/operator/toprprec.nim b/tests/operator/toprprec.nim deleted file mode 100644 index ce33934b5..000000000 --- a/tests/operator/toprprec.nim +++ /dev/null @@ -1,39 +0,0 @@ -discard """ - file: "toprprec.nim" - output: "done" -""" -# Test operator precedence: - -template `@` (x: expr): expr {.immediate.} = self.x -template `@!` (x: expr): expr {.immediate.} = x -template `===` (x: expr): expr {.immediate.} = x - -type - TO = object - x: int - TA = tuple[a, b: int, obj: TO] - -proc init(self: var TA): string = - @a = 3 - === @b = 4 - @obj.x = 4 - @! === result = "abc" - result = @b.`$` - -assert 3+5*5-2 == 28- -26-28 - -proc `^-` (x, y: int): int = - # now right-associative! - result = x - y - -assert 34 ^- 6 ^- 2 == 30 -assert 34 - 6 - 2 == 26 - - -var s: TA -assert init(s) == "4" - -echo "done" - - - diff --git a/tests/operator/tprecedence.nim b/tests/operator/tprecedence.nim deleted file mode 100644 index 6b1b250a2..000000000 --- a/tests/operator/tprecedence.nim +++ /dev/null @@ -1,11 +0,0 @@ -discard """ - output: "true" -""" - -# Test the new predence rules - -proc `\+` (x, y: int): int = result = x + y -proc `\*` (x, y: int): int = result = x * y - -echo 5 \+ 1 \* 9 == 14 - diff --git a/tests/parser/toprprec.nim b/tests/parser/toprprec.nim new file mode 100644 index 000000000..ce33934b5 --- /dev/null +++ b/tests/parser/toprprec.nim @@ -0,0 +1,39 @@ +discard """ + file: "toprprec.nim" + output: "done" +""" +# Test operator precedence: + +template `@` (x: expr): expr {.immediate.} = self.x +template `@!` (x: expr): expr {.immediate.} = x +template `===` (x: expr): expr {.immediate.} = x + +type + TO = object + x: int + TA = tuple[a, b: int, obj: TO] + +proc init(self: var TA): string = + @a = 3 + === @b = 4 + @obj.x = 4 + @! === result = "abc" + result = @b.`$` + +assert 3+5*5-2 == 28- -26-28 + +proc `^-` (x, y: int): int = + # now right-associative! + result = x - y + +assert 34 ^- 6 ^- 2 == 30 +assert 34 - 6 - 2 == 26 + + +var s: TA +assert init(s) == "4" + +echo "done" + + + diff --git a/tests/parser/tprecedence.nim b/tests/parser/tprecedence.nim new file mode 100644 index 000000000..6b1b250a2 --- /dev/null +++ b/tests/parser/tprecedence.nim @@ -0,0 +1,11 @@ +discard """ + output: "true" +""" + +# Test the new predence rules + +proc `\+` (x, y: int): int = result = x + y +proc `\*` (x, y: int): int = result = x * y + +echo 5 \+ 1 \* 9 == 14 + diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim new file mode 100644 index 000000000..d1e0585d2 --- /dev/null +++ b/tests/showoff/tdrdobbs_examples.nim @@ -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 .. Date: Thu, 23 Jan 2014 08:47:22 +0100 Subject: closure iterators work --- compiler/lambdalifting.nim | 54 +++++++++++++++++++++++++---------- doc/manual.txt | 16 ++++++++++- tests/closure/tnamedparamanonproc.nim | 4 +-- todo.txt | 35 +++++++++++++---------- 4 files changed, 76 insertions(+), 33 deletions(-) (limited to 'tests') diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 352b40693..a9c4a8757 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -116,7 +116,7 @@ type TDep = tuple[e: PEnv, field: PSym] TEnv {.final.} = object of TObject attachedNode: PNode - closure: PSym # if != nil it is a used environment + createdVar: PSym # if != nil it is a used environment capturedVars: seq[PSym] # captured variables in this environment deps: seq[TDep] # dependencies up: PEnv @@ -544,19 +544,20 @@ proc addVar*(father, v: PNode) = addSon(vpart, ast.emptyNode) addSon(father, vpart) -proc getClosureVar(o: POuterContext, e: PEnv): PSym = - if e.closure == nil: - result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info) - incl(result.flags, sfShadowed) - result.typ = newType(tyRef, o.fn) - result.typ.rawAddSon(e.tup) - e.closure = result - else: - result = e.closure +proc newClosureCreationVar(o: POuterContext; e: PEnv): PSym = + result = newSym(skVar, getIdent(envName), o.fn, e.attachedNode.info) + incl(result.flags, sfShadowed) + result.typ = newType(tyRef, o.fn) + result.typ.rawAddSon(e.tup) -proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = - var env = getClosureVar(o, scope) +proc getClosureVar(o: POuterContext; e: PEnv): PSym = + if e.createdVar == nil: + result = newClosureCreationVar(o, e) + e.createdVar = result + else: + result = e.createdVar +proc rawClosureCreation(o: POuterContext, scope: PEnv; env: PSym): PNode = result = newNodeI(nkStmtList, env.info) var v = newNodeI(nkVarSection, env.info) addVar(v, newSymNode(env)) @@ -577,6 +578,21 @@ proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = # add ``env.up = env2`` result.add(newAsgnStmt(indirectAccess(env, field, env.info), newSymNode(getClosureVar(o, e)), env.info)) + +proc generateClosureCreation(o: POuterContext, scope: PEnv): PNode = + var env = getClosureVar(o, scope) + result = rawClosureCreation(o, scope, env) + +proc generateIterClosureCreation(o: POuterContext; env: PEnv; + scope: PNode): PSym = + result = newClosureCreationVar(o, env) + let cc = rawClosureCreation(o, env, result) + var insertPoint = scope.sons[0] + if insertPoint.kind == nkEmpty: scope.sons[0] = cc + else: + assert cc.kind == nkStmtList and insertPoint.kind == nkStmtList + for x in cc: insertPoint.add(x) + if env.createdVar == nil: env.createdVar = result proc interestingIterVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags @@ -635,8 +651,16 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = var closure = PEnv(idTableGet(o.lambdasToEnv, local)) if closure != nil: - # we need to replace the lambda with '(lambda, env)': - let a = closure.closure + # we need to replace the lambda with '(lambda, env)': + if local.kind == skIterator and local.typ.callConv == ccClosure: + # consider: [i1, i2, i1] Since we merged the iterator's closure + # with the captured owning variables, we need to generate the + # closure generation code again: + let createdVar = generateIterClosureCreation(o, closure, + closure.attachedNode) + return makeClosure(local, createdVar, n.info) + + let a = closure.createdVar if a != nil: return makeClosure(local, a, n.info) else: @@ -646,7 +670,7 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = if scope.sons[0].kind == nkEmpty: # change the empty node to contain the closure construction: scope.sons[0] = generateClosureCreation(o, closure) - let x = closure.closure + let x = closure.createdVar assert x != nil return makeClosure(local, x, n.info) diff --git a/doc/manual.txt b/doc/manual.txt index 9f84bc951..faf62dcee 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -2837,8 +2837,22 @@ The builtin ``system.finished`` can be used to determine if an iterator has finished its operation; no exception is raised on an attempt to invoke an iterator that has already finished its work. -One always has to +Closure iterators are *resumable functions* and so one has to provide the +arguments to every call. To get around this limitation one can capture +parameters of an outer factory proc: +.. code-block:: nimrod + proc mycount(a, b: int): iterator (): int = + return iterator (): int = + var x = a + while x <= b: + yield x + inc x + + let foo = mycount 1, 4 + + for f in foo(): + echo f Type sections diff --git a/tests/closure/tnamedparamanonproc.nim b/tests/closure/tnamedparamanonproc.nim index 272b84e91..94e32894f 100644 --- a/tests/closure/tnamedparamanonproc.nim +++ b/tests/closure/tnamedparamanonproc.nim @@ -4,8 +4,8 @@ type TButtonClicked = proc(button: PButton) {.nimcall.} proc newButton*(onClick: TButtonClicked) = - nil - + discard + proc main() = newButton(onClick = proc(b: PButton) = var requestomat = 12 diff --git a/todo.txt b/todo.txt index 943d982c4..d0aec9c8c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,20 +1,8 @@ version 0.9.4 ============= -- test&finish first class iterators: - * nested iterators -- implement strongSpaces:on -- ensure (ref T)(a, b) works as a type conversion and type constructor +- better debugging support for writes to locations - document new templating symbol binding rules -- make '--implicitStatic:on' the default -- change comment handling in the AST - -- special rule for ``[]=`` -- ``=`` should be overloadable; requires specialization for ``=``; general - lift mechanism in the compiler is already implemented for 'fields' -- built-in 'getImpl' -- optimize 'genericReset'; 'newException' leads to code bloat -- stack-less GC - fix eval in macros.nim @@ -37,12 +25,29 @@ Bugs version 0.9.x ============= -- macros as type pragmas +- ensure (ref T)(a, b) works as a type conversion and type constructor +- optimize 'genericReset'; 'newException' leads to code bloat +- stack-less GC +- implement strongSpaces:on +- make '--implicitStatic:on' the default - implicit deref for parameter matching + +- special rule for ``[]=`` +- ``=`` should be overloadable; requires specialization for ``=``; general + lift mechanism in the compiler is already implemented for 'fields' +- built-in 'getImpl' + +- change comment handling in the AST; that's lots of work as c2nim and pas2nim + make use of the fast every node can have a comment! + + +version 0.9.X +============= + +- macros as type pragmas - lazy overloading resolution: * special case ``tyStmt`` - FFI: - * test libffi on windows * test: times.format with the FFI - document NimMain and check whether it works for threading - 'quote' without 'do' doesn't work: parser/grammar issue; could be supported -- cgit 1.4.1-2-gfad0