summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-10-28 17:57:58 +0200
committerAraq <rumpf_a@web.de>2011-10-28 17:57:58 +0200
commit22115a2c6a43709aba02054b77ce2e641f280be1 (patch)
treebe232f47fb7beacb4761e9ebb882265734268401
parenta0a8934a4f089f8a438da280a4c80051ba3607b5 (diff)
downloadNim-22115a2c6a43709aba02054b77ce2e641f280be1.tar.gz
splicing tested and documented
-rwxr-xr-xlib/system.nim43
-rwxr-xr-xtests/accept/run/tslices.nim16
-rw-r--r--tests/rodfiles/bmethods.nim3
-rw-r--r--tests/rodfiles/bmethods2.nim3
-rw-r--r--tests/rodfiles/deada.nim3
-rw-r--r--tests/rodfiles/deada2.nim3
-rwxr-xr-xtodo.txt31
7 files changed, 72 insertions, 30 deletions
diff --git a/lib/system.nim b/lib/system.nim
index 885449537..8657efe2a 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1930,36 +1930,37 @@ proc `[]`*(s: string, x: TSlice[int]): string {.inline.} =
   ## slice operation for strings. Negative indexes are supported.
   result = s.substr(x.a-|s, x.b-|s)
 
-template spliceImpl(x, start, endp, spliced: expr): stmt =
-  var 
-    count = endp - start + 1
-    shift = spliced.len - count
-    newLen = x.len + shift
-    totalShifted = x.len - (start + count)
-    firstShifted = newLen - totalShifted
-
+template spliceImpl(s, a, L, b: expr): stmt =
+  # make room for additional elements or cut:
+  var slen = s.len
+  var shift = b.len - L
+  var newLen = slen + shift
   if shift > 0:
-    setLen(x, newLen)
-
-  for i in countdown(newLen - 1, firstShifted):
-    shallowCopy(x[i], x[i-shift])
-
-  for c in countup(0, spliced.len - 1):
-    x[start + c] = spliced[c]
-
-  if shift < 0:
-    setLen(x, newLen)
+    # enlarge:
+    setLen(s, newLen)
+    for i in countdown(newLen-1, a+shift+1): shallowCopy(s[i], s[i-shift])
+  else:
+    for i in countup(a+b.len, s.len-1+shift): shallowCopy(s[i], s[i-shift])
+    # cut down:
+    setLen(s, newLen)
+  # fill the hole:
+  for i in 0 .. <b.len: s[i+a] = b[i]  
 
 proc `[]=`*(s: var string, x: TSlice[int], b: string) = 
   ## slice assignment for strings. Negative indexes are supported. If
   ## ``b.len`` is not exactly the number of elements that are referred to
-  ## by `x`, a `splice`:idx: is performed. 
+  ## by `x`, a `splice`:idx: is performed:
+  ##
+  ## .. code-block:: nimrod
+  ##   var s = "abcdef"
+  ##   s[1 .. -2] = "xyz"
+  ##   assert s == "axyzf"
   var a = x.a-|s
   var L = x.b-|s - a + 1
   if L == b.len:
     for i in 0 .. <L: s[i+a] = b[i]
   else:
-    spliceImpl(s, x.a, x.b, b)
+    spliceImpl(s, a, L, b)
 
 proc `[]`*[Idx, T](a: array[Idx, T], x: TSlice[int]): seq[T] =
   ## slice operation for arrays. Negative indexes are **not** supported
@@ -2015,7 +2016,7 @@ proc `[]=`*[T](s: var seq[T], x: TSlice[int], b: openArray[T]) =
   if L == b.len:
     for i in 0 .. <L: s[i+a] = b[i]
   else:
-    spliceImpl(s, x.a, x.b, b)
+    spliceImpl(s, a, L, b)
 
 proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo".}
   ## get type information for `x`. Ordinary code should not use this, but
diff --git a/tests/accept/run/tslices.nim b/tests/accept/run/tslices.nim
index 1061b4245..0de1171e3 100755
--- a/tests/accept/run/tslices.nim
+++ b/tests/accept/run/tslices.nim
@@ -4,6 +4,8 @@ discard """
 456456
 456456
 Zugr5nd
+egerichtetd
+verichtetd
 '''
 """
 
@@ -41,3 +43,17 @@ echo()
 
 echo mystr
 
+mystr[4..4] = "u"
+
+# test full replacement
+mystr[.. -2] = "egerichtet"
+
+echo mystr
+
+mystr[0..2] = "ve"
+echo mystr
+
+var s = "abcdef"
+s[1 .. -2] = "xyz"
+assert s == "axyzf"
+
diff --git a/tests/rodfiles/bmethods.nim b/tests/rodfiles/bmethods.nim
index f665efa09..995942ad6 100644
--- a/tests/rodfiles/bmethods.nim
+++ b/tests/rodfiles/bmethods.nim
@@ -1,6 +1,5 @@
 discard """
-  output: '''
-derived class
+  output: '''derived class
 base class
 '''
 """
diff --git a/tests/rodfiles/bmethods2.nim b/tests/rodfiles/bmethods2.nim
index c4b9c37b6..ac24a2201 100644
--- a/tests/rodfiles/bmethods2.nim
+++ b/tests/rodfiles/bmethods2.nim
@@ -1,6 +1,5 @@
 discard """
-  output: '''
-derived class 2
+  output: '''derived class 2
 base class
 '''
 """
diff --git a/tests/rodfiles/deada.nim b/tests/rodfiles/deada.nim
index dca776640..3fa4192f8 100644
--- a/tests/rodfiles/deada.nim
+++ b/tests/rodfiles/deada.nim
@@ -1,6 +1,5 @@
 discard """
-  output: '''
-246
+  output: '''246
 '''
 """
 
diff --git a/tests/rodfiles/deada2.nim b/tests/rodfiles/deada2.nim
index ee8298371..2925b4d43 100644
--- a/tests/rodfiles/deada2.nim
+++ b/tests/rodfiles/deada2.nim
@@ -1,6 +1,5 @@
 discard """
-  output: '''
-246
+  output: '''246
 xyzabc
 '''
 """
diff --git a/todo.txt b/todo.txt
index 6455ca8a4..de27c6fa1 100755
--- a/todo.txt
+++ b/todo.txt
@@ -5,7 +5,6 @@ Version 0.8.14
 - 'let x = y'
 - fix actors.nim
 - make threadvar efficient again on linux after testing
-- document & test splicing; don't forget to test negative indexes
 - dead code elim for JS backend
 
 
@@ -17,6 +16,36 @@ incremental compilation
 - implement lib/pure/memfiles properly
 
 
+Destructors
+-----------
+
+A destructor is bound to a proc instead of a type. The proc is then called
+an *init proc*. A destructor is called at
+scope exit for the local variables (declared with ``var`` or ``let``)
+that are initialized with its corresponding init proc:
+
+.. code-block:: nimrod
+  proc autoOpen(filename: string): TFile {.destructor: close.} =
+    result = open(filename)
+    
+  var f = autoOpen("abc.txt")
+
+A template ``atScopeExit`` can easily be defined with this mechanism. However
+unfortunately the regex problem is not solved at all: 
+
+.. code-block:: nimrod
+  if x =~ re"abc":
+    ...
+
+We really need some form of escape analysis; ``var`` or ``let`` is not enough!
+Hm, but what if the procs declare that property: 
+  
+.. code-block:: nimrod
+  proc `=~` (s: string, pattern: TRegex{.noEscape.}): bool
+
+So it's bound to a type again?
+
+
 version 0.9.0
 =============