diff --git a/compiler/vm.nim b/compiler/vm.nim index 161b025a65..93d2f9daed 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2332,9 +2332,17 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = localError(c.config, sym.info, "NimScript: attempt to call non-routine: " & sym.name.s) +proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode = + result = newNodeI(nkEmpty, n.info) + result.typ = newType(tyError, idgen, owner) + result.typ.flags.incl tfCheckedForDestructor + proc evalStmt*(c: PCtx, n: PNode) = let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genStmt(c, n) + if c.cannotEval: + c.cannotEval = false + return # execute new instructions; this redundant opcEof check saves us lots # of allocations in 'execute': if c.code[start].opcode != opcEof: @@ -2345,7 +2353,10 @@ proc evalExpr*(c: PCtx, n: PNode): PNode = # `nim --eval:"expr"` might've used it at some point for idetools; could # be revived for nimsuggest let n = transformExpr(c.graph, c.idgen, c.module, n) + c.cannotEval = false let start = genExpr(c, n) + if c.cannotEval: + return errorNode(c.idgen, c.module, n) assert c.code[start].opcode != opcEof result = execute(c, start) @@ -2398,7 +2409,10 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator; var c = PCtx g.vm let oldMode = c.mode c.mode = mode + c.cannotEval = false let start = genExpr(c, n, requiresValue = mode!=emStaticStmt) + if c.cannotEval: + return errorNode(idgen, prc, n) if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info) assert c.code[start].opcode != opcEof when debugEchoCode: c.echoCode start @@ -2469,11 +2483,6 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) = # to prevent endless recursion in macro instantiation const evalMacroLimit = 1000 -#proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode = -# result = newNodeI(nkEmpty, n.info) -# result.typ = newType(tyError, idgen, owner) -# result.typ.flags.incl tfCheckedForDestructor - proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstCounter: ref int; n, nOrig: PNode, sym: PSym): PNode = #if g.config.errorCounter > 0: return errorNode(idgen, module, n) @@ -2497,7 +2506,10 @@ proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstC c.comesFromHeuristic.line = 0'u16 c.callsite = nOrig c.templInstCounter = templInstCounter + c.cannotEval = false let start = genProc(c, sym) + if c.cannotEval: + return errorNode(idgen, module, n) var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil) let maxSlots = sym.offset diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index bdb0aeed15..42e58c63b8 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -270,6 +270,7 @@ type templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst vmstateDiff*: seq[(PSym, PNode)] # we remember the "diff" to global state here (feature for IC) procToCodePos*: Table[int, int] + cannotEval*: bool PStackFrame* = ref TStackFrame TStackFrame* {.acyclic.} = object diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 0c7a49984f..ddb877d93a 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1545,6 +1545,7 @@ template cannotEval(c: PCtx; n: PNode) = if c.config.cmd == cmdCheck: localError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree) + c.cannotEval = true return globalError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree)