slice support in system.nim; syntactic sugar for tables; cleanup of grammar/parser
This commit is contained in:
parent
05fee773ec
commit
4ba4999bb7
8 changed files with 234 additions and 97 deletions
|
|
@ -173,49 +173,30 @@ proc parseSymbol(p: var TParser): PNode =
|
||||||
of tkAccent:
|
of tkAccent:
|
||||||
result = newNodeP(nkAccQuoted, p)
|
result = newNodeP(nkAccQuoted, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
var id = ""
|
||||||
|
while true:
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkBracketLe:
|
of tkBracketLe:
|
||||||
var s = "["
|
id.add("[]")
|
||||||
getTok(p)
|
getTok(p)
|
||||||
while true:
|
|
||||||
if p.tok.tokType == tkComma:
|
|
||||||
add(s, ",")
|
|
||||||
getTok(p)
|
|
||||||
elif (p.tok.tokType == tkOpr) and (p.tok.ident.s == "$"):
|
|
||||||
add(s, "$..")
|
|
||||||
getTok(p)
|
|
||||||
eat(p, tkDotDot)
|
|
||||||
if (p.tok.tokType == tkOpr) and (p.tok.ident.s == "$"):
|
|
||||||
add(s, '$')
|
|
||||||
getTok(p)
|
|
||||||
elif p.tok.tokType == tkDotDot:
|
|
||||||
add(s, "..")
|
|
||||||
getTok(p)
|
|
||||||
if (p.tok.tokType == tkOpr) and (p.tok.ident.s == "$"):
|
|
||||||
add(s, '$')
|
|
||||||
getTok(p)
|
|
||||||
else: break
|
|
||||||
eat(p, tkBracketRi)
|
eat(p, tkBracketRi)
|
||||||
add(s, ']')
|
of tkEquals:
|
||||||
if p.tok.tokType == tkEquals:
|
id.add('=')
|
||||||
add(s, '=')
|
|
||||||
getTok(p)
|
getTok(p)
|
||||||
addSon(result, newIdentNodeP(getIdent(s), p))
|
|
||||||
of tkParLe:
|
of tkParLe:
|
||||||
addSon(result, newIdentNodeP(getIdent("()"), p))
|
id.add("()")
|
||||||
getTok(p)
|
getTok(p)
|
||||||
eat(p, tkParRi)
|
eat(p, tkParRi)
|
||||||
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot:
|
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot:
|
||||||
var id = p.tok.ident
|
id.add(p.tok.ident.s)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
if p.tok.tokType == tkEquals:
|
of tkIntLit..tkCharLit:
|
||||||
addSon(result, newIdentNodeP(getIdent(id.s & '='), p))
|
id.add(tokToStr(p.tok))
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
addSon(result, newIdentNodeP(id, p))
|
if id.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
||||||
else:
|
break
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
add(result, newIdentNodeP(getIdent(id), p))
|
||||||
result = ast.emptyNode
|
|
||||||
eat(p, tkAccent)
|
eat(p, tkAccent)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
||||||
|
|
@ -247,14 +228,7 @@ proc accExpr(p: var TParser): PNode =
|
||||||
eat(p, tkAccent)
|
eat(p, tkAccent)
|
||||||
|
|
||||||
proc indexExpr(p: var TParser): PNode =
|
proc indexExpr(p: var TParser): PNode =
|
||||||
# indexExpr ::= expr ['=' expr]
|
|
||||||
result = parseExpr(p)
|
result = parseExpr(p)
|
||||||
if p.tok.tokType == tkEquals:
|
|
||||||
var a = result
|
|
||||||
result = newNodeP(nkExprEqExpr, p)
|
|
||||||
addSon(result, a)
|
|
||||||
getTok(p)
|
|
||||||
addSon(result, parseExpr(p))
|
|
||||||
|
|
||||||
proc indexExprList(p: var TParser, first: PNode): PNode =
|
proc indexExprList(p: var TParser, first: PNode): PNode =
|
||||||
result = newNodeP(nkBracketExpr, p)
|
result = newNodeP(nkBracketExpr, p)
|
||||||
|
|
|
||||||
|
|
@ -709,41 +709,11 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
GlobalError(n.Info, errUndeclaredFieldX, i.s)
|
GlobalError(n.Info, errUndeclaredFieldX, i.s)
|
||||||
|
|
||||||
proc whichSliceOpr(n: PNode): string =
|
|
||||||
if n.sons[0].kind == nkEmpty:
|
|
||||||
if n.sons[1].kind == nkEmpty: result = "[..]"
|
|
||||||
else: result = "[..$]"
|
|
||||||
elif n.sons[1].kind == nkEmpty:
|
|
||||||
result = "[$..]"
|
|
||||||
else:
|
|
||||||
result = "[$..$]"
|
|
||||||
|
|
||||||
proc addSliceOpr(result: var string, n: PNode) =
|
|
||||||
if n[0].kind == nkEmpty:
|
|
||||||
if n[1].kind == nkEmpty: result.add("..")
|
|
||||||
else: result.add("..$")
|
|
||||||
elif n[1].kind == nkEmpty: result.add("$..")
|
|
||||||
else: result.add("$..$")
|
|
||||||
|
|
||||||
proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
|
proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
|
||||||
result = newNodeI(nkCall, n.info)
|
result = newNodeI(nkCall, n.info)
|
||||||
add(result, ast.emptyNode) # fill with the correct node later
|
result.add(newIdentNode(
|
||||||
add(result, n[0])
|
if inAsgn: getIdent"[]=" else: getIdent"[]", n.info))
|
||||||
var opr = "["
|
for i in 0 .. n.len-1: result.add(n[i])
|
||||||
for i in 1..n.len-1:
|
|
||||||
if i > 1: add(opr, ",")
|
|
||||||
if n[i].kind == nkRange:
|
|
||||||
# we have a slice argument
|
|
||||||
checkSonsLen(n[i], 2)
|
|
||||||
addSliceOpr(opr, n[i])
|
|
||||||
addSon(result, n[i][0])
|
|
||||||
addSon(result, n[i][1])
|
|
||||||
else:
|
|
||||||
add(result, n[i])
|
|
||||||
if inAsgn: add(opr, "]=")
|
|
||||||
else: add(opr, "]")
|
|
||||||
# now we know the operator
|
|
||||||
result.sons[0] = newIdentNode(getIdent(opr), n.info)
|
|
||||||
|
|
||||||
proc semDeref(c: PContext, n: PNode): PNode =
|
proc semDeref(c: PContext, n: PNode): PNode =
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
|
|
@ -773,10 +743,11 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
n.sons[i] = semExprWithType(c, n.sons[i], flags - {efAllowType})
|
n.sons[i] = semExprWithType(c, n.sons[i], flags - {efAllowType})
|
||||||
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||||
if arg != nil: n.sons[1] = arg
|
if arg != nil:
|
||||||
else: GlobalError(n.info, errIndexTypesDoNotMatch)
|
n.sons[1] = arg
|
||||||
result = n
|
result = n
|
||||||
result.typ = elemType(arr)
|
result.typ = elemType(arr)
|
||||||
|
#GlobalError(n.info, errIndexTypesDoNotMatch)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
n.sons[0] = makeDeref(n.sons[0])
|
n.sons[0] = makeDeref(n.sons[0])
|
||||||
|
|
@ -862,6 +833,21 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||||
m = fitNode(c, typ, n.sons[i])
|
m = fitNode(c, typ, n.sons[i])
|
||||||
addSon(result, m)
|
addSon(result, m)
|
||||||
|
|
||||||
|
proc semTableConstr(c: PContext, n: PNode): PNode =
|
||||||
|
# we simply transform ``{key: value, key2: value}`` to
|
||||||
|
# ``[(key, value), (key2, value2)]``
|
||||||
|
result = newNodeI(nkBracket, n.info)
|
||||||
|
for i in 0..n.len-1:
|
||||||
|
var x = n.sons[i]
|
||||||
|
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||||
|
var pair = newNodeI(nkPar, x.info)
|
||||||
|
pair.add(x[0])
|
||||||
|
pair.add(x[1])
|
||||||
|
result.add(pair)
|
||||||
|
else:
|
||||||
|
illFormedAst(x)
|
||||||
|
result = semExpr(c, result)
|
||||||
|
|
||||||
type
|
type
|
||||||
TParKind = enum
|
TParKind = enum
|
||||||
paNone, paSingle, paTupleFields, paTuplePositions
|
paNone, paSingle, paTupleFields, paTuplePositions
|
||||||
|
|
@ -967,7 +953,8 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
result = semTemplateExpr(c, result, s, semCheck)
|
result = semTemplateExpr(c, result, s, semCheck)
|
||||||
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
|
GlobalError(n.info, errInvalidExpressionX,
|
||||||
|
renderTree(a, {renderNoComments}))
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -1090,6 +1077,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
checkSonsLen(n, 3)
|
checkSonsLen(n, 3)
|
||||||
of nkCheckedFieldExpr:
|
of nkCheckedFieldExpr:
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
|
of nkTableConstr:
|
||||||
|
result = semTableConstr(c, n)
|
||||||
of nkSymChoice:
|
of nkSymChoice:
|
||||||
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,11 @@ plusExpr ::= mulExpr (OP7 optInd mulExpr)*
|
||||||
mulExpr ::= dollarExpr (OP8 optInd dollarExpr)*
|
mulExpr ::= dollarExpr (OP8 optInd dollarExpr)*
|
||||||
dollarExpr ::= primary (OP9 optInd primary)*
|
dollarExpr ::= primary (OP9 optInd primary)*
|
||||||
|
|
||||||
indexExpr ::= expr ['=' expr]
|
indexExpr ::= expr
|
||||||
|
|
||||||
castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
|
castExpr ::= 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
|
||||||
addrExpr ::= 'addr' '(' optInd expr optPar ')'
|
addrExpr ::= 'addr' '(' optInd expr optPar ')'
|
||||||
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')'
|
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')' | '[' ']'
|
||||||
| '[' (',' | ['$'] '..' ['$'])* ']'
|
|
||||||
| '=' | literal)+ '`'
|
| '=' | literal)+ '`'
|
||||||
| IDENT
|
| IDENT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1817,6 +1817,34 @@ required. ``Elif`` parts are also allowed (but unlikely to be good
|
||||||
style).
|
style).
|
||||||
|
|
||||||
|
|
||||||
|
Table constructor
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A `table constructor`:idx: is syntactic sugar for an array constructor:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
{"key1": "value1", "key2": "value2"}
|
||||||
|
|
||||||
|
# is the same as:
|
||||||
|
[("key1", "value1"), ("key2", "value2")]
|
||||||
|
|
||||||
|
|
||||||
|
The empty table can be written ``{:}`` (in contrast to the empty set
|
||||||
|
which is ``{}``) which is thus another way to write as the empty array
|
||||||
|
constructor ``[]``. This slightly unusal way of supporting tables
|
||||||
|
has lots of advantages:
|
||||||
|
|
||||||
|
* The order of the (key,value)-pairs is preserved, thus it is easy to
|
||||||
|
support ordered dicts with for example ``{key: val}.newOrderedTable``.
|
||||||
|
* A table literal can be put into a ``const`` section and the compiler
|
||||||
|
can easily put it into the executable's data section just like it can
|
||||||
|
for arrays and the generated data section requires a minimal amount
|
||||||
|
of memory.
|
||||||
|
* Every table implementation is treated equal syntactically.
|
||||||
|
* Apart from the minimal syntactic sugar the language core does not need to
|
||||||
|
know about tables.
|
||||||
|
|
||||||
|
|
||||||
Type conversions
|
Type conversions
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
Syntactically a `type conversion` is like a procedure call, but a
|
Syntactically a `type conversion` is like a procedure call, but a
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,16 @@ proc newStringTable*(keyValuePairs: openarray[string],
|
||||||
result[keyValuePairs[i]] = keyValuePairs[i + 1]
|
result[keyValuePairs[i]] = keyValuePairs[i + 1]
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
|
|
||||||
|
proc newStringTable*(keyValuePairs: openarray[tuple[key, val: string]],
|
||||||
|
mode: TStringTableMode = modeCaseSensitive): PStringTable {.
|
||||||
|
rtl, extern: "nst$1WithTableConstr".} =
|
||||||
|
## creates a new string table with given key value pairs.
|
||||||
|
## Example::
|
||||||
|
## var mytab = newStringTable({"key1": "val1", "key2": "val2"},
|
||||||
|
## modeCaseInsensitive)
|
||||||
|
result = newStringTable(mode)
|
||||||
|
for key, val in items(keyvaluePairs): result[key] = val
|
||||||
|
|
||||||
proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {.
|
proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {.
|
||||||
rtl, extern: "nstFormat".} =
|
rtl, extern: "nstFormat".} =
|
||||||
## The `%` operator for string tables.
|
## The `%` operator for string tables.
|
||||||
|
|
@ -198,3 +208,9 @@ proc `$`*(t: PStringTable): string {.rtl, extern: "nstDollar".} =
|
||||||
result.add(val)
|
result.add(val)
|
||||||
result.add("}")
|
result.add("}")
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
var x = {"k": "v", "11": "22", "565": "67"}.newStringTable
|
||||||
|
assert x["k"] == "v"
|
||||||
|
assert x["11"] == "22"
|
||||||
|
assert x["565"] == "67"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,8 @@ proc `..`*[T](a, b: T): TSlice[T] {.noSideEffect, inline.} =
|
||||||
|
|
||||||
proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
|
proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
|
||||||
## `slice`:idx: operator that constructs an interval ``[low(T), b]``
|
## `slice`:idx: operator that constructs an interval ``[low(T), b]``
|
||||||
result.a = low(b)
|
when int(low(b)) == low(int): result.a = 0
|
||||||
|
else: result.a = low(b)
|
||||||
result.b = b
|
result.b = b
|
||||||
|
|
||||||
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
|
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
|
||||||
|
|
@ -1006,7 +1007,7 @@ proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
|
||||||
|
|
||||||
proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
|
proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
|
||||||
## The stingify operator for an enumeration argument. This works for
|
## The stingify operator for an enumeration argument. This works for
|
||||||
## any enumeration type thanks to compiler magic. If a
|
## any enumeration type thanks to compiler magic. If
|
||||||
## a ``$`` operator for a concrete enumeration is provided, this is
|
## a ``$`` operator for a concrete enumeration is provided, this is
|
||||||
## used instead. (In other words: *Overwriting* is possible.)
|
## used instead. (In other words: *Overwriting* is possible.)
|
||||||
|
|
||||||
|
|
@ -1268,7 +1269,11 @@ proc `<`*[T: tuple](x, y: T): bool =
|
||||||
|
|
||||||
proc `$`*[T: tuple](x: T): string =
|
proc `$`*[T: tuple](x: T): string =
|
||||||
## generic ``$`` operator for tuples that is lifted from the components
|
## generic ``$`` operator for tuples that is lifted from the components
|
||||||
## of `x`.
|
## of `x`. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## $(23, 45) == "(23, 45)"
|
||||||
|
## $() == "()"
|
||||||
result = "("
|
result = "("
|
||||||
for name, value in fieldPairs(x):
|
for name, value in fieldPairs(x):
|
||||||
if result.len > 1: result.add(", ")
|
if result.len > 1: result.add(", ")
|
||||||
|
|
@ -1277,6 +1282,19 @@ proc `$`*[T: tuple](x: T): string =
|
||||||
result.add($value)
|
result.add($value)
|
||||||
result.add(")")
|
result.add(")")
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc `$`*[T](a: openArray[T]): string =
|
||||||
|
## generic ``$`` operator for open arrays that is lifted from the elements
|
||||||
|
## of `a`. Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## $[23, 45] == "[23, 45]"
|
||||||
|
result = "["
|
||||||
|
for x in items(a):
|
||||||
|
if result.len > 1: result.add(", ")
|
||||||
|
result.add($x)
|
||||||
|
result.add("]")
|
||||||
|
|
||||||
# ----------------- GC interface ---------------------------------------------
|
# ----------------- GC interface ---------------------------------------------
|
||||||
|
|
||||||
proc GC_disable*() {.rtl, inl.}
|
proc GC_disable*() {.rtl, inl.}
|
||||||
|
|
@ -1751,3 +1769,74 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} =
|
||||||
|
|
||||||
{.pop.} # checks
|
{.pop.} # checks
|
||||||
{.pop.} # hints
|
{.pop.} # hints
|
||||||
|
|
||||||
|
template `-|`(b, s: expr): expr =
|
||||||
|
(if b >= 0: b else: s.len + b)
|
||||||
|
|
||||||
|
proc `[]`*(s: string, x: TSlice[int]): string {.inline.} =
|
||||||
|
## slice operation for strings. Negative indexes are supported.
|
||||||
|
result = s.copy(x.a-|s, x.b-|s)
|
||||||
|
|
||||||
|
proc `[]=`*(s: var string, x: TSlice[int], b: string) =
|
||||||
|
## slice assignment for strings. Negative indexes are supported.
|
||||||
|
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:
|
||||||
|
raise newException(EOutOfRange, "differing lengths for slice assignment")
|
||||||
|
|
||||||
|
proc `[]`*[Idx, T](a: array[Idx, T], x: TSlice[int]): seq[T] =
|
||||||
|
## slice operation for arrays. Negative indexes are NOT supported because
|
||||||
|
## the array might have negative bounds.
|
||||||
|
var L = x.b - x.a + 1
|
||||||
|
newSeq(result, L)
|
||||||
|
for i in 0.. <L: result[i] = a[i + x.a]
|
||||||
|
|
||||||
|
proc `[]=`*[Idx, T](a: var array[Idx, T], x: TSlice[int], b: openArray[T]) =
|
||||||
|
## slice assignment for arrays. Negative indexes are NOT supported because
|
||||||
|
## the array might have negative bounds.
|
||||||
|
var L = x.b - x.a + 1
|
||||||
|
if L == b.len:
|
||||||
|
for i in 0 .. <L: a[i+x.a] = b[i]
|
||||||
|
else:
|
||||||
|
raise newException(EOutOfRange, "differing lengths for slice assignment")
|
||||||
|
|
||||||
|
proc `[]`*[Idx, T](a: array[Idx, T], x: TSlice[Idx]): seq[T] =
|
||||||
|
## slice operation for arrays. Negative indexes are NOT supported because
|
||||||
|
## the array might have negative bounds.
|
||||||
|
var L = ord(x.b) - ord(x.a) + 1
|
||||||
|
newSeq(result, L)
|
||||||
|
var j = x.a
|
||||||
|
for i in 0.. <L:
|
||||||
|
result[i] = a[j]
|
||||||
|
inc(j)
|
||||||
|
|
||||||
|
proc `[]=`*[Idx, T](a: var array[Idx, T], x: TSlice[Idx], b: openArray[T]) =
|
||||||
|
## slice assignment for arrays. Negative indexes are NOT supported because
|
||||||
|
## the array might have negative bounds.
|
||||||
|
var L = ord(x.b) - ord(x.a) + 1
|
||||||
|
if L == b.len:
|
||||||
|
var j = x.a
|
||||||
|
for i in 0 .. <L:
|
||||||
|
a[j] = b[i]
|
||||||
|
inc(j)
|
||||||
|
else:
|
||||||
|
raise newException(EOutOfRange, "differing lengths for slice assignment")
|
||||||
|
|
||||||
|
proc `[]`*[T](s: seq[T], x: TSlice[int]): seq[T] =
|
||||||
|
## slice operation for sequences. Negative indexes are supported.
|
||||||
|
var a = x.a-|s
|
||||||
|
var L = x.b-|s - a + 1
|
||||||
|
newSeq(result, L)
|
||||||
|
for i in 0.. <L: result[i] = s[i + a]
|
||||||
|
|
||||||
|
proc `[]=`*[T](s: var seq[T], x: TSlice[int], b: openArray[T]) =
|
||||||
|
## slice assignment for sequences. Negative indexes are supported.
|
||||||
|
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:
|
||||||
|
raise newException(EOutOfRange, "differing lengths for slice assignment")
|
||||||
|
|
||||||
|
|
|
||||||
43
tests/accept/run/tslices.nim
Normal file
43
tests/accept/run/tslices.nim
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
discard """
|
||||||
|
file: "tslices.nim"
|
||||||
|
output: '''456456
|
||||||
|
456456
|
||||||
|
456456
|
||||||
|
Zugr5nd
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Test the new slices.
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
var mystr = "Abgrund"
|
||||||
|
mystr[..1] = "Zu"
|
||||||
|
|
||||||
|
mystr[4..4] = "5"
|
||||||
|
|
||||||
|
type
|
||||||
|
TEnum = enum e1, e2, e3, e4, e5, e6
|
||||||
|
|
||||||
|
var myarr: array[TEnum, int] = [1, 2, 3, 4, 5, 6]
|
||||||
|
myarr[e1..e3] = myarr[e4..e6]
|
||||||
|
myarr[..e3] = myarr[e4..e6]
|
||||||
|
|
||||||
|
for x in items(myarr): stdout.write(x)
|
||||||
|
echo()
|
||||||
|
|
||||||
|
var myarr2: array[0..5, int] = [1, 2, 3, 4, 5, 6]
|
||||||
|
myarr2[0..2] = myarr2[3..5]
|
||||||
|
|
||||||
|
for x in items(myarr2): stdout.write(x)
|
||||||
|
echo()
|
||||||
|
|
||||||
|
|
||||||
|
var myseq = @[1, 2, 3, 4, 5, 6]
|
||||||
|
myseq[0..2] = myseq[-3.. -1]
|
||||||
|
|
||||||
|
for x in items(myseq): stdout.write(x)
|
||||||
|
echo()
|
||||||
|
|
||||||
|
echo mystr
|
||||||
|
|
||||||
5
todo.txt
5
todo.txt
|
|
@ -1,5 +1,5 @@
|
||||||
- clean up the tests!
|
- clean up the tests!
|
||||||
- fake-consts and semantic checking for table constructor
|
- fake-consts, implict ref/ptr->var conversion
|
||||||
|
|
||||||
|
|
||||||
High priority (version 0.9.0)
|
High priority (version 0.9.0)
|
||||||
|
|
@ -10,7 +10,7 @@ High priority (version 0.9.0)
|
||||||
- fix overloading resolution
|
- fix overloading resolution
|
||||||
- wrong co-/contravariance
|
- wrong co-/contravariance
|
||||||
- make ^ available as operator
|
- make ^ available as operator
|
||||||
|
- iterators should not always be destructive
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
----
|
----
|
||||||
|
|
@ -59,7 +59,6 @@ Low priority
|
||||||
- 'nimrod def': does not always work
|
- 'nimrod def': does not always work
|
||||||
- test branch coverage
|
- test branch coverage
|
||||||
- checked exceptions
|
- checked exceptions
|
||||||
- slicing
|
|
||||||
|
|
||||||
|
|
||||||
Library
|
Library
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue