summary refs log tree commit diff stats
path: root/tests/closure
diff options
context:
space:
mode:
authorMiran <narimiran@users.noreply.github.com>2018-10-12 17:02:46 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-10-12 17:02:46 +0200
commit7f18d7cbc1fc8ad87c389b8d4d873e1d1169f794 (patch)
tree8c4839495fd6fc10376dc44cc8f9c7e3c625d18f /tests/closure
parentd2b04a8bc7a78845d25e8b789184ae54e98073ec (diff)
downloadNim-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')
-rw-r--r--tests/closure/tclosure.nim728
-rw-r--r--tests/closure/tclosure0.nim87
-rw-r--r--tests/closure/tclosure2.nim101
-rw-r--r--tests/closure/tclosure3.nim21
-rw-r--r--tests/closure/tclosure4.nim13
-rw-r--r--tests/closure/tclosurebug2.nim194
-rw-r--r--tests/closure/tclosureinference3304.nim15
-rw-r--r--tests/closure/tcodegenerr1923.nim9
-rw-r--r--tests/closure/tdeeplynested.nim20
-rw-r--r--tests/closure/tdonotation.nim50
-rw-r--r--tests/closure/tfib50.nim22
-rw-r--r--tests/closure/tflatmap.nim24
-rw-r--r--tests/closure/tforum.nim44
-rw-r--r--tests/closure/tfutclosure2138.nim10
-rw-r--r--tests/closure/tinterf.nim24
-rw-r--r--tests/closure/tissue1502def.nim6
-rw-r--r--tests/closure/tissue1642.nim3
-rw-r--r--tests/closure/tissue1846.nim16
-rw-r--r--tests/closure/tissue1911.nim7
-rw-r--r--tests/closure/tissue600.nim4
-rw-r--r--tests/closure/tissues.nim55
-rw-r--r--tests/closure/tjester.nim32
-rw-r--r--tests/closure/tnamedparamanonproc.nim14
-rw-r--r--tests/closure/tnested.nim180
-rw-r--r--tests/closure/tnestedclosure.nim51
-rw-r--r--tests/closure/tnestedproc.nim12
-rw-r--r--tests/closure/tnoclosure.nim25
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