proper error message when attempting to eval C'imported procs

This commit is contained in:
Araq 2011-11-20 17:17:47 +01:00
commit 04e5c6718e
3 changed files with 53 additions and 63 deletions

View file

@ -70,6 +70,11 @@ proc popStackFrame*(c: PEvalContext) {.inline.} =
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): 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) = proc stackTraceAux(x: PStackFrame) =
if x != nil: if x != nil:
stackTraceAux(x.next) stackTraceAux(x.next)
@ -89,7 +94,7 @@ proc stackTraceAux(x: PStackFrame) =
proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") = proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") =
MsgWriteln("stack trace: (most recent call last)") MsgWriteln("stack trace: (most recent call last)")
stackTraceAux(c.tos) stackTraceAux(c.tos)
Fatal(n.info, msg, arg) LocalError(n.info, msg, arg)
proc isSpecial(n: PNode): bool {.inline.} = proc isSpecial(n: PNode): bool {.inline.} =
result = (n.kind == nkExceptBranch) result = (n.kind == nkExceptBranch)
@ -335,15 +340,17 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
if (idx >= 0) and (idx < sonsLen(x)): if (idx >= 0) and (idx < sonsLen(x)):
result = x.sons[int(idx)] result = x.sons[int(idx)]
if result.kind == nkExprColonExpr: result = result.sons[1] 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: of nkBracket, nkMetaNode:
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] if (idx >= 0) and (idx < sonsLen(x)):
else: stackTrace(c, n, errIndexOutOfBounds) result = x.sons[int(idx)]
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
of nkStrLit..nkTripleStrLit: else:
if efLValue in flags: stackTrace(c, n, errIndexOutOfBounds)
InternalError(n.info, "cannot evaluate write access to char") of nkStrLit..nkTripleStrLit:
if efLValue in flags: return raiseCannotEval(c, n)
result = newNodeIT(nkCharLit, x.info, getSysType(tyChar)) result = newNodeIT(nkCharLit, x.info, getSysType(tyChar))
if (idx >= 0) and (idx < len(x.strVal)): if (idx >= 0) and (idx < len(x.strVal)):
result.intVal = ord(x.strVal[int(idx) + 0]) 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) result = evalAux(c, n.sons[0], flags)
if isSpecial(result): return if isSpecial(result): return
var x = result 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 var field = n.sons[1].sym
for i in countup(0, sonsLen(x) - 1): for i in countup(0, sonsLen(x) - 1):
var it = x.sons[i] var it = x.sons[i]
@ -389,7 +396,7 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return 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)): if (idx >= 0) and (idx < len(x.strVal)):
x.strVal[int(idx)] = chr(int(result.intVal)) 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 nkCharLit..nkInt64Lit: x.intVal = result.intVal
of nkFloatLit..nkFloat64Lit: x.floatVal = result.floatVal of nkFloatLit..nkFloat64Lit: x.floatVal = result.floatVal
of nkStrLit..nkTripleStrLit: x.strVal = result.strVal of nkStrLit..nkTripleStrLit: x.strVal = result.strVal
of nkIdent: x.ident = result.ident
of nkSym: x.sym = result.sym
else: else:
if not (x.kind in {nkEmpty..nkNilLit}): if x.kind notin {nkEmpty..nkNilLit}:
discardSons(x) discardSons(x)
for i in countup(0, sonsLen(result) - 1): addSon(x, result.sons[i]) for i in countup(0, sonsLen(result) - 1): addSon(x, result.sons[i])
result = emptyNode result = emptyNode
@ -421,22 +430,15 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode =
var x = result var x = result
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
if (x.kind != result.kind): if x.kind != result.kind:
stackTrace(c, n, errCannotInterpretNodeX, $n.kind) stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
else: else:
case x.kind case x.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkInt64Lit: swap(x.intVal, result.intVal)
var tmpi = x.intVal of nkFloatLit..nkFloat64Lit: swap(x.floatVal, result.floatVal)
x.intVal = result.intVal of nkStrLit..nkTripleStrLit: swap(x.strVal, result.strVal)
result.intVal = tmpi of nkIdent: swap(x.ident, result.ident)
of nkFloatLit..nkFloat64Lit: of nkSym: swap(x.sym, result.sym)
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
else: else:
var tmpn = copyTree(x) var tmpn = copyTree(x)
discardSons(x) discardSons(x)
@ -444,7 +446,7 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode =
discardSons(result) discardSons(result)
for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i]) for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i])
result = emptyNode result = emptyNode
proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
var s = n.sym var s = n.sym
case s.kind case s.kind
@ -460,10 +462,9 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = c.tos.params[s.position + 1] result = c.tos.params[s.position + 1]
of skConst: result = s.ast of skConst: result = s.ast
of skEnumField: result = newIntNodeT(s.position, n) of skEnumField: result = newIntNodeT(s.position, n)
else: else: result = nil
stackTrace(c, n, errCannotInterpretNodeX, $s.kind) if result == nil or sfImportc in s.flags:
result = emptyNode result = raiseCannotEval(c, n)
if result == nil: stackTrace(c, n, errCannotInterpretNodeX, s.name.s)
proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode =
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
@ -474,7 +475,7 @@ proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode =
var b = result var b = result
case a.kind case a.kind
of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b) of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b)
else: internalError(n.info, "evalIncDec") else: return raiseCannotEval(c, n)
result = emptyNode result = emptyNode
proc getStrValue(n: PNode): string = 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.kind != nkIntLit: InternalError(n.info, "evalAnd")
if result.intVal != 0: result = evalAux(c, n.sons[2], {}) 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 = 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 :-) # we ignore the finalizer for now and most likely forever :-)
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
@ -539,7 +535,8 @@ proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
of nkRefTy: of nkRefTy:
# XXX efLValue? # XXX efLValue?
result = result.sons[0] 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 = proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0], {efLValue}) result = evalAux(c, n.sons[0], {efLValue})
@ -737,7 +734,7 @@ proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode =
var b = result var b = result
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: add(a.strVal, chr(int(getOrdValue(b)))) of nkStrLit..nkTripleStrLit: add(a.strVal, chr(int(getOrdValue(b))))
else: InternalError(n.info, "evalAppendStrCh") else: return raiseCannotEval(c, n)
result = emptyNode result = emptyNode
proc evalConStrStr(c: PEvalContext, n: PNode): PNode = proc evalConStrStr(c: PEvalContext, n: PNode): PNode =
@ -759,7 +756,7 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
var b = result var b = result
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrOrChar(b) of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrOrChar(b)
else: InternalError(n.info, "evalAppendStrStr") else: return raiseCannotEval(c, n)
result = emptyNode result = emptyNode
proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode = proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode =
@ -770,7 +767,7 @@ proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode =
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
if a.kind == nkBracket: addSon(a, copyTree(b)) if a.kind == nkBracket: addSon(a, copyTree(b))
else: InternalError(n.info, "evalAppendSeqElem") else: return raiseCannotEval(c, n)
result = emptyNode result = emptyNode
proc evalRepr(c: PEvalContext, n: PNode): PNode = 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) result.sons[i] = evalTemplateAux(templ.sons[i], actual, sym)
proc evalTemplateArgs(n: PNode, s: PSym): PNode = 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 ``()`` # if the template has zero arguments, it can be called without ``()``
# `n` is then a nkSym or something similar # `n` is then a nkSym or something similar
var a: int
case n.kind case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
a = sonsLen(n) a = sonsLen(n)
else: a = 0 else: a = 0
var f = sonsLen(s.typ)
if a > f: GlobalError(n.info, errWrongNumberOfArguments) if a > f: GlobalError(n.info, errWrongNumberOfArguments)
result = copyNode(n) result = copyNode(n)
for i in countup(1, f - 1): for i in countup(1, f - 1):
if i < a: var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast)
arg = n.sons[i]
else:
arg = copyTree(s.typ.n.sons[i].sym.ast)
addSon(result, arg) addSon(result, arg)
var evalTemplateCounter = 0 var evalTemplateCounter = 0
@ -886,7 +874,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
case m case m
of mNone: result = evalCall(c, n) of mNone: result = evalCall(c, n)
of mOf: result = evalOf(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 mHigh: result = evalHigh(c, n)
of mAssert: result = evalAssert(c, n) of mAssert: result = evalAssert(c, n)
of mExit: result = evalExit(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") internalError(n.info, "request to create a NimNode with invalid kind")
result = newNodeI(TNodeKind(int(k)), result = newNodeI(TNodeKind(int(k)),
if a.kind == nkNilLit: n.info else: a.info) if a.kind == nkNilLit: n.info else: a.info)
of mNCopyNimNode: of mNCopyNimNode:
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
result = copyNode(result) result = copyNode(result)
@ -1235,9 +1223,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result.typ = n.typ result.typ = n.typ
of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr,
nkLambda, nkContinueStmt, nkIdent: nkLambda, nkContinueStmt, nkIdent:
stackTrace(c, n, errCannotInterpretNodeX, $n.kind) result = raiseCannotEval(c, n)
else: InternalError(n.info, "evalAux: " & $n.kind) else: InternalError(n.info, "evalAux: " & $n.kind)
if result == nil: if result == nil:
InternalError(n.info, "evalAux: returned nil " & $n.kind) InternalError(n.info, "evalAux: returned nil " & $n.kind)
inc(gNestedEvals) inc(gNestedEvals)
@ -1248,8 +1236,11 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
gWhileCounter = evalMaxIterations gWhileCounter = evalMaxIterations
gNestedEvals = evalMaxRecDepth gNestedEvals = evalMaxRecDepth
result = evalAux(c, n, {}) result = evalAux(c, n, {})
if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1): if result.kind == nkExceptBranch:
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) 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 = proc evalConstExpr*(module: PSym, e: PNode): PNode =
var p = newEvalContext(module, "", true) var p = newEvalContext(module, "", true)

