proper error message when attempting to eval C'imported procs

This commit is contained in:
Araq
2011-11-20 17:17:47 +01:00
parent 1392049aea
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 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)

View File

@@ -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",

View File

@@ -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