summary refs log tree commit diff stats
path: root/lib/pure/collections
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/collections')
-rw-r--r--lib/pure/collections/LockFreeHash.nim4
-rw-r--r--lib/pure/collections/critbits.nim2
-rw-r--r--lib/pure/collections/intsets.nim2
-rw-r--r--lib/pure/collections/lists.nim24
-rw-r--r--lib/pure/collections/queues.nim2
-rw-r--r--lib/pure/collections/rtarrays.nim1
-rw-r--r--lib/pure/collections/sequtils.nim206
-rw-r--r--lib/pure/collections/sets.nim4
-rw-r--r--lib/pure/collections/sharedstrings.nim6
-rw-r--r--lib/pure/collections/tables.nim8
10 files changed, 189 insertions, 70 deletions
diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim
index 954d62491..28fa2a81b 100644
--- a/lib/pure/collections/LockFreeHash.nim
+++ b/lib/pure/collections/LockFreeHash.nim
@@ -49,13 +49,11 @@ when sizeof(int) == 4: # 32bit
     Raw = range[0..1073741823]
     ## The range of uint values that can be stored directly in a value slot
     ## when on a 32 bit platform
-  {.deprecated: [TRaw: Raw].}
 elif sizeof(int) == 8: # 64bit
   type
     Raw = range[0'i64..4611686018427387903'i64]
     ## The range of uint values that can be stored directly in a value slot
     ## when on a 64 bit platform
-  {.deprecated: [TRaw: Raw].}
 else:
   {.error: "unsupported platform".}
 
@@ -74,7 +72,6 @@ type
     copyDone: int
     next: PConcTable[K,V]
     data: EntryArr
-{.deprecated: [TEntry: Entry, TEntryArr: EntryArr].}
 
 proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
   expVal: int, match: bool): int
@@ -544,7 +541,6 @@ when not defined(testing) and isMainModule:
     Data = tuple[k: string,v: TestObj]
     PDataArr = array[0..numTests-1, Data]
     Dict = PConcTable[string,TestObj]
-  {.deprecated: [TTestObj: TestObj, TData: Data].}
 
   var
     thr: array[0..numThreads-1, Thread[Dict]]
diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim
index c94e08098..32e0299ba 100644
--- a/lib/pure/collections/critbits.nim
+++ b/lib/pure/collections/critbits.nim
@@ -33,8 +33,6 @@ type
     root: Node[T]
     count: int
 
-{.deprecated: [TCritBitTree: CritBitTree].}
-
 proc len*[T](c: CritBitTree[T]): int =
   ## returns the number of elements in `c` in O(1).
   result = c.count
diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim
index 545958977..def96b8f7 100644
--- a/lib/pure/collections/intsets.nim
+++ b/lib/pure/collections/intsets.nim
@@ -44,8 +44,6 @@ type
     data: TrunkSeq
     a: array[0..33, int] # profiling shows that 34 elements are enough
 
-{.deprecated: [TIntSet: IntSet, TTrunk: Trunk, TTrunkSeq: TrunkSeq].}
-
 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 e69acc8d9..15ce5d074 100644
--- a/lib/pure/collections/lists.nim
+++ b/lib/pure/collections/lists.nim
@@ -45,15 +45,6 @@ type
 
   SomeLinkedNode*[T] = SinglyLinkedNode[T] | DoublyLinkedNode[T]
 
-{.deprecated: [TDoublyLinkedNode: DoublyLinkedNodeObj,
-    PDoublyLinkedNode: DoublyLinkedNode,
-    TSinglyLinkedNode: SinglyLinkedNodeObj,
-    PSinglyLinkedNode: SinglyLinkedNode,
-    TDoublyLinkedList: DoublyLinkedList,
-    TSinglyLinkedRing: SinglyLinkedRing,
-    TDoublyLinkedRing: DoublyLinkedRing,
-    TSinglyLinkedList: SinglyLinkedList].}
-
 proc initSinglyLinkedList*[T](): SinglyLinkedList[T] =
   ## creates a new singly linked list that is empty.
   discard
@@ -149,11 +140,26 @@ proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} =
   ## exist, true otherwise.
   result = find(L, value) != nil
 