View file

@ -309,7 +309,7 @@ const
errXExpectsObjectTypes: "\'$1\' expects object types", errXExpectsObjectTypes: "\'$1\' expects object types",
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
errTooManyIterations: "interpretation requires too many iterations", errTooManyIterations: "interpretation requires too many iterations",
errCannotInterpretNodeX: "cannot interpret node kind \'$1\'", errCannotInterpretNodeX: "cannot evaluate \'$1\'",
errFieldXNotFound: "field \'$1\' cannot be found", errFieldXNotFound: "field \'$1\' cannot be found",
errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'", errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
errAssertionFailed: "assertion failed", errAssertionFailed: "assertion failed",

View file

@ -3,11 +3,11 @@ Version 0.8.14
- optimize unused constants away (affected by HLO) - optimize unused constants away (affected by HLO)
- fix thread tests - fix thread tests
- error message for imported procs in compiletime mode
version 0.9.0 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 - dead code elim for JS backend; 'of' operator for JS backend
- test the sort implementation again - test the sort implementation again
- 'let x = y' - 'let x = y'
@ -56,7 +56,6 @@ Bugs
version 0.9.XX 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 - implicit ref/ptr->var conversion; the compiler may store an object
implicitly on the heap for write barrier efficiency; better: implicitly on the heap for write barrier efficiency; better:
proc specialization in the code gen proc specialization in the code gen