diff options
Diffstat (limited to 'tests/closure')
-rw-r--r-- | tests/closure/t11042.nim | 55 | ||||
-rw-r--r-- | tests/closure/t15594.nim | 10 | ||||
-rw-r--r-- | tests/closure/t1641.nim | 20 | ||||
-rw-r--r-- | tests/closure/t19095.nim | 35 | ||||
-rw-r--r-- | tests/closure/t20152.nim | 20 | ||||
-rw-r--r-- | tests/closure/t8550.nim | 13 | ||||
-rw-r--r-- | tests/closure/t9334.nim | 19 | ||||
-rw-r--r-- | tests/closure/tboehmdeepcopy.nim | 18 | ||||
-rw-r--r-- | tests/closure/tcapture.nim | 34 | ||||
-rw-r--r-- | tests/closure/tclosure.nim | 504 | ||||
-rw-r--r-- | tests/closure/tclosure_issues.nim | 82 | ||||
-rw-r--r-- | tests/closure/texplicit_dummy_closure.nim | 25 | ||||
-rw-r--r-- | tests/closure/tinfer_closure_for_nestedproc.nim | 42 | ||||
-rw-r--r-- | tests/closure/tinvalidclosure.nim | 12 | ||||
-rw-r--r-- | tests/closure/tinvalidclosure2.nim | 14 | ||||
-rw-r--r-- | tests/closure/tinvalidclosure3.nim | 12 | ||||
-rw-r--r-- | tests/closure/tinvalidclosure4.nim | 9 | ||||
-rw-r--r-- | tests/closure/tinvalidclosure5.nim | 10 | ||||
-rw-r--r-- | tests/closure/tmacrobust1512.nim | 123 | ||||
-rw-r--r-- | tests/closure/tnested.nim | 215 | ||||
-rw-r--r-- | tests/closure/tstmtlist.nim | 9 | ||||
-rw-r--r-- | tests/closure/ttimeinfo.nim | 22 | ||||
-rw-r--r-- | tests/closure/uclosures.nim | 23 |
23 files changed, 1326 insertions, 0 deletions
diff --git a/tests/closure/t11042.nim b/tests/closure/t11042.nim new file mode 100644 index 000000000..6a3928316 --- /dev/null +++ b/tests/closure/t11042.nim @@ -0,0 +1,55 @@ +discard """ + output:''' +foo: 1 +foo: 2 +bar: 1 +bar: 2 +foo: 1 +foo: 2 +bar: 1 +bar: 2 +bar: 3 +bar: 4 +bar: 5 +bar: 6 +bar: 7 +bar: 8 +bar: 9 +''' +""" + +# bug #11042 +block: + iterator foo: int = + for x in 1..2: + echo "foo: ", x + for y in 1..2: + discard + + for x in foo(): discard + + let bar = iterator: int = + for x in 1..2: + echo "bar: ", x + for y in 1..2: + discard + + for x in bar(): discard + + +block: + iterator foo: int = + for x in 1..2: + echo "foo: ", x + for y in 1..2: + discard + + for x in foo(): discard + + let bar = iterator: int = + for x in 1..9: + echo "bar: ", x + for y in 1..2: + discard + + for x in bar(): discard \ No newline at end of file diff --git a/tests/closure/t15594.nim b/tests/closure/t15594.nim new file mode 100644 index 000000000..aacd9ed84 --- /dev/null +++ b/tests/closure/t15594.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "The variable name cannot be `result`!" +""" + +import sugar + +proc begin(): int = + capture result: + echo 1+1 + result diff --git a/tests/closure/t1641.nim b/tests/closure/t1641.nim new file mode 100644 index 000000000..a3e4da367 --- /dev/null +++ b/tests/closure/t1641.nim @@ -0,0 +1,20 @@ +discard """ + output: '''foo 0 +bar 0 +baz''' +""" + +# bug #1641 +proc baz() = + echo "baz" + +proc bar(x: int, p: proc()) = + echo "bar ", x + p() + +proc foo(x: int, p: proc(x: int)) = + echo "foo ", x + p(x) + +let x = 0 +x.foo do(x: int): x.bar do(): baz() diff --git a/tests/closure/t19095.nim b/tests/closure/t19095.nim new file mode 100644 index 000000000..880456e02 --- /dev/null +++ b/tests/closure/t19095.nim @@ -0,0 +1,35 @@ +discard """ + action: compile +""" + +block: + func inCheck() = + discard + + iterator iter(): int = + yield 0 + yield 0 + + func search() = + let inCheck = 0 + + for i in iter(): + + proc hello() = + inCheck() + + search() +block: + iterator iter(): int = + yield 0 + yield 0 + + func search() = + let lmrMoveCounter = 0 + + for i in iter(): + + proc hello() = + discard lmrMoveCounter + + search() diff --git a/tests/closure/t20152.nim b/tests/closure/t20152.nim new file mode 100644 index 000000000..484ea0741 --- /dev/null +++ b/tests/closure/t20152.nim @@ -0,0 +1,20 @@ +discard """ + action: compile +""" + +proc foo() = + iterator it():int {.closure.} = + yield 1 + proc useIter() {.nimcall.} = + var iii = it # <-- illegal capture + doAssert iii() == 1 + useIter() +foo() + +proc foo2() = + proc bar() = # Local function, but not a closure, because no captures + echo "hi" + proc baz() {.nimcall.} = # Calls local function + bar() + baz() +foo2() diff --git a/tests/closure/t8550.nim b/tests/closure/t8550.nim new file mode 100644 index 000000000..a07f45cdc --- /dev/null +++ b/tests/closure/t8550.nim @@ -0,0 +1,13 @@ +discard """ + targets: "c js" + output: "@[\"42\"]" +""" + +proc chk_fail(): seq[string] = + iterator x(): int {.closure.} = yield 42 + proc f(cl: iterator(): int {.closure.}): seq[string] = + result = @[] + for i in cl(): result.add($i) + result = f(x) + +echo(chk_fail()) diff --git a/tests/closure/t9334.nim b/tests/closure/t9334.nim new file mode 100644 index 000000000..36a9a7d77 --- /dev/null +++ b/tests/closure/t9334.nim @@ -0,0 +1,19 @@ +discard """ + cmd: "nim $target --hints:off $options -r $file" + nimout: '''@[1] +@[1, 1] +''' + nimoutFull: true +""" +proc p(s: var seq[int]): auto = + let sptr = addr s + return proc() = sptr[].add 1 + +proc f = + var data = @[1] + p(data)() + echo repr data + +static: + f() # prints [1] +f() # prints [1, 1] diff --git a/tests/closure/tboehmdeepcopy.nim b/tests/closure/tboehmdeepcopy.nim new file mode 100644 index 000000000..7c937ca10 --- /dev/null +++ b/tests/closure/tboehmdeepcopy.nim @@ -0,0 +1,18 @@ +discard """ + cmd: "nim c --gc:boehm $options $file" + output: '''meep''' + disabled: "windows" +""" + +proc callit(it: proc ()) = + it() + +proc main = + var outer = "meep" + proc x = + echo outer + var y: proc() + deepCopy(y, x) + callit(y) + +main() diff --git a/tests/closure/tcapture.nim b/tests/closure/tcapture.nim new file mode 100644 index 000000000..dafc44739 --- /dev/null +++ b/tests/closure/tcapture.nim @@ -0,0 +1,34 @@ +discard """ + output: ''' +to be, or not to be +(v: 1) +(w: -1) +(v: 1) +(w: -1) +''' + joinable: false +""" + +import sequtils, sugar + +let m = @[proc (s: string): string = "to " & s, proc (s: string): string = "not to " & s] +var l = m.mapIt(capture([it], proc (s: string): string = it(s))) +let r = l.mapIt(it("be")) +echo r[0] & ", or " & r[1] + +type + O = object + v: int + U = object + w: int +var o = O(v: 1) +var u = U(w: -1) +var execute: proc() +capture o, u: + execute = proc() = + echo o + echo u +execute() +o.v = -1 +u.w = 1 +execute() diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim new file mode 100644 index 000000000..401a71d40 --- /dev/null +++ b/tests/closure/tclosure.nim @@ -0,0 +1,504 @@ +discard """ + targets: "c" + output: ''' +1 3 6 11 20 foo +foo88 +23 24foo 88 +18 +18 +99 +99 +99 +99 99 +99 99 +12 99 99 +12 99 99 +success +@[1, 2, 5] +click at 10,20 +lost focus 1 +lost focus 2 +registered handler for UserEvent 1 +registered handler for UserEvent 2 +registered handler for UserEvent 3 +registered handler for UserEvent 4 +asdas +processClient end +false +baro0 +foo88 +23 24foo 88 +foo88 +23 24foo 88 +11 +@[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1] +''' +joinable: false +""" + + +block tclosure: + proc map(n: var openArray[int], fn: proc (x: int): int {.closure}) = + for i in 0..n.len-1: n[i] = fn(n[i]) + + proc each(n: openArray[int], fn: proc(x: int) {.closure.}) = + for i in 0..n.len-1: + fn(n[i]) + + var myData: array[0..4, int] = [0, 1, 2, 3, 4] + + proc testA() = + var p = 0 + map(myData, proc (x: int): int = + result = x + 1 shl (proc (y: int): int = + return y + p + )(0) + inc(p)) + + testA() + + myData.each do (x: int): + write(stdout, x) + write(stdout, " ") + + #OUT 2 4 6 8 10 + + # bug #5015 + + type Mutator = proc(matched: string): string {.noSideEffect, gcsafe.} + + proc putMutated( + MutatorCount: static[int], + mTable: static[array[MutatorCount, Mutator]], input: string) = + for i in 0..<MutatorCount: echo mTable[i](input) + + proc mutator0(matched: string): string = + "foo" + + const + mTable = [Mutator(mutator0)] + + putMutated(1, mTable, "foo") + + + +block tclosure0: + when true: + # test simple closure within dummy 'main': + proc dummy = + proc main2(param: int) = + var fooB = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo fooB, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + main2(24) + + dummy() + + when true: + proc outer2(x:int) : proc(y:int):int = # curry-ed application + return proc(y:int):int = x*y + + var fn = outer2(6) # the closure + echo fn(3) # it works + + var rawP = fn.rawProc() + var rawE = fn.rawEnv() + + # A type to cast the function pointer into a nimcall + type TimesClosure = proc(a: int, x: pointer): int {.nimcall.} + + # Call the function with its closure + echo cast[TimesClosure](rawP)(3, rawE) + + when true: + proc outer = + var x, y: int = 99 + proc innerA = echo x + proc innerB = + echo y + innerA() + + innerA() + innerB() + + outer() + + when true: + proc indirectDep = + var x, y: int = 99 + proc innerA = echo x, " ", y + proc innerB = + innerA() + + innerA() + innerB() + + indirectDep() + + when true: + proc needlessIndirection = + var x, y: int = 99 + proc indirection = + var z = 12 + proc innerA = echo z, " ", x, " ", y + proc innerB = + innerA() + + innerA() + innerB() + indirection() + + needlessIndirection() + + + + + + +block tclosure3: + proc main = + const n = 30 + for iterations in 0..10_000: + var s: seq[proc(): string {.closure.}] = @[] + for i in 0 .. n-1: + (proc () = + let ii = i + s.add(proc(): string = return $(ii*ii)))() + for i in 0 .. n-1: + let val = s[i]() + if val != $(i*i): echo "bug ", val + + if getOccupiedMem() > 5000_000: quit("still a leak!") + echo "success" + + main() + + + +import json, tables, sequtils +block tclosure4: + proc run(json_params: OrderedTable) = + let json_elems = json_params["files"].elems + # These fail compilation. + var files = map(json_elems, proc (x: JsonNode): string = x.str) + + let text = """{"files": ["a", "b", "c"]}""" + run((text.parseJson).fields) + + + +import sugar +block inference3304: + type + List[T] = ref object + val: T + + proc foo[T](l: List[T]): seq[int] = + @[1,2,3,5].filter(x => x != l.val) + + echo(foo(List[int](val: 3))) + + + +block tcodegenerr1923: + type + Foo[M] = proc() : M + + proc bar[M](f : Foo[M]) = + discard f() + + proc baz() : int = 42 + + bar(baz) + + + +block doNotation: + type + Button = object + Event = object + x, y: int + + proc onClick(x: Button, handler: proc(x: Event)) = + handler(Event(x: 10, y: 20)) + + proc onFocusLost(x: Button, handler: proc()) = + handler() + + proc onUserEvent(x: Button, eventName: string, handler: proc) = + echo "registered handler for ", eventName + + var b = Button() + + b.onClick do (e: Event): + echo "click at ", e.x, ",", e.y + + b.onFocusLost do (): + echo "lost focus 1" + + b.onFocusLost do (): + echo "lost focus 2" + + b.onUserEvent("UserEvent 1") do (): + discard + + onUserEvent(b, "UserEvent 2") do (): + discard + + b.onUserEvent("UserEvent 3") do (): + discard + + b.onUserEvent("UserEvent 4", () => echo "event 4") + + + +import tables +block fib50: + proc memoize(f: proc (a: int64): int64): proc (a: int64): int64 = + var previous = initTable[int64, int64]() + return proc(i: int64): int64 = + if not previous.hasKey i: + previous[i] = f(i) + return previous[i] + + var fib: proc(a: int64): int64 + + fib = memoize(proc (i: int64): int64 = + if i == 0 or i == 1: + return 1 + return fib(i-1) + fib(i-2) + ) + + doAssert fib(50) == 20365011074 + + + +block tflatmap: + # bug #3995 + type + RNG = tuple[] + Rand[A] = (RNG) -> (A, RNG) + + proc nextInt(r: RNG): (int, RNG) = + (1, ()) + + proc flatMap[A,B](f: Rand[A], g: A -> Rand[B]): Rand[B] = + (rng: RNG) => ( + let (a, rng2) = f(rng); + let g1 = g(a); + g1(rng2) + ) + + proc map[A,B](s: Rand[A], f: A -> B): Rand[B] = + let g: A -> Rand[B] = (a: A) => ((rng: RNG) => (f(a), rng)) + flatMap(s, g) + + discard nextInt.map(i => i - i mod 2) + + + +block tforum: + type + PAsyncHttpServer = ref object + value: string + PFutureBase = ref object + callback: proc () {.closure.} + value: string + failed: bool + + proc accept(server: PAsyncHttpServer): PFutureBase = + new(result) + result.callback = proc () = + discard + server.value = "hahaha" + + proc processClient(): PFutureBase = + new(result) + + proc serve(server: PAsyncHttpServer): PFutureBase = + iterator serveIter(): PFutureBase {.closure.} = + echo server.value + while true: + var acceptAddrFut = server.accept() + yield acceptAddrFut + var fut = acceptAddrFut.value + + var f = processClient() + f.callback = + proc () = + echo("processClient end") + echo(f.failed) + yield f + var x = serveIter + for i in 0 .. 1: + result = x() + result.callback() + + discard serve(PAsyncHttpServer(value: "asdas")) + + + +block futclosure2138: + proc any[T](list: varargs[T], pred: (T) -> bool): bool = + for item in list: + if pred(item): + result = true + break + + proc contains(s: string, words: varargs[string]): bool = + any(words, (word) => s.contains(word)) + + + +block tinterf: + type + ITest = tuple[ + setter: proc(v: int) {.closure.}, + getter1: proc(): int {.closure.}, + getter2: proc(): int {.closure.}] + + proc getInterf(): ITest = + var shared1, shared2: int + + return (setter: proc (x: int) = + shared1 = x + shared2 = x + 10, + getter1: proc (): int = result = shared1, + getter2: proc (): int = return shared2) + + var i = getInterf() + i.setter(56) + + doAssert i.getter1() == 56 + doAssert i.getter2() == 66 + + + +block tjester: + type + Future[T] = ref object + data: T + callback: proc () {.closure.} + + proc cbOuter(response: string) {.discardable.} = + iterator cbIter(): Future[int] {.closure.} = + for i in 0..7: + proc foo(): int = + iterator fooIter(): Future[int] {.closure.} = + echo response, i + yield Future[int](data: 17) + var iterVar = fooIter + iterVar().data + yield Future[int](data: foo()) + + var iterVar2 = cbIter + proc cb2() {.closure.} = + try: + if not finished(iterVar2): + let next = iterVar2() + if next != nil: + next.callback = cb2 + except: + echo "WTF" + cb2() + + cbOuter "baro" + + + +block tnamedparamanonproc: + type + PButton = ref object + TButtonClicked = proc(button: PButton) {.nimcall.} + + proc newButton(onClick: TButtonClicked) = + discard + + proc main() = + newButton(onClick = proc(b: PButton) = + var requestomat = 12 + ) + + main() + + + +block tnestedclosure: + proc main(param: int) = + var foo = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo foo, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + + # test simple closure within dummy 'main': + proc dummy = + proc main2(param: int) = + var fooB = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo fooB, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + main2(24) + + dummy() + + main(24) + + # Jester + async triggered this bug: + proc cbOuter() = + var response = "hohoho" + block: + proc cbIter() = + block: + proc fooIter() = + doAssert response == "hohoho" + fooIter() + cbIter() + cbOuter() + + + +block tnestedproc: + proc p(x, y: int): int = + result = x + y + + echo p((proc (): int = + var x = 7 + return x)(), + (proc (): int = return 4)()) + + + +block tnoclosure: + proc pascal(n: int) = + var row = @[1] + for r in 1..n: + row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1]) + echo row + pascal(10) + +block: # bug #22297 + iterator f: int {.closure.} = + try: + yield 12 + finally: + return 14 + + let s = f + doAssert s() == 12 + doAssert s() == 14 diff --git a/tests/closure/tclosure_issues.nim b/tests/closure/tclosure_issues.nim new file mode 100644 index 000000000..b1a2d7c6b --- /dev/null +++ b/tests/closure/tclosure_issues.nim @@ -0,0 +1,82 @@ +discard """ + output: '''true +(999, 0) +ok 0 +ok 1 +ok 2 +''' +""" + + +block tissue600: + for i in 1..1: + var reported = false + proc report() = + reported = true + + + +import sequtils +block tissue1502def: + let xs: seq[tuple[key: string, val: seq[string]]] = @[("foo", @["bar"])] + + let maps = xs.map( + proc(x: auto): tuple[typ: string, maps: seq[string]] = + (x.key, x.val.map(proc(x: string): string = x))) + + + +block tissue1642: + var i = 0 + proc p() = inc(i) + + + +block tissue1846: + type + TBinOp[T] = proc (x,y: T): bool + THeap[T] = object + cmp: TBinOp[T] + + proc less[T](x,y: T): bool = + x < y + + proc initHeap[T](cmp: TBinOp[T]): THeap[T] = + result.cmp = cmp + + var h = initHeap[int](less[int]) + echo h.cmp(2,3) + + + +block tissue1911: + proc foo(x: int) : auto = + + proc helper() : int = x + proc bar() : int = helper() + proc baz() : int = helper() + + return (bar, baz) + +# bug #11523 +proc foo(): proc = + let a = 999 + return proc(): (int, int) = + return (a, 0) + +echo foo()() + + +block tissue7104: + proc sp(cb: proc())= + cb() + + sp do (): + var i = 0 + echo "ok ", i + sp do (): + inc i + echo "ok ", i + sp do (): + inc i + echo "ok ", i diff --git a/tests/closure/texplicit_dummy_closure.nim b/tests/closure/texplicit_dummy_closure.nim new file mode 100644 index 000000000..02b9ac7c7 --- /dev/null +++ b/tests/closure/texplicit_dummy_closure.nim @@ -0,0 +1,25 @@ +discard """ + disabled: true +""" + +# This is a regression of the new lambda lifting; detected by Aporia +import asyncio, sockets +import os + +type + Window = object + oneInstSock*: AsyncSocket + IODispatcher*: Dispatcher + +var + win: Window + +proc initSocket() = + win.oneInstSock = asyncSocket() + #win.oneInstSock.handleAccept = + proc test(s: AsyncSocket) = + var client: AsyncSocket + proc dummy(c: AsyncSocket) {.closure.} = + discard + client.handleRead = dummy + test(win.oneInstSock) diff --git a/tests/closure/tinfer_closure_for_nestedproc.nim b/tests/closure/tinfer_closure_for_nestedproc.nim new file mode 100644 index 000000000..6450d1492 --- /dev/null +++ b/tests/closure/tinfer_closure_for_nestedproc.nim @@ -0,0 +1,42 @@ +discard """ + action: compile +""" + +# bug #9441 +import asyncdispatch, asyncfutures, strtabs + +type + Request = object + Context = object + position: int + accept: bool + headers: StringTableRef + Handler = proc (r: ref Request, c: Context): Future[Context] + +proc respond(req: Request): Future[void] = discard + +proc handle*(h: Handler): auto = # (proc (req: Request): Future[void]) = + proc server(req: Request): Future[void] {.async.} = + let emptyCtx = Context( + position: 0, + accept: true, + headers: newStringTable() + ) + var reqHeap = new(Request) + reqHeap[] = req + var + f: Future[Context] + ctx: Context + try: + f = h(reqHeap, emptyCtx) + ctx = await f + except: + discard + if f.failed: + await req.respond() + else: + if not ctx.accept: + await req.respond() + return server + +waitFor handle(nil)(Request()) diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim new file mode 100644 index 000000000..37d0f68a2 --- /dev/null +++ b/tests/closure/tinvalidclosure.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "type mismatch: got <proc (x: int){.nimcall, gcsafe.}>" + line: 12 +""" + +proc ugh[T](x: T) {.nimcall.} = + echo "ugha" + + +proc takeCdecl(p: proc (x: int) {.cdecl.}) = discard + +takeCDecl(ugh[int]) diff --git a/tests/closure/tinvalidclosure2.nim b/tests/closure/tinvalidclosure2.nim new file mode 100644 index 000000000..2d58f0215 --- /dev/null +++ b/tests/closure/tinvalidclosure2.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: "illegal capture 'A'" + line: 10 +""" + +proc outer() = + var A: int + + proc ugh[T](x: T) {.cdecl.} = + echo "ugha", A, x + + ugh[int](12) + +outer() diff --git a/tests/closure/tinvalidclosure3.nim b/tests/closure/tinvalidclosure3.nim new file mode 100644 index 000000000..0cbdaf39e --- /dev/null +++ b/tests/closure/tinvalidclosure3.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "illegal capture 'x'" + line: 9 +""" + +proc outer(arg: string) = + var x = 0 + proc inner {.inline.} = + echo "inner", x + inner() + +outer("abc") diff --git a/tests/closure/tinvalidclosure4.nim b/tests/closure/tinvalidclosure4.nim new file mode 100644 index 000000000..7985a2488 --- /dev/null +++ b/tests/closure/tinvalidclosure4.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "illegal capture 'v'" + line: 7 +""" + +proc outer(v: int) = + proc b {.nimcall.} = echo v + b() +outer(5) diff --git a/tests/closure/tinvalidclosure5.nim b/tests/closure/tinvalidclosure5.nim new file mode 100644 index 000000000..3b5f46a40 --- /dev/null +++ b/tests/closure/tinvalidclosure5.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "type mismatch: got <proc (){.closure, gcsafe.}> but expected 'A = proc (){.nimcall.}'" + line: 9 +""" + +type A = proc() {.nimcall.} +proc main = + let b = 1 + let a: A = proc() = echo b + diff --git a/tests/closure/tmacrobust1512.nim b/tests/closure/tmacrobust1512.nim new file mode 100644 index 000000000..0f44c5e1a --- /dev/null +++ b/tests/closure/tmacrobust1512.nim @@ -0,0 +1,123 @@ +discard """ +output: "" +""" + +import macros, strutils + +# https://github.com/nim-lang/Nim/issues/1512 + +proc macrobust0(input: string): string = + var output = "" + proc p1(a:string) = + output.add(a) + + proc p2(a:string) = p1(a) + proc p3(a:string) = p2(a) + proc p4(a:string) = p3(a) + proc p5(a:string) = p4(a) + proc p6(a:string) = p5(a) + proc p7(a:string) = p6(a) + proc p8(a:string) = p7(a) + proc p9(a:string) = p8(a) + proc p10(a:string) = p9(a) + proc p11(a:string) = p10(a) + proc p12(a:string) = p11(a) + proc p13(a:string) = p12(a) + proc p14(a:string) = p13(a) + proc p15(a:string) = p14(a) + proc p16(a:string) = p15(a) + proc p17(a:string) = p16(a) + proc p18(a:string) = p17(a) + proc p19(a:string) = p18(a) + proc p20(a:string) = p19(a) + + for a in input.split(): + p20(a) + p19(a) + p18(a) + p17(a) + p16(a) + p15(a) + p14(a) + p13(a) + p12(a) + p11(a) + p10(a) + p9(a) + p8(a) + p7(a) + p6(a) + p5(a) + p4(a) + p3(a) + p2(a) + p1(a) + + result = output + +macro macrobust(input: static[string]): untyped = + var output = "" + proc p1(a:string) = + output.add(a) + + proc p2(a:string) = p1(a) + proc p3(a:string) = p2(a) + proc p4(a:string) = p3(a) + proc p5(a:string) = p4(a) + proc p6(a:string) = p5(a) + proc p7(a:string) = p6(a) + proc p8(a:string) = p7(a) + proc p9(a:string) = p8(a) + proc p10(a:string) = p9(a) + proc p11(a:string) = p10(a) + proc p12(a:string) = p11(a) + proc p13(a:string) = p12(a) + proc p14(a:string) = p13(a) + proc p15(a:string) = p14(a) + proc p16(a:string) = p15(a) + proc p17(a:string) = p16(a) + proc p18(a:string) = p17(a) + proc p19(a:string) = p18(a) + proc p20(a:string) = p19(a) + + for a in input.split(): + p20(a) + p19(a) + p18(a) + p17(a) + p16(a) + p15(a) + p14(a) + p13(a) + p12(a) + p11(a) + p10(a) + p9(a) + p8(a) + p7(a) + p6(a) + p5(a) + p4(a) + p3(a) + p2(a) + p1(a) + + result = newLit(output) + +const input = """ + fdsasadfsdfa sadfsdafsdaf + dsfsdafdsfadsfa fsdaasdfasdf + fsdafsadfsad asdfasdfasdf + fdsasdfasdfa sadfsadfsadf + sadfasdfsdaf sadfsdafsdaf dsfasdaf + sadfsdafsadf fdsasdafsadf fdsasadfsdaf + sdfasadfsdafdfsa sadfsadfsdaf + sdafsdaffsda sdfasadfsadf + fsdasdafsdfa sdfasdfafsda + sdfasdafsadf sdfasdafsdaf sdfasdafsdaf +""" + +let str1 = macrobust(input) +let str2 = macrobust0(input) + +doAssert str1 == str2 diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim new file mode 100644 index 000000000..ec5af9b13 --- /dev/null +++ b/tests/closure/tnested.nim @@ -0,0 +1,215 @@ +discard """ +targets: "c js" +output: ''' +foo88 +23 24foo 88 +foo88 +23 24foo 88 +11 +int: 108 +0 +11 +1 +11 +2 +11 +3 +11 +4 +11 +5 +11 +6 +11 +7 +11 +8 +11 +9 +11 +11 +py +py +py +py +px +6 +proc (){.closure, noSideEffect, gcsafe.} +''' +""" + + +block tnestedclosure: + proc main(param: int) = + var foo = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo foo, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + + # test simple closure within dummy 'main': + proc dummy = + proc main2(param: int) = + var fooB = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo fooB, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + main2(24) + + dummy() + + main(24) + + # Jester + async triggered this bug: + proc cbOuter() = + var response = "hohoho" + block: + proc cbIter() = + block: + proc fooIter() = + doAssert response == "hohoho" + fooIter() + cbIter() + cbOuter() + + +block tnestedproc: + proc p(x, y: int): int = + result = x + y + + echo p((proc (): int = + var x = 7 + return x)(), + (proc (): int = return 4)()) + + +block deeplynested: + # bug #4070 + proc id(f: (proc())): auto = + return f + + proc foo(myinteger: int): (iterator(): int) = + return iterator(): int {.closure.} = + proc bar() = + proc kk() = + echo "int: ", myinteger + kk() + id(bar)() + + discard foo(108)() + + +block tclosure2: + when true: + proc ax = + for xxxx in 0..9: + var i = 0 + proc bx = + if i > 10: + echo xxxx + return + i += 1 + #for j in 0 .. 0: echo i + bx() + + bx() + echo i + + ax() + + when true: + proc accumulator(start: int): (proc(): int {.closure.}) = + var x = start-1 + #let dummy = proc = + # discard start + + result = proc (): int = + #var x = 9 + for i in 0 .. 0: x = x + 1 + + return x + + var a = accumulator(3) + let b = accumulator(4) + echo a() + b() + a() + + + proc outer = + + proc py() = + # no closure here: + for i in 0..3: echo "py" + + py() + + outer() + + + when true: + proc outer2 = + var errorValue = 3 + proc fac[T](n: T): T = + if n < 0: result = errorValue + elif n <= 1: result = 1 + else: result = n * fac(n-1) + + proc px() {.closure.} = + echo "px" + + proc py() {.closure.} = + echo "py" + + let + mapping = { + "abc": px, + "xyz": py + } + mapping[0][1]() + + echo fac(3) + + + outer2() + +# bug #5688 + +import typetraits + +block: + proc myDiscard[T](a: T) = discard + + proc foo() = + let a = 5 + let f = (proc() = + myDiscard (proc() = echo a) + ) + echo name(typeof(f)) + + foo() + + +block: + iterator foo: int {.closure.} = + yield 1 + yield 2 + yield 3 + + proc pork = + let call = foo + for i in call(): + discard i + + let call2 = foo + while not finished(call2): + discard call2() + + pork() diff --git a/tests/closure/tstmtlist.nim b/tests/closure/tstmtlist.nim new file mode 100644 index 000000000..6a1390617 --- /dev/null +++ b/tests/closure/tstmtlist.nim @@ -0,0 +1,9 @@ +discard """ + action: compile +""" + +proc foo(x: proc()) = x() +foo: echo "a" #[tt.Warning + ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]# +foo do: echo "b" #[tt.Warning + ^ statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead [StmtListLambda]]# diff --git a/tests/closure/ttimeinfo.nim b/tests/closure/ttimeinfo.nim new file mode 100644 index 000000000..24d535cbf --- /dev/null +++ b/tests/closure/ttimeinfo.nim @@ -0,0 +1,22 @@ +discard """ +output: ''' +@[2000-01-01T00:00:00Z, 2001-01-01T00:00:00Z, 2002-01-01T00:00:00Z, 2003-01-01T00:00:00Z, 2004-01-01T00:00:00Z, 2005-01-01T00:00:00Z, 2006-01-01T00:00:00Z, 2007-01-01T00:00:00Z, 2008-01-01T00:00:00Z, 2009-01-01T00:00:00Z, 2010-01-01T00:00:00Z, 2011-01-01T00:00:00Z, 2012-01-01T00:00:00Z, 2013-01-01T00:00:00Z, 2014-01-01T00:00:00Z, 2015-01-01T00:00:00Z] +@[2000-01-01T00:00:00Z, 2001-01-01T00:00:00Z, 2002-01-01T00:00:00Z, 2003-01-01T00:00:00Z, 2004-01-01T00:00:00Z, 2005-01-01T00:00:00Z, 2006-01-01T00:00:00Z, 2007-01-01T00:00:00Z, 2008-01-01T00:00:00Z, 2009-01-01T00:00:00Z, 2010-01-01T00:00:00Z, 2011-01-01T00:00:00Z, 2012-01-01T00:00:00Z, 2013-01-01T00:00:00Z, 2014-01-01T00:00:00Z, 2015-01-01T00:00:00Z] +''' +""" + +# bug #2073 + +import sequtils +import times + +# 1 +proc f(n: int): DateTime = + initDateTime(1, mJan, n, 0, 0, 0, utc()) + +echo toSeq(2000 || 2015).map(f) + +# 2 +echo toSeq(2000 || 2015).map(proc (n: int): DateTime = + initDateTime(1, mJan, n, 0, 0, 0, utc()) +) diff --git a/tests/closure/uclosures.nim b/tests/closure/uclosures.nim new file mode 100644 index 000000000..f259cfeb9 --- /dev/null +++ b/tests/closure/uclosures.nim @@ -0,0 +1,23 @@ +# This test is included from within tunittests +import unittest + +test "loop variables are captured by ref": + var funcs: seq[proc (): int {.closure.}] = @[] + + for i in 0..10: + let ii = i + funcs.add do -> int: return ii * ii + + check funcs[0]() == 100 + check funcs[3]() == 100 + +test "loop variables in closureScope are captured by copy": + var funcs: seq[proc (): int {.closure.}] = @[] + + for i in 0..10: + closureScope: + let ii = i + funcs.add do -> int: return ii * ii + + check funcs[0]() == 0 + check funcs[3]() == 9 |