From 20b5f31c03fb556ec0aa2428a40adbac004d8987 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 13 Jan 2014 02:10:03 +0100 Subject: new tester; all tests categorized --- tests/generics/tbintre2.nim | 31 ++ tests/generics/tbintree.nim | 107 +++++ tests/generics/tcan_alias_generic.nim | 11 + tests/generics/tcan_alias_specialised_generic.nim | 17 + tests/generics/tcan_inherit_generic.nim | 17 + tests/generics/tcan_specialise_generic.nim | 11 + tests/generics/texplicitgeneric1.nim | 38 ++ tests/generics/texplicitgeneric2.nim | 35 ++ tests/generics/tforwardgeneric.nim | 13 + tests/generics/tgeneric0.nim | 19 + tests/generics/tgeneric1.nim | 53 +++ tests/generics/tgeneric2.nim | 15 + tests/generics/tgeneric3.nim | 474 ++++++++++++++++++++++ tests/generics/tgeneric4.nim | 10 + tests/generics/tgenericdefaults.nim | 29 ++ tests/generics/tgenericmatcher.nim | 22 + tests/generics/tgenericmatcher2.nim | 18 + tests/generics/tgenericprocvar.nim | 36 ++ tests/generics/tgenericprop.nim | 12 + tests/generics/tgenericrefs.nim | 26 ++ tests/generics/tgenericshardcases.nim | 36 ++ tests/generics/tgenerictmpl.nim | 12 + tests/generics/tgenericvariant.nim | 23 ++ tests/generics/tspecialised_is_equivalent.nim | 15 + tests/generics/tthread_generic.nim | 39 ++ tests/generics/tvarargs_vs_generic.nim | 26 ++ 26 files changed, 1145 insertions(+) create mode 100644 tests/generics/tbintre2.nim create mode 100644 tests/generics/tbintree.nim create mode 100644 tests/generics/tcan_alias_generic.nim create mode 100644 tests/generics/tcan_alias_specialised_generic.nim create mode 100644 tests/generics/tcan_inherit_generic.nim create mode 100644 tests/generics/tcan_specialise_generic.nim create mode 100644 tests/generics/texplicitgeneric1.nim create mode 100644 tests/generics/texplicitgeneric2.nim create mode 100644 tests/generics/tforwardgeneric.nim create mode 100644 tests/generics/tgeneric0.nim create mode 100644 tests/generics/tgeneric1.nim create mode 100644 tests/generics/tgeneric2.nim create mode 100644 tests/generics/tgeneric3.nim create mode 100644 tests/generics/tgeneric4.nim create mode 100644 tests/generics/tgenericdefaults.nim create mode 100644 tests/generics/tgenericmatcher.nim create mode 100644 tests/generics/tgenericmatcher2.nim create mode 100644 tests/generics/tgenericprocvar.nim create mode 100644 tests/generics/tgenericprop.nim create mode 100644 tests/generics/tgenericrefs.nim create mode 100644 tests/generics/tgenericshardcases.nim create mode 100644 tests/generics/tgenerictmpl.nim create mode 100644 tests/generics/tgenericvariant.nim create mode 100644 tests/generics/tspecialised_is_equivalent.nim create mode 100644 tests/generics/tthread_generic.nim create mode 100644 tests/generics/tvarargs_vs_generic.nim (limited to 'tests/generics') 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" + -- cgit 1.4.1-2-gfad0