From 0be71677d99511c210d7ff62e642dcb32956ed5d Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 20 Oct 2017 17:23:36 +0200 Subject: macros.nim: added missing pairs iterator --- lib/core/macros.nim | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/core') diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 8c70d2b47..22c479a4a 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -986,6 +986,11 @@ iterator items*(n: NimNode): NimNode {.inline.} = for i in 0 ..< n.len: yield n[i] +iterator pairs*(n: NimNode): (int, NimNode) {.inline.} = + ## Iterates over the children of the NimNode ``n`` and its indices. + for i in 0 ..< n.len: + yield (i, n[i]) + iterator children*(n: NimNode): NimNode {.inline.} = ## Iterates over the children of the NimNode ``n``. for i in 0 ..< n.len: -- cgit 1.4.1-2-gfad0 From 6a3288a60e78c9b17f2640fff20ab94969914974 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 29 Oct 2017 08:55:30 +0100 Subject: more replacements for the deprecated '<' --- lib/core/macros.nim | 6 +++--- lib/deprecated/pure/actors.nim | 6 +++--- lib/pure/collections/critbits.nim | 2 +- lib/pure/collections/tableimpl.nim | 2 +- lib/pure/concurrency/threadpool.nim | 4 ++-- lib/pure/future.nim | 6 +++--- lib/pure/json.nim | 16 ++++++++-------- lib/pure/marshal.nim | 2 +- lib/pure/selectors.nim | 4 ++-- lib/pure/strutils.nim | 6 +++--- lib/pure/uri.nim | 2 +- lib/system/debugger.nim | 2 +- lib/system/gc.nim | 6 +++--- lib/system/gc2.nim | 6 +++--- lib/system/gc_ms.nim | 4 ++-- lib/system/repr.nim | 2 +- lib/system/reprjs.nim | 6 +++--- lib/system/sysstr.nim | 2 +- lib/wrappers/openssl.nim | 2 +- 19 files changed, 43 insertions(+), 43 deletions(-) (limited to 'lib/core') diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 22c479a4a..d3f541153 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -839,7 +839,7 @@ proc newNilLit*(): NimNode {.compileTime.} = ## New nil literal shortcut result = newNimNode(nnkNilLit) -proc last*(node: NimNode): NimNode {.compileTime.} = node[`*(p, b: untyped): untyped = if c[0].kind == nnkIdent and c[0].ident == !"->": var procTy = createProcType(c[1], c[2]) params[0] = procTy[0][0] - for i in 1 .. ) got (" & $c[0].ident & ").") @@ -96,7 +96,7 @@ macro `=>`*(p, b: untyped): untyped = if p[0].kind == nnkIdent and p[0].ident == !"->": var procTy = createProcType(p[1], p[2]) params[0] = procTy[0][0] - for i in 1 .. ) got (" & $p[0].ident & ").") diff --git a/lib/pure/json.nim b/lib/pure/json.nim index fd7a3af03..3d86cc9d7 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -823,13 +823,13 @@ proc toJson(x: NimNode): NimNode {.compiletime.} = of nnkBracket: # array if x.len == 0: return newCall(bindSym"newJArray") result = newNimNode(nnkBracket) - for i in 0 .. s.len: return -1 - + if sub.len == 1: return find(s, sub[0], start, last) - + var a {.noinit.}: SkipTable initSkipTable(a, sub) result = find(a, s, sub, start, last) diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 4b2e4e052..c702b054c 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -250,7 +250,7 @@ proc combine*(base: Uri, reference: Uri): Uri = proc combine*(uris: varargs[Uri]): Uri = ## Combines multiple URIs together. result = uris[0] - for i in 1 .. 0 : add(result, ", ") # advance pointer and point to element at index @@ -192,7 +192,7 @@ proc reprRecordAux(result: var string, o: pointer, typ: PNimType, cl: var ReprCl reprAux(result, val, typ.node.typ, cl) else: # if the object has more than one field, sons is not nil and contains the fields. - for i in 0 .. Date: Sun, 29 Oct 2017 19:46:17 +0100 Subject: work in progress: new implementation for 'a[^1]' --- changelog.md | 6 +++ compiler/ast.nim | 13 ++----- compiler/cgendata.nim | 2 +- compiler/parser.nim | 2 +- compiler/semexprs.nim | 2 +- compiler/semobjconstr.nim | 15 ++++--- compiler/semstmts.nim | 2 +- compiler/semtypes.nim | 4 +- lib/core/macros.nim | 23 +++++++---- lib/pure/asyncmacro.nim | 14 +++---- lib/pure/random.nim | 2 +- lib/system.nim | 99 +++++++++++++++++++++++------------------------ todo.txt | 1 - 13 files changed, 96 insertions(+), 89 deletions(-) (limited to 'lib/core') diff --git a/changelog.md b/changelog.md index 6dea3ee63..5740f8589 100644 --- a/changelog.md +++ b/changelog.md @@ -22,3 +22,9 @@ for more information. - The **unary** ``<`` is now deprecated, for ``.. <`` use ``..<`` for other usages use the ``pred`` proc. +- We changed how array accesses "from backwards" like ``a[^1]`` or ``a[0..^1]`` are + implemented. These are now implemented purely in ``system.nim`` without compiler + support. ``system.Slice`` now takes 2 generic parameters so that it can + take ``BackwardsIndex`` indices. ``BackwardsIndex`` is produced by ``system.^``. + This means if you overload ``[]`` or ``[]=`` you need to ensure they also work + with ``system.BackwardsIndex`` (if applicable for the accessors). diff --git a/compiler/ast.nim b/compiler/ast.nim index 43aa3e484..e6d967dde 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1017,16 +1017,11 @@ proc add*(father, son: PNode) = type Indexable = PNode | PType -template `[]`*(n: Indexable, i: int): Indexable = - n.sons[i] +template `[]`*(n: Indexable, i: int): Indexable = n.sons[i] +template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x -template `-|`*(b, s: untyped): untyped = - (if b >= 0: b else: s.len + b) - -# son access operators with support for negative indices -template `{}`*(n: Indexable, i: int): untyped = n[i -| n] -template `{}=`*(n: Indexable, i: int, s: Indexable) = - n.sons[i -| n] = s +template `[]`*(n: Indexable, i: BackwardsIndex): Indexable = n[n.len - i.int] +template `[]=`*(n: Indexable, i: BackwardsIndex; x: Indexable) = n[n.len - i.int] = x when defined(useNodeIds): const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879 diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index be087095f..19ab2fe50 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -154,7 +154,7 @@ proc includeHeader*(this: BModule; header: string) = proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} = # section in the current block - result = p.blocks[^1].sections[s] + result = p.blocks[p.blocks.len-1].sections[s] proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} = # top level proc sections diff --git a/compiler/parser.nim b/compiler/parser.nim index e0885c388..113922189 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1905,7 +1905,7 @@ proc parseVariable(p: var TParser): PNode = #| variable = (varTuple / identColonEquals) colonBody? indAndComment if p.tok.tokType == tkParLe: result = parseVarTuple(p) else: result = parseIdentColonEquals(p, {withPragma, withDot}) - result{-1} = postExprBlocks(p, result{-1}) + result[^1] = postExprBlocks(p, result[^1]) indAndComment(p, result) proc parseBind(p: var TParser, k: TNodeKind): PNode = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 3cba0abd8..195625489 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1665,7 +1665,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode = # We transform the do block into a template with a param for # each interpolation. We'll pass this template to getAst. var - quotedBlock = n{-1} + quotedBlock = n[^1] op = if n.len == 3: expectString(c, n[1]) else: "``" quotes = newSeq[PNode](1) # the quotes will be added to a nkCall statement diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index c73b042fe..56d160aa4 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -78,13 +78,13 @@ proc caseBranchMatchesExpr(branch, matched: PNode): bool = proc pickCaseBranch(caseExpr, matched: PNode): PNode = # XXX: Perhaps this proc already exists somewhere - let endsWithElse = caseExpr{-1}.kind == nkElse + let endsWithElse = caseExpr[^1].kind == nkElse for i in 1 .. caseExpr.len - 1 - int(endsWithElse): if caseExpr[i].caseBranchMatchesExpr(matched): return caseExpr[i] if endsWithElse: - return caseExpr{-1} + return caseExpr[^1] iterator directFieldsInRecList(recList: PNode): PNode = # XXX: We can remove this case by making all nkOfBranch nodes @@ -136,17 +136,20 @@ proc semConstructFields(c: PContext, recNode: PNode, of nkRecCase: template fieldsPresentInBranch(branchIdx: int): string = - fieldsPresentInInitExpr(recNode[branchIdx]{-1}, initExpr) + let branch = recNode[branchIdx] + let fields = branch[branch.len - 1] + fieldsPresentInInitExpr(fields, initExpr) template checkMissingFields(branchNode: PNode) = - checkForMissingFields(branchNode{-1}, initExpr) + let fields = branchNode[branchNode.len - 1] + checkForMissingFields(fields, initExpr) let discriminator = recNode.sons[0]; internalAssert discriminator.kind == nkSym var selectedBranch = -1 for i in 1 ..< recNode.len: - let innerRecords = recNode[i]{-1} + let innerRecords = recNode[i][^1] let status = semConstructFields(c, innerRecords, initExpr, flags) if status notin {initNone, initUnknown}: mergeInitStatus(result, status) @@ -250,7 +253,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = var t = semTypeNode(c, n.sons[0], nil) result = newNodeIT(nkObjConstr, n.info, t) for child in n: result.add child - + t = skipTypes(t, {tyGenericInst, tyAlias}) if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst, tyAlias}) if t.kind != tyObject: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 55d84c6fc..540ef4c07 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -823,7 +823,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = a.sons[0] = newSymNode(s) proc checkCovariantParamsUsages(genericType: PType) = - var body = genericType{-1} + var body = genericType[^1] proc traverseSubTypes(t: PType): bool = template error(msg) = localError(genericType.sym.info, msg) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index cebbbad47..18ea87341 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1618,8 +1618,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = var a = n.sons[i] if a.kind != nkIdentDefs: illFormedAst(n) let L = a.len - var def = a{-1} - let constraint = a{-2} + var def = a[^1] + let constraint = a[^2] var typ: PType if constraint.kind != nkEmpty: diff --git a/lib/core/macros.nim b/lib/core/macros.nim index d3f541153..fc5b5bfb7 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -129,13 +129,6 @@ const nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit} -proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.} - ## get `n`'s `i`'th child. - -proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild", - noSideEffect.} - ## set `n`'s `i`'th child to `child`. - proc `!`*(s: string): NimIdent {.magic: "StrToIdent", noSideEffect.} ## constructs an identifier from the string `s` @@ -162,6 +155,20 @@ proc sameType*(a, b: NimNode): bool {.magic: "SameNodeType", noSideEffect.} = proc len*(n: NimNode): int {.magic: "NLen", noSideEffect.} ## returns the number of children of `n`. +proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.} + ## get `n`'s `i`'th child. + +proc `[]`*(n: NimNode, i: BackwardsIndex): NimNode = n[n.len - i.int] + ## get `n`'s `i`'th child. + +proc `[]=`*(n: NimNode, i: int, child: NimNode) {.magic: "NSetChild", + noSideEffect.} + ## set `n`'s `i`'th child to `child`. + +proc `[]=`*(n: NimNode, i: BackwardsIndex, child: NimNode) = + ## set `n`'s `i`'th child to `child`. + n[n.len - i.int] = child + proc add*(father, child: NimNode): NimNode {.magic: "NAdd", discardable, noSideEffect, locks: 0.} ## Adds the `child` to the `father` node. Returns the @@ -1104,7 +1111,7 @@ proc eqIdent*(node: NimNode; s: string): bool {.compileTime.} = else: result = false -proc hasArgOfName* (params: NimNode; name: string): bool {.compiletime.}= +proc hasArgOfName*(params: NimNode; name: string): bool {.compiletime.}= ## Search nnkFormalParams for an argument. assert params.kind == nnkFormalParams for i in 1 ..< params.len: diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index 6e7d7993f..981190211 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -61,14 +61,14 @@ proc generateExceptionCheck(futSym, else: var exceptionChecks: seq[tuple[cond, body: NimNode]] = @[] let errorNode = newDotExpr(futSym, newIdentNode("error")) - for i in 1 .. FormalParams (3) -> IdentDefs, the parameter (i) -> # parameter type (1). result[0][3][i][1] = splitParamType(result[0][3][i][1], async=false) @@ -521,7 +521,7 @@ proc splitProc(prc: NimNode): (NimNode, NimNode) = result[1] = prc.copyNimTree() if result[1][3][0].kind == nnkBracketExpr: result[1][3][0][1] = splitParamType(result[1][3][0][1], async=true) - for i in 1 .. FormalParams (3) -> IdentDefs, the parameter (i) -> # parameter type (1). result[1][3][i][1] = splitParamType(result[1][3][i][1], async=true) diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 27fbfad45..2c406faa1 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -93,7 +93,7 @@ proc random*(max: float): float {.benign.} = let u = (0x3FFu64 shl 52u64) or (x shr 12u64) result = (cast[float](u) - 1.0) * max -proc random*[T](x: Slice[T]): T = +proc random*[T](x: Slice[T, T]): T = ## For a slice `a .. b` returns a value in the range `a .. b-1`. result = T(random(x.b - x.a)) + x.a diff --git a/lib/system.nim b/lib/system.nim index 3b7a93eca..3ea2d8ef8 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -308,13 +308,14 @@ when defined(nimArrIdx): shallowCopy(x, y) type - Slice*[T] = object ## builtin slice type - a*, b*: T ## the bounds + Slice*[T, U] = object ## builtin slice type + a*: T ## the lower bound (inclusive) + b*: U ## the upper bound (inclusive) when defined(nimalias): {.deprecated: [TSlice: Slice].} -proc `..`*[T](a, b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".} = +proc `..`*[T, U](a: T, b: U): Slice[T, U] {.noSideEffect, inline, magic: "DotDot".} = ## `slice`:idx: operator that constructs an interval ``[a, b]``, both `a` ## and `b` are inclusive. Slices can also be used in the set constructor ## and in ordinal case statements, but then they are special-cased by the @@ -322,7 +323,7 @@ proc `..`*[T](a, b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".} = result.a = a result.b = b -proc `..`*[T](b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".} = +proc `..`*[T](b: T): Slice[T, T] {.noSideEffect, inline, magic: "DotDot".} = ## `slice`:idx: operator that constructs an interval ``[default(T), b]`` result.b = b @@ -1168,7 +1169,7 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.} ## is achieved by reversing the parameters for ``contains``; ``in`` then ## passes its arguments in reverse order. -proc contains*[T](s: Slice[T], value: T): bool {.noSideEffect, inline.} = +proc contains*[T](s: Slice[T, T], value: T): bool {.noSideEffect, inline.} = ## Checks if `value` is within the range of `s`; returns true iff ## `value >= s.a and value <= s.b` ## @@ -2087,7 +2088,7 @@ proc clamp*[T](x, a, b: T): T = if x > b: return b return x -proc len*[T: Ordinal](x: Slice[T]): int {.noSideEffect, inline.} = +proc len*[T: Ordinal](x: Slice[T, T]): int {.noSideEffect, inline.} = ## length of ordinal slice, when x.b < x.a returns zero length ## ## .. code-block:: Nim @@ -2155,7 +2156,7 @@ iterator items*(E: typedesc[enum]): E = for v in low(E)..high(E): yield v -iterator items*[T](s: Slice[T]): T = +iterator items*[T](s: Slice[T, T]): T = ## iterates over the slice `s`, yielding each value between `s.a` and `s.b` ## (inclusively). for x in s.a..s.b: @@ -3414,14 +3415,13 @@ proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## integer division that results in a float. result = toFloat(x) / toFloat(y) -proc `^`*[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".} -proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} = +type + BackwardsIndex* = distinct int ## type that is constructed by ``^`` for + ## reversed array accesses. + +template `^`*(x: int): BackwardsIndex = BackwardsIndex(x) ## builtin `roof`:idx: operator that can be used for convenient array access. - ## ``a[^x]`` is rewritten to ``a[a.len-x]``. However currently the ``a`` - ## expression must not have side effects for this to compile. Note that since - ## this is a builtin, it automatically works for all kinds of - ## overloaded ``[]`` or ``[]=`` accessors. - discard + ## ``a[^x]`` is a shortcut for ``a[a.len-x]``. template `..^`*(a, b: untyped): untyped = ## a shortcut for '.. ^' to avoid the common gotcha that a space between @@ -3453,17 +3453,20 @@ template spliceImpl(s, a, L, b: untyped): untyped = # fill the hole: for i in 0 ..< b.len: s[a+i] = b[i] +template `^^`(s, i: untyped): untyped = + (when i is BackwardsIndex: s.len - int(i) else: int(i)) + when hasAlloc or defined(nimscript): - proc `[]`*(s: string, x: Slice[int]): string {.inline.} = + proc `[]`*[T, U](s: string, x: Slice[T, U]): string {.inline.} = ## slice operation for strings. ## returns the inclusive range [s[x.a], s[x.b]]: ## ## .. code-block:: nim ## var s = "abcdef" ## assert s[1..3] == "bcd" - result = s.substr(x.a, x.b) + result = s.substr(s ^^ x.a, s ^^ x.b) - proc `[]=`*(s: var string, x: Slice[int], b: string) = + proc `[]=`*[T, U](s: var string, x: Slice[T, U], b: string) = ## slice assignment for strings. If ## ``b.len`` is not exactly the number of elements that are referred to ## by `x`, a `splice`:idx: is performed: @@ -3472,75 +3475,69 @@ when hasAlloc or defined(nimscript): ## var s = "abcdef" ## s[1 .. ^2] = "xyz" ## assert s == "axyzf" - var a = x.a - var L = x.b - a + 1 + var a = s ^^ x.a + var L = (s ^^ x.b) - a + 1 if L == b.len: for i in 0..`_. diff --git a/todo.txt b/todo.txt index 7c2a9088d..c9f64bd8b 100644 --- a/todo.txt +++ b/todo.txt @@ -3,7 +3,6 @@ version 1.0 battle plan - make FlowVar compatible to Futures - remove 'mod x' type rule -- implement x[^1] differently, no compiler magic - fix "high priority" bugs - try to fix as many compiler crashes as reasonable -- cgit 1.4.1-2-gfad0