+proc append*[T](L: var SinglyLinkedList[T],
+                n: SinglyLinkedNode[T]) {.inline.} =
+  ## appends a node `n` to `L`. Efficiency: O(1).
+  n.next = nil
+  if L.tail != nil:
+    assert(L.tail.next == nil)
+    L.tail.next = n
+  L.tail = n
+  if L.head == nil: L.head = n
+
+proc append*[T](L: var SinglyLinkedList[T], value: T) {.inline.} =
+  ## appends a value to `L`. Efficiency: O(1).
+  append(L, newSinglyLinkedNode(value))
+
 proc prepend*[T](L: var SinglyLinkedList[T],
                  n: SinglyLinkedNode[T]) {.inline.} =
   ## prepends a node to `L`. Efficiency: O(1).
   n.next = L.head
   L.head = n
+  if L.tail == nil: L.tail = n
 
 proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} =
   ## prepends a node to `L`. Efficiency: O(1).
diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim
index ce792d6da..9a1d169fb 100644
--- a/lib/pure/collections/queues.nim
+++ b/lib/pure/collections/queues.nim
@@ -46,8 +46,6 @@ type
     data: seq[T]
     rd, wr, count, mask: int
 
-{.deprecated: [TQueue: Queue].}
-
 proc initQueue*[T](initialSize: int = 4): Queue[T] =
   ## Create a new queue.
   ## Optionally, the initial capacity can be reserved via `initialSize` as a
diff --git a/lib/pure/collections/rtarrays.nim b/lib/pure/collections/rtarrays.nim
index 3849117a0..90dbf0049 100644
--- a/lib/pure/collections/rtarrays.nim
+++ b/lib/pure/collections/rtarrays.nim
@@ -19,7 +19,6 @@ type
     L: Natural
     spart: seq[T]
     apart: array[ArrayPartSize, T]
-  UncheckedArray* {.unchecked.}[T] = array[0, T]
 
 template usesSeqPart(x): untyped = x.L > ArrayPartSize
 
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 2e21786bb..39ba6df49 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -115,7 +115,7 @@ proc repeat*[T](x: T, n: Natural): seq[T] =
   for i in 0 ..< n:
     result[i] = x
 
-proc deduplicate*[T](s: openArray[T]): seq[T] =
+proc deduplicate*[T](s: openArray[T], isSorted: bool = false): seq[T] =
   ## Returns a new sequence without duplicates.
   ##
   ## Example:
@@ -129,8 +129,17 @@ proc deduplicate*[T](s: openArray[T]): seq[T] =
   ##   assert unique1 == @[1, 3, 4, 2, 8]
   ##   assert unique2 == @["a", "c", "d"]
   result = @[]
-  for itm in items(s):
-    if not result.contains(itm): result.add(itm)
+  if s.len > 0:
+    if isSorted:
+      var prev = s[0]
+      result.add(prev)
+      for i in 1..s.high:
+        if s[i] != prev:
+          prev = s[i]
+          result.add(prev)
+    else:
+      for itm in items(s):
+        if not result.contains(itm): result.add(itm)
 
 proc zip*[S, T](s1: openArray[S], s2: openArray[T]): seq[tuple[a: S, b: T]] =
   ## Returns a new sequence with a combination of the two input containers.
@@ -504,36 +513,76 @@ template anyIt*(s, pred: untyped): bool =
       break
   result
 
-template toSeq*(iter: untyped): untyped =
-  ## Transforms any iterator into a sequence.
-  ##
-  ## Example:
-  ##
-  ## .. code-block::
-  ##   let
-  ##     numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
-  ##     odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
-  ##       if x mod 2 == 1:
-  ##         result = true)
-  ##   assert odd_numbers == @[1, 3, 5, 7, 9]
-
-  # Note: see also `mapIt` for explanation of some of the implementation
-  # subtleties.
-  when compiles(iter.len):
+template toSeq1(s: not iterator): untyped =
+  # overload for typed but not iterator
+  type outType = type(items(s))
+  when compiles(s.len):
     block:
-      evalOnceAs(iter2, iter, true)
-      var result = newSeq[type(iter)](iter2.len)
+      evalOnceAs(s2, s, compiles((let _ = s)))
       var i = 0
-      for x in iter2:
-        result[i] = x
-        inc i
+      var result = newSeq[outType](s2.len)
+      for it in s2:
+        result[i] = it
+        i += 1
       result
   else:
-    var result: seq[type(iter)] = @[]
-    for x in iter:
-      result.add(x)
+    var result: seq[outType] = @[]
+    for it in s:
+      result.add(it)
     result
 
+template toSeq2(iter: iterator): untyped =
+  # overload for iterator
+  evalOnceAs(iter2, iter(), false)
+  when compiles(iter2.len):
+    var i = 0
+    var result = newSeq[type(iter2)](iter2.len)
+    for x in iter2:
+      result[i] = x
+      inc i
+    result
+  else:
+    type outType = type(iter2())
+    var result: seq[outType] = @[]
+    when compiles(iter2()):
+      evalOnceAs(iter4, iter, false)
+      let iter3=iter4()
+      for x in iter3():
+        result.add(x)
+    else:
+      for x in iter2():
+        result.add(x)
+    result
+
+template toSeq*(iter: untyped): untyped =
+  ## Transforms any iterable into a sequence.
+  runnableExamples:
+    let
+      numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
+      odd_numbers = toSeq(filter(numeric, proc(x: int): bool = x mod 2 == 1))
+    doAssert odd_numbers == @[1, 3, 5, 7, 9]
+
+  when compiles(toSeq1(iter)):
+    toSeq1(iter)
+  elif compiles(toSeq2(iter)):
+    toSeq2(iter)
+  else:
+    # overload for untyped, eg: `toSeq(myInlineIterator(3))`
+    when compiles(iter.len):
+      block:
+        evalOnceAs(iter2, iter, true)
+        var result = newSeq[type(iter)](iter2.len)
+        var i = 0
+        for x in iter2:
+          result[i] = x
+          inc i
+        result
+    else:
+      var result: seq[type(iter)] = @[]
+      for x in iter:
+        result.add(x)
+      result
+
 template foldl*(sequence, operation: untyped): untyped =
   ## Template to fold a sequence from left to right, returning the accumulation.
   ##
@@ -673,10 +722,16 @@ template mapIt*(s: typed, op: untyped): untyped =
   ##     nums = @[1, 2, 3, 4]
   ##     strings = nums.mapIt($(4 * it))
   ##   assert strings == @["4", "8", "12", "16"]
-  type outType = type((
-    block:
-      var it{.inject.}: type(items(s));
-      op))
+  when defined(nimHasTypeof):
+    type outType = typeof((
+      block:
+        var it{.inject.}: typeof(items(s), typeOfIter);
+        op), typeOfProc)
+  else:
+    type outType = type((
+      block:
+        var it{.inject.}: type(items(s));
+        op))
   when compiles(s.len):
     block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580
 
@@ -781,6 +836,7 @@ macro mapLiterals*(constructor, op: untyped;
 
 when isMainModule:
   import strutils
+  from algorithm import sorted
 
   # helper for testing double substitution side effects which are handled
   # by `evalOnceAs`
@@ -856,10 +912,18 @@ when isMainModule:
       unique2 = deduplicate(dup2)
       unique3 = deduplicate(dup3)
       unique4 = deduplicate(dup4)
+      unique5 = deduplicate(dup1.sorted, true)
+      unique6 = deduplicate(dup2, true)
+      unique7 = deduplicate(dup3.sorted, true)
+      unique8 = deduplicate(dup4, true)
     assert unique1 == @[1, 3, 4, 2, 8]
     assert unique2 == @["a", "c", "d"]
     assert unique3 == @[1, 3, 4, 2, 8]
     assert unique4 == @["a", "c", "d"]
+    assert unique5 == @[1, 2, 3, 4, 8]
+    assert unique6 == @["a", "c", "d"]
+    assert unique7 == @[1, 2, 3, 4, 8]
+    assert unique8 == @["a", "c", "d"]
 
   block: # zip test
     let
@@ -1027,12 +1091,72 @@ when isMainModule:
     assert anyIt(anumbers, it > 9) == false
 
   block: # toSeq test
-    let
-      numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
-      odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
-        if x mod 2 == 1:
-          result = true)
-    assert odd_numbers == @[1, 3, 5, 7, 9]
+    block:
+      let
+        numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
+        odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
+          if x mod 2 == 1:
+            result = true)
+      assert odd_numbers == @[1, 3, 5, 7, 9]
+
+    block:
+      doAssert [1,2].toSeq == @[1,2]
+      doAssert @[1,2].toSeq == @[1,2]
+
+      doAssert @[1,2].toSeq == @[1,2]
+      doAssert toSeq(@[1,2]) == @[1,2]
+
+    block:
+      iterator myIter(seed:int):auto=
+        for i in 0..<seed:
+          yield i
+      doAssert toSeq(myIter(2)) == @[0, 1]
+
+    block:
+      iterator myIter():auto{.inline.}=
+        yield 1
+        yield 2
+
+      doAssert myIter.toSeq == @[1,2]
+      doAssert toSeq(myIter) == @[1,2]
+
+    block:
+      iterator myIter():int {.closure.} =
+        yield 1
+        yield 2
+
+      doAssert myIter.toSeq == @[1,2]
+      doAssert toSeq(myIter) == @[1,2]
+
+    block:
+      proc myIter():auto=
+        iterator ret():int{.closure.}=
+          yield 1
+          yield 2
+        result = ret
+
+      doAssert myIter().toSeq == @[1,2]
+      doAssert toSeq(myIter()) == @[1,2]
+
+    block:
+      proc myIter(n:int):auto=
+        var counter = 0
+        iterator ret():int{.closure.}=
+          while counter<n:
+            yield counter
+            counter.inc
+        result = ret
+
+      block:
+        let myIter3 = myIter(3)
+        doAssert myIter3.toSeq == @[0,1,2]
+      block:
+        let myIter3 = myIter(3)
+        doAssert toSeq(myIter3) == @[0,1,2]
+      block:
+        # makes sure this does not hang forever
+        doAssert myIter(3).toSeq == @[0,1,2]
+        doAssert toSeq(myIter(3)) == @[0,1,2]
 
   block:
     # tests https://github.com/nim-lang/Nim/issues/7187
