diff options
author | Miran <narimiran@users.noreply.github.com> | 2018-10-12 17:02:46 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-10-12 17:02:46 +0200 |
commit | 7f18d7cbc1fc8ad87c389b8d4d873e1d1169f794 (patch) | |
tree | 8c4839495fd6fc10376dc44cc8f9c7e3c625d18f /tests/closure | |
parent | d2b04a8bc7a78845d25e8b789184ae54e98073ec (diff) | |
download | Nim-7f18d7cbc1fc8ad87c389b8d4d873e1d1169f794.tar.gz |
Merge tests into a larger file (part 1 of ∞) (#9318)
* merge actiontable tests * merge arithm tests * merge array tests * merge assign tests * merge bind tests * merge casestmt tests * merge closure tests * merge cnt seq tests * merge collections tests * merge concept issues tests * merge concept tests * fix failing tests * smaller outputs Use `doAssert` where possible. * fix wrong output * split `tcomputedgoto` * revert merging concepts * fix failing test
Diffstat (limited to 'tests/closure')
27 files changed, 920 insertions, 847 deletions
diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim index f4364c24a..141968462 100644 --- a/tests/closure/tclosure.nim +++ b/tests/closure/tclosure.nim @@ -1,64 +1,706 @@ discard """ file: "tclosure.nim" - output: '''1 3 6 11 20 foo''' + 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] +''' """ -# Test the closure implementation -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 foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int = - for i in 0..n.len-1: - result = fn(result, n[i]) +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]) + proc foldr(n: openarray[int], fn: proc (x, y: int): int {.closure}): int = + for i in 0..n.len-1: + result = fn(result, n[i]) -var - myData: array[0..4, int] = [0, 1, 2, 3, 4] + proc each(n: openarray[int], fn: proc(x: int) {.closure.}) = + for i in 0..n.len-1: + fn(n[i]) -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)) + var myData: array[0..4, int] = [0, 1, 2, 3, 4] -testA() + 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)) -myData.each do (x: int): - write(stdout, x) - write(stdout, " ") + testA() -#OUT 2 4 6 8 10 + myData.each do (x: int): + write(stdout, x) + write(stdout, " ") -type - ITest = tuple[ - setter: proc(v: int), - getter: proc(): int] + #OUT 2 4 6 8 10 -proc getInterf(): ITest = - var shared: int + type + ITest = tuple[ + setter: proc(v: int), + getter: proc(): int] - return (setter: proc (x: int) = shared = x, - getter: proc (): int = return shared) + proc getInterf(): ITest = + var shared: int + return (setter: proc (x: int) = shared = x, + getter: proc (): int = return shared) -# bug #5015 -type Mutator* = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.} + # bug #5015 -proc putMutated*( - MutatorCount: static[int], - mTable: static[array[MutatorCount, Mutator]], input: string) = - for i in 0..<MutatorCount: echo mTable[i](input) + type Mutator = proc(matched: string): string {.noSideEffect, gcsafe, locks: 0.} -proc mutator0(matched: string): string = - "foo" + proc putMutated( + MutatorCount: static[int], + mTable: static[array[MutatorCount, Mutator]], input: string) = + for i in 0..<MutatorCount: echo mTable[i](input) -const - mTable = [Mutator(mutator0)] + proc mutator0(matched: string): string = + "foo" -putMutated(1, mTable, "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..50_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) + #var files = json_elems.map do (x: JsonNode) -> string: x.str + + let text = """{"files": ["a", "b", "c"]}""" + run((text.parseJson).fields) + + + +import hashes, math +block tclosurebug2: + type + TSlotEnum = enum seEmpty, seFilled, seDeleted + TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B] + TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]] + + TOrderedKeyValuePair[A, B] = tuple[ + slot: TSlotEnum, next: int, key: A, val: B] + TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]] + OrderedTable[A, B] = object ## table that remembers insertion order + data: TOrderedKeyValuePairSeq[A, B] + counter, first, last: int + + const + growthFactor = 2 + + proc mustRehash(length, counter: int): bool {.inline.} = + assert(length > counter) + result = (length * 2 < counter * 3) or (length - counter < 4) + + proc nextTry(h, maxHash: Hash): Hash {.inline.} = + result = ((5 * h) + 1) and maxHash + + template rawGetImpl() {.dirty.} = + var h: Hash = hash(key) and high(t.data) # start with real hash value + while t.data[h].slot != seEmpty: + if t.data[h].key == key and t.data[h].slot == seFilled: + return h + h = nextTry(h, high(t.data)) + result = -1 + + template rawInsertImpl() {.dirty.} = + var h: Hash = hash(key) and high(data) + while data[h].slot == seFilled: + h = nextTry(h, high(data)) + data[h].key = key + data[h].val = val + data[h].slot = seFilled + + template addImpl() {.dirty.} = + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) + inc(t.counter) + + template putImpl() {.dirty.} = + var index = rawGet(t, key) + if index >= 0: + t.data[index].val = val + else: + addImpl() + + proc len[A, B](t: OrderedTable[A, B]): int {.inline.} = + ## returns the number of keys in `t`. + result = t.counter + + template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = + var h = t.first + while h >= 0: + var nxt = t.data[h].next + if t.data[h].slot == seFilled: yieldStmt + h = nxt + + iterator pairs[A, B](t: OrderedTable[A, B]): tuple[key: A, val: B] = + ## iterates over any (key, value) pair in the table `t` in insertion + ## order. + forAllOrderedPairs: + yield (t.data[h].key, t.data[h].val) + + iterator mpairs[A, B](t: var OrderedTable[A, B]): tuple[key: A, val: var B] = + ## iterates over any (key, value) pair in the table `t` in insertion + ## order. The values can be modified. + forAllOrderedPairs: + yield (t.data[h].key, t.data[h].val) + + iterator keys[A, B](t: OrderedTable[A, B]): A = + ## iterates over any key in the table `t` in insertion order. + forAllOrderedPairs: + yield t.data[h].key + + iterator values[A, B](t: OrderedTable[A, B]): B = + ## iterates over any value in the table `t` in insertion order. + forAllOrderedPairs: + yield t.data[h].val + + iterator mvalues[A, B](t: var OrderedTable[A, B]): var B = + ## iterates over any value in the table `t` in insertion order. The values + ## can be modified. + forAllOrderedPairs: + yield t.data[h].val + + proc rawGet[A, B](t: OrderedTable[A, B], key: A): int = + rawGetImpl() + + proc `[]`[A, B](t: OrderedTable[A, B], key: A): B = + ## retrieves the value at ``t[key]``. If `key` is not in `t`, + ## default empty value for the type `B` is returned + ## and no exception is raised. One can check with ``hasKey`` whether the key + ## exists. + var index = rawGet(t, key) + if index >= 0: result = t.data[index].val + + proc mget[A, B](t: var OrderedTable[A, B], key: A): var B = + ## retrieves the value at ``t[key]``. The value can be modified. + ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. + var index = rawGet(t, key) + if index >= 0: result = t.data[index].val + else: raise newException(KeyError, "key not found: " & $key) + + proc hasKey[A, B](t: OrderedTable[A, B], key: A): bool = + ## returns true iff `key` is in the table `t`. + result = rawGet(t, key) >= 0 + + proc rawInsert[A, B](t: var OrderedTable[A, B], + data: var TOrderedKeyValuePairSeq[A, B], + key: A, val: B) = + rawInsertImpl() + data[h].next = -1 + if t.first < 0: t.first = h + if t.last >= 0: data[t.last].next = h + t.last = h + + proc enlarge[A, B](t: var OrderedTable[A, B]) = + var n: TOrderedKeyValuePairSeq[A, B] + newSeq(n, len(t.data) * growthFactor) + var h = t.first + t.first = -1 + t.last = -1 + while h >= 0: + var nxt = t.data[h].next + if t.data[h].slot == seFilled: + rawInsert(t, n, t.data[h].key, t.data[h].val) + h = nxt + swap(t.data, n) + + proc `[]=`[A, B](t: var OrderedTable[A, B], key: A, val: B) = + ## puts a (key, value)-pair into `t`. + putImpl() + + proc add[A, B](t: var OrderedTable[A, B], key: A, val: B) = + ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists. + addImpl() + + proc iniOrderedTable[A, B](initialSize=64): OrderedTable[A, B] = + ## creates a new ordered hash table that is empty. `initialSize` needs to be + ## a power of two. + assert isPowerOfTwo(initialSize) + result.counter = 0 + result.first = -1 + result.last = -1 + newSeq(result.data, initialSize) + + proc toOrderedTable[A, B](pairs: openarray[tuple[key: A, + val: B]]): OrderedTable[A, B] = + ## creates a new ordered hash table that contains the given `pairs`. + result = iniOrderedTable[A, B](nextPowerOfTwo(pairs.len+10)) + for key, val in items(pairs): result[key] = val + + proc sort[A, B](t: var OrderedTable[A,B], + cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) = + ## sorts the ordered table so that the entry with the highest counter comes + ## first. This is destructive (with the advantage of being efficient)! + ## You must not modify `t` afterwards! + ## You can use the iterators `pairs`, `keys`, and `values` to iterate over + ## `t` in the sorted order. + + # we use shellsort here; fast enough and simple + var h = 1 + while true: + h = 3 * h + 1 + if h >= high(t.data): break + while true: + h = h div 3 + for i in countup(h, high(t.data)): + var j = i + #echo(t.data.len, " ", j, " - ", h) + #echo(repr(t.data[j-h])) + proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int = + if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}: + return 0 + elif x.slot in {seEmpty, seDeleted}: + return -1 + elif y.slot in {seEmpty, seDeleted}: + return 1 + else: + let item1 = (x.key, x.val) + let item2 = (y.key, y.val) + return cmp(item1, item2) + + while rawCmp(t.data[j-h], t.data[j]) <= 0: + swap(t.data[j], t.data[j-h]) + j = j-h + if j < h: break + if h == 1: break + + + +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: + echo "lost focus 1" + + b.onFocusLost do: + echo "lost focus 2" + + b.onUserEvent("UserEvent 1") do: + discard + + b.onUserEvent "UserEvent 2": + discard + + b.onUserEvent("UserEvent 3"): + 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) + + let f = 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) diff --git a/tests/closure/tclosure0.nim b/tests/closure/tclosure0.nim deleted file mode 100644 index 9952268d5..000000000 --- a/tests/closure/tclosure0.nim +++ /dev/null @@ -1,87 +0,0 @@ -discard """ - output: '''foo88 -23 24foo 88 -18 -18 -99 -99 -99 -99 99 -99 99 -12 99 99 -12 99 99''' -""" - -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() diff --git a/tests/closure/tclosure2.nim b/tests/closure/tclosure2.nim deleted file mode 100644 index 9c5ee1426..000000000 --- a/tests/closure/tclosure2.nim +++ /dev/null @@ -1,101 +0,0 @@ -discard """ - output: '''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''' -""" - -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() - diff --git a/tests/closure/tclosure3.nim b/tests/closure/tclosure3.nim deleted file mode 100644 index 4de07bdb5..000000000 --- a/tests/closure/tclosure3.nim +++ /dev/null @@ -1,21 +0,0 @@ -discard """ - file: "tclosure3.nim" - output: "success" -""" - -proc main = - const n = 30 - for iterations in 0..50_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() diff --git a/tests/closure/tclosure4.nim b/tests/closure/tclosure4.nim deleted file mode 100644 index bc134ded6..000000000 --- a/tests/closure/tclosure4.nim +++ /dev/null @@ -1,13 +0,0 @@ - -import json, tables, sequtils - -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) - #var files = json_elems.map do (x: JsonNode) -> string: x.str - echo "Hey!" - -when isMainModule: - let text = """{"files": ["a", "b", "c"]}""" - run((text.parseJson).fields) diff --git a/tests/closure/tclosurebug2.nim b/tests/closure/tclosurebug2.nim deleted file mode 100644 index 5f8911dfa..000000000 --- a/tests/closure/tclosurebug2.nim +++ /dev/null @@ -1,194 +0,0 @@ -import hashes, math - -type - TSlotEnum = enum seEmpty, seFilled, seDeleted - TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B] - TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]] - - TOrderedKeyValuePair[A, B] = tuple[ - slot: TSlotEnum, next: int, key: A, val: B] - TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]] - TOrderedTable*[A, B] = object ## table that remembers insertion order - data: TOrderedKeyValuePairSeq[A, B] - counter, first, last: int - -const - growthFactor = 2 - -proc mustRehash(length, counter: int): bool {.inline.} = - assert(length > counter) - result = (length * 2 < counter * 3) or (length - counter < 4) - -proc nextTry(h, maxHash: Hash): Hash {.inline.} = - result = ((5 * h) + 1) and maxHash - -template rawGetImpl() {.dirty.} = - var h: Hash = hash(key) and high(t.data) # start with real hash value - while t.data[h].slot != seEmpty: - if t.data[h].key == key and t.data[h].slot == seFilled: - return h - h = nextTry(h, high(t.data)) - result = -1 - -template rawInsertImpl() {.dirty.} = - var h: Hash = hash(key) and high(data) - while data[h].slot == seFilled: - h = nextTry(h, high(data)) - data[h].key = key - data[h].val = val - data[h].slot = seFilled - -template addImpl() {.dirty.} = - if mustRehash(len(t.data), t.counter): enlarge(t) - rawInsert(t, t.data, key, val) - inc(t.counter) - -template putImpl() {.dirty.} = - var index = rawGet(t, key) - if index >= 0: - t.data[index].val = val - else: - addImpl() - -proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} = - ## returns the number of keys in `t`. - result = t.counter - -template forAllOrderedPairs(yieldStmt: untyped) {.dirty.} = - var h = t.first - while h >= 0: - var nxt = t.data[h].next - if t.data[h].slot == seFilled: yieldStmt - h = nxt - -iterator pairs*[A, B](t: TOrderedTable[A, B]): tuple[key: A, val: B] = - ## iterates over any (key, value) pair in the table `t` in insertion - ## order. - forAllOrderedPairs: - yield (t.data[h].key, t.data[h].val) - -iterator mpairs*[A, B](t: var TOrderedTable[A, B]): tuple[key: A, val: var B] = - ## iterates over any (key, value) pair in the table `t` in insertion - ## order. The values can be modified. - forAllOrderedPairs: - yield (t.data[h].key, t.data[h].val) - -iterator keys*[A, B](t: TOrderedTable[A, B]): A = - ## iterates over any key in the table `t` in insertion order. - forAllOrderedPairs: - yield t.data[h].key - -iterator values*[A, B](t: TOrderedTable[A, B]): B = - ## iterates over any value in the table `t` in insertion order. - forAllOrderedPairs: - yield t.data[h].val - -iterator mvalues*[A, B](t: var TOrderedTable[A, B]): var B = - ## iterates over any value in the table `t` in insertion order. The values - ## can be modified. - forAllOrderedPairs: - yield t.data[h].val - -proc rawGet[A, B](t: TOrderedTable[A, B], key: A): int = - rawGetImpl() - -proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B = - ## retrieves the value at ``t[key]``. If `key` is not in `t`, - ## default empty value for the type `B` is returned - ## and no exception is raised. One can check with ``hasKey`` whether the key - ## exists. - var index = rawGet(t, key) - if index >= 0: result = t.data[index].val - -proc mget*[A, B](t: var TOrderedTable[A, B], key: A): var B = - ## retrieves the value at ``t[key]``. The value can be modified. - ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. - var index = rawGet(t, key) - if index >= 0: result = t.data[index].val - else: raise newException(KeyError, "key not found: " & $key) - -proc hasKey*[A, B](t: TOrderedTable[A, B], key: A): bool = - ## returns true iff `key` is in the table `t`. - result = rawGet(t, key) >= 0 - -proc rawInsert[A, B](t: var TOrderedTable[A, B], - data: var TOrderedKeyValuePairSeq[A, B], - key: A, val: B) = - rawInsertImpl() - data[h].next = -1 - if t.first < 0: t.first = h - if t.last >= 0: data[t.last].next = h - t.last = h - -proc enlarge[A, B](t: var TOrderedTable[A, B]) = - var n: TOrderedKeyValuePairSeq[A, B] - newSeq(n, len(t.data) * growthFactor) - var h = t.first - t.first = -1 - t.last = -1 - while h >= 0: - var nxt = t.data[h].next - if t.data[h].slot == seFilled: - rawInsert(t, n, t.data[h].key, t.data[h].val) - h = nxt - swap(t.data, n) - -proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) = - ## puts a (key, value)-pair into `t`. - putImpl() - -proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) = - ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists. - addImpl() - -proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] = - ## creates a new ordered hash table that is empty. `initialSize` needs to be - ## a power of two. - assert isPowerOfTwo(initialSize) - result.counter = 0 - result.first = -1 - result.last = -1 - newSeq(result.data, initialSize) - -proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A, - val: B]]): TOrderedTable[A, B] = - ## creates a new ordered hash table that contains the given `pairs`. - result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10)) - for key, val in items(pairs): result[key] = val - -proc sort*[A, B](t: var TOrderedTable[A,B], - cmp: proc (x, y: tuple[key: A, val: B]): int {.closure.}) = - ## sorts the ordered table so that the entry with the highest counter comes - ## first. This is destructive (with the advantage of being efficient)! - ## You must not modify `t` afterwards! - ## You can use the iterators `pairs`, `keys`, and `values` to iterate over - ## `t` in the sorted order. - - # we use shellsort here; fast enough and simple - var h = 1 - while true: - h = 3 * h + 1 - if h >= high(t.data): break - while true: - h = h div 3 - for i in countup(h, high(t.data)): - var j = i - #echo(t.data.len, " ", j, " - ", h) - #echo(repr(t.data[j-h])) - proc rawCmp(x, y: TOrderedKeyValuePair[A, B]): int = - if x.slot in {seEmpty, seDeleted} and y.slot in {seEmpty, seDeleted}: - return 0 - elif x.slot in {seEmpty, seDeleted}: - return -1 - elif y.slot in {seEmpty, seDeleted}: - return 1 - else: - let item1 = (x.key, x.val) - let item2 = (y.key, y.val) - return cmp(item1, item2) - - while rawCmp(t.data[j-h], t.data[j]) <= 0: - swap(t.data[j], t.data[j-h]) - j = j-h - if j < h: break - if h == 1: break diff --git a/tests/closure/tclosureinference3304.nim b/tests/closure/tclosureinference3304.nim deleted file mode 100644 index db4aa1d04..000000000 --- a/tests/closure/tclosureinference3304.nim +++ /dev/null @@ -1,15 +0,0 @@ -discard """ - output: '''@[1, 2, 5]''' -""" - -import future, sequtils - -type - List[T] = ref object - val: T - -proc foo[T](l: List[T]): seq[int] = - @[1,2,3,5].filter(x => x != l.val) - -when isMainModule: - echo(foo(List[int](val: 3))) diff --git a/tests/closure/tcodegenerr1923.nim b/tests/closure/tcodegenerr1923.nim deleted file mode 100644 index ee131ae15..000000000 --- a/tests/closure/tcodegenerr1923.nim +++ /dev/null @@ -1,9 +0,0 @@ -type - Foo[M] = proc() : M - -proc bar[M](f : Foo[M]) = - discard f() - -proc baz() : int = 42 - -bar(baz) \ No newline at end of file diff --git a/tests/closure/tdeeplynested.nim b/tests/closure/tdeeplynested.nim deleted file mode 100644 index ddf4fa6a4..000000000 --- a/tests/closure/tdeeplynested.nim +++ /dev/null @@ -1,20 +0,0 @@ -discard """ - output: '''int: 108''' -""" - -# 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)() diff --git a/tests/closure/tdonotation.nim b/tests/closure/tdonotation.nim deleted file mode 100644 index cc4f46bab..000000000 --- a/tests/closure/tdonotation.nim +++ /dev/null @@ -1,50 +0,0 @@ -discard """ -output: ''' -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 -''' -""" - -import future - -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: - echo "lost focus 1" - -b.onFocusLost do: - echo "lost focus 2" - -b.onUserEvent("UserEvent 1") do: - discard - -b.onUserEvent "UserEvent 2": - discard - -b.onUserEvent("UserEvent 3"): - discard - -b.onUserEvent("UserEvent 4", () => echo "event 4") - diff --git a/tests/closure/tfib50.nim b/tests/closure/tfib50.nim deleted file mode 100644 index 719aa3ad5..000000000 --- a/tests/closure/tfib50.nim +++ /dev/null @@ -1,22 +0,0 @@ -discard """ - output: "20365011074" -""" - -import tables - -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) -) - -echo fib(50) diff --git a/tests/closure/tflatmap.nim b/tests/closure/tflatmap.nim deleted file mode 100644 index 240756424..000000000 --- a/tests/closure/tflatmap.nim +++ /dev/null @@ -1,24 +0,0 @@ - -# bug #3995 - -import future - -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) - -let f = nextInt.map(i => i - i mod 2) diff --git a/tests/closure/tforum.nim b/tests/closure/tforum.nim deleted file mode 100644 index 4f6a16ff7..000000000 --- a/tests/closure/tforum.nim +++ /dev/null @@ -1,44 +0,0 @@ -discard """ - output: '''asdas -processClient end -false -''' -""" - -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")) diff --git a/tests/closure/tfutclosure2138.nim b/tests/closure/tfutclosure2138.nim deleted file mode 100644 index e18834074..000000000 --- a/tests/closure/tfutclosure2138.nim +++ /dev/null @@ -1,10 +0,0 @@ -import future, sequtils - -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)) \ No newline at end of file diff --git a/tests/closure/tinterf.nim b/tests/closure/tinterf.nim deleted file mode 100644 index 1ac6da945..000000000 --- a/tests/closure/tinterf.nim +++ /dev/null @@ -1,24 +0,0 @@ -discard """ - output: '''56 66''' -""" - -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) - -echo i.getter1(), " ", i.getter2() - diff --git a/tests/closure/tissue1502def.nim b/tests/closure/tissue1502def.nim deleted file mode 100644 index 0aa6b16e3..000000000 --- a/tests/closure/tissue1502def.nim +++ /dev/null @@ -1,6 +0,0 @@ -import sequtils -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))) \ No newline at end of file diff --git a/tests/closure/tissue1642.nim b/tests/closure/tissue1642.nim deleted file mode 100644 index 5b921fc05..000000000 --- a/tests/closure/tissue1642.nim +++ /dev/null @@ -1,3 +0,0 @@ -block: - var i = 0 - proc p() = inc(i) \ No newline at end of file diff --git a/tests/closure/tissue1846.nim b/tests/closure/tissue1846.nim deleted file mode 100644 index 3fbef169d..000000000 --- a/tests/closure/tissue1846.nim +++ /dev/null @@ -1,16 +0,0 @@ -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 - -when isMainModule: - var h = initHeap[int](less[int]) - - echo h.cmp(2,3) \ No newline at end of file diff --git a/tests/closure/tissue1911.nim b/tests/closure/tissue1911.nim deleted file mode 100644 index 311d99134..000000000 --- a/tests/closure/tissue1911.nim +++ /dev/null @@ -1,7 +0,0 @@ -proc foo(x: int) : auto = - - proc helper() : int = x - proc bar() : int = helper() - proc baz() : int = helper() - - return (bar, baz) \ No newline at end of file diff --git a/tests/closure/tissue600.nim b/tests/closure/tissue600.nim deleted file mode 100644 index eacc7a123..000000000 --- a/tests/closure/tissue600.nim +++ /dev/null @@ -1,4 +0,0 @@ -for i in 1..1: - var reported = false - proc report() = - reported = true \ No newline at end of file diff --git a/tests/closure/tissues.nim b/tests/closure/tissues.nim new file mode 100644 index 000000000..d33e3b403 --- /dev/null +++ b/tests/closure/tissues.nim @@ -0,0 +1,55 @@ +discard """ + file: "tissues.nim" + output: '''true''' +""" + + +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) diff --git a/tests/closure/tjester.nim b/tests/closure/tjester.nim deleted file mode 100644 index 84e0fcb71..000000000 --- a/tests/closure/tjester.nim +++ /dev/null @@ -1,32 +0,0 @@ -discard """ - output: '''baro0''' -""" - -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" diff --git a/tests/closure/tnamedparamanonproc.nim b/tests/closure/tnamedparamanonproc.nim deleted file mode 100644 index 94e32894f..000000000 --- a/tests/closure/tnamedparamanonproc.nim +++ /dev/null @@ -1,14 +0,0 @@ - -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() diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim new file mode 100644 index 000000000..f8d69011a --- /dev/null +++ b/tests/closure/tnested.nim @@ -0,0 +1,180 @@ +discard """ + file: "tnested.nim" + 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 +''' +""" + + +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() diff --git a/tests/closure/tnestedclosure.nim b/tests/closure/tnestedclosure.nim deleted file mode 100644 index 0628a6977..000000000 --- a/tests/closure/tnestedclosure.nim +++ /dev/null @@ -1,51 +0,0 @@ -discard """ - output: '''foo88 -23 24foo 88 -foo88 -23 24foo 88 -hohoho''' -""" - -# test nested closure -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() = - echo response - fooIter() - - cbIter() - -cbOuter() diff --git a/tests/closure/tnestedproc.nim b/tests/closure/tnestedproc.nim deleted file mode 100644 index 7eeeff198..000000000 --- a/tests/closure/tnestedproc.nim +++ /dev/null @@ -1,12 +0,0 @@ -discard """ - output: "11" -""" - -proc p(x, y: int): int = - result = x + y - -echo p((proc (): int = - var x = 7 - return x)(), - (proc (): int = return 4)()) - diff --git a/tests/closure/tnoclosure.nim b/tests/closure/tnoclosure.nim deleted file mode 100644 index 25cce0040..000000000 --- a/tests/closure/tnoclosure.nim +++ /dev/null @@ -1,25 +0,0 @@ -discard """ - output: '''@[1] -@[1, 1] -@[1, 2, 1] -@[1, 3, 3, 1] -@[1, 4, 6, 4, 1] -@[1, 5, 10, 10, 5, 1] -@[1, 6, 15, 20, 15, 6, 1] -@[1, 7, 21, 35, 35, 21, 7, 1] -@[1, 8, 28, 56, 70, 56, 28, 8, 1] -@[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]''' -""" - -import sequtils - -proc pascal(n: int) = - var row = @[1] - for r in 1..n: - echo row - row = zip(row & @[0], @[0] & row).mapIt(it[0] + it[1]) - -pascal(10) - -# bug #3499 last snippet fixed -# bug 705 last snippet fixed |