mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-01 10:52:14 +00:00
basic generic collections implemented and tested
This commit is contained in:
@@ -83,11 +83,11 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
markUsed(n, s)
|
||||
result = newSymNode(s, n.info)
|
||||
|
||||
proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
|
||||
proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
|
||||
var diff = inheritanceDiff(castDest, src)
|
||||
if diff == high(int):
|
||||
GlobalError(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
|
||||
typeToString(src), typeToString(castDest)]))
|
||||
if diff == high(int):
|
||||
GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
|
||||
src.typeToString, castDest.typeToString])
|
||||
|
||||
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||
const
|
||||
|
||||
@@ -12,28 +12,28 @@
|
||||
## be manipulated directly for efficiency.
|
||||
|
||||
type
|
||||
TDoublyLinkedNode*[T] {.pure,
|
||||
final.} = object ## a node a doubly linked list consists of
|
||||
TDoublyLinkedNode* {.pure,
|
||||
final.}[T] = object ## a node a doubly linked list consists of
|
||||
next*, prev*: ref TDoublyLinkedNode[T]
|
||||
value*: T
|
||||
PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T]
|
||||
|
||||
TSinglyLinkedNode*[T] {.pure,
|
||||
final.} = object ## a node a singly linked list consists of
|
||||
TSinglyLinkedNode* {.pure,
|
||||
final.}[T] = object ## a node a singly linked list consists of
|
||||
next*: ref TSinglyLinkedNode[T]
|
||||
value*: T
|
||||
PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T]
|
||||
|
||||
TSinglyLinkedList*[T] {.pure, final.} = object ## a singly linked list
|
||||
TSinglyLinkedList* {.pure, final.}[T] = object ## a singly linked list
|
||||
head*, tail*: PSinglyLinkedNode[T]
|
||||
|
||||
TDoublyLinkedList*[T] {.pure, final.} = object ## a doubly linked list
|
||||
TDoublyLinkedList* {.pure, final.}[T] = object ## a doubly linked list
|
||||
head*, tail*: PDoublyLinkedNode[T]
|
||||
|
||||
TSinglyLinkedRing*[T] {.pure, final.} = object ## a singly linked ring
|
||||
TSinglyLinkedRing* {.pure, final.}[T] = object ## a singly linked ring
|
||||
head*: PSinglyLinkedNode[T]
|
||||
|
||||
TDoublyLinkedRing*[T] {.pure, final.} = object ## a doubly linked ring
|
||||
TDoublyLinkedRing* {.pure, final.}[T] = object ## a doubly linked ring
|
||||
head*: PDoublyLinkedNode[T]
|
||||
|
||||
proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] =
|
||||
@@ -240,17 +240,15 @@ proc prepend*[T](L: var TSinglyLinkedRing[T], value: T) =
|
||||
|
||||
proc append*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) =
|
||||
## appends a node `n` to `L`. Efficiency: O(1).
|
||||
if L.tail != nil:
|
||||
L.tail.next = n
|
||||
n.prev = L.tail
|
||||
if L.head != nil:
|
||||
n.next = L.head
|
||||
n.prev = L.head.prev
|
||||
L.head.prev.next = n
|
||||
L.head.prev = n
|
||||
else:
|
||||
# both head and tail are nil:
|
||||
assert L.head == nil
|
||||
L.head = n
|
||||
n.prev = n
|
||||
n.next = n
|
||||
L.tail = n
|
||||
L.head = n
|
||||
|
||||
proc append*[T](L: var TDoublyLinkedRing[T], value: T) =
|
||||
## appends a value to `L`. Efficiency: O(1).
|
||||
@@ -259,13 +257,11 @@ proc append*[T](L: var TDoublyLinkedRing[T], value: T) =
|
||||
proc prepend*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) =
|
||||
## prepends a node `n` to `L`. Efficiency: O(1).
|
||||
if L.head != nil:
|
||||
L.head.prev = n
|
||||
n.prev = L.tail
|
||||
n.next = L.head
|
||||
n.prev = L.head.prev
|
||||
L.head.prev.next = n
|
||||
L.head.prev = n
|
||||
else:
|
||||
# both head and tail are nil:
|
||||
assert L.tail == nil
|
||||
L.tail = n
|
||||
n.prev = n
|
||||
n.next = n
|
||||
L.head = n
|
||||
@@ -276,19 +272,14 @@ proc prepend*[T](L: var TDoublyLinkedRing[T], value: T) =
|
||||
|
||||
proc remove*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) =
|
||||
## removes `n` from `L`. Efficiency: O(1).
|
||||
if n == L.tail:
|
||||
if n == L.head:
|
||||
# only element:
|
||||
L.tail = nil
|
||||
L.head = nil
|
||||
else:
|
||||
L.tail = n.prev
|
||||
elif n == L.head:
|
||||
L.head = n.next
|
||||
n.next.prev = n.prev
|
||||
n.prev.next = n.next
|
||||
# break cycles for the GC; not necessary, but might help:
|
||||
n.next = nil
|
||||
n.prev = nil
|
||||
if n == L.head:
|
||||
var p = L.head.prev
|
||||
if p == L.head:
|
||||
# only one element left:
|
||||
L.head = nil
|
||||
else:
|
||||
L.head = L.head.prev
|
||||
|
||||
|
||||
|
||||
231
lib/pure/collections/sets.nim
Normal file
231
lib/pure/collections/sets.nim
Normal file
@@ -0,0 +1,231 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## The ``sets`` module implements an efficient hash set and ordered hash set.
|
||||
##
|
||||
## Note: The data types declared here have *value semantics*: This means that
|
||||
## ``=`` performs a copy of the hash table. If you are overly concerned with
|
||||
## efficiency and know what you do (!), you can define the symbol
|
||||
## ``shallowADT`` to compile a version that uses shallow copies instead.
|
||||
|
||||
import
|
||||
os, hashes, math
|
||||
|
||||
when defined(shallowADT):
|
||||
{.pragma: myShallow, shallow.}
|
||||
else:
|
||||
{.pragma: myShallow.}
|
||||
|
||||
type
|
||||
TSlotEnum = enum seEmpty, seFilled, seDeleted
|
||||
TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A]
|
||||
TKeyValuePairSeq[A] = seq[TKeyValuePair[A]]
|
||||
TSet* {.final, myShallow.}[A] = object
|
||||
data: TKeyValuePairSeq[A]
|
||||
counter: int
|
||||
|
||||
proc len*[A](s: TSet[A]): int =
|
||||
## returns the number of keys in `s`.
|
||||
result = s.counter
|
||||
|
||||
proc card*[A](s: TSet[A]): int =
|
||||
## alias for `len`.
|
||||
result = s.counter
|
||||
|
||||
iterator items*[A](s: TSet[A]): A =
|
||||
## iterates over any key in the table `t`.
|
||||
for h in 0..high(s.data):
|
||||
if s.data[h].slot == seFilled: yield s.data[h].key
|
||||
|
||||
const
|
||||
growthFactor = 2
|
||||
|
||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
template rawGetImpl() =
|
||||
var h: THash = hash(key) and high(s.data) # start with real hash value
|
||||
while s.data[h].slot != seEmpty:
|
||||
if s.data[h].key == key and s.data[h].slot == seFilled:
|
||||
return h
|
||||
h = nextTry(h, high(s.data))
|
||||
result = -1
|
||||
|
||||
template rawInsertImpl() =
|
||||
var h: THash = hash(key) and high(data)
|
||||
while data[h].slot == seFilled:
|
||||
h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].slot = seFilled
|
||||
|
||||
proc RawGet[A](s: TSet[A], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc contains*[A](s: TSet[A], key: A): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
var index = RawGet(t, key)
|
||||
result = index >= 0
|
||||
|
||||
proc RawInsert[A](s: var TSet[A], data: var TKeyValuePairSeq[A], key: A) =
|
||||
rawInsertImpl()
|
||||
|
||||
proc Enlarge[A](s: var TSet[A]) =
|
||||
var n: TKeyValuePairSeq[A]
|
||||
newSeq(n, len(s.data) * growthFactor)
|
||||
for i in countup(0, high(s.data)):
|
||||
if s.data[i].slot == seFilled: RawInsert(s, n, s.data[i].key)
|
||||
swap(s.data, n)
|
||||
|
||||
template inclImpl() =
|
||||
var index = RawGet(s, key)
|
||||
if index < 0:
|
||||
if mustRehash(len(s.data), s.counter): Enlarge(s)
|
||||
RawInsert(s, s.data, key)
|
||||
inc(s.counter)
|
||||
|
||||
template containsOrInclImpl() =
|
||||
var index = RawGet(s, key)
|
||||
if index >= 0:
|
||||
result = true
|
||||
else:
|
||||
if mustRehash(len(s.data), s.counter): Enlarge(s)
|
||||
RawInsert(s, s.data, key)
|
||||
inc(s.counter)
|
||||
|
||||
proc incl*[A](s: var TSet[A], key: A) =
|
||||
## includes an element `key` in `s`.
|
||||
inclImpl()
|
||||
|
||||
proc excl*[A](s: var TSet[A], key: A) =
|
||||
## excludes `key` from the set `s`.
|
||||
var index = RawGet(t, key)
|
||||
if index >= 0:
|
||||
s.data[index].slot = seDeleted
|
||||
dec(s.counter)
|
||||
|
||||
proc containsOrIncl*[A](s: var TSet[A], key: A): bool =
|
||||
## returns true if `s` contains `key`, otherwise `key` is included in `s`
|
||||
## and false is returned.
|
||||
containsOrInclImpl()
|
||||
|
||||
proc initSet*[A](initialSize=64): TSet[A] =
|
||||
## creates a new hash set that is empty. `initialSize` needs to be
|
||||
## a power of two.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toSet*[A](keys: openarray[A]): TSet[A] =
|
||||
## creates a new hash set that contains the given `keys`.
|
||||
result = initSet[A](nextPowerOfTwo(keys.len+10))
|
||||
for key in items(keys): result.incl(key)
|
||||
|
||||
template dollarImpl(): stmt =
|
||||
result = "{"
|
||||
for key in items(s):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.add($key)
|
||||
result.add("}")
|
||||
|
||||
proc `$`*[A](s: TSet[A]): string =
|
||||
## The `$` operator for hash sets.
|
||||
dollarImpl()
|
||||
|
||||
# ------------------------------ ordered table ------------------------------
|
||||
|
||||
type
|
||||
TOrderedKeyValuePair[A] = tuple[
|
||||
slot: TSlotEnum, next: int, key: A]
|
||||
TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]]
|
||||
TOrderedSet* {.
|
||||
final, myShallow.}[A] = object ## set that remembers insertion order
|
||||
data: TOrderedKeyValuePairSeq[A]
|
||||
counter, first, last: int
|
||||
|
||||
proc len*[A](s: TOrderedSet[A]): int {.inline.} =
|
||||
## returns the number of keys in `s`.
|
||||
result = t.counter
|
||||
|
||||
proc card*[A](s: TOrderedSet[A]): int {.inline.} =
|
||||
## alias for `len`.
|
||||
result = t.counter
|
||||
|
||||
template forAllOrderedPairs(yieldStmt: stmt) =
|
||||
var h = s.first
|
||||
while h >= 0:
|
||||
var nxt = s.data[h].next
|
||||
if s.data[h].slot == seFilled: yieldStmt
|
||||
h = nxt
|
||||
|
||||
iterator items*[A](s: TOrderedSet[A]): A =
|
||||
## iterates over any key in the set `s` in insertion order.
|
||||
forAllOrderedPairs:
|
||||
yield s.data[h].key
|
||||
|
||||
proc RawGet[A](s: TOrderedSet[A], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc contains*[A](s: TOrderedSet[A], key: A): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
var index = RawGet(s, key)
|
||||
result = index >= 0
|
||||
|
||||
proc RawInsert[A](s: var TOrderedSet[A],
|
||||
data: var TOrderedKeyValuePairSeq[A], key: A) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
if s.first < 0: s.first = h
|
||||
if s.last >= 0: data[s.last].next = h
|
||||
s.last = h
|
||||
|
||||
proc Enlarge[A](s: var TOrderedSet[A]) =
|
||||
var n: TOrderedKeyValuePairSeq[A]
|
||||
newSeq(n, len(s.data) * growthFactor)
|
||||
var h = s.first
|
||||
s.first = -1
|
||||
s.last = -1
|
||||
while h >= 0:
|
||||
var nxt = s.data[h].next
|
||||
if s.data[h].slot == seFilled:
|
||||
RawInsert(s, n, s.data[h].key)
|
||||
h = nxt
|
||||
swap(s.data, n)
|
||||
|
||||
proc incl*[A](s: var TOrderedSet[A], key: A) =
|
||||
## includes an element `key` in `s`.
|
||||
inclImpl()
|
||||
|
||||
proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool =
|
||||
## returns true if `s` contains `key`, otherwise `key` is included in `s`
|
||||
## and false is returned.
|
||||
containsOrInclImpl()
|
||||
|
||||
proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] =
|
||||
## creates a new ordered hash set that is empty. `initialSize` needs to be
|
||||
## a power of two.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toOrderedSet*[A](keys: openarray[A]): TOrderedSet[A] =
|
||||
## creates a new ordered hash set that contains the given `keys`.
|
||||
result = initOrderedSet[A](nextPowerOfTwo(keys.len+10))
|
||||
for key in items(keys): result.incl(key)
|
||||
|
||||
proc `$`*[A](s: TOrderedSet[A]): string =
|
||||
## The `$` operator for ordered hash sets.
|
||||
dollarImpl()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf, Dominik Picheta
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -12,7 +12,7 @@
|
||||
##
|
||||
## Note: The data types declared here have *value semantics*: This means that
|
||||
## ``=`` performs a copy of the hash table. If you are overly concerned with
|
||||
## efficiency and don't need this behaviour, you can define the symbol
|
||||
## efficiency and know what you do (!), you can define the symbol
|
||||
## ``shallowADT`` to compile a version that uses shallow copies instead.
|
||||
|
||||
import
|
||||
@@ -123,7 +123,7 @@ proc del*[A, B](t: var TTable[A, B], key: A) =
|
||||
dec(t.counter)
|
||||
|
||||
proc initTable*[A, B](initialSize=64): TTable[A, B] =
|
||||
## creates a new hash table table that is empty. `initialSize` needs to be
|
||||
## creates a new hash table that is empty. `initialSize` needs to be
|
||||
## a power of two.
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
@@ -132,7 +132,7 @@ proc initTable*[A, B](initialSize=64): TTable[A, B] =
|
||||
proc toTable*[A, B](pairs: openarray[tuple[key: A,
|
||||
val: B]]): TTable[A, B] =
|
||||
## creates a new hash table that contains the given `pairs`.
|
||||
result = initTable[A](nextPowerOfTwo(pairs.len+10))
|
||||
result = initTable[A, B](nextPowerOfTwo(pairs.len+10))
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
template dollarImpl(): stmt =
|
||||
@@ -148,7 +148,7 @@ template dollarImpl(): stmt =
|
||||
result.add("}")
|
||||
|
||||
proc `$`*[A, B](t: TTable[A, B]): string =
|
||||
## The `$` operator for string tables.
|
||||
## The `$` operator for hash tables.
|
||||
dollarImpl()
|
||||
|
||||
# ------------------------------ ordered table ------------------------------
|
||||
@@ -167,11 +167,11 @@ proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} =
|
||||
result = t.counter
|
||||
|
||||
template forAllOrderedPairs(yieldStmt: stmt) =
|
||||
var i = t.first
|
||||
while i >= 0:
|
||||
var nxt = t.data[i].next
|
||||
var h = t.first
|
||||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
if t.data[h].slot == seFilled: yieldStmt
|
||||
i = nxt
|
||||
h = nxt
|
||||
|
||||
iterator pairs*[A, B](t: TOrderedTable[A, B]): tuple[key: A, val: B] =
|
||||
## iterates over any (key, value) pair in the table `t` in insertion
|
||||
@@ -204,23 +204,29 @@ proc hasKey*[A, B](t: TOrderedTable[A, B], key: A): bool =
|
||||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert[A, B](t: TOrderedTable[A, B],
|
||||
proc RawInsert[A, B](t: var TOrderedTable[A, B],
|
||||
data: var TOrderedKeyValuePairSeq[A, B],
|
||||
key: A, val: B) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
if first < 0: first = h
|
||||
if last >= 0: data[last].next = h
|
||||
lastEntry = h
|
||||
if t.first < 0: t.first = h
|
||||
if t.last >= 0: data[t.last].next = h
|
||||
t.last = h
|
||||
|
||||
proc Enlarge[A, B](t: TOrderedTable[A, B]) =
|
||||
proc Enlarge[A, B](t: var TOrderedTable[A, B]) =
|
||||
var n: TOrderedKeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
forAllOrderedPairs:
|
||||
RawInsert(t, n, t.data[h].key, t.data[h].val)
|
||||
var h = t.first
|
||||
t.first = -1
|
||||
t.last = -1
|
||||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
if t.data[h].slot == seFilled:
|
||||
RawInsert(t, n, t.data[h].key, t.data[h].val)
|
||||
h = nxt
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`*[A, B](t: TOrderedTable[A, B], key: A, val: B) =
|
||||
proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
|
||||
## puts a (key, value)-pair into `t`.
|
||||
putImpl()
|
||||
|
||||
@@ -240,7 +246,7 @@ proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A,
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
proc `$`*[A, B](t: TOrderedTable[A, B]): string =
|
||||
## The `$` operator for hash tables.
|
||||
## The `$` operator for ordered hash tables.
|
||||
dollarImpl()
|
||||
|
||||
# ------------------------------ count tables -------------------------------
|
||||
@@ -295,14 +301,14 @@ proc RawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
||||
proc Enlarge[A](t: TCountTable[A]) =
|
||||
proc Enlarge[A](t: var TCountTable[A]) =
|
||||
var n: seq[tuple[key: A, val: int]]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if t.data[i].val != 0: RawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`*[A](t: TCountTable[A], key: A, val: int) =
|
||||
proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) =
|
||||
## puts a (key, value)-pair into `t`. `val` has to be positive.
|
||||
assert val > 0
|
||||
PutImpl()
|
||||
@@ -323,7 +329,7 @@ proc `$`*[A](t: TCountTable[A]): string =
|
||||
## The `$` operator for count tables.
|
||||
dollarImpl()
|
||||
|
||||
proc inc*[A](t: TCountTable[A], key: A, val = 1) =
|
||||
proc inc*[A](t: var TCountTable[A], key: A, val = 1) =
|
||||
## increments `t[key]` by `val`.
|
||||
var index = RawGet(t, key)
|
||||
if index >= 0:
|
||||
@@ -351,8 +357,8 @@ proc Largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||
result.key = t.data[maxIdx].key
|
||||
result.val = t.data[maxIdx].val
|
||||
|
||||
proc sort*[A](t: var TCountTable[A]) =
|
||||
## sorts the count table so that the entry with the highest counter comes
|
||||
proc sort*[A](t: var TCountTable[A]) =
|
||||
## sorts the count table so that the entry with the highest counter comes
|
||||
## first. This is destructive! You must not modify `t` afterwards!
|
||||
## You can use the iterators `pairs`, `keys`, and `values` to iterate over
|
||||
## `t` in the sorted order.
|
||||
@@ -361,35 +367,14 @@ proc sort*[A](t: var TCountTable[A]) =
|
||||
var h = 1
|
||||
while true:
|
||||
h = 3 * h + 1
|
||||
if h >= t.data.high: break
|
||||
while true:
|
||||
if h >= high(t.data): break
|
||||
while true:
|
||||
h = h div 3
|
||||
for i in countup(h, t.data.high):
|
||||
for i in countup(h, high(t.data)):
|
||||
var j = i
|
||||
while t.data[j-h].val < t.data[j].val:
|
||||
while t.data[j-h].val <= t.data[j].val:
|
||||
swap(t.data[j], t.data[j-h])
|
||||
j = j-h
|
||||
if j < h: break
|
||||
if h == 1: break
|
||||
|
||||
when isMainModule:
|
||||
var table = initHashTable[string, float]()
|
||||
table["test"] = 1.2345
|
||||
table["111"] = 1.000043
|
||||
echo table
|
||||
table.del("111")
|
||||
echo table
|
||||
#echo repr(table["111"])
|
||||
#echo(repr(table["1212"]))
|
||||
table["111"] = 1.5
|
||||
table["011"] = 67.9
|
||||
echo table
|
||||
table.del("test")
|
||||
table.del("111")
|
||||
echo table
|
||||
|
||||
|
||||
echo hash("test")
|
||||
echo hash("test")
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
"""
|
||||
|
||||
import lists
|
||||
|
||||
const
|
||||
data = [1, 2, 3, 4, 5, 6]
|
||||
|
||||
block SinglyLinkedListTest1:
|
||||
var L: TSinglyLinkedList[int]
|
||||
for d in items(data): L.prepend(d)
|
||||
assert($L == "[6, 5, 4, 3, 2, 1]")
|
||||
|
||||
assert(4 in L)
|
||||
|
||||
block SinglyLinkedListTest2:
|
||||
var L: TSinglyLinkedList[string]
|
||||
for d in items(data): L.prepend($d)
|
||||
assert($L == "[6, 5, 4, 3, 2, 1]")
|
||||
|
||||
assert("4" in L)
|
||||
|
||||
|
||||
block DoublyLinkedListTest1:
|
||||
var L: TDoublyLinkedList[int]
|
||||
for d in items(data): L.prepend(d)
|
||||
for d in items(data): L.append(d)
|
||||
L.remove(L.find(1))
|
||||
assert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]")
|
||||
|
||||
assert(4 in L)
|
||||
|
||||
block SinglyLinkedRingTest1:
|
||||
var L: TSinglyLinkedRing[int]
|
||||
L.prepend(4)
|
||||
assert($L == "[4]")
|
||||
L.prepend(4)
|
||||
|
||||
assert($L == "[4, 4]")
|
||||
assert(4 in L)
|
||||
|
||||
|
||||
block DoublyLinkedRingTest1:
|
||||
var L: TDoublyLinkedRing[int]
|
||||
L.prepend(4)
|
||||
assert($L == "[4]")
|
||||
L.prepend(4)
|
||||
|
||||
assert($L == "[4, 4]")
|
||||
assert(4 in L)
|
||||
|
||||
L.append(3)
|
||||
L.append(5)
|
||||
assert($L == "[4, 4, 3, 5]")
|
||||
|
||||
L.remove(L.find(3))
|
||||
L.remove(L.find(5))
|
||||
L.remove(L.find(4))
|
||||
L.remove(L.find(4))
|
||||
assert($L == "[]")
|
||||
assert(4 notin L)
|
||||
|
||||
|
||||
echo "true"
|
||||
|
||||
|
||||
62
tests/accept/run/tsets2.nim
Normal file
62
tests/accept/run/tsets2.nim
Normal file
@@ -0,0 +1,62 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
cmd: "nimrod cc --gc:none --hints:on $# $#"
|
||||
"""
|
||||
|
||||
import hashes, sets
|
||||
|
||||
const
|
||||
data = [
|
||||
"34", "12",
|
||||
"90", "0",
|
||||
"1", "2",
|
||||
"3", "4",
|
||||
"5", "6",
|
||||
"7", "8",
|
||||
"9", "---00",
|
||||
"10", "11", "19",
|
||||
"20", "30", "40",
|
||||
"50", "60", "70",
|
||||
"80"]
|
||||
|
||||
block tableTest1:
|
||||
var t = initSet[tuple[x, y: int]]()
|
||||
t.incl((0,0))
|
||||
t.incl((1,0))
|
||||
assert(not t.containsOrIncl((0,1)))
|
||||
t.incl((1,1))
|
||||
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert((x,y) in t)
|
||||
#assert($t ==
|
||||
# "{(x: 0, y: 0), (x: 0, y: 1), (x: 1, y: 0), (x: 1, y: 1)}")
|
||||
|
||||
block setTest2:
|
||||
var t = initSet[string]()
|
||||
t.incl("test")
|
||||
t.incl("111")
|
||||
t.incl("123")
|
||||
t.excl("111")
|
||||
|
||||
t.incl("012")
|
||||
t.incl("123") # test duplicates
|
||||
|
||||
assert "123" in t
|
||||
assert "111" notin t # deleted
|
||||
|
||||
for key in items(data): t.incl(key)
|
||||
for key in items(data): assert key in t
|
||||
|
||||
|
||||
block orderedSetTest1:
|
||||
var t = data.toOrderedSet
|
||||
for key in items(data): assert key in t
|
||||
var i = 0
|
||||
# `items` needs to yield in insertion order:
|
||||
for key in items(t):
|
||||
assert key == data[i]
|
||||
inc(i)
|
||||
|
||||
echo "true"
|
||||
|
||||
@@ -1,18 +1,84 @@
|
||||
discard """
|
||||
output: '''true'''
|
||||
cmd: "nimrod cc --gc:none --hints:on $# $#"
|
||||
"""
|
||||
|
||||
import hashes, tables
|
||||
|
||||
var t = initTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
const
|
||||
data = {
|
||||
"34": 123456, "12": 789,
|
||||
"90": 343, "0": 34404,
|
||||
"1": 344004, "2": 344774,
|
||||
"3": 342244, "4": 3412344,
|
||||
"5": 341232144, "6": 34214544,
|
||||
"7": 3434544, "8": 344544,
|
||||
"9": 34435644, "---00": 346677844,
|
||||
"10": 34484, "11": 34474, "19": 34464,
|
||||
"20": 34454, "30": 34141244, "40": 344114,
|
||||
"50": 344490, "60": 344491, "70": 344492,
|
||||
"80": 344497}
|
||||
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
block tableTest1:
|
||||
var t = initTable[tuple[x, y: int], string]()
|
||||
t[(0,0)] = "00"
|
||||
t[(1,0)] = "10"
|
||||
t[(0,1)] = "01"
|
||||
t[(1,1)] = "11"
|
||||
for x in 0..1:
|
||||
for y in 0..1:
|
||||
assert t[(x,y)] == $x & $y
|
||||
assert($t ==
|
||||
"{(x: 0, y: 0): 00, (x: 0, y: 1): 01, (x: 1, y: 0): 10, (x: 1, y: 1): 11}")
|
||||
|
||||
block tableTest2:
|
||||
var t = initTable[string, float]()
|
||||
t["test"] = 1.2345
|
||||
t["111"] = 1.000043
|
||||
t["123"] = 1.23
|
||||
t.del("111")
|
||||
|
||||
t["012"] = 67.9
|
||||
t["123"] = 1.5 # test overwriting
|
||||
|
||||
assert t["123"] == 1.5
|
||||
assert t["111"] == 0.0 # deleted
|
||||
assert(not hasKey(t, "111"))
|
||||
|
||||
for key, val in items(data): t[key] = val.toFloat
|
||||
for key, val in items(data): assert t[key] == val.toFloat
|
||||
|
||||
|
||||
block orderedTableTest1:
|
||||
var t = initOrderedTable[string, int](2)
|
||||
for key, val in items(data): t[key] = val
|
||||
for key, val in items(data): assert t[key] == val
|
||||
var i = 0
|
||||
# `pairs` needs to yield in insertion order:
|
||||
for key, val in pairs(t):
|
||||
assert key == data[i][0]
|
||||
assert val == data[i][1]
|
||||
inc(i)
|
||||
|
||||
block countTableTest1:
|
||||
var s = data.toTable
|
||||
var t = initCountTable[string]()
|
||||
for k in s.Keys: t.inc(k)
|
||||
for k in t.keys: assert t[k] == 1
|
||||
t.inc("90", 3)
|
||||
t.inc("12", 2)
|
||||
t.inc("34", 1)
|
||||
assert t.largest()[0] == "90"
|
||||
|
||||
t.sort()
|
||||
var i = 0
|
||||
for k, v in t.pairs:
|
||||
case i
|
||||
of 0: assert k == "90" and v == 4
|
||||
of 1: assert k == "12" and v == 3
|
||||
of 2: assert k == "34" and v == 2
|
||||
else: break
|
||||
inc i
|
||||
|
||||
echo "true"
|
||||
|
||||
|
||||
18
todo.txt
18
todo.txt
@@ -4,12 +4,13 @@
|
||||
from different heaps: n.next = otherHeapPtr
|
||||
|
||||
* add --deadlock_prevention:on|off switch? timeout for locks?
|
||||
|
||||
* test the sort implementation again
|
||||
|
||||
|
||||
High priority (version 0.9.0)
|
||||
=============================
|
||||
|
||||
- iterators should not always be destructive!
|
||||
- warning for implicit openArray -> varargs convention
|
||||
- implement explicit varargs
|
||||
- tests: run modules that contain "#RUN_ME", compile the other
|
||||
@@ -19,7 +20,6 @@ High priority (version 0.9.0)
|
||||
- fix overloading resolution
|
||||
- wrong co-/contravariance
|
||||
- make ^ available as operator
|
||||
- iterators should not always be destructive
|
||||
|
||||
Bugs
|
||||
----
|
||||
@@ -30,12 +30,23 @@ Bugs
|
||||
- BUG: generic assign still buggy
|
||||
- Optimization: If we use a temporary for the result anyway the code gen
|
||||
should make use of this fact to generate better code...
|
||||
- sorting with leads to a strange memory corruption!
|
||||
--> system.swap or genericAssign is broken! And indeed, if reference counts
|
||||
are not modified and the GC is triggered in between a swap, bad things
|
||||
may happen!
|
||||
|
||||
proc sort*[A](t: var TCountTable[A]) =
|
||||
for i in 0 .. high(t.data)-1:
|
||||
var maxIdx = i
|
||||
for j in i+1 .. high(t.data):
|
||||
if t.data[j].val == 3: echo "touched! ", t.data[j].key
|
||||
if t.data[j].val > t.data[maxIdx].val: maxIdx = j
|
||||
swap(t.data[maxIdx], t.data[i])
|
||||
|
||||
|
||||
To implement
|
||||
------------
|
||||
|
||||
* hash tables and sets; count tables; ordered dicts
|
||||
* distinct types for array/seq indexes
|
||||
* implement closures for the C code generator
|
||||
* GC: marker procs for native Nimrod GC and Boehm GC
|
||||
@@ -68,6 +79,7 @@ Low priority
|
||||
Library
|
||||
-------
|
||||
|
||||
- specialized bit sets; specialized string sets
|
||||
- locale support
|
||||
- conversion between character sets
|
||||
- bignums
|
||||
|
||||
@@ -48,6 +48,9 @@ Changes affecting backwards compatibility
|
||||
Additions
|
||||
---------
|
||||
|
||||
- Added ``lists`` module which contains generic linked lists.
|
||||
- Added ``sets`` module which contains generic hash sets.
|
||||
- Added ``tables`` module which contains generic hash tables.
|
||||
- Added ``scgi`` module.
|
||||
- Added ``smtp`` module.
|
||||
- Added ``re.findAll``, ``pegs.findAll``.
|
||||
|
||||
@@ -38,6 +38,7 @@ srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
|
||||
srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors"
|
||||
srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
|
||||
srcdoc: "impure/rdstdin;wrappers/zmq"
|
||||
srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
|
||||
|
||||
webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
|
||||
webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"
|
||||
|
||||
Reference in New Issue
Block a user