@@ -1135,5 +1259,13 @@ when isMainModule:
       A, B
     doAssert mapIt(X, $it) == @["A", "B"]
 
+  block:
+    # bug #9093
+    let inp = "a:b,c:d"
+
+    let outp = inp.split(",").mapIt(it.split(":"))
+    doAssert outp == @[@["a", "b"], @["c", "d"]]
+
+
   when not defined(testing):
     echo "Finished doc tests"
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 7355aae02..1273cbc33 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -39,8 +39,6 @@ type
     data: KeyValuePairSeq[A]
     counter: int
 
-{.deprecated: [TSet: HashSet].}
-
 template default[T](t: typedesc[T]): T =
   ## Used by clear methods to get a default value.
   var v: T
@@ -631,8 +629,6 @@ type
     data: OrderedKeyValuePairSeq[A]
     counter, first, last: int
 
-{.deprecated: [TOrderedSet: OrderedSet].}
-
 proc clear*[A](s: var OrderedSet[A]) =
   ## Clears the OrderedSet back to an empty state, without shrinking
   ## any of the existing storage. O(n) where n is the size of the hash bucket.
diff --git a/lib/pure/collections/sharedstrings.nim b/lib/pure/collections/sharedstrings.nim
index 7e9de4b73..b283cd4b1 100644
--- a/lib/pure/collections/sharedstrings.nim
+++ b/lib/pure/collections/sharedstrings.nim
@@ -12,6 +12,8 @@
 type
   UncheckedCharArray = UncheckedArray[char]
 
+import system/helpers2
+
 type
   Buffer = ptr object
     refcount: int
@@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len
 
 proc `[]`*(s: SharedString; i: Natural): char =
   if i < s.len: result = s.buffer.data[i+s.first]
-  else: raise newException(IndexError, "index out of bounds")
+  else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
 
 proc `[]=`*(s: var SharedString; i: Natural; value: char) =
   if i < s.len: s.buffer.data[i+s.first] = value
-  else: raise newException(IndexError, "index out of bounds")
+  else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
 
 proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString =
   #incRef(src.buffer)
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index 9fdae33ed..f46a368b1 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -125,8 +125,6 @@ type
     counter: int
   TableRef*[A,B] = ref Table[A, B]
 
-{.deprecated: [TTable: Table, PTable: TableRef].}
-
 template maxHash(t): untyped = high(t.data)
 template dataLen(t): untyped = len(t.data)
 
@@ -520,8 +518,6 @@ type
     counter, first, last: int
   OrderedTableRef*[A, B] = ref OrderedTable[A, B]
 
-{.deprecated: [TOrderedTable: OrderedTable, POrderedTable: OrderedTableRef].}
-
 proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} =
   ## returns the number of keys in ``t``.
   result = t.counter
@@ -795,7 +791,7 @@ proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
   getOrDefault(t[], key)
 
 proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A, default: B): B =
-  ## retrieves the value at ``t[key]`` iff ``key`` is in ``t``. Otherwise, 
+  ## retrieves the value at ``t[key]`` iff ``key`` is in ``t``. Otherwise,
   ## ``default`` is returned.
   getOrDefault(t[], key, default)
 
@@ -892,8 +888,6 @@ type
     counter: int
   CountTableRef*[A] = ref CountTable[A]
 
-{.deprecated: [TCountTable: CountTable, PCountTable: CountTableRef].}
-
 proc len*[A](t: CountTable[A]): int =
   ## returns the number of keys in ``t``.
   result = t.counter