diff options
-rw-r--r-- | compiler/semgnrc.nim | 34 | ||||
-rw-r--r-- | compiler/semmagic.nim | 25 | ||||
-rw-r--r-- | lib/system.nim | 1 |
3 files changed, 45 insertions, 15 deletions
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index ed0244b0c..9c9281da0 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -30,6 +30,13 @@ type GenericCtx = object toMixin: IntSet cursorInBody: bool # only for nimsuggest + bracketExpr: PNode + +template withBracketExpr(x, body: untyped) = + let old = ctx.bracketExpr + ctx.bracketExpr = x + body + ctx.bracketExpr = old type TSemGenericFlag = enum @@ -227,6 +234,10 @@ proc semGenericStmt(c: PContext, n: PNode, discard of skProc, skMethod, skIterators, skConverter, skModule: result.sons[0] = symChoice(c, fn, s, scOption) + # do check of 's.magic==mRoof' here because it might be some + # other '^' but after overload resolution the proper one: + if ctx.bracketExpr != nil and n.len == 2 and s.name.s == "^": + result.add ctx.bracketExpr first = 1 of skGenericParam: result.sons[0] = newSymNodeTypeDesc(s, fn.info) @@ -251,12 +262,17 @@ proc semGenericStmt(c: PContext, n: PNode, let flags = if mixinContext: flags+{withinMixin} else: flags for i in countup(first, sonsLen(result) - 1): result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx) - of nkBracketExpr, nkCurlyExpr: + of nkCurlyExpr: result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"), - n.info) + result.add newIdentNode(getIdent("{}"), n.info) for i in 0 ..< n.len: result.add(n[i]) result = semGenericStmt(c, result, flags, ctx) + of nkBracketExpr: + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent("[]"), n.info) + for i in 0 ..< n.len: result.add(n[i]) + withBracketExpr n.sons[0]: + result = semGenericStmt(c, result, flags, ctx) of nkAsgn, nkFastAsgn: checkSonsLen(n, 2) let a = n.sons[0] @@ -264,13 +280,19 @@ proc semGenericStmt(c: PContext, n: PNode, let k = a.kind case k - of nkBracketExpr, nkCurlyExpr: + of nkCurlyExpr: result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="), - n.info) + result.add newIdentNode(getIdent("{}="), n.info) for i in 0 ..< a.len: result.add(a[i]) result.add(b) result = semGenericStmt(c, result, flags, ctx) + of nkBracketExpr: + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent("[]="), n.info) + for i in 0 ..< a.len: result.add(a[i]) + result.add(b) + withBracketExpr a.sons[0]: + result = semGenericStmt(c, result, flags, ctx) else: for i in countup(0, sonsLen(n) - 1): result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 65185f762..deef38ae3 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -32,6 +32,9 @@ type proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode +proc skipAddr(n: PNode): PNode {.inline.} = + (if n.kind == nkHiddenAddr: n.sons[0] else: n) + proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode = result = newNodeI(nkBracketExpr, n.info) for i in 1..<n.len: result.add(n[i]) @@ -45,7 +48,8 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode = proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode = # rewrite `[]=`(a, i, x) back to ``a[i] = x``. let b = newNodeI(nkBracketExpr, n.info) - for i in 1..n.len-2: b.add(n[i]) + b.add(n[1].skipAddr) + for i in 2..n.len-2: b.add(n[i]) result = newNodeI(nkAsgn, n.info, 2) result.sons[0] = b result.sons[1] = n.lastSon @@ -179,25 +183,28 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])): localError(n.info, "use '^' instead of '-'; negative indexing is obsolete") of mRoof: - # error correction: - result = n.sons[1] - if c.p.bracketExpr.isNil: + let bracketExpr = if n.len == 3: n.sons[2] else: c.p.bracketExpr + if bracketExpr.isNil: localError(n.info, "no surrounding array access context for '^'") - elif c.p.bracketExpr.checkForSideEffects != seNoSideEffect: + result = n.sons[1] + elif bracketExpr.checkForSideEffects != seNoSideEffect: localError(n.info, "invalid context for '^' as '$#' has side effects" % - renderTree(c.p.bracketExpr)) - elif c.p.bracketExpr.typ.isStrangeArray: + renderTree(bracketExpr)) + result = n.sons[1] + elif bracketExpr.typ.isStrangeArray: localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" % - renderTree(c.p.bracketExpr)) + renderTree(bracketExpr)) + result = n.sons[1] else: # ^x is rewritten to: len(a)-x let lenExpr = newNodeI(nkCall, n.info) lenExpr.add newIdentNode(getIdent"len", n.info) - lenExpr.add c.p.bracketExpr + lenExpr.add bracketExpr let lenExprB = semExprWithType(c, lenExpr) if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ): localError(n.info, "'$#' has to be of an ordinal type for '^'" % renderTree(lenExpr)) + result = n.sons[1] else: result = newNodeIT(nkCall, n.info, getSysType(tyInt)) result.add newSymNode(createMagic("-", mSubI), n.info) diff --git a/lib/system.nim b/lib/system.nim index 27c23e0bc..8f529b8c0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3465,6 +3465,7 @@ proc procCall*(x: expr) {.magic: "ProcCall", compileTime.} = ## procCall someMethod(a, b) discard +proc `^`*[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".} proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} = ## 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`` |