summary refs log tree commit diff stats
path: root/tests/generics
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-01-13 02:10:03 +0100
committerAraq <rumpf_a@web.de>2014-01-13 02:10:03 +0100
commit20b5f31c03fb556ec0aa2428a40adbac004d8987 (patch)
tree58086941e7d6bb8f480ca1173a95722ada9435b2 /tests/generics
parent51ee524109cf7e3e86c676bc1676063a01bfd979 (diff)
downloadNim-20b5f31c03fb556ec0aa2428a40adbac004d8987.tar.gz
new tester; all tests categorized
Diffstat (limited to 'tests/generics')
-rw-r--r--tests/generics/tbintre2.nim31
-rw-r--r--tests/generics/tbintree.nim107
-rw-r--r--tests/generics/tcan_alias_generic.nim11
-rw-r--r--tests/generics/tcan_alias_specialised_generic.nim17
-rw-r--r--tests/generics/tcan_inherit_generic.nim17
-rw-r--r--tests/generics/tcan_specialise_generic.nim11
-rw-r--r--tests/generics/texplicitgeneric1.nim38
-rw-r--r--tests/generics/texplicitgeneric2.nim35
-rw-r--r--tests/generics/tforwardgeneric.nim13
-rw-r--r--tests/generics/tgeneric0.nim19
-rw-r--r--tests/generics/tgeneric1.nim53
-rw-r--r--tests/generics/tgeneric2.nim15
-rw-r--r--tests/generics/tgeneric3.nim474
-rw-r--r--tests/generics/tgeneric4.nim10
-rw-r--r--tests/generics/tgenericdefaults.nim29
-rw-r--r--tests/generics/tgenericmatcher.nim22
-rw-r--r--tests/generics/tgenericmatcher2.nim18
-rw-r--r--tests/generics/tgenericprocvar.nim36
-rw-r--r--tests/generics/tgenericprop.nim12
-rw-r--r--tests/generics/tgenericrefs.nim26
-rw-r--r--tests/generics/tgenericshardcases.nim36
-rw-r--r--tests/generics/tgenerictmpl.nim12
-rw-r--r--tests/generics/tgenericvariant.nim23
-rw-r--r--tests/generics/tspecialised_is_equivalent.nim15
-rw-r--r--tests/generics/tthread_generic.nim39
-rw-r--r--tests/generics/tvarargs_vs_generic.nim26
26 files changed, 1145 insertions, 0 deletions
diff --git a/tests/generics/tbintre2.nim b/tests/generics/tbintre2.nim
new file mode 100644
index 000000000..2a7225411
--- /dev/null
+++ b/tests/generics/tbintre2.nim
@@ -0,0 +1,31 @@
+discard """
+  file: "tbintre2.nim"
+  output: "helloworld99110223"
+"""
+# Same test, but check module boundaries
+
+import tbintree
+
+var
+  root: PBinaryTree[string]
+  x = newNode("hello")
+add(root, x)
+add(root, "world")
+if find(root, "world"):
+  for str in items(root):
+    stdout.write(str)
+else:
+  stdout.writeln("BUG")
+
+var
+  r2: PBinaryTree[int]
+add(r2, newNode(110))
+add(r2, 223)
+add(r2, 99)
+for y in items(r2):
+  stdout.write(y)
+
+#OUT helloworld99110223
+
+
+
diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim
new file mode 100644
index 000000000..8cc8acb82
--- /dev/null
+++ b/tests/generics/tbintree.nim
@@ -0,0 +1,107 @@
+discard """
+  file: "tbintree.nim"
+  output: "helloworld99110223"
+"""
+type
+  TBinaryTree[T] = object      # TBinaryTree is a generic type with
+                               # with generic param ``T``
+    le, ri: ref TBinaryTree[T] # left and right subtrees; may be nil
+    data: T                    # the data stored in a node
+  PBinaryTree*[A] = ref TBinaryTree[A] # type that is exported
+
+proc newNode*[T](data: T): PBinaryTree[T] =
+  # constructor for a node
+  new(result)
+  result.data = data
+
+proc add*[Ty](root: var PBinaryTree[Ty], n: PBinaryTree[Ty]) =
+  # insert a node into the tree
+  if root == nil:
+    root = n
+  else:
+    var it = root
+    while it != nil:
+      # compare the data items; uses the generic ``cmp`` proc that works for
+      # any type that has a ``==`` and ``<`` operator
+      var c = cmp(n.data, it.data)
+      if c < 0:
+        if it.le == nil:
+          it.le = n
+          return
+        it = it.le
+      else:
+        if it.ri == nil:
+          it.ri = n
+          return
+        it = it.ri
+
+proc add*[Ty](root: var PBinaryTree[Ty], data: Ty) =
+  # convenience proc:
+  add(root, newNode(data))
+
+proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
+  # for testing this needs to be recursive, so that the
+  # instantiated type is checked for proper tyGenericInst envelopes
+  if b == nil:
+    result = false
+  else:
+    var c = cmp(data, b.data)
+    if c < 0: result = find(b.le, data)
+    elif c > 0: result = find(b.ri, data)
+    else: result = true
+
+iterator preorder*[T](root: PBinaryTree[T]): T =
+  # Preorder traversal of a binary tree.
+  # Since recursive iterators are not yet implemented,
+  # this uses an explicit stack:
+  var stack: seq[PBinaryTree[T]] = @[root]
+  while stack.len > 0:
+    var n = stack.pop()
+    while n != nil:
+      yield n.data
+      add(stack, n.ri)  # push right subtree onto the stack
+      n = n.le          # and follow the left pointer
+
+iterator items*[T](root: PBinaryTree[T]): T =
+  ## Inorder traversal of the binary tree.
+  var stack: seq[PBinaryTree[T]] = @[]
+  var n = root
+  while true:
+    while n != nil:
+      add(stack, n)
+      n = n.le
+    if stack.len > 0:
+      n = stack.pop()
+      yield n.data
+      n = n.ri
+    if stack.len == 0 and n == nil: break
+
+proc debug[T](a: PBinaryTree[T]) =
+  if a != nil:
+    debug(a.le)
+    echo a.data
+    debug(a.ri)
+
+when isMainModule:
+  var
+    root: PBinaryTree[string]
+    x = newNode("hello")
+  add(root, x)
+  add(root, "world")
+  if find(root, "world"):
+    for str in items(root):
+      stdout.write(str)
+  else:
+    stdout.writeln("BUG")
+
+  var
+    r2: PBinaryTree[int]
+  add(r2, newNode(110))
+  add(r2, 223)
+  add(r2, 99)
+  for y in items(r2):
+    stdout.write(y)
+
+#OUT helloworld99110223
+
+
diff --git a/tests/generics/tcan_alias_generic.nim b/tests/generics/tcan_alias_generic.nim
new file mode 100644
index 000000000..e90bdc6d2
--- /dev/null
+++ b/tests/generics/tcan_alias_generic.nim
@@ -0,0 +1,11 @@
+##
+## can_alias_generic Nimrod Module
+##
+## Created by Eric Doughty-Papassideris on 2011-02-16.
+## Copyright (c) 2011 FWA. All rights reserved.
+
+type
+  TGen[T] = object
+  TGen2[T] = TGen[T]
+  
+
diff --git a/tests/generics/tcan_alias_specialised_generic.nim b/tests/generics/tcan_alias_specialised_generic.nim
new file mode 100644
index 000000000..8d4a29abd
--- /dev/null
+++ b/tests/generics/tcan_alias_specialised_generic.nim
@@ -0,0 +1,17 @@
+discard """
+  disabled: false
+"""
+
+##
+## can_alias_specialised_generic Nimrod Module
+##
+## Created by Eric Doughty-Papassideris on 2011-02-16.
+## Copyright (c) 2011 FWA. All rights reserved.
+
+type
+  TGen[T] = object
+  TSpef = TGen[string]
+  
+var
+  s: TSpef
+
diff --git a/tests/generics/tcan_inherit_generic.nim b/tests/generics/tcan_inherit_generic.nim
new file mode 100644
index 000000000..a6f4d946b
--- /dev/null
+++ b/tests/generics/tcan_inherit_generic.nim
@@ -0,0 +1,17 @@
+##
+## can_inherit_generic Nimrod Module
+##
+## Created by Eric Doughty-Papassideris on 2011-02-16.
+## Copyright (c) 2011 FWA. All rights reserved.
+
+type
+  TGen[T] = object of TObject
+    x, y: T
+  
+  TSpef[T] = object of TGen[T]
+
+
+var s: TSpef[float]
+s.x = 0.4
+s.y = 0.6
+
diff --git a/tests/generics/tcan_specialise_generic.nim b/tests/generics/tcan_specialise_generic.nim
new file mode 100644
index 000000000..64d5f56e3
--- /dev/null
+++ b/tests/generics/tcan_specialise_generic.nim
@@ -0,0 +1,11 @@
+##
+## can_specialise_generic Nimrod Module
+##
+## Created by Eric Doughty-Papassideris on 2011-02-16.
+## Copyright (c) 2011 FWA. All rights reserved.
+
+type
+  TGen[T] = object {.inheritable.}
+  TSpef = object of TGen[string]
+  
+
diff --git a/tests/generics/texplicitgeneric1.nim b/tests/generics/texplicitgeneric1.nim
new file mode 100644
index 000000000..6cca71ac0
--- /dev/null
+++ b/tests/generics/texplicitgeneric1.nim
@@ -0,0 +1,38 @@
+discard """
+  file: "texplicitgeneric1.nim"
+  output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13"
+"""
+# test explicit type instantiation
+
+type
+  TDict*[TKey, TValue] = object 
+    data: seq[tuple[k: TKey, v: TValue]]
+  PDict*[TKey, #with `==`(a, b: TKey): bool
+               #     hash(a: TKey): int, 
+         TValue] = ref TDict[TKey, TValue]
+  
+proc newDict*[TKey, TValue](): PDict[TKey, TValue] = 
+  new(result)
+  result.data = @[]
+  
+proc add*[TKey, TValue](d: PDict[TKey, TValue], k: TKey, v: TValue) = 
+  d.data.add((k, v))
+  
+iterator items*[Tkey, tValue](d: PDict[TKey, TValue]): tuple[k: TKey, 
+               v: TValue] = 
+  for k, v in items(d.data): yield (k, v)
+    
+var d = newDict[int, string]()
+d.add(12, "12")
+d.add(13, "13")
+for k, v in items(d): 
+  stdout.write("Key: ", $k, " value: ", v)
+
+var c = newDict[char, string]()
+c.add('A', "12")
+c.add('B', "13")
+for k, v in items(c): 
+  stdout.write(" Key: ", $k, " value: ", v)
+
+
+
diff --git a/tests/generics/texplicitgeneric2.nim b/tests/generics/texplicitgeneric2.nim
new file mode 100644
index 000000000..95461d023
--- /dev/null
+++ b/tests/generics/texplicitgeneric2.nim
@@ -0,0 +1,35 @@
+discard """
+  output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13"
+  disabled: true
+"""
+
+# test explicit type instantiation
+
+type
+  TDict*[TKey, TValue] = object 
+    data: seq[tuple[k: TKey, v: TValue]]
+  PDict*[TKey, TValue] = ref TDict[TKey, TValue]
+  
+proc newDict*[TKey, TValue](): PDict[TKey, TValue] = 
+  new(result)
+  result.data = @[]
+  
+proc add*(d: PDict, k: TKey, v: TValue) = 
+  d.data.add((k, v))
+  
+
+#iterator items*(d: PDict): tuple[k: TKey, v: TValue] = 
+#  for k, v in items(d.data): yield (k, v)
+    
+var d = newDict[int, string]()
+d.add(12, "12")
+d.add(13, "13")
+for k, v in items(d): 
+  stdout.write("Key: ", $k, " value: ", v)
+
+var c = newDict[char, string]()
+c.add('A', "12")
+c.add('B', "13")
+for k, v in items(c): 
+  stdout.write(" Key: ", $k, " value: ", v)
+
diff --git a/tests/generics/tforwardgeneric.nim b/tests/generics/tforwardgeneric.nim
new file mode 100644
index 000000000..c5943b966
--- /dev/null
+++ b/tests/generics/tforwardgeneric.nim
@@ -0,0 +1,13 @@
+discard """
+  output: "1.1000000000000001e+00 11"
+  ccodecheck: "!@'ClEnv'"
+"""
+
+proc p[T](a, b: T): T
+
+echo p(0.9, 0.1), " ", p(9, 1)
+
+proc p[T](a, b: T): T =
+  let c = b
+  result = a + b + c
+
diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim
new file mode 100644
index 000000000..9292b729f
--- /dev/null
+++ b/tests/generics/tgeneric0.nim
@@ -0,0 +1,19 @@
+import tables
+
+type
+  TX = TTable[string, int]
+
+proc foo(models: seq[TTable[string, float]]): seq[float] =
+  result = @[]
+  for model in models.items:
+    result.add model["foobar"]
+
+# bug #686
+type TType[T; A] = array[A, T]
+
+proc foo[T](p: TType[T, range[0..1]]) =
+  echo "foo"
+proc foo[T](p: TType[T, range[0..2]]) =
+  echo "bar"
+
+
diff --git a/tests/generics/tgeneric1.nim b/tests/generics/tgeneric1.nim
new file mode 100644
index 000000000..5d20a864b
--- /dev/null
+++ b/tests/generics/tgeneric1.nim
@@ -0,0 +1,53 @@
+discard """
+  output: "100 0"
+"""
+
+# A min-heap.
+type
+  TNode[T] = tuple[priority: int, data: T]
+
+  TBinHeap[T] = object
+    heap: seq[TNode[T]]
+    last: int
+  
+  PBinHeap[T] = ref TBinHeap[T]
+
+proc newBinHeap*[T](heap: var PBinHeap[T], size: int) =
+  new(heap)
+  heap.last = 0
+  newSeq(heap.heap, size)
+  #newSeq(heap.seq, size)
+ 
+proc parent(elem: int): int {.inline.} =
+  return (elem-1) div 2
+
+proc siftUp[T](heap: PBinHeap[T], elem: int) =
+  var idx = elem
+  while idx != 0:
+    var p = parent(idx)
+    if heap.heap[idx].priority < heap.heap[p].priority:
+      swap(heap.heap[idx], heap.heap[p])
+      idx = p
+    else:
+      break
+
+proc add*[T](heap: PBinHeap[T], priority: int, data: T) =
+  var node: TNode[T]
+  node.priority = priority
+  node.data = data
+  heap.heap[heap.last] = node
+  siftUp(heap, heap.last)
+  inc(heap.last)
+
+proc print*[T](heap: PBinHeap[T]) =
+  for i in countup(0, heap.last):
+    stdout.write($heap.heap[i].data, " ")
+
+var
+  heap: PBinHeap[int]
+
+newBinHeap(heap, 256)
+add(heap, 1, 100)
+print(heap)
+
+
diff --git a/tests/generics/tgeneric2.nim b/tests/generics/tgeneric2.nim
new file mode 100644
index 000000000..56803017a
--- /dev/null
+++ b/tests/generics/tgeneric2.nim
@@ -0,0 +1,15 @@
+import tables
+
+type
+  TX = TTable[string, int]
+
+proc foo(models: seq[TX]): seq[int] =
+  result = @[]
+  for model in models.items:
+    result.add model["foobar"]
+
+type
+  obj = object
+    field: TTable[string, string]
+var t: Obj
+discard initTable[type(t.field), string]()
diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim
new file mode 100644
index 000000000..3c543ecfa
--- /dev/null
+++ b/tests/generics/tgeneric3.nim
@@ -0,0 +1,474 @@
+import strutils
+
+type
+  PNode[T,D] = ref TNode[T,D]
+  TItem {.acyclic, pure, final, shallow.} [T,D] = object
+        key: T
+        value: D
+        node: PNode[T,D]
+        when not (D is string):
+          val_set: Bool
+
+  TItems[T,D] = seq[ref TItem[T,D]]
+  TNode {.acyclic, pure, final, shallow.} [T,D] = object
+        slots: TItems[T,D]
+        left: PNode[T,D]
+        count: Int32
+
+
+  RPath[T,D] = tuple[
+    Xi: Int,
+    Nd: PNode[T,D] ]
+
+const
+  cLen1 = 2
+  cLen2 = 16
+  cLen3 = 32
+  cLenCenter = 80
+  clen4 = 96
+  cLenMax = 128
+  cCenter = cLenMax div 2
+
+proc len[T,D] (n:PNode[T,D]): Int {.inline.} =
+  return n.Count
+
+proc clean[T: TOrdinal|TNumber](o: var T) {.inline.} = nil
+
+proc clean[T: string|seq](o: var T) {.inline.} =
+  o = nil
+
+proc clean[T,D] (o: ref TItem[T,D]) {.inline.} = 
+  when (D is string) :
+    o.Value = nil
+  else :
+    o.val_set = false
+
+proc isClean[T,D] (it: ref TItem[T,D]): Bool {.inline.} = 
+  when (D is string) :
+    return it.Value == nil
+  else :
+    return not it.val_set
+
+proc isClean[T,D] (n: PNode[T,D], x: Int): Bool {.inline.} = 
+  when (D is string) :
+    return n.slots[x].Value == nil
+  else :
+    return not n.slots[x].val_set
+
+proc setItem[T,D] (AKey: T, AValue: D, ANode: PNode[T,D]): ref TItem[T,D] {.inline.} = 
+  new(Result)
+  Result.Key = AKey
+  Result.Value = AValue
+  Result.Node = ANode
+  when not (D is string) :
+    Result.val_set = true
+
+proc cmp[T:Int8|Int16|Int32|Int64|Int] (a,b: T): T {.inline.} =
+  return a-b
+
+template binSearchImpl *(docmp: expr) {.immediate.} =
+  var bFound = false
+  result = 0
+  var H = haystack.len -1
+  while result <= H :
+    var I {.inject.} = (result + H) shr 1
+    var SW = docmp 
+    if SW < 0: result = I + 1 
+    else:
+      H = I - 1
+      if SW == 0 : bFound = True
+  if bFound: inc(result)
+  else: result = - result
+
+proc bSearch[T,D] (haystack: PNode[T,D], needle:T): Int {.inline.} =
+  binSearchImpl(haystack.slots[I].key.cmp(needle))
+
+proc DeleteItem[T,D] (n: PNode[T,D], x: Int): PNode[T,D] {.inline.} =
+  var w = n.slots[x]
+  if w.Node != nil : 
+    clean(w)
+    return n
+  dec(n.Count)
+  if n.Count > 0 :
+    for i in countup(x, n.Count -1) : n.slots[i] = n.slots[i + 1]
+    n.slots[n.Count] = nil
+    case n.Count 
+    of cLen1 : setLen(n.slots, cLen1)
+    of cLen2 : setLen(n.slots, cLen2)
+    of cLen3 : setLen(n.slots, cLen3)
+    of cLenCenter : setLen(n.slots, cLenCenter)
+    of cLen4 : setLen(n.slots, cLen4)
+    else: nil
+    Result = n
+
+  else :
+    Result = n.Left
+    n.slots = nil
+    n.Left = nil
+
+proc InternalDelete[T,D] (ANode: PNode[T,D], key: T, AValue: var D): PNode[T,D] = 
+  var Path: array[0..20, RPath[T,D]]
+  var n = ANode
+  Result = n
+  clean(AValue)
+  var h = 0
+  while n != nil:
+    var x = bSearch(n, key)
+    if x <= 0 :
+      Path[h].Nd = n
+      Path[h].Xi = - x
+      inc(h)
+      if x == 0 :
+        n = n.Left
+      else :
+        x = (-x) -1
+        if x < n.Count :
+          n = n.slots[x].Node
+        else :
+          n = nil
+    else : 
+      dec(x)
+      if isClean(n, x) : return
+      AValue = n.slots[x].Value
+      var n2 = DeleteItem(n, x)
+      dec(h)
+      while (n2 != n) and (h >=0) :
+        n = n2 
+        var w = addr Path[h]
+        x  = w.Xi -1
+        if x >= 0 :
+          if (n == nil) and isClean(w.Nd, x) :
+            n = w.Nd
+            n.slots[x].Node = nil 
+            n2 = DeleteItem(n, x)
+          else :
+            w.Nd.slots[x].Node = n
+            return
+        else :
+          w.Nd.Left = n
+          return
+        dec(h)
+      if h < 0:
+        Result = n2
+      return
+
+proc InternalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
+  var wn = n
+  while wn != nil :
+    var x = bSearch(wn, key)
+    if x <= 0 :
+      if x == 0 :
+        wn = wn.Left
+      else :
+        x = (-x) -1
+        if x < wn.Count : 
+          wn = wn.slots[x].Node
+        else :
+          return nil
+
+    else :
+      return wn.slots[x - 1]
+  return nil
+
+proc traceTree[T,D](root: PNode[T,D]) =
+  proc traceX(x: Int) = 
+    write stdout, "("
+    write stdout, x
+    write stdout, ") "
+
+  proc traceEl(el: ref TItem[T,D]) =
+    write stdout, " key: "
+    write stdout, el.Key
+    write stdout, " value: "
+    write stdout, el.Value
+
+
+  proc traceln(space: string) =
+    writeln stdout, ""
+    write stdout, space
+
+  proc doTrace(n: PNode[T,D], level: Int) =
+    var space = repeatChar(2 * level)
+    traceln(space)
+    write stdout, "node: "
+    if n == nil:
+      writeln stdout, "is empty"
+      return
+    write stdout, n.Count
+    write stdout, " elements: "
+    if n.Left != nil:
+      traceln(space)
+      write stdout, "left: "
+      doTrace(n.left, level +1)
+    for i, el in n.slots :
+      if el != nil and not isClean(el):
+        traceln(space)
+        traceX(i)
+        if i >= n.Count: 
+          write stdout, "error "
+        else:
+          traceEl(el)
+          if el.Node != nil: doTrace(el.Node, level +1)
+          else : write stdout, " empty "
+      elif i < n.Count :
+        traceln(space)
+        traceX(i)
+        write stdout, "clean: "
+        when T is string :
+          if el.Key != nil: write stdout, el.Key
+        else : write stdout, el.Key
+        if el.Node != nil: doTrace(el.Node, level +1)
+        else : write stdout, " empty "
+    writeln stdout,""
+
+  doTrace(root, 0)
+
+proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], AKey: T, AValue: D) =
+  var x = - APath.Xi
+  inc(APath.Nd.Count)
+  case APath.Nd.Count 
+  of cLen1: setLen(APath.Nd.slots, cLen2)
+  of cLen2: setLen(APath.Nd.slots, cLen3)
+  of cLen3: setLen(APath.Nd.slots, cLenCenter)
+  of cLenCenter: setLen(APath.Nd.slots, cLen4)
+  of cLen4: setLen(APath.Nd.slots, cLenMax)
+  else: nil
+  for i in countdown(APath.Nd.Count.int - 1, x + 1): shallowCopy(APath.Nd.slots[i], APath.Nd.slots[i - 1])
+  APath.Nd.slots[x] = setItem(AKey, AValue, ANode)
+
+
+proc SplitPage[T,D](n, left: PNode[T,D], xi: Int, AKey:var T, AValue:var D): PNode[T,D] =
+  var x = -Xi
+  var it1: TItems[T,D]
+  it1.newSeq(cLenCenter)
+  new(Result)
+  Result.slots.newSeq(cLenCenter)
+  Result.Count = cCenter
+  if x == cCenter:
+    for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
+    for i in 0..cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
+    Result.Left = n
+  else :
+    if x < cCenter :
+      for i in 0..x-1: shallowCopy(it1[i], left.slots[i])
+      it1[x] = setItem(AKey, AValue, n)
+      for i in x+1 .. cCenter -1: shallowCopy(it1[i], left.slots[i-1])
+      var w = left.slots[cCenter -1]
+      AKey = w.Key
+      AValue = w.Value
+      Result.Left = w.Node
+      for i in 0..cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
+    else :
+      for i in 0..cCenter -1: shallowCopy(it1[i], left.slots[i])
+      x = x - (cCenter + 1)
+      for i in 0..x-1: shallowCopy(Result.slots[i], left.slots[cCenter + i + 1])
+      Result.slots[x] = setItem(AKey, AValue, n)
+      for i in x+1 .. cCenter -1: shallowCopy(Result.slots[i], left.slots[cCenter + i])
+      var w = left.slots[cCenter]
+      AKey = w.Key
+      AValue = w.Value
+      Result.Left = w.Node
+  left.Count = cCenter
+  shallowCopy(left.slots, it1)
+
+
+proc InternalPut[T,D](ANode: ref TNode[T,D], AKey: T, AValue: D, OldValue: var D): ref TNode[T,D] =
+  var h: Int
+  var Path: array[0..30, RPath[T,D]]
+  var left: PNode[T,D]
+  var n = ANode
+
+
+  Result = ANode
+  h = 0
+  while n != nil:
+    var x = bSearch[T,D](n, AKey)
+    if x <= 0 :
+      Path[h].Nd = n
+      Path[h].Xi = x
+      inc(h) 
+      if x == 0 :
+        n = n.Left
+      else :
+        x = (-x) -1
+        if x < n.Count :
+          n = n.slots[x].Node
+        else :
+          n = nil
+    else :
+      var w = n.slots[x - 1]
+      OldValue = w.Value
+      w.Value = AValue
+      return
+
+  dec(h)
+  left = nil
+  var lKey = AKey
+  var lValue = AValue
+  while h >= 0 :
+    if Path[h].Nd.Count < cLenMax :
+      InsertItem(Path[h], n, lKey, lValue)
+      return
+    else :
+      left = Path[h].Nd
+      n = SplitPage(n, left, Path[h].Xi, lKey, lValue)
+    dec(h)
+
+  new(Result)
+  Result.slots.newSeq(cLen1)
+  Result.Count = 1
+  Result.Left = left
+  Result.slots[0] = setItem(lKey, lValue, n)
+
+
+proc CleanTree[T,D](n: PNode[T,D]): PNode[T,D] =
+  if n.Left != nil :
+    n.Left = CleanTree(n.Left)
+  for i in 0 .. n.Count - 1 :
+    var w = n.slots[i]
+    if w.Node != nil :
+        w.Node = CleanTree(w.Node)
+    clean(w.Value)
+    clean(w.Key)
+  n.slots = nil
+  return nil
+
+
+proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]): PNode[T,D] {.closure.} ): PNode[T,D] =
+  if n != nil :
+    if n.Left != nil :
+      n.Left = VisitAllNodes(n.Left, visit)    
+    for i in 0 .. n.Count - 1 :
+      var w = n.slots[i]
+      if w.Node != nil :
+        w.Node = VisitAllNodes(w.Node, visit)    
+    return visit(n)
+  return nil
+
+proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]) {.closure.} ) =
+  if n != nil:
+    if n.Left != nil :
+      VisitAllNodes(n.Left, visit)    
+    for i in 0 .. n.Count - 1 :
+      var w = n.slots[i]
+      if w.Node != nil :
+        VisitAllNodes(w.Node, visit)    
+    visit(n)
+
+proc VisitAll[T,D](n: PNode[T,D], visit: proc(AKey: T, AValue: D) {.closure.} ) =
+  if n != nil:
+    if n.Left != nil :
+      VisitAll(n.Left, visit) 
+    for i in 0 .. n.Count - 1 :
+      var w = n.slots[i]
+      if not w.isClean :
+        visit(w.Key, w.Value)   
+      if w.Node != nil :
+        VisitAll(w.Node, visit)    
+
+proc VisitAll[T,D](n: PNode[T,D], visit: proc(AKey: T, AValue: var D):Bool {.closure.} ): PNode[T,D] =
+  if n != nil:
+    var n1 = n.Left
+    if n1 != nil :
+      var n2 = VisitAll(n1, visit) 
+      if n1 != n2 :
+        n.Left = n2
+    var i = 0
+    while i < n.Count :
+      var w = n.slots[i]
+      if not w.isClean :
+        if visit(w.Key, w.Value) :
+          Result = DeleteItem(n, i)
+          if Result == nil : return
+          dec(i)
+      n1 = w.Node
+      if n1 != nil :
+        var n2 = VisitAll(n1, visit)
+        if n1 != n2 :
+          w.Node = n2
+      inc(i)
+  return n
+
+iterator keys* [T,D] (n: PNode[T,D]): T =
+  if n != nil :
+    var Path: array[0..20, RPath[T,D]]
+    var level = 0
+    var nd = n
+    var i = -1
+    while true : 
+      if i < nd.Count :
+        Path[level].Nd = nd
+        Path[level].Xi = i
+        if i < 0 :
+          if nd.Left != nil :
+            nd = nd.Left
+            inc(level)
+          else : inc(i)
+        else :
+          var w = nd.slots[i]
+          if not w.isClean() :
+            yield w.Key
+          if w.Node != nil :
+            nd = w.Node
+            i = -1
+            inc(level)
+          else : inc(i)
+      else :
+        dec(level)
+        if level < 0 : break
+        nd = Path[level].Nd
+        i = Path[level].Xi
+        inc(i)
+
+
+when isMainModule:
+
+  proc test() =
+    var oldValue: Int
+    var root = InternalPut[int, int](nil, 312, 312, oldValue)
+    var someOtherRoot = InternalPut[string, int](nil, "312", 312, oldValue)
+    var it1 = InternalFind(root, 312)
+    echo it1.Value
+
+    for i in 1..1_000_000:
+      root = InternalPut(root, i, i, oldValue)
+
+    var cnt = 0
+    oldValue = -1
+    when true : # code compiles, when this or the other when is switched to false
+      for k in root.keys :
+        if k <= oldValue :
+          echo k
+        oldValue = k
+        inc(cnt)
+      echo cnt
+    when true :
+      cnt = 0
+      VisitAll(root, proc(key, val: int) = inc(cnt))
+      echo cnt
+      when true :
+        root = VisitAll(root, proc(key: int, value: var int): bool =
+          return key mod 2 == 0 )
+      cnt = 0
+      oldValue = -1
+      VisitAll(root, proc(key: int, value: int) {.closure.} =
+        if key <= oldValue :
+          echo key
+        oldValue = key
+        inc(cnt) )
+      echo cnt
+      root = VisitAll(root, proc(key: int, value: var int): bool =
+        return key mod 2 != 0 )
+      cnt = 0
+      oldValue = -1
+      VisitAll(root, proc(key: int, value: int) {.closure.} =
+        if key <= oldValue :
+          echo "error ", key
+        oldValue = key
+        inc(cnt) )
+      echo cnt
+      #traceTree(root)
+
+
+
+  test()  
\ No newline at end of file
diff --git a/tests/generics/tgeneric4.nim b/tests/generics/tgeneric4.nim
new file mode 100644
index 000000000..f79096636
--- /dev/null
+++ b/tests/generics/tgeneric4.nim
@@ -0,0 +1,10 @@
+type
+  TIDGen*[A: Ordinal] = object
+    next: A
+    free: seq[A]
+
+proc newIDGen*[A]: TIDGen[A] =
+    newSeq result.free, 0
+
+var x = newIDGen[int]()
+
diff --git a/tests/generics/tgenericdefaults.nim b/tests/generics/tgenericdefaults.nim
new file mode 100644
index 000000000..ad96f1851
--- /dev/null
+++ b/tests/generics/tgenericdefaults.nim
@@ -0,0 +1,29 @@
+type 
+  TFoo[T, U, R = int] = object
+    x: T
+    y: U
+    z: R
+
+  TBar[T] = TFoo[T, array[4, T], T]
+
+var x1: TFoo[int, float]
+
+static:
+  assert type(x1.x) is int
+  assert type(x1.y) is float
+  assert type(x1.z) is int
+  
+var x2: TFoo[string, R = float, U = seq[int]]
+
+static:
+  assert type(x2.x) is string
+  assert type(x2.y) is seq[int]
+  assert type(x2.z) is float
+
+var x3: TBar[float]
+
+static:
+  assert type(x3.x) is float
+  assert type(x3.y) is array[4, float]
+  assert type(x3.z) is float
+
diff --git a/tests/generics/tgenericmatcher.nim b/tests/generics/tgenericmatcher.nim
new file mode 100644
index 000000000..edd0c4cf1
--- /dev/null
+++ b/tests/generics/tgenericmatcher.nim
@@ -0,0 +1,22 @@
+discard """
+  disabled: false
+"""
+
+type
+  TMatcherKind = enum
+    mkTerminal, mkSequence, mkAlternation, mkRepeat
+  TMatcher[T] = object
+    case kind: TMatcherKind
+    of mkTerminal:
+      value: T
+    of mkSequence, mkAlternation:
+      matchers: seq[TMatcher[T]]
+    of mkRepeat:
+      matcher: PMatcher[T]
+      min, max: int
+  PMatcher[T] = ref TMatcher[T]
+
+var 
+  m: PMatcher[int]
+
+
diff --git a/tests/generics/tgenericmatcher2.nim b/tests/generics/tgenericmatcher2.nim
new file mode 100644
index 000000000..aa2f9dbb3
--- /dev/null
+++ b/tests/generics/tgenericmatcher2.nim
@@ -0,0 +1,18 @@
+
+type
+  TMatcherKind = enum
+    mkTerminal, mkSequence, mkAlternation, mkRepeat
+  TMatcher[T] = object
+    case kind: TMatcherKind
+    of mkTerminal:
+      value: T
+    of mkSequence, mkAlternation:
+      matchers: seq[TMatcher[T]]
+    of mkRepeat:
+      matcher: ref TMatcher[T]
+      min, max: int
+
+var 
+  m: ref TMatcher[int]
+
+
diff --git a/tests/generics/tgenericprocvar.nim b/tests/generics/tgenericprocvar.nim
new file mode 100644
index 000000000..1eba81fec
--- /dev/null
+++ b/tests/generics/tgenericprocvar.nim
@@ -0,0 +1,36 @@
+discard """
+  output: "0false12"
+"""
+
+# Test multiple generic instantiation of generic proc vars:
+
+proc threadProcWrapper[TMsg]() =
+  var x: TMsg
+  stdout.write($x)
+
+#var x = threadProcWrapper[int]
+#x()
+
+#var y = threadProcWrapper[bool]
+#y()
+
+threadProcWrapper[int]()
+threadProcWrapper[bool]()
+
+type
+  TFilterProc[T,D] = proc (item: T, env:D): bool {.nimcall.}
+
+proc filter[T,D](data: seq[T], env:D, pred: TFilterProc[T,D]): seq[T] =
+  result = @[]
+  for e in data:
+    if pred(e, env): result.add(e)
+
+proc predTest(item: int, value: int): Bool =
+  return item <= value
+
+proc test(data: seq[int], value: int): seq[int] =
+  return filter(data, value, predTest)
+
+for x in items(test(@[1,2,3], 2)):
+  stdout.write(x)
+
diff --git a/tests/generics/tgenericprop.nim b/tests/generics/tgenericprop.nim
new file mode 100644
index 000000000..7cddf5617
--- /dev/null
+++ b/tests/generics/tgenericprop.nim
@@ -0,0 +1,12 @@
+
+type
+  TProperty[T] = object of TObject
+    getProc: proc(property: TProperty[T]): T {.nimcall.}
+    setProc: proc(property: TProperty[T], value: T) {.nimcall.}
+    value: T
+
+proc newProperty[T](value: TObject): TProperty[T] =
+  result.getProc = proc (property: TProperty[T]) =
+    return property.value
+
+
diff --git a/tests/generics/tgenericrefs.nim b/tests/generics/tgenericrefs.nim
new file mode 100644
index 000000000..ef931dfa7
--- /dev/null
+++ b/tests/generics/tgenericrefs.nim
@@ -0,0 +1,26 @@
+type 
+  PA[T] = ref TA[T]
+  TA[T] = object
+    field: T
+var a: PA[string]
+new(a)
+a.field = "some string"
+
+when false:
+  # Compiles unless you use var a: PA[string]
+  type 
+    PA = ref TA
+    TA[T] = object
+
+
+  # Cannot instantiate:
+  type 
+    TA[T] = object
+      a: PA[T]
+    PA[T] = ref TA[T]
+
+  type 
+    PA[T] = ref TA[T]
+    TA[T] = object
+
+
diff --git a/tests/generics/tgenericshardcases.nim b/tests/generics/tgenericshardcases.nim
new file mode 100644
index 000000000..2ef63bc20
--- /dev/null
+++ b/tests/generics/tgenericshardcases.nim
@@ -0,0 +1,36 @@
+discard """
+  file: "tgenericshardcases.nim"
+  output: "2\n5\n126\n3"
+"""
+
+import typetraits
+
+proc typeNameLen(x: typedesc): int {.compileTime.} =
+  result = x.name.len
+  
+macro selectType(a, b: typedesc): typedesc =
+  result = a
+
+type
+  Foo[T] = object
+    data1: array[T.high, int]
+    data2: array[typeNameLen(T), float] # data3: array[0..T.typeNameLen, selectType(float, int)]
+
+  MyEnum = enum A, B, C, D
+
+var f1: Foo[MyEnum]
+var f2: Foo[int8]
+
+echo high(f1.data1) # (D = 3) - 1 == 2
+echo high(f1.data2) # (MyEnum.len = 6) - 1 == 5
+
+echo high(f2.data1) # 127 - 1 == 126
+echo high(f2.data2) # int8.len - 1 == 3
+
+#static:
+# assert high(f1.data1) == ord(D)
+# assert high(f1.data2) == 6 # length of MyEnum
+
+# assert high(f2.data1) == 127
+# assert high(f2.data2) == 4 # length of int8
+
diff --git a/tests/generics/tgenerictmpl.nim b/tests/generics/tgenerictmpl.nim
new file mode 100644
index 000000000..a749e6570
--- /dev/null
+++ b/tests/generics/tgenerictmpl.nim
@@ -0,0 +1,12 @@
+
+template tmp[T](x: var seq[T]) =
+  #var yz: T  # XXX doesn't work yet
+  x = @[1, 2, 3]
+
+macro tmp2[T](x: var seq[T]): stmt =
+  nil
+
+var y: seq[int]
+tmp(y)
+tmp(y)
+echo y.repr
diff --git a/tests/generics/tgenericvariant.nim b/tests/generics/tgenericvariant.nim
new file mode 100644
index 000000000..51d01355a
--- /dev/null
+++ b/tests/generics/tgenericvariant.nim
@@ -0,0 +1,23 @@
+type  
+  TMaybe[T] = object
+    case empty: Bool
+    of False: value: T
+    else: nil
+
+proc Just*[T](val: T): TMaybe[T] =
+  result.empty = False
+  result.value = val
+
+proc Nothing[T](): TMaybe[T] =
+  result.empty = True
+
+proc safeReadLine(): TMaybe[string] =
+  var r = stdin.readLine()
+  if r == "": return Nothing[string]()
+  else: return Just(r)
+
+when isMainModule:
+  var Test = Just("Test")
+  echo(Test.value)
+  var mSomething = safeReadLine()
+  echo(mSomething.value)
diff --git a/tests/generics/tspecialised_is_equivalent.nim b/tests/generics/tspecialised_is_equivalent.nim
new file mode 100644
index 000000000..60b976e90
--- /dev/null
+++ b/tests/generics/tspecialised_is_equivalent.nim
@@ -0,0 +1,15 @@
+##
+## specialised_is_equivalent Nimrod Module
+##
+## Created by Eric Doughty-Papassideris on 2011-02-16.
+## Copyright (c) 2011 FWA. All rights reserved.
+
+type
+  TGen[T] = tuple[a: T]
+  TSpef = tuple[a: string]
+
+var
+  a: TGen[string]
+  b: TSpef
+a = b
+
diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim
new file mode 100644
index 000000000..beae4b652
--- /dev/null
+++ b/tests/generics/tthread_generic.nim
@@ -0,0 +1,39 @@
+discard """
+  cmd: "nimrod cc --hints:on --threads:on $# $#"
+"""
+
+type
+  TThreadFuncArgs[T] = object of TObject
+    a: proc(): T {.thread.}
+    b: proc(val: T) {.thread.}
+
+proc handleThreadFunc(arg: TThreadFuncArgs[int]){.thread.} =
+  var func = arg.a
+  var callback = arg.b
+  var output = func()
+  callback(output)
+
+proc `@||->`*[T](func: proc(): T {.thread.}, 
+                 callback: proc(val: T){.thread.}): TThread[TThreadFuncArgs[T]] =
+  var thr: TThread[TThreadFuncArgs[T]]
+  var args: TThreadFuncArgs[T]
+  args.a = func
+  args.b = callback
+  createThread(thr, handleThreadFunc, args)
+  return thr
+
+proc `||->`*[T](func: proc(): T{.thread.}, callback: proc(val: T){.thread.}) =
+  discard func @||-> callback
+
+when isMainModule:
+  import os
+  proc testFunc(): int {.thread.} =
+    return 1
+  proc callbackFunc(val: int) {.thread.} =
+    echo($(val))
+   
+  var thr = (testFunc @||-> callbackFunc)
+  echo("test")
+  joinThread(thr)
+  os.sleep(3000)
+
diff --git a/tests/generics/tvarargs_vs_generic.nim b/tests/generics/tvarargs_vs_generic.nim
new file mode 100644
index 000000000..122f3e453
--- /dev/null
+++ b/tests/generics/tvarargs_vs_generic.nim
@@ -0,0 +1,26 @@
+discard """
+  output: "direct\ngeneric\ngeneric"
+"""
+
+proc withDirectType(args: string) =
+  echo "direct"
+
+proc withDirectType[T](arg: T) =
+  echo "generic"
+
+proc withOpenArray(args: openarray[string]) =
+  echo "openarray"
+
+proc withOpenArray[T](arg: T) =
+  echo "generic"
+
+proc withVarargs(args: varargs[string]) =
+  echo "varargs"
+
+proc withVarargs[T](arg: T) =
+  echo "generic"
+
+withDirectType "string"
+withOpenArray "string"
+withVarargs "string"
+