splicing tested and documented
This commit is contained in:
parent
a0a8934a4f
commit
22115a2c6a
7 changed files with 72 additions and 30 deletions
|
|
@ -1930,36 +1930,37 @@ proc `[]`*(s: string, x: TSlice[int]): string {.inline.} =
|
||||||
## slice operation for strings. Negative indexes are supported.
|
## slice operation for strings. Negative indexes are supported.
|
||||||
result = s.substr(x.a-|s, x.b-|s)
|
result = s.substr(x.a-|s, x.b-|s)
|
||||||
|
|
||||||
template spliceImpl(x, start, endp, spliced: expr): stmt =
|
template spliceImpl(s, a, L, b: expr): stmt =
|
||||||
var
|
# make room for additional elements or cut:
|
||||||
count = endp - start + 1
|
var slen = s.len
|
||||||
shift = spliced.len - count
|
var shift = b.len - L
|
||||||
newLen = x.len + shift
|
var newLen = slen + shift
|
||||||
totalShifted = x.len - (start + count)
|
|
||||||
firstShifted = newLen - totalShifted
|
|
||||||
|
|
||||||
if shift > 0:
|
if shift > 0:
|
||||||
setLen(x, newLen)
|
# enlarge:
|
||||||
|
setLen(s, newLen)
|
||||||
for i in countdown(newLen - 1, firstShifted):
|
for i in countdown(newLen-1, a+shift+1): shallowCopy(s[i], s[i-shift])
|
||||||
shallowCopy(x[i], x[i-shift])
|
else:
|
||||||
|
for i in countup(a+b.len, s.len-1+shift): shallowCopy(s[i], s[i-shift])
|
||||||
for c in countup(0, spliced.len - 1):
|
# cut down:
|
||||||
x[start + c] = spliced[c]
|
setLen(s, newLen)
|
||||||
|
# fill the hole:
|
||||||
if shift < 0:
|
for i in 0 .. <b.len: s[i+a] = b[i]
|
||||||
setLen(x, newLen)
|
|
||||||
|
|
||||||
proc `[]=`*(s: var string, x: TSlice[int], b: string) =
|
proc `[]=`*(s: var string, x: TSlice[int], b: string) =
|
||||||
## slice assignment for strings. Negative indexes are supported. If
|
## slice assignment for strings. Negative indexes are supported. If
|
||||||
## ``b.len`` is not exactly the number of elements that are referred to
|
## ``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 a = x.a-|s
|
||||||
var L = x.b-|s - a + 1
|
var L = x.b-|s - a + 1
|
||||||
if L == b.len:
|
if L == b.len:
|
||||||
for i in 0 .. <L: s[i+a] = b[i]
|
for i in 0 .. <L: s[i+a] = b[i]
|
||||||
else:
|
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] =
|
proc `[]`*[Idx, T](a: array[Idx, T], x: TSlice[int]): seq[T] =
|
||||||
## slice operation for arrays. Negative indexes are **not** supported
|
## 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:
|
if L == b.len:
|
||||||
for i in 0 .. <L: s[i+a] = b[i]
|
for i in 0 .. <L: s[i+a] = b[i]
|
||||||
else:
|
else:
|
||||||
spliceImpl(s, x.a, x.b, b)
|
spliceImpl(s, a, L, b)
|
||||||
|
|
||||||
proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo".}
|
proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo".}
|
||||||
## get type information for `x`. Ordinary code should not use this, but
|
## get type information for `x`. Ordinary code should not use this, but
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ discard """
|
||||||
456456
|
456456
|
||||||
456456
|
456456
|
||||||
Zugr5nd
|
Zugr5nd
|
||||||
|
egerichtetd
|
||||||
|
verichtetd
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -41,3 +43,17 @@ echo()
|
||||||
|
|
||||||
echo mystr
|
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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''
|
output: '''derived class
|
||||||
derived class
|
|
||||||
base class
|
base class
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''
|
output: '''derived class 2
|
||||||
derived class 2
|
|
||||||
base class
|
base class
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''
|
output: '''246
|
||||||
246
|
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''
|
output: '''246
|
||||||
246
|
|
||||||
xyzabc
|
xyzabc
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
31
todo.txt
31
todo.txt
|
|
@ -5,7 +5,6 @@ Version 0.8.14
|
||||||
- 'let x = y'
|
- 'let x = y'
|
||||||
- fix actors.nim
|
- fix actors.nim
|
||||||
- make threadvar efficient again on linux after testing
|
- make threadvar efficient again on linux after testing
|
||||||
- document & test splicing; don't forget to test negative indexes
|
|
||||||
- dead code elim for JS backend
|
- dead code elim for JS backend
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -17,6 +16,36 @@ incremental compilation
|
||||||
- implement lib/pure/memfiles properly
|
- 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
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue