diff options
-rwxr-xr-x | compiler/evals.nim | 111 | ||||
-rwxr-xr-x | compiler/msgs.nim | 2 | ||||
-rwxr-xr-x | todo.txt | 3 |
3 files changed, 53 insertions, 63 deletions
diff --git a/compiler/evals.nim b/compiler/evals.nim index 9f677b705..c92143a5b 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -70,6 +70,11 @@ proc popStackFrame*(c: PEvalContext) {.inline.} = proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode +proc raiseCannotEval(c: PEvalContext, n: PNode): PNode = + result = newNodeI(nkExceptBranch, n.info) + # creating a nkExceptBranch without sons + # means that it could not be evaluated + proc stackTraceAux(x: PStackFrame) = if x != nil: stackTraceAux(x.next) @@ -89,7 +94,7 @@ proc stackTraceAux(x: PStackFrame) = proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") = MsgWriteln("stack trace: (most recent call last)") stackTraceAux(c.tos) - Fatal(n.info, msg, arg) + LocalError(n.info, msg, arg) proc isSpecial(n: PNode): bool {.inline.} = result = (n.kind == nkExceptBranch) @@ -335,15 +340,17 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] if result.kind == nkExprColonExpr: result = result.sons[1] - else: stackTrace(c, n, errIndexOutOfBounds) - if not aliasNeeded(result, flags): result = copyTree(result) + if not aliasNeeded(result, flags): result = copyTree(result) + else: + stackTrace(c, n, errIndexOutOfBounds) of nkBracket, nkMetaNode: - if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] - else: stackTrace(c, n, errIndexOutOfBounds) - if not aliasNeeded(result, flags): result = copyTree(result) - of nkStrLit..nkTripleStrLit: - if efLValue in flags: - InternalError(n.info, "cannot evaluate write access to char") + if (idx >= 0) and (idx < sonsLen(x)): + result = x.sons[int(idx)] + if not aliasNeeded(result, flags): result = copyTree(result) + else: + stackTrace(c, n, errIndexOutOfBounds) + of nkStrLit..nkTripleStrLit: + if efLValue in flags: return raiseCannotEval(c, n) result = newNodeIT(nkCharLit, x.info, getSysType(tyChar)) if (idx >= 0) and (idx < len(x.strVal)): result.intVal = ord(x.strVal[int(idx) + 0]) @@ -359,7 +366,7 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = evalAux(c, n.sons[0], flags) if isSpecial(result): return var x = result - if x.kind != nkPar: InternalError(n.info, "evalFieldAccess") + if x.kind != nkPar: return raiseCannotEval(c, n) var field = n.sons[1].sym for i in countup(0, sonsLen(x) - 1): var it = x.sons[i] @@ -389,7 +396,7 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode = result = evalAux(c, n.sons[1], {}) if isSpecial(result): return - if result.kind != nkCharLit: InternalError(n.info, "no character") + if result.kind != nkCharLit: return raiseCannotEval(c, n) if (idx >= 0) and (idx < len(x.strVal)): x.strVal[int(idx)] = chr(int(result.intVal)) @@ -408,8 +415,10 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode = of nkCharLit..nkInt64Lit: x.intVal = result.intVal of nkFloatLit..nkFloat64Lit: x.floatVal = result.floatVal of nkStrLit..nkTripleStrLit: x.strVal = result.strVal + of nkIdent: x.ident = result.ident + of nkSym: x.sym = result.sym else: - if not (x.kind in {nkEmpty..nkNilLit}): + if x.kind notin {nkEmpty..nkNilLit}: discardSons(x) for i in countup(0, sonsLen(result) - 1): addSon(x, result.sons[i]) result = emptyNode @@ -421,22 +430,15 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode = var x = result result = evalAux(c, n.sons[1], {efLValue}) if isSpecial(result): return - if (x.kind != result.kind): + if x.kind != result.kind: stackTrace(c, n, errCannotInterpretNodeX, $n.kind) - else: + else: case x.kind - of nkCharLit..nkInt64Lit: - var tmpi = x.intVal - x.intVal = result.intVal - result.intVal = tmpi - of nkFloatLit..nkFloat64Lit: - var tmpf = x.floatVal - x.floatVal = result.floatVal - result.floatVal = tmpf - of nkStrLit..nkTripleStrLit: - var tmps = x.strVal - x.strVal = result.strVal - result.strVal = tmps + of nkCharLit..nkInt64Lit: swap(x.intVal, result.intVal) + of nkFloatLit..nkFloat64Lit: swap(x.floatVal, result.floatVal) + of nkStrLit..nkTripleStrLit: swap(x.strVal, result.strVal) + of nkIdent: swap(x.ident, result.ident) + of nkSym: swap(x.sym, result.sym) else: var tmpn = copyTree(x) discardSons(x) @@ -444,7 +446,7 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode = discardSons(result) for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i]) result = emptyNode - + proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = var s = n.sym case s.kind @@ -460,10 +462,9 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = c.tos.params[s.position + 1] of skConst: result = s.ast of skEnumField: result = newIntNodeT(s.position, n) - else: - stackTrace(c, n, errCannotInterpretNodeX, $s.kind) - result = emptyNode - if result == nil: stackTrace(c, n, errCannotInterpretNodeX, s.name.s) + else: result = nil + if result == nil or sfImportc in s.flags: + result = raiseCannotEval(c, n) proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = result = evalAux(c, n.sons[1], {efLValue}) @@ -474,7 +475,7 @@ proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = var b = result case a.kind of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b) - else: internalError(n.info, "evalIncDec") + else: return raiseCannotEval(c, n) result = emptyNode proc getStrValue(n: PNode): string = @@ -510,13 +511,8 @@ proc evalAnd(c: PEvalContext, n: PNode): PNode = if result.kind != nkIntLit: InternalError(n.info, "evalAnd") if result.intVal != 0: result = evalAux(c, n.sons[2], {}) -proc evalNoOpt(c: PEvalContext, n: PNode): PNode = - result = newNodeI(nkExceptBranch, n.info) - # creating a nkExceptBranch without sons - # means that it could not be evaluated - proc evalNew(c: PEvalContext, n: PNode): PNode = - if c.optEval: return evalNoOpt(c, n) + if c.optEval: return raiseCannotEval(c, n) # we ignore the finalizer for now and most likely forever :-) result = evalAux(c, n.sons[1], {efLValue}) if isSpecial(result): return @@ -539,7 +535,8 @@ proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = of nkRefTy: # XXX efLValue? result = result.sons[0] - else: InternalError(n.info, "evalDeref " & $result.kind) + else: + result = raiseCannotEval(c, n) proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = evalAux(c, n.sons[0], {efLValue}) @@ -737,7 +734,7 @@ proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode = var b = result case a.kind of nkStrLit..nkTripleStrLit: add(a.strVal, chr(int(getOrdValue(b)))) - else: InternalError(n.info, "evalAppendStrCh") + else: return raiseCannotEval(c, n) result = emptyNode proc evalConStrStr(c: PEvalContext, n: PNode): PNode = @@ -759,7 +756,7 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode = var b = result case a.kind of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrOrChar(b) - else: InternalError(n.info, "evalAppendStrStr") + else: return raiseCannotEval(c, n) result = emptyNode proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode = @@ -770,7 +767,7 @@ proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode = if isSpecial(result): return var b = result if a.kind == nkBracket: addSon(a, copyTree(b)) - else: InternalError(n.info, "evalAppendSeqElem") + else: return raiseCannotEval(c, n) result = emptyNode proc evalRepr(c: PEvalContext, n: PNode): PNode = @@ -820,28 +817,19 @@ proc evalTemplateAux*(templ, actual: PNode, sym: PSym): PNode = result.sons[i] = evalTemplateAux(templ.sons[i], actual, sym) proc evalTemplateArgs(n: PNode, s: PSym): PNode = - var - f, a: int - arg: PNode - - f = sonsLen(s.typ) - # if the template has zero arguments, it can be called without ``()`` # `n` is then a nkSym or something similar + var a: int case n.kind of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: a = sonsLen(n) else: a = 0 - + var f = sonsLen(s.typ) if a > f: GlobalError(n.info, errWrongNumberOfArguments) result = copyNode(n) for i in countup(1, f - 1): - if i < a: - arg = n.sons[i] - else: - arg = copyTree(s.typ.n.sons[i].sym.ast) - + var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast) addSon(result, arg) var evalTemplateCounter = 0 @@ -886,7 +874,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = case m of mNone: result = evalCall(c, n) of mOf: result = evalOf(c, n) - of mSizeOf: internalError(n.info, "sizeof() should have been evaluated") + of mSizeOf: result = raiseCannotEval(c, n) of mHigh: result = evalHigh(c, n) of mAssert: result = evalAssert(c, n) of mExit: result = evalExit(c, n) @@ -1070,7 +1058,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = internalError(n.info, "request to create a NimNode with invalid kind") result = newNodeI(TNodeKind(int(k)), if a.kind == nkNilLit: n.info else: a.info) - of mNCopyNimNode: + of mNCopyNimNode: result = evalAux(c, n.sons[1], {efLValue}) if isSpecial(result): return result = copyNode(result) @@ -1235,9 +1223,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result.typ = n.typ of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, nkLambda, nkContinueStmt, nkIdent: - stackTrace(c, n, errCannotInterpretNodeX, $n.kind) + result = raiseCannotEval(c, n) else: InternalError(n.info, "evalAux: " & $n.kind) - if result == nil: + if result == nil: InternalError(n.info, "evalAux: returned nil " & $n.kind) inc(gNestedEvals) @@ -1248,8 +1236,11 @@ proc eval*(c: PEvalContext, n: PNode): PNode = gWhileCounter = evalMaxIterations gNestedEvals = evalMaxRecDepth result = evalAux(c, n, {}) - if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1): - stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) + if result.kind == nkExceptBranch: + if sonsLen(result) >= 1: + stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) + else: + stackTrace(c, n, errCannotInterpretNodeX, renderTree(n)) proc evalConstExpr*(module: PSym, e: PNode): PNode = var p = newEvalContext(module, "", true) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 880ed8d2e..8106a6862 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -309,7 +309,7 @@ const errXExpectsObjectTypes: "\'$1\' expects object types", errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", errTooManyIterations: "interpretation requires too many iterations", - errCannotInterpretNodeX: "cannot interpret node kind \'$1\'", + errCannotInterpretNodeX: "cannot evaluate \'$1\'", errFieldXNotFound: "field \'$1\' cannot be found", errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'", errAssertionFailed: "assertion failed", diff --git a/todo.txt b/todo.txt index 50824ace1..2dd5a8c73 100755 --- a/todo.txt +++ b/todo.txt @@ -3,11 +3,11 @@ Version 0.8.14 - optimize unused constants away (affected by HLO) - fix thread tests -- error message for imported procs in compiletime mode version 0.9.0 ============= +- GC: marker procs for native Nimrod GC and Boehm GC; precise stack marking - dead code elim for JS backend; 'of' operator for JS backend - test the sort implementation again - 'let x = y' @@ -56,7 +56,6 @@ Bugs version 0.9.XX ============== -- GC: marker procs for native Nimrod GC and Boehm GC; precise stack marking - implicit ref/ptr->var conversion; the compiler may store an object implicitly on the heap for write barrier efficiency; better: proc specialization in the code gen |