diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lexer.nim | 19 | ||||
-rw-r--r-- | compiler/msgs.nim | 10 | ||||
-rw-r--r-- | compiler/parser.nim | 9 | ||||
-rw-r--r-- | compiler/vm.nim | 30 | ||||
-rw-r--r-- | compiler/vmdef.nim | 5 | ||||
-rw-r--r-- | compiler/vmgen.nim | 9 | ||||
-rw-r--r-- | compiler/vmops.nim | 5 |
7 files changed, 66 insertions, 21 deletions
diff --git a/compiler/lexer.nim b/compiler/lexer.nim index cbc87972d..dbeec8acf 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -116,7 +116,8 @@ type literal*: string # the parsed (string) literal; and # documentation comments are here too line*, col*: int - + + TErrorHandler* = proc (info: TLineInfo; msg: TMsgKind; arg: string) TLexer* = object of TBaseLexer fileIdx*: int32 indentAhead*: int # if > 0 an indendation has already been read @@ -124,7 +125,7 @@ type # needs so much look-ahead currLineIndent*: int strongSpaces*: bool - + errorHandler*: TErrorHandler var gLinesCompiled*: int # all lines that have been compiled @@ -222,12 +223,18 @@ proc getColumn(L: TLexer): int = proc getLineInfo(L: TLexer): TLineInfo = result = newLineInfo(L.fileIdx, L.lineNumber, getColNumber(L, L.bufpos)) -proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = - msgs.message(getLineInfo(L), msg, arg) +proc dispMessage(L: TLexer; info: TLineInfo; msg: TMsgKind; arg: string) = + if L.errorHandler.isNil: + msgs.message(info, msg, arg) + else: + L.errorHandler(info, msg, arg) + +proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = + L.dispMessage(getLineInfo(L), msg, arg) -proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = +proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart) - msgs.message(info, msg, arg) + L.dispMessage(info, msg, arg) proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: set[char]) = var pos = L.bufpos # use registers for pos, buf diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 944446624..7f4f81dd0 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -450,7 +450,7 @@ type projPath*: string # This is relative to the project's root shortName*: string # short name of the module quotedName*: PRope # cached quoted short name for codegen - # purpoes + # purposes lines*: seq[PRope] # the source code of the module # used for better error messages and @@ -789,6 +789,14 @@ proc writeSurroundingSrc(info: TLineInfo) = msgWriteln(indent & info.sourceLine.ropeToStr) msgWriteln(indent & repeatChar(info.col, ' ') & '^') +proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = + let frmt = case msg + of warnMin..warnMax: PosWarningFormat + of hintMin..hintMax: PosHintFormat + else: PosErrorFormat + result = frmt % [toMsgFilename(info), coordToStr(info.line), + coordToStr(info.col), getMessageStr(msg, arg)] + proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, eh: TErrorHandling) = var frmt: string diff --git a/compiler/parser.nim b/compiler/parser.nim index 20c037c00..e4de75a07 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -41,8 +41,7 @@ type proc parseAll*(p: var TParser): PNode proc closeParser*(p: var TParser) proc parseTopLevelStmt*(p: var TParser): PNode -proc parseString*(s: string, filename: string = "", line: int = 0): PNode - + # helpers for the other parsers proc isOperator*(tok: TToken): bool proc getTok*(p: var TParser) @@ -96,7 +95,7 @@ proc parMessage(p: TParser, msg: TMsgKind, arg = "") = proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) = ## Produce and emit a parser message to output about the token `tok` - lexMessage(p.lex, msg, prettyTok(tok)) + parMessage(p, msg, prettyTok(tok)) template withInd(p: expr, body: stmt) {.immediate.} = let oldInd = p.currInd @@ -1995,7 +1994,8 @@ proc parseTopLevelStmt(p: var TParser): PNode = if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok) break -proc parseString(s: string, filename: string = "", line: int = 0): PNode = +proc parseString*(s: string; filename: string = ""; line: int = 0; + errorHandler: TErrorHandler = nil): PNode = ## Parses a string into an AST, returning the top node. ## `filename` and `line`, although optional, provide info so that the ## compiler can generate correct error messages referring to the original @@ -2007,6 +2007,7 @@ proc parseString(s: string, filename: string = "", line: int = 0): PNode = # XXX for now the builtin 'parseStmt/Expr' functions do not know about strong # spaces... openParser(parser, filename, stream, false) + parser.lex.errorHandler = errorHandler result = parser.parseAll closeParser(parser) diff --git a/compiler/vm.nim b/compiler/vm.nim index e5b357a11..a15807b24 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -814,7 +814,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = if prc.offset < -1: # it's a callback: c.callbacks[-prc.offset-2].value( - VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs))) + VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs), + currentException: c.currentExceptionB)) elif sfImportc in prc.flags: if allowFFI notin c.features: globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI") @@ -1146,16 +1147,31 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcParseExprToAst: decodeB(rkNode) # c.debug[pc].line.int - countLines(regs[rb].strVal) ? + var error: string let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath, - c.debug[pc].line.int) - if sonsLen(ast) != 1: - globalError(c.debug[pc], errExprExpected, "multiple statements") - regs[ra].node = ast.sons[0] + c.debug[pc].line.int, + proc (info: TLineInfo; msg: TMsgKind; arg: string) = + if error.isNil: error = formatMsg(info, msg, arg)) + if not error.isNil: + c.errorFlag = error + elif sonsLen(ast) != 1: + c.errorFlag = formatMsg(c.debug[pc], errExprExpected, "multiple statements") + else: + regs[ra].node = ast.sons[0] of opcParseStmtToAst: decodeB(rkNode) + var error: string let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath, - c.debug[pc].line.int) - regs[ra].node = ast + c.debug[pc].line.int, + proc (info: TLineInfo; msg: TMsgKind; arg: string) = + if error.isNil: error = formatMsg(info, msg, arg)) + if not error.isNil: + c.errorFlag = error + else: + regs[ra].node = ast + of opcQueryErrorFlag: + createStr regs[ra] + regs[ra].node.strVal = c.errorFlag of opcCallSite: ensureKind(rkNode) if c.callsite != nil: regs[ra].node = c.callsite diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index d7cdafb69..c06606318 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -92,6 +92,7 @@ type opcGorge, opcParseExprToAst, opcParseStmtToAst, + opcQueryErrorFlag, opcNError, opcNWarning, opcNHint, @@ -174,6 +175,7 @@ type VmArgs* = object ra*, rb*, rc*: Natural slots*: pointer + currentException*: PNode VmCallback* = proc (args: VmArgs) {.closure.} PCtx* = ref TCtx @@ -195,6 +197,7 @@ type loopIterations*: int comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces callbacks*: seq[tuple[key: string, value: VmCallback]] + errorFlag*: string TPosition* = distinct int @@ -204,7 +207,7 @@ proc newCtx*(module: PSym): PCtx = PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations, - comesFromHeuristic: unknownLineInfo(), callbacks: @[]) + comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "") proc refresh*(c: PCtx, module: PSym) = c.module = module diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index e0e34306c..da31eab3d 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -987,8 +987,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = unused(n, dest) genUnaryStmt(c, n, opcNWarning) of mNError: - unused(n, dest) - genUnaryStmt(c, n, opcNError) + if n.len <= 1: + # query error condition: + c.gABC(n, opcQueryErrorFlag, dest) + else: + # setter + unused(n, dest) + genUnaryStmt(c, n, opcNError) of mNCallSite: if dest < 0: dest = c.getTemp(n.typ) c.gABC(n, opcCallSite, dest) diff --git a/compiler/vmops.nim b/compiler/vmops.nim index aa25d208a..ef2bfabb2 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -44,6 +44,10 @@ template wrap2svoid(op) {.immediate, dirty.} = op(getString(a, 0), getString(a, 1)) systemop op +proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} = + setResult(a, if a.currentException.isNil: "" + else: a.currentException.sons[2].strVal) + proc registerAdditionalOps*(c: PCtx) = wrap1f(sqrt) wrap1f(ln) @@ -73,3 +77,4 @@ proc registerAdditionalOps*(c: PCtx) = wrap1s(dirExists) wrap1s(fileExists) wrap2svoid(writeFile) + systemop getCurrentExceptionMsg |