diff options
Diffstat (limited to 'compiler/semmagic.nim')
-rw-r--r-- | compiler/semmagic.nim | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index d5d6bbbd3..478e2cf37 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -10,10 +10,24 @@ # This include file implements the semantic checking for magics. # included from sem.nim +proc semAddr(c: PContext; n: PNode): PNode = + result = newNodeI(nkAddr, n.info) + let x = semExprWithType(c, n) + if isAssignable(c, x) notin {arLValue, arLocalLValue}: + localError(n.info, errExprHasNoAddress) + result.add x + result.typ = makePtrType(c, x.typ) + +proc semTypeOf(c: PContext; n: PNode): PNode = + result = newNodeI(nkTypeOfExpr, n.info) + let typExpr = semExprWithType(c, n, {efInTypeof}) + result.add typExpr + result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter})) + proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode = var r = isPartOf(n[1], n[2]) result = newIntNodeT(ord(r), n) - + proc expectIntLit(c: PContext, n: PNode): int = let x = c.semConstExpr(c, n) case x.kind @@ -31,7 +45,7 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode = line.intVal = toLinenumber(info) result.add(filename) result.add(line) - + proc evalTypeTrait(trait: PNode, operand: PType, context: PSym): PNode = let typ = operand.skipTypes({tyTypeDesc}) case trait.sym.name.s.normalize @@ -40,7 +54,7 @@ proc evalTypeTrait(trait: PNode, operand: PType, context: PSym): PNode = result.typ = newType(tyString, context) result.info = trait.info of "arity": - result = newIntNode(nkIntLit, typ.n.len-1) + result = newIntNode(nkIntLit, typ.len - ord(typ.kind==tyProc)) result.typ = newType(tyInt, context) result.info = trait.info else: @@ -66,18 +80,18 @@ proc semOrd(c: PContext, n: PNode): PNode = proc semBindSym(c: PContext, n: PNode): PNode = result = copyNode(n) result.add(n.sons[0]) - + let sl = semConstExpr(c, n.sons[1]) - if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: + if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: localError(n.sons[1].info, errStringLiteralExpected) return errorNode(c, n) - + let isMixin = semConstExpr(c, n.sons[2]) if isMixin.kind != nkIntLit or isMixin.intVal < 0 or isMixin.intVal > high(TSymChoiceRule).int: localError(n.sons[2].info, errConstExprExpected) return errorNode(c, n) - + let id = newIdentNode(getIdent(sl.strVal), n.info) let s = qualifiedLookUp(c, id) if s != nil: @@ -110,15 +124,33 @@ proc semLocals(c: PContext, n: PNode): PNode = addSon(tupleType.n, newSymNode(field)) addSonSkipIntLit(tupleType, field.typ) - + var a = newSymNode(it, result.info) if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a) result.add(a) proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode -proc magicsAfterOverloadResolution(c: PContext, n: 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 + of mAddr: + checkSonsLen(n, 2) + result = semAddr(c, n.sons[1]) + of mTypeOf: + checkSonsLen(n, 2) + result = semTypeOf(c, n.sons[1]) of mIsPartOf: result = semIsPartOf(c, n, flags) of mTypeTrait: result = semTypeTraits(c, n) of mAstToStr: @@ -133,4 +165,42 @@ 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] + of mPlugin: + let plugin = getPlugin(n[0].sym) + if plugin.isNil: + localError(n.info, "cannot find plugin " & n[0].sym.name.s) + result = n + else: + result = plugin(c, n) else: result = n |