new tester; all tests categorized
This commit is contained in:
parent
51ee524109
commit
20b5f31c03
481 changed files with 794 additions and 2506 deletions
31
tests/generics/tbintre2.nim
Normal file
31
tests/generics/tbintre2.nim
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
107
tests/generics/tbintree.nim
Normal file
107
tests/generics/tbintree.nim
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
11
tests/generics/tcan_alias_generic.nim
Normal file
11
tests/generics/tcan_alias_generic.nim
Normal file
|
|
@ -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]
|
||||
|
||||
|
||||
17
tests/generics/tcan_alias_specialised_generic.nim
Normal file
17
tests/generics/tcan_alias_specialised_generic.nim
Normal file
|
|
@ -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
|
||||
|
||||
17
tests/generics/tcan_inherit_generic.nim
Normal file
17
tests/generics/tcan_inherit_generic.nim
Normal file
|
|
@ -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
|
||||
|
||||
11
tests/generics/tcan_specialise_generic.nim
Normal file
11
tests/generics/tcan_specialise_generic.nim
Normal file
|
|
@ -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]
|
||||
|
||||
|
||||
38
tests/generics/texplicitgeneric1.nim
Normal file
38
tests/generics/texplicitgeneric1.nim
Normal file
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
35
tests/generics/texplicitgeneric2.nim
Normal file
35
tests/generics/texplicitgeneric2.nim
Normal file
|
|
@ -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)
|
||||
|
||||
13
tests/generics/tforwardgeneric.nim
Normal file
13
tests/generics/tforwardgeneric.nim
Normal file
|
|
@ -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
|
||||
|
||||
19
tests/generics/tgeneric0.nim
Normal file
19
tests/generics/tgeneric0.nim
Normal file
|
|
@ -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"
|
||||
|
||||
|
||||
53
tests/generics/tgeneric1.nim
Normal file
53
tests/generics/tgeneric1.nim
Normal file
|
|
@ -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)
|
||||
|
||||
|
||||
15
tests/generics/tgeneric2.nim
Normal file
15
tests/generics/tgeneric2.nim
Normal file
|
|
@ -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]()
|
||||
474
tests/generics/tgeneric3.nim
Normal file
474
tests/generics/tgeneric3.nim
Normal file
|
|
@ -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()
|
||||
10
tests/generics/tgeneric4.nim
Normal file
10
tests/generics/tgeneric4.nim
Normal file
|
|
@ -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]()
|
||||
|
||||
29
tests/generics/tgenericdefaults.nim
Normal file
29
tests/generics/tgenericdefaults.nim
Normal file
|
|
@ -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
|
||||
|
||||
22
tests/generics/tgenericmatcher.nim
Normal file
22
tests/generics/tgenericmatcher.nim
Normal file
|
|
@ -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]
|
||||
|
||||
|
||||
18
tests/generics/tgenericmatcher2.nim
Normal file
18
tests/generics/tgenericmatcher2.nim
Normal file
|
|
@ -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]
|
||||
|
||||
|
||||
36
tests/generics/tgenericprocvar.nim
Normal file
36
tests/generics/tgenericprocvar.nim
Normal file
|
|
@ -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)
|
||||
|
||||
12
tests/generics/tgenericprop.nim
Normal file
12
tests/generics/tgenericprop.nim
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
26
tests/generics/tgenericrefs.nim
Normal file
26
tests/generics/tgenericrefs.nim
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
36
tests/generics/tgenericshardcases.nim
Normal file
36
tests/generics/tgenericshardcases.nim
Normal file
|
|
@ -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
|
||||
|
||||
12
tests/generics/tgenerictmpl.nim
Normal file
12
tests/generics/tgenerictmpl.nim
Normal file
|
|
@ -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
|
||||
23
tests/generics/tgenericvariant.nim
Normal file
23
tests/generics/tgenericvariant.nim
Normal file
|
|
@ -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)
|
||||
15
tests/generics/tspecialised_is_equivalent.nim
Normal file
15
tests/generics/tspecialised_is_equivalent.nim
Normal file
|
|
@ -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
|
||||
|
||||
39
tests/generics/tthread_generic.nim
Normal file
39
tests/generics/tthread_generic.nim
Normal file
|
|
@ -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)
|
||||
|
||||
26
tests/generics/tvarargs_vs_generic.nim
Normal file
26
tests/generics/tvarargs_vs_generic.nim
Normal file
|
|
@ -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"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue