diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 638cb5c1ef..7d9c6909a7 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -161,3 +161,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimUseStrictDefs") defineSymbol("nimHasNolineTooLong") + defineSymbol("nimHasQuirkyBoots") diff --git a/compiler/msgs.nim b/compiler/msgs.nim index f69e7733e0..b171b9b92e 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -443,7 +443,8 @@ proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string, elif eh == doAbort and conf.cmd != cmdIdeTools: quit(conf, msg) elif eh == doRaise: - raiseRecoverableError(s) + #raiseRecoverableError(s) + quit(conf, msg) proc `==`*(a, b: TLineInfo): bool = result = a.line == b.line and a.fileIndex == b.fileIndex diff --git a/compiler/nim.cfg b/compiler/nim.cfg index 023374f036..a6f5ab7755 100644 --- a/compiler/nim.cfg +++ b/compiler/nim.cfg @@ -51,4 +51,6 @@ define:useStdoutAsStdmsg #warningAsError[ProveInit]:on @end -#--exceptions:quirky +@if nimHasQuirkyBoots: + exceptions:quirky +@end diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 5fb74406be..3c709a1d77 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -996,9 +996,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, incl(sym.flags, sfSideEffect) of wNoreturn: noVal(c, it) - # Disable the 'noreturn' annotation when in the "Quirky Exceptions" mode! - if c.config.exc != excQuirky: - incl(sym.flags, sfNoReturn) + incl(sym.flags, sfNoReturn) if sym.typ[0] != nil: localError(c.config, sym.ast[paramsPos][0].info, ".noreturn with return type not allowed") diff --git a/compiler/semcall.nim b/compiler/semcall.nim index a4114497fb..17706e486a 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -321,7 +321,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = # only in case of an error). if c.config.m.errorOutputs == {}: # fail fast: - globalError(c.config, n.info, "type mismatch") + localError(c.config, n.info, "type mismatch") return # see getMsgDiagnostic: if nfExplicitCall notin n.flags and {nfDotField, nfDotSetter} * n.flags != {}: @@ -483,7 +483,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode, #writeMatches(alt) if c.config.m.errorOutputs == {}: # quick error message for performance of 'compiles' built-in: - globalError(c.config, n.info, errGenerated, "ambiguous call") + localError(c.config, n.info, errGenerated, "ambiguous call") elif c.config.errorCounter == 0: # don't cascade errors var args = "(" diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d62e256105..7d059c0dc4 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -47,7 +47,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode template rejectEmptyNode(n: PNode) = # No matter what a nkEmpty node is not what we want here - if n.kind == nkEmpty: illFormedAst(n, c.config) + if n.kind == nkEmpty: illFormedAstLocal(n, c.config) proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = rejectEmptyNode(n) @@ -1827,7 +1827,7 @@ proc goodLineInfo(arg: PNode): TLineInfo = proc makeTupleAssignments(c: PContext; n: PNode): PNode = ## expand tuple unpacking assignment into series of assignments - ## + ## ## mirrored with semstmts.makeVarTupleSection let lhs = n[0] let value = semExprWithType(c, n[1], {efTypeAllowed}) diff --git a/compiler/vm.nim b/compiler/vm.nim index bbd08beaa9..ad198e5461 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2274,11 +2274,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = inc pc proc execute(c: PCtx, start: int): PNode = + if c.couldNotEval: + c.couldNotEval = false + return nil var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil) newSeq(tos.slots, c.prc.regInfo.len) result = rawExecute(c, start, tos).regToNode proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = + if c.couldNotEval: + c.couldNotEval = false + return nil c.loopIterations = c.config.maxLoopIterationsVM if sym.kind in routineKinds: if sym.typ.len-1 != args.len: @@ -2309,6 +2315,10 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = proc evalStmt*(c: PCtx, n: PNode) = let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genStmt(c, n) + if c.couldNotEval: + c.couldNotEval = false + return + # execute new instructions; this redundant opcEof check saves us lots # of allocations in 'execute': if c.code[start].opcode != opcEof: @@ -2318,6 +2328,9 @@ proc evalExpr*(c: PCtx, n: PNode): PNode = # deadcode # `nim --eval:"expr"` might've used it at some point for idetools; could # be revived for nimsuggest + if c.couldNotEval: + c.couldNotEval = false + return nil let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genExpr(c, n) assert c.code[start].opcode != opcEof @@ -2373,6 +2386,10 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator; let oldMode = c.mode c.mode = mode let start = genExpr(c, n, requiresValue = mode!=emStaticStmt) + if c.couldNotEval: + c.couldNotEval = false + return nil + if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info) assert c.code[start].opcode != opcEof when debugEchoCode: c.echoCode start diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index bdb0aeed15..e7ea76e1ba 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -257,6 +257,7 @@ type mode*: TEvalMode features*: TSandboxFlags traceActive*: bool + couldNotEval*: bool loopIterations*: int comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces callbacks*: seq[VmCallback] diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 2e54812a05..84eb3d6261 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1535,7 +1535,8 @@ proc setSlot(c: PCtx; v: PSym) = v.position = getFreeRegister(c, if v.kind == skLet: slotFixedLet else: slotFixedVar, start = 1) proc cannotEval(c: PCtx; n: PNode) {.noinline.} = - globalError(c.config, n.info, "cannot evaluate at compile time: " & + c.couldNotEval = true + localError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree) proc isOwnedBy(a, b: PSym): bool = @@ -1747,7 +1748,10 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = s.kind in {skParam, skResult}): if dest < 0: dest = s.position + ord(s.kind == skParam) - internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + if dest < c.prc.regInfo.len: + internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp) + else: + cannotEval(c, n) else: # we need to generate an assignment: let requiresCopy = c.prc.regInfo[dest].kind >= slotSomeTemp and @@ -1781,6 +1785,7 @@ proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; c.freeTemp(b) proc genObjAccessAux(c: PCtx; n: PNode; a, b: int, dest: var TDest; flags: TGenFlags) = + if c.couldNotEval: return if dest < 0: dest = c.getTemp(n.typ) if {gfNodeAddr} * flags != {}: c.gABC(n, opcLdObjAddr, dest, a, b) @@ -1796,8 +1801,6 @@ proc genObjAccessAux(c: PCtx; n: PNode; a, b: int, dest: var TDest; flags: TGenF proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = genObjAccessAux(c, n, c.genx(n[0], flags), genField(c, n[1]), dest, flags) - - proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = internalAssert c.config, n.kind == nkCheckedFieldExpr # nkDotExpr to access the requested field @@ -1815,6 +1818,7 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags # Load the object in `dest` c.gen(accessExpr[0], dest, flags) + if c.couldNotEval: return # Load the discriminant var discVal = c.getTemp(disc.typ) c.gABC(n, opcLdObj, discVal, dest, genField(c, disc)) @@ -1841,6 +1845,7 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = var objR: TDest = -1 genCheckedObjAccessAux(c, n, objR, flags) + if c.couldNotEval: return let accessExpr = n[0] # Field symbol @@ -2119,6 +2124,7 @@ proc procIsCallback(c: PCtx; s: PSym): bool = proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = when defined(nimCompilerStacktraceHints): setFrameMsg c.config$n.info & " " & $n.kind & " " & $flags + #if c.couldNotEval: return case n.kind of nkSym: let s = n.sym @@ -2289,7 +2295,8 @@ proc genStmt*(c: PCtx; n: PNode): int = c.gen(n, d) c.gABC(n, opcEof) if d >= 0: - globalError(c.config, n.info, "VM problem: dest register is set") + c.couldNotEval = true + localError(c.config, n.info, "VM problem: dest register is set") proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int = c.removeLastEof @@ -2298,7 +2305,8 @@ proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int = c.gen(n, d) if d < 0: if requiresValue: - globalError(c.config, n.info, "VM problem: dest register is not set") + c.couldNotEval = true + localError(c.config, n.info, "VM problem: dest register is not set") d = 0 c.gABC(n, opcEof, d)