diff options
Diffstat (limited to 'lib/pure/collections')
-rw-r--r-- | lib/pure/collections/LockFreeHash.nim | 73 | ||||
-rw-r--r-- | lib/pure/collections/baseutils.nim | 41 | ||||
-rw-r--r-- | lib/pure/collections/critbits.nim | 82 | ||||
-rw-r--r-- | lib/pure/collections/intsets.nim | 17 | ||||
-rw-r--r-- | lib/pure/collections/lists.nim | 86 | ||||
-rw-r--r-- | lib/pure/collections/queues.nim | 10 | ||||
-rw-r--r-- | lib/pure/collections/sequtils.nim | 52 | ||||
-rw-r--r-- | lib/pure/collections/sets.nim | 47 | ||||
-rw-r--r-- | lib/pure/collections/tables.nim | 44 |
9 files changed, 227 insertions, 225 deletions
diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index b94b542ff..57beb83c9 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -1,8 +1,40 @@ #nimrod c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim -import baseutils, unsigned, math, hashes +import unsigned, math, hashes +#------------------------------------------------------------------------------ +## Memory Utility Functions + +proc newHeap*[T](): ptr T = + result = cast[ptr T](alloc0(sizeof(T))) + +proc copyNew*[T](x: var T): ptr T = + var + size = sizeof(T) + mem = alloc(size) + copyMem(mem, x.addr, size) + return cast[ptr T](mem) + +proc copyTo*[T](val: var T, dest: int) = + copyMem(pointer(dest), val.addr, sizeof(T)) + +proc allocType*[T](): pointer = alloc(sizeof(T)) + +proc newShared*[T](): ptr T = + result = cast[ptr T](allocShared0(sizeof(T))) + +proc copyShared*[T](x: var T): ptr T = + var + size = sizeof(T) + mem = allocShared(size) + copyMem(mem, x.addr, size) + return cast[ptr T](mem) +#------------------------------------------------------------------------------ +## Pointer arithmetic + +proc `+`*(p: pointer, i: int): pointer {.inline.} = + cast[pointer](cast[int](p) + i) const minTableSize = 8 @@ -194,7 +226,7 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable #Prevent new values from appearing in the old table by priming oldVal = atomic_load_n(oldTbl[idx].value.addr, ATOMIC_RELAXED) while not isPrime(oldVal): - var box = if oldVal == NULL or isTomb(oldVal) : oldVal.setTomb.setPrime + var box = if oldVal == 0 or isTomb(oldVal) : oldVal.setTomb.setPrime else: oldVal.setPrime if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, box, false, ATOMIC_RELAXED, ATOMIC_RELAXED): @@ -209,8 +241,8 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable return false if isTomb(oldVal): echo("oldVal is Tomb!!!, should not happen") - if pop(oldVal) != NULL: - result = setVal(newTbl, pop(oldKey), pop(oldVal), NULL, true) == NULL + if pop(oldVal) != 0: + result = setVal(newTbl, pop(oldKey), pop(oldVal), 0, true) == 0 if result: #echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal) else: @@ -323,7 +355,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, idx = idx and (table.len - 1) #echo("try set idx = " & $idx & "for" & $key) var - probedKey = NULL + probedKey = 0 openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr, key, false, ATOMIC_RELAXED, ATOMIC_RELAXED) if openKey: @@ -339,7 +371,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if keyEQ[K](probedKey, key): #echo("we found the matching slot") break # We found a matching slot - if (not(expVal != NULL and match)) and (probes >= reProbeLimit or key.isTomb): + if (not(expVal != 0 and match)) and (probes >= reProbeLimit or key.isTomb): if key.isTomb: echo("Key is Tombstone") #if probes >= reProbeLimit: echo("Too much probing " & $probes) #echo("try to resize") @@ -361,7 +393,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, return oldVal nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST) if nextTable == nil and - ((oldVal == NULL and + ((oldVal == 0 and (probes >= reProbeLimit or table.used / table.len > 0.8)) or (isPrime(oldVal))): if table.used / table.len > 0.8: echo("resize because usage ratio = " & @@ -380,12 +412,12 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr, val, false, ATOMIC_RELEASE, ATOMIC_RELAXED): #echo("val set at table " & $cast[int](table)) - if expVal != NULL: - if (oldVal == NULL or isTomb(oldVal)) and not isTomb(val): + if expVal != 0: + if (oldVal == 0 or isTomb(oldVal)) and not isTomb(val): discard atomic_add_fetch(table.active.addr, 1, ATOMIC_RELAXED) - elif not (oldVal == NULL or isTomb(oldVal)) and isTomb(val): + elif not (oldVal == 0 or isTomb(oldVal)) and isTomb(val): discard atomic_add_fetch(table.active.addr, -1, ATOMIC_RELAXED) - if oldVal == NULL and expVal != NULL: + if oldVal == 0 and expVal != 0: return setTomb(oldVal) else: return oldVal if isPrime(oldVal): @@ -415,7 +447,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = if not isPrime(val): if isTomb(val): #echo("val was tomb but not prime") - return NULL + return 0 else: #echo("-GotIt- idx = ", idx, " key = ", key, " val ", val ) return val @@ -427,7 +459,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = if probes >= reProbeLimit*4 or key.isTomb: if newTable == nil: #echo("too many probes and no new table ", key, " ", idx ) - return NULL + return 0 else: newTable = helpCopy(table) return getVal(newTable, key) @@ -437,10 +469,10 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = #------------------------------------------------------------------------------ #proc set*(table: var PConcTable[TRaw,TRaw], key: TRaw, val: TRaw) = -# discard setVal(table, pack(key), pack(key), NULL, false) +# discard setVal(table, pack(key), pack(key), 0, false) #proc set*[V](table: var PConcTable[TRaw,V], key: TRaw, val: ptr V) = -# discard setVal(table, pack(key), cast[int](val), NULL, false) +# discard setVal(table, pack(key), cast[int](val), 0, false) proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) = when not (K is TRaw): @@ -451,10 +483,10 @@ proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) = var newVal = cast[int](copyShared(val)) else: var newVal = pack(val) - var oldPtr = pop(setVal(table, newKey, newVal, NULL, false)) + var oldPtr = pop(setVal(table, newKey, newVal, 0, false)) #echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr)) when not (V is TRaw): - if newVal != oldPtr and oldPtr != NULL: + if newVal != oldPtr and oldPtr != 0: deallocShared(cast[ptr V](oldPtr)) @@ -573,10 +605,3 @@ when isMainModule: # echo(i, " = ", hashInt(i) and 8191) deleteConcTable(table) - - - - - - - diff --git a/lib/pure/collections/baseutils.nim b/lib/pure/collections/baseutils.nim deleted file mode 100644 index 565a89ccb..000000000 --- a/lib/pure/collections/baseutils.nim +++ /dev/null @@ -1,41 +0,0 @@ - - - -#------------------------------------------------------------------------------ -## Useful Constants -const NULL* = 0 - - -#------------------------------------------------------------------------------ -## Memory Utility Functions - -proc newHeap*[T](): ptr T = - result = cast[ptr T](alloc0(sizeof(T))) - -proc copyNew*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = alloc(size) - copyMem(mem, x.addr, size) - return cast[ptr T](mem) - -proc copyTo*[T](val: var T, dest: int) = - copyMem(pointer(dest), val.addr, sizeof(T)) - -proc allocType*[T](): pointer = alloc(sizeof(T)) - -proc newShared*[T](): ptr T = - result = cast[ptr T](allocShared0(sizeof(T))) - -proc copyShared*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = allocShared(size) - copyMem(mem, x.addr, size) - return cast[ptr T](mem) - -#------------------------------------------------------------------------------ -## Pointer arithmetic - -proc `+`*(p: pointer, i: int): pointer {.inline.} = - cast[pointer](cast[int](p) + i) \ No newline at end of file diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 1fde1f419..8f506409b 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,30 +12,32 @@ ## by Adam Langley. type - TNode[T] = object {.pure, final, acyclic.} + NodeObj[T] = object {.pure, final, acyclic.} byte: int ## byte index of the difference otherbits: char case isLeaf: bool - of false: child: array[0..1, ref TNode[T]] + of false: child: array[0..1, ref NodeObj[T]] of true: key: string when T isnot void: val: T - PNode[T] = ref TNode[T] - TCritBitTree*[T] = object {. + Node[T] = ref NodeObj[T] + CritBitTree*[T] = object {. pure, final.} ## The crit bit tree can either be used ## as a mapping from strings to ## some type ``T`` or as a set of ## strings if ``T`` is void. - root: PNode[T] + root: Node[T] count: int - -proc len*[T](c: TCritBitTree[T]): int = + +{.deprecated: [TCritBitTree: CritBitTree].} + +proc len*[T](c: CritBitTree[T]): int = ## returns the number of elements in `c` in O(1). result = c.count -proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] = +proc rawGet[T](c: CritBitTree[T], key: string): Node[T] = var it = c.root while it != nil: if not it.isLeaf: @@ -45,15 +47,15 @@ proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] = else: return if it.key == key: it else: nil -proc contains*[T](c: TCritBitTree[T], key: string): bool {.inline.} = +proc contains*[T](c: CritBitTree[T], key: string): bool {.inline.} = ## returns true iff `c` contains the given `key`. result = rawGet(c, key) != nil -proc hasKey*[T](c: TCritBitTree[T], key: string): bool {.inline.} = +proc hasKey*[T](c: CritBitTree[T], key: string): bool {.inline.} = ## alias for `contains`. result = rawGet(c, key) != nil -proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = +proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = if c.root == nil: new c.root c.root.isleaf = true @@ -84,7 +86,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = let ch = it.key[newByte] let dir = (1 + (ord(ch) or newOtherBits)) shr 8 - var inner: PNode[T] + var inner: Node[T] new inner new result result.isLeaf = true @@ -106,7 +108,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] = wherep[] = inner inc c.count -proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool = +proc containsOrIncl*[T](c: var CritBitTree[T], key: string, val: T): bool = ## returns true iff `c` contains the given `key`. If the key does not exist ## ``c[key] = val`` is performed. let oldCount = c.count @@ -115,23 +117,23 @@ proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool = when T isnot void: if not result: n.val = val -proc containsOrIncl*(c: var TCritBitTree[void], key: string): bool = +proc containsOrIncl*(c: var CritBitTree[void], key: string): bool = ## returns true iff `c` contains the given `key`. If the key does not exist ## it is inserted into `c`. let oldCount = c.count var n = rawInsert(c, key) result = c.count == oldCount -proc incl*(c: var TCritBitTree[void], key: string) = +proc incl*(c: var CritBitTree[void], key: string) = ## includes `key` in `c`. discard rawInsert(c, key) -proc `[]=`*[T](c: var TCritBitTree[T], key: string, val: T) = +proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) = ## puts a (key, value)-pair into `t`. var n = rawInsert(c, key) n.val = val -proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} = +proc `[]`*[T](c: CritBitTree[T], key: string): T {.inline.} = ## retrieves the value at ``c[key]``. If `key` is not in `t`, ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key @@ -139,22 +141,22 @@ proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} = let n = rawGet(c, key) if n != nil: result = n.val -proc mget*[T](c: var TCritBitTree[T], key: string): var T {.inline.} = +proc mget*[T](c: var CritBitTree[T], key: string): var T {.inline.} = ## retrieves the value at ``c[key]``. The value can be modified. - ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. + ## If `key` is not in `t`, the ``KeyError`` exception is raised. let n = rawGet(c, key) if n != nil: result = n.val - else: raise newException(EInvalidKey, "key not found: " & $key) + else: raise newException(KeyError, "key not found: " & $key) -proc excl*[T](c: var TCritBitTree[T], key: string) = +proc excl*[T](c: var CritBitTree[T], key: string) = ## removes `key` (and its associated value) from the set `c`. ## If the `key` does not exist, nothing happens. var p = c.root var wherep = addr(c.root) - var whereq: ptr PNode = nil + var whereq: ptr Node[T] = nil if p == nil: return var dir = 0 - var q: PNode + var q: Node[T] while not p.isLeaf: whereq = wherep q = p @@ -170,7 +172,7 @@ proc excl*[T](c: var TCritBitTree[T], key: string) = whereq[] = q.child[1 - dir] dec c.count -iterator leaves[T](n: PNode[T]): PNode[T] = +iterator leaves[T](n: Node[T]): Node[T] = if n != nil: # XXX actually we could compute the necessary stack size in advance: # it's rougly log2(c.count). @@ -183,33 +185,33 @@ iterator leaves[T](n: PNode[T]): PNode[T] = assert(it != nil) yield it -iterator keys*[T](c: TCritBitTree[T]): string = +iterator keys*[T](c: CritBitTree[T]): string = ## yields all keys in lexicographical order. for x in leaves(c.root): yield x.key -iterator values*[T](c: TCritBitTree[T]): T = +iterator values*[T](c: CritBitTree[T]): T = ## yields all values of `c` in the lexicographical order of the ## corresponding keys. for x in leaves(c.root): yield x.val -iterator mvalues*[T](c: var TCritBitTree[T]): var T = +iterator mvalues*[T](c: var CritBitTree[T]): var T = ## yields all values of `c` in the lexicographical order of the ## corresponding keys. The values can be modified. for x in leaves(c.root): yield x.val -iterator items*[T](c: TCritBitTree[T]): string = +iterator items*[T](c: CritBitTree[T]): string = ## yields all keys in lexicographical order. for x in leaves(c.root): yield x.key -iterator pairs*[T](c: TCritBitTree[T]): tuple[key: string, val: T] = +iterator pairs*[T](c: CritBitTree[T]): tuple[key: string, val: T] = ## yields all (key, value)-pairs of `c`. for x in leaves(c.root): yield (x.key, x.val) -iterator mpairs*[T](c: var TCritBitTree[T]): tuple[key: string, val: var T] = +iterator mpairs*[T](c: var CritBitTree[T]): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c`. The yielded values can be modified. for x in leaves(c.root): yield (x.key, x.val) -proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] = +proc allprefixedAux[T](c: CritBitTree[T], key: string): Node[T] = var p = c.root var top = p if p != nil: @@ -223,42 +225,42 @@ proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] = if p.key[i] != key[i]: return result = top -iterator itemsWithPrefix*[T](c: TCritBitTree[T], prefix: string): string = +iterator itemsWithPrefix*[T](c: CritBitTree[T], prefix: string): string = ## yields all keys starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.key -iterator keysWithPrefix*[T](c: TCritBitTree[T], prefix: string): string = +iterator keysWithPrefix*[T](c: CritBitTree[T], prefix: string): string = ## yields all keys starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.key -iterator valuesWithPrefix*[T](c: TCritBitTree[T], prefix: string): T = +iterator valuesWithPrefix*[T](c: CritBitTree[T], prefix: string): T = ## yields all values of `c` starting with `prefix` of the ## corresponding keys. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.val -iterator mvaluesWithPrefix*[T](c: var TCritBitTree[T], prefix: string): var T = +iterator mvaluesWithPrefix*[T](c: var CritBitTree[T], prefix: string): var T = ## yields all values of `c` starting with `prefix` of the ## corresponding keys. The values can be modified. let top = allprefixedAux(c, prefix) for x in leaves(top): yield x.val -iterator pairsWithPrefix*[T](c: TCritBitTree[T], +iterator pairsWithPrefix*[T](c: CritBitTree[T], prefix: string): tuple[key: string, val: T] = ## yields all (key, value)-pairs of `c` starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield (x.key, x.val) -iterator mpairsWithPrefix*[T](c: var TCritBitTree[T], +iterator mpairsWithPrefix*[T](c: var CritBitTree[T], prefix: string): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c` starting with `prefix`. ## The yielded values can be modified. let top = allprefixedAux(c, prefix) for x in leaves(top): yield (x.key, x.val) -proc `$`*[T](c: TCritBitTree[T]): string = +proc `$`*[T](c: CritBitTree[T]): string = ## turns `c` into a string representation. Example outputs: ## ``{keyA: value, keyB: value}``, ``{:}`` ## If `T` is void the outputs look like: @@ -285,7 +287,7 @@ proc `$`*[T](c: TCritBitTree[T]): string = result.add("}") when isMainModule: - var r: TCritBitTree[void] + var r: CritBitTree[void] r.incl "abc" r.incl "xyz" r.incl "def" diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index f1e67fc0e..678c428c1 100644 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -9,7 +9,7 @@ ## The ``intsets`` module implements an efficient int set implemented as a ## sparse bit set. -## **Note**: Since Nimrod currently does not allow the assignment operator to +## **Note**: Since Nim currently does not allow the assignment operator to ## be overloaded, ``=`` for int sets performs some rather meaningless shallow ## copy; use ``assign`` to get a deep copy. @@ -17,7 +17,7 @@ import os, hashes, math type - TBitScalar = int + BitScalar = int const InitIntSetSize = 8 # must be a power of two! @@ -25,8 +25,8 @@ const BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and # divisible by 64 TrunkMask = BitsPerTrunk - 1 - IntsPerTrunk = BitsPerTrunk div (sizeof(TBitScalar) * 8) - IntShift = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width + IntsPerTrunk = BitsPerTrunk div (sizeof(BitScalar) * 8) + IntShift = 5 + ord(sizeof(BitScalar) == 8) # 5 or 6, depending on int width IntMask = 1 shl IntShift - 1 type @@ -34,15 +34,16 @@ type TTrunk {.final.} = object next: PTrunk # all nodes are connected with this pointer key: int # start address at bit 0 - bits: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector + bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector TTrunkSeq = seq[PTrunk] - TIntSet* {.final.} = object ## an efficient set of 'int' implemented as a - ## sparse bit set + IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set counter, max: int head: PTrunk data: TTrunkSeq +{.deprecated: [TIntSet: IntSet].} + proc mustRehash(length, counter: int): bool {.inline.} = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index b8f8d20b5..b7ca5a7af 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -15,52 +15,58 @@ when not defined(nimhygiene): {.pragma: dirty.} type - TDoublyLinkedNode* {.pure, - final.}[T] = object ## a node a doubly linked list consists of - next*, prev*: ref TDoublyLinkedNode[T] + DoublyLinkedNodeObj*[T] = object ## a node a doubly linked list consists of + next*, prev*: ref DoublyLinkedNodeObj[T] value*: T - PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T] + DoublyLinkedNode*[T] = ref DoublyLinkedNodeObj[T] - TSinglyLinkedNode* {.pure, - final.}[T] = object ## a node a singly linked list consists of - next*: ref TSinglyLinkedNode[T] + SinglyLinkedNodeObj*[T] = object ## a node a singly linked list consists of + next*: ref SinglyLinkedNodeObj[T] value*: T - PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T] + SinglyLinkedNode*[T] = ref SinglyLinkedNodeObj[T] - TSinglyLinkedList* {.pure, final.}[T] = object ## a singly linked list - head*, tail*: PSinglyLinkedNode[T] + SinglyLinkedList*[T] = object ## a singly linked list + head*, tail*: SinglyLinkedNode[T] - TDoublyLinkedList* {.pure, final.}[T] = object ## a doubly linked list - head*, tail*: PDoublyLinkedNode[T] + DoublyLinkedList*[T] = object ## a doubly linked list + head*, tail*: DoublyLinkedNode[T] - TSinglyLinkedRing* {.pure, final.}[T] = object ## a singly linked ring - head*: PSinglyLinkedNode[T] + SinglyLinkedRing*[T] = object ## a singly linked ring + head*: SinglyLinkedNode[T] - TDoublyLinkedRing* {.pure, final.}[T] = object ## a doubly linked ring - head*: PDoublyLinkedNode[T] - -proc initSinglyLinkedList*[T](): TSinglyLinkedList[T] = + DoublyLinkedRing*[T] = object ## a doubly linked ring + head*: DoublyLinkedNode[T] + +{.deprecated: [TDoublyLinkedNode: DoublyLinkedNodeObj, + PDoublyLinkedNode: DoublyLinkedNode, + TSinglyLinkedNode: SinglyLinkedNodeObj, + PSinglyLinkedNode: SinglyLinkedNode, + TDoublyLinkedList: DoublyLinkedList, + TSinglyLinkedRing: SinglyLinkedRing, + TDoublyLinkedRing: DoublyLinkedRing].} + +proc initSinglyLinkedList*[T](): SinglyLinkedList[T] = ## creates a new singly linked list that is empty. discard -proc initDoublyLinkedList*[T](): TDoublyLinkedList[T] = +proc initDoublyLinkedList*[T](): DoublyLinkedList[T] = ## creates a new doubly linked list that is empty. discard -proc initSinglyLinkedRing*[T](): TSinglyLinkedRing[T] = +proc initSinglyLinkedRing*[T](): SinglyLinkedRing[T] = ## creates a new singly linked ring that is empty. discard -proc initDoublyLinkedRing*[T](): TDoublyLinkedRing[T] = +proc initDoublyLinkedRing*[T](): DoublyLinkedRing[T] = ## creates a new doubly linked ring that is empty. discard -proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] = +proc newDoublyLinkedNode*[T](value: T): DoublyLinkedNode[T] = ## creates a new doubly linked node with the given `value`. new(result) result.value = value -proc newSinglyLinkedNode*[T](value: T): PSinglyLinkedNode[T] = +proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] = ## creates a new singly linked node with the given `value`. new(result) result.value = value @@ -99,38 +105,38 @@ template findImpl() {.dirty.} = for x in nodes(L): if x.value == value: return x -iterator items*[T](L: TDoublyLinkedList[T]): T = +iterator items*[T](L: DoublyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: TSinglyLinkedList[T]): T = +iterator items*[T](L: SinglyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: TSinglyLinkedRing[T]): T = +iterator items*[T](L: SinglyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() -iterator items*[T](L: TDoublyLinkedRing[T]): T = +iterator items*[T](L: DoublyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() -iterator nodes*[T](L: TSinglyLinkedList[T]): PSinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: TDoublyLinkedList[T]): PDoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedList[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: TSinglyLinkedRing[T]): PSinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedRing[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() -iterator nodes*[T](L: TDoublyLinkedRing[T]): PDoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedRing[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() @@ -142,33 +148,33 @@ template dollarImpl() {.dirty.} = result.add($x.value) result.add("]") -proc `$`*[T](L: TSinglyLinkedList[T]): string = +proc `$`*[T](L: SinglyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TDoublyLinkedList[T]): string = +proc `$`*[T](L: DoublyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TSinglyLinkedRing[T]): string = +proc `$`*[T](L: SinglyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: TDoublyLinkedRing[T]): string = +proc `$`*[T](L: DoublyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc find*[T](L: TSinglyLinkedList[T], value: T): PSinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedList[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: TDoublyLinkedList[T], value: T): PDoublyLinkedNode[T] = +proc find*[T](L: DoublyLinkedList[T], value: T): DoublyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: TSinglyLinkedRing[T], value: T): PSinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedRing[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() @@ -300,5 +306,3 @@ proc remove*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) = L.head = nil else: L.head = L.head.prev - - diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim index 5481272f0..d1c94868a 100644 --- a/lib/pure/collections/queues.nim +++ b/lib/pure/collections/queues.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -12,13 +12,15 @@ import math type - TQueue* {.pure, final.}[T] = object ## a queue + Queue*[T] = object ## a queue data: seq[T] rd, wr, count, mask: int - + +{.deprecated: [TQueue: Queue].} + proc initQueue*[T](initialSize=4): TQueue[T] = ## creates a new queue. `initialSize` needs to be a power of 2. - assert IsPowerOfTwo(initialSize) + assert isPowerOfTwo(initialSize) result.mask = initialSize-1 newSeq(result.data, initialSize) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 2629e9f40..9d22f0c3c 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2011 Alex Mitchell # # See the file "copying.txt", included in this @@ -31,7 +31,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## s1 = @[1, 2, 3] ## s2 = @[4, 5] @@ -50,7 +50,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = proc deduplicate*[T](seq1: seq[T]): seq[T] = ## Returns a new sequence without duplicates. ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4] ## dup2 = @["a", "a", "c", "d", "d"] @@ -69,7 +69,7 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] = ## fields `a` and `b`. If one sequence is shorter, the remaining items in the ## longer sequence are discarded. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## short = @[1, 2, 3] ## long = @[6, 5, 4, 3, 2, 1] @@ -104,7 +104,7 @@ proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let numbers = @[1, 2, 3, 4, 5, 6, 7] ## assert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]] ## assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] @@ -155,7 +155,7 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let numbers = @[1, 4, 5, 8, 9, 7, 4] ## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0): ## echo($n) @@ -169,7 +169,7 @@ proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## colors = @["red", "yellow", "black"] ## f1 = filter(colors, proc(x: string): bool = x.len < 6) @@ -184,7 +184,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1] ## keepIf(floats, proc(x: float): bool = x > 10) ## assert floats == @[13.0, 12.5, 10.1] @@ -202,7 +202,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) = ## ## Example: ## - ##.. code-block:: nimrod + ##.. code-block:: ## let outcome = @[1,1,1,1,1,1,1,1] ## var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1] ## dest.delete(3, 8) @@ -223,7 +223,7 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) = ## ## Example: ## - ##.. code-block:: nimrod + ##.. code-block:: ## var dest = @[1,1,1,1,1,1,1,1] ## let ## src = @[2,2,2,2,2,2] @@ -254,7 +254,7 @@ template filterIt*(seq1, pred: expr): expr {.immediate.} = ## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``. ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44] ## acceptable = filterIt(temperatures, it < 50 and it > -10) @@ -273,7 +273,7 @@ template keepItIf*(varSeq, pred: expr) = ## the ``it`` variable for testing, like: ``keepItIf("abcxyz", it == 'x')``. ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var candidates = @["foo", "bar", "baz", "foobar"] ## keepItIf(candidates, it.len == 3 and it[0] == 'b') ## assert candidates == @["bar", "baz"] @@ -292,7 +292,7 @@ template toSeq*(iter: expr): expr {.immediate.} = ## ## Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9] ## odd_numbers = toSeq(filter(numeric) do (x: int) -> bool: @@ -318,18 +318,18 @@ template foldl*(sequence, operation: expr): expr = ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) - ## 3). Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numbers = @[5, 9, 11] ## addition = foldl(numbers, a + b) ## substraction = foldl(numbers, a - b) ## multiplication = foldl(numbers, a * b) - ## words = @["nim", "rod", "is", "cool"] + ## words = @["nim", "is", "cool"] ## concatenation = foldl(words, a & b) ## assert addition == 25, "Addition is (((5)+9)+11)" ## assert substraction == -15, "Substraction is (((5)-9)-11)" ## assert multiplication == 495, "Multiplication is (((5)*9)*11)" - ## assert concatenation == "nimrodiscool" + ## assert concatenation == "nimiscool" assert sequence.len > 0, "Can't fold empty sequences" var result {.gensym.}: type(sequence[0]) result = sequence[0] @@ -354,18 +354,18 @@ template foldr*(sequence, operation: expr): expr = ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 - ## (3))). Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## numbers = @[5, 9, 11] ## addition = foldr(numbers, a + b) ## substraction = foldr(numbers, a - b) ## multiplication = foldr(numbers, a * b) - ## words = @["nim", "rod", "is", "cool"] + ## words = @["nim", "is", "cool"] ## concatenation = foldr(words, a & b) ## assert addition == 25, "Addition is (5+(9+(11)))" ## assert substraction == 7, "Substraction is (5-(9-(11)))" ## assert multiplication == 495, "Multiplication is (5*(9*(11)))" - ## assert concatenation == "nimrodiscool" + ## assert concatenation == "nimiscool" assert sequence.len > 0, "Can't fold empty sequences" var result {.gensym.}: type(sequence[0]) result = sequence[sequence.len - 1] @@ -384,7 +384,7 @@ template mapIt*(seq1, typ, pred: expr): expr = ## since the new returned sequence can have a different type than the ## original. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## let ## nums = @[1, 2, 3, 4] ## strings = nums.mapIt(string, $(4 * it)) @@ -401,7 +401,7 @@ template mapIt*(varSeq, pred: expr) = ## expression. The expression has to return the same type as the sequence you ## are mutating. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var nums = @[1, 2, 3, 4] ## nums.mapIt(it * 3) ## assert nums[0] + nums[3] == 15 @@ -412,7 +412,7 @@ template mapIt*(varSeq, pred: expr) = template newSeqWith*(len: int, init: expr): expr = ## creates a new sequence, calling `init` to initialize each value. Example: ## - ## .. code-block:: nimrod + ## .. code-block:: ## var seq2D = newSeqWith(20, newSeq[bool](10)) ## seq2D[0][0] = true ## seq2D[1][0] = true @@ -503,12 +503,12 @@ when isMainModule: addition = foldl(numbers, a + b) substraction = foldl(numbers, a - b) multiplication = foldl(numbers, a * b) - words = @["nim", "rod", "is", "cool"] + words = @["nim", "is", "cool"] concatenation = foldl(words, a & b) assert addition == 25, "Addition is (((5)+9)+11)" assert substraction == -15, "Substraction is (((5)-9)-11)" assert multiplication == 495, "Multiplication is (((5)*9)*11)" - assert concatenation == "nimrodiscool" + assert concatenation == "nimiscool" block: # foldr tests let @@ -516,12 +516,12 @@ when isMainModule: addition = foldr(numbers, a + b) substraction = foldr(numbers, a - b) multiplication = foldr(numbers, a * b) - words = @["nim", "rod", "is", "cool"] + words = @["nim", "is", "cool"] concatenation = foldr(words, a & b) assert addition == 25, "Addition is (5+(9+(11)))" assert substraction == 7, "Substraction is (5-(9-(11)))" assert multiplication == 495, "Multiplication is (5*(9*(11)))" - assert concatenation == "nimrodiscool" + assert concatenation == "nimiscool" block: # delete tests let outcome = @[1,1,1,1,1,1,1,1] diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 3adf21a25..1201241f1 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,17 +24,19 @@ when not defined(nimhygiene): {.pragma: dirty.} type - TSlotEnum = enum seEmpty, seFilled, seDeleted - TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A] - TKeyValuePairSeq[A] = seq[TKeyValuePair[A]] - TSet* {.final, myShallow.}[A] = object ## \ + SlotEnum = enum seEmpty, seFilled, seDeleted + KeyValuePair[A] = tuple[slot: SlotEnum, key: A] + KeyValuePairSeq[A] = seq[KeyValuePair[A]] + HashSet* {.myShallow.}[A] = object ## \ ## A generic hash set. ## - ## Use `init() <#init,TSet[A],int>`_ or `initSet[type]() <#initSet>`_ + ## Use `init() <#init,HashSet[A],int>`_ or `initSet[type]() <#initSet>`_ ## before calling other procs on it. - data: TKeyValuePairSeq[A] + data: KeyValuePairSeq[A] counter: int +{.deprecated: [TSet: HashSet].} + proc isValid*[A](s: TSet[A]): bool = ## Returns `true` if the set has been initialized with `initSet <#initSet>`_. ## @@ -43,7 +45,7 @@ proc isValid*[A](s: TSet[A]): bool = ## your own procs to verify that sets passed to your procs are correctly ## initialized. Example: ## - ## .. code-block :: nimrod + ## .. code-block :: ## proc savePreferences(options: TSet[string]) = ## assert options.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! @@ -490,19 +492,20 @@ proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] = # ------------------------------ ordered set ------------------------------ type - TOrderedKeyValuePair[A] = tuple[ - slot: TSlotEnum, next: int, key: A] - TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]] - TOrderedSet* {. - final, myShallow.}[A] = object ## \ + OrderedKeyValuePair[A] = tuple[ + slot: SlotEnum, next: int, key: A] + OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]] + OrderedSet* {.myShallow.}[A] = object ## \ ## A generic hash set that remembers insertion order. ## - ## Use `init() <#init,TOrderedSet[A],int>`_ or `initOrderedSet[type]() + ## Use `init() <#init,OrderedSet[A],int>`_ or `initOrderedSet[type]() ## <#initOrderedSet>`_ before calling other procs on it. data: TOrderedKeyValuePairSeq[A] counter, first, last: int -proc isValid*[A](s: TOrderedSet[A]): bool = +{.deprecated: [TOrderedSet: OrderedSet].} + +proc isValid*[A](s: OrderedSet[A]): bool = ## Returns `true` if the ordered set has been initialized with `initSet ## <#initOrderedSet>`_. ## @@ -511,13 +514,13 @@ proc isValid*[A](s: TOrderedSet[A]): bool = ## in your own procs to verify that ordered sets passed to your procs are ## correctly initialized. Example: ## - ## .. code-block :: nimrod + ## .. code-block:: ## proc saveTarotCards(cards: TOrderedSet[int]) = ## assert cards.isValid, "Pass an initialized set!" ## # Do stuff here, may crash in release builds! result = not s.data.isNil -proc len*[A](s: TOrderedSet[A]): int {.inline.} = +proc len*[A](s: OrderedSet[A]): int {.inline.} = ## Returns the number of keys in `s`. ## ## Due to an implementation detail you can call this proc on variables which @@ -734,14 +737,14 @@ proc `==`*[A](s, t: TOrderedSet[A]): bool = proc testModule() = ## Internal micro test to validate docstrings and such. block isValidTest: - var options: TSet[string] + var options: HashSet[string] proc savePreferences(options: TSet[string]) = assert options.isValid, "Pass an initialized set!" options = initSet[string]() options.savePreferences block lenTest: - var values: TSet[int] + var values: HashSet[int] assert(not values.isValid) assert values.len == 0 assert values.card == 0 @@ -835,14 +838,14 @@ proc testModule() = assert b == toSet(["1", "2", "3"]) block isValidTest: - var cards: TOrderedSet[string] + var cards: OrderedSet[string] proc saveTarotCards(cards: TOrderedSet[string]) = assert cards.isValid, "Pass an initialized set!" cards = initOrderedSet[string]() cards.saveTarotCards block lenTest: - var values: TOrderedSet[int] + var values: OrderedSet[int] assert(not values.isValid) assert values.len == 0 assert values.card == 0 @@ -879,7 +882,7 @@ proc testModule() = assert(a == b) # https://github.com/Araq/Nimrod/issues/1413 block initBlocks: - var a: TOrderedSet[int] + var a: OrderedSet[int] a.init(4) a.incl(2) a.init diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 95caf9195..320d54111 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -1,6 +1,6 @@ # # -# Nimrod's Runtime Library +# Nim's Runtime Library # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -28,7 +28,7 @@ ## you add such a proc for your custom type everything will work. See this ## example: ## -## .. code-block:: nimrod +## .. code-block:: ## type ## Person = object ## firstName, lastName: string @@ -61,13 +61,15 @@ import {.pragma: myShallow.} type - TSlotEnum = enum seEmpty, seFilled, seDeleted - TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B] - TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]] - TTable* {.final, myShallow.}[A, B] = object ## generic hash table - data: TKeyValuePairSeq[A, B] + SlotEnum = enum seEmpty, seFilled, seDeleted + KeyValuePair[A, B] = tuple[slot: SlotEnum, key: A, val: B] + KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]] + Table* {.myShallow.}[A, B] = object ## generic hash table + data: KeyValuePairSeq[A, B] counter: int - PTable*[A,B] = ref TTable[A, B] + TableRef*[A,B] = ref Table[A, B] + +{.deprecated: [TTable: Table, PTable: TableRef].} when not defined(nimhygiene): {.pragma: dirty.} @@ -158,12 +160,12 @@ proc hasKey*[A, B](t: TTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B], +proc rawInsert[A, B](t: var TTable[A, B], data: var KeyValuePairSeq[A, B], key: A, val: B) = rawInsertImpl() proc enlarge[A, B](t: var TTable[A, B]) = - var n: TKeyValuePairSeq[A, B] + var n: KeyValuePairSeq[A, B] newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val) @@ -347,14 +349,16 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] = # ------------------------------ ordered table ------------------------------ type - TOrderedKeyValuePair[A, B] = tuple[ - slot: TSlotEnum, next: int, key: A, val: B] - TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]] - TOrderedTable* {. - final, myShallow.}[A, B] = object ## table that remembers insertion order - data: TOrderedKeyValuePairSeq[A, B] + OrderedKeyValuePair[A, B] = tuple[ + slot: SlotEnum, next: int, key: A, val: B] + OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]] + OrderedTable* {. + myShallow.}[A, B] = object ## table that remembers insertion order + data: OrderedKeyValuePairSeq[A, B] counter, first, last: int - POrderedTable*[A, B] = ref TOrderedTable[A, B] + OrderedTableRef*[A, B] = ref OrderedTable[A, B] + +{.deprecated: [TOrderedTable: OrderedTable, POrderedTable: OrderedTableRef].} proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} = ## returns the number of keys in `t`. @@ -608,11 +612,13 @@ proc sort*[A, B](t: POrderedTable[A, B], # ------------------------------ count tables ------------------------------- type - TCountTable* {.final, myShallow.}[ + CountTable* {.myShallow.}[ A] = object ## table that counts the number of each key data: seq[tuple[key: A, val: int]] counter: int - PCountTable*[A] = ref TCountTable[A] + CountTableRef*[A] = ref CountTable[A] + +{.deprecated: [TCountTable: CountTable, PCountTable: CountTableRef].} proc len*[A](t: TCountTable[A]): int = ## returns the number of keys in `t`. |