summary refs log tree commit diff stats
path: root/compiler/semmagic.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semmagic.nim')
-rw-r--r--compiler/semmagic.nim43
1 files changed, 43 insertions, 0 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 3c9784152..de7700be6 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -130,6 +130,18 @@ proc semLocals(c: PContext, n: PNode): PNode =
         result.add(a)
 
 proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
+
+proc isStrangeArray(t: PType): bool =
+  let t = t.skipTypes(abstractInst)
+  result = t.kind == tyArray and t.firstOrd != 0
+
+proc isNegative(n: PNode): bool =
+  let n = n.skipConv
+  if n.kind in {nkCharLit..nkUInt64Lit}:
+    result = n.intVal < 0
+  elif n.kind in nkCallKinds and n.sons[0].kind == nkSym:
+    result = n.sons[0].sym.magic in {mUnaryMinusI, mUnaryMinusI64}
+
 proc magicsAfterOverloadResolution(c: PContext, n: PNode,
                                    flags: TExprFlags): PNode =
   case n[0].sym.magic
@@ -153,4 +165,35 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
   of mProcCall:
     result = n
     result.typ = n[1].typ
+  of mDotDot:
+    result = n
+    # disallow negative indexing for now:
+    if not c.p.bracketExpr.isNil:
+      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:
+      localError(n.info, "no surrounding array access context for '^'")
+    elif c.p.bracketExpr.checkForSideEffects != seNoSideEffect:
+      localError(n.info, "invalid context for '^' as '$#' has side effects" %
+        renderTree(c.p.bracketExpr))
+    elif c.p.bracketExpr.typ.isStrangeArray:
+      localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
+        renderTree(c.p.bracketExpr))
+    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
+      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))
+      else:
+        result = newNodeIT(nkCall, n.info, getSysType(tyInt))
+        result.add newSymNode(createMagic("-", mSubI), n.info)
+        result.add lenExprB
+        result.add n.sons[1]
   else: result = n