summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDmitry Atamanov <data-man@users.noreply.github.com>2018-08-20 17:55:22 +0300
committerAndreas Rumpf <rumpf_a@web.de>2018-08-20 16:55:22 +0200
commitb75808c7d992ea47f8d6abc656b881b2aa0f86de (patch)
tree15db5f0070445def74e12bd957fe54cf5b347712
parentb28c7d434b16ebd9cc33ef1d6b267b49660153ba (diff)
downloadNim-b75808c7d992ea47f8d6abc656b881b2aa0f86de.tar.gz
Fixes ropes regressions due to the not-nil strings (#8687)
-rw-r--r--lib/pure/ropes.nim19
-rw-r--r--tests/stdlib/tropes.nim36
2 files changed, 46 insertions, 9 deletions
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index fb371cdce..559afd279 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -37,8 +37,6 @@ type
     length: int
     data: string # != nil if a leaf
 
-proc isConc(r: Rope): bool {.inline.} = return r.length > 0
-
 # Note that the left and right pointers are not needed for leafs.
 # Leaves have relatively high memory overhead (~30 bytes on a 32
 # bit machine) and we produce many of them. This is why we cache and
@@ -50,12 +48,12 @@ proc isConc(r: Rope): bool {.inline.} = return r.length > 0
 proc len*(a: Rope): int {.rtl, extern: "nro$1".} =
   ## the rope's length
   if a == nil: result = 0
-  else: result = abs a.length
+  else: result = a.length
 
 proc newRope(): Rope = new(result)
 proc newRope(data: string): Rope =
   new(result)
-  result.length = -len(data)
+  result.length = len(data)
   result.data = data
 
 var
@@ -170,7 +168,9 @@ proc `&`*(a, b: Rope): Rope {.rtl, extern: "nroConcRopeRope".} =
     result = a
   else:
     result = newRope()
-    result.length = abs(a.length) + abs(b.length)
+    result.length = a.length + b.length
+    result.left = a
+    result.right = b
 
 proc `&`*(a: Rope, b: string): Rope {.rtl, extern: "nroConcRopeStr".} =
   ## the concatenation operator for ropes.
@@ -199,11 +199,11 @@ proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} =
   var j = i
   if x == nil: return
   while true:
-    if not isConc(x):
-      if x.data.len <% j: return x.data[j]
+    if x != nil and x.data.len > 0:
+      if j < x.data.len: return x.data[j]
       return '\0'
     else:
-      if x.left.len >% j:
+      if x.left.length > j:
         x = x.left
       else:
         x = x.right
@@ -215,7 +215,8 @@ iterator leaves*(r: Rope): string =
     var stack = @[r]
     while stack.len > 0:
       var it = stack.pop
-      while isConc(it):
+      while it.left != nil:
+        assert(it.right != nil)
         stack.add(it.right)
         it = it.left
         assert(it != nil)
diff --git a/tests/stdlib/tropes.nim b/tests/stdlib/tropes.nim
new file mode 100644
index 000000000..59239a600
--- /dev/null
+++ b/tests/stdlib/tropes.nim
@@ -0,0 +1,36 @@
+discard """
+  file: "tropes.nim"
+  output: '''0
+3
+
+123
+3
+6
+123
+123456
+2
+3'''
+"""
+import ropes
+
+var
+  r1 = rope("")
+  r2 = rope("123")
+
+echo r1.len
+echo r2.len
+
+echo r1
+echo r2
+
+r1.add("123")
+r2.add("456")
+
+echo r1.len
+echo r2.len
+
+echo r1
+echo r2
+
+echo r1[1]
+echo r2[2]
\ No newline at end of file