From a797a04b0d2c1824d1cde04bce96f1b52d86ab57 Mon Sep 17 00:00:00 2001 From: hlaaftana <10591326+hlaaftana@users.noreply.github.com> Date: Wed, 24 Nov 2021 14:22:40 +0300 Subject: [PATCH] parseExpr/parseStmt accept filename, fixes #13540 (#19182) --- changelog.md | 4 ++++ compiler/vm.nim | 9 ++++----- compiler/vmgen.nim | 4 ++-- lib/core/macros.nim | 14 ++++++++------ tests/macros/mparsefile.nim | 4 ++++ tests/macros/tparsefile.nim | 11 +++++++++++ 6 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 tests/macros/mparsefile.nim create mode 100644 tests/macros/tparsefile.nim diff --git a/changelog.md b/changelog.md index 093dc6a8fa6c..b2b8d869c110 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,10 @@ filename argument for more informative errors. - Module `colors` expanded with missing colors from the CSS color standard. - Fixed `lists.SinglyLinkedList` being broken after removing the last node ([#19353](https://github.com/nim-lang/Nim/pull/19353)). +- `macros.parseExpr` and `macros.parseStmt` now accept an optional + filename argument for more informative errors. + +## `std/smtp` ## Language changes diff --git a/compiler/vm.nim b/compiler/vm.nim index 676ffcf1967a..b3fbdcfabcb7 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1760,11 +1760,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = elif instr.opcode == opcNHint: message(c.config, info, hintUser, a.strVal) of opcParseExprToAst: - decodeB(rkNode) - # c.debug[pc].line.int - countLines(regs[rb].strVal) ? + decodeBC(rkNode) var error: string let ast = parseString(regs[rb].node.strVal, c.cache, c.config, - toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int, + regs[rc].node.strVal, 0, proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} = if error.len == 0 and msg <= errMax: error = formatMsg(conf, info, msg, arg)) @@ -1776,10 +1775,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = else: regs[ra].node = ast[0] of opcParseStmtToAst: - decodeB(rkNode) + decodeBC(rkNode) var error: string let ast = parseString(regs[rb].node.strVal, c.cache, c.config, - toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int, + regs[rc].node.strVal, 0, proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} = if error.len == 0 and msg <= errMax: error = formatMsg(conf, info, msg, arg)) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 5be4d48664dc..c0c4bac19605 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1229,9 +1229,9 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = unused(c, n, dest) genBinaryStmtVar(c, n, opcAddSeqElem) of mParseExprToAst: - genUnaryABC(c, n, dest, opcParseExprToAst) + genBinaryABC(c, n, dest, opcParseExprToAst) of mParseStmtToAst: - genUnaryABC(c, n, dest, opcParseStmtToAst) + genBinaryABC(c, n, dest, opcParseStmtToAst) of mTypeTrait: let tmp = c.genx(n[1]) if dest < 0: dest = c.getTemp(n.typ) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index f6ac3aa81794..04e86d116415 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -516,27 +516,29 @@ proc lineInfo*(arg: NimNode): string = ## Return line info in the form `filepath(line, column)`. $arg.lineInfoObj -proc internalParseExpr(s: string): NimNode {. +proc internalParseExpr(s, filename: string): NimNode {. magic: "ParseExprToAst", noSideEffect.} -proc internalParseStmt(s: string): NimNode {. +proc internalParseStmt(s, filename: string): NimNode {. magic: "ParseStmtToAst", noSideEffect.} proc internalErrorFlag*(): string {.magic: "NError", noSideEffect.} ## Some builtins set an error flag. This is then turned into a proper ## exception. **Note**: Ordinary application code should not call this. -proc parseExpr*(s: string): NimNode {.noSideEffect.} = +proc parseExpr*(s: string; filename: string = ""): NimNode {.noSideEffect.} = ## Compiles the passed string to its AST representation. ## Expects a single expression. Raises `ValueError` for parsing errors. - result = internalParseExpr(s) + ## A filename can be given for more informative errors. + result = internalParseExpr(s, filename) let x = internalErrorFlag() if x.len > 0: raise newException(ValueError, x) -proc parseStmt*(s: string): NimNode {.noSideEffect.} = +proc parseStmt*(s: string; filename: string = ""): NimNode {.noSideEffect.} = ## Compiles the passed string to its AST representation. ## Expects one or more statements. Raises `ValueError` for parsing errors. - result = internalParseStmt(s) + ## A filename can be given for more informative errors. + result = internalParseStmt(s, filename) let x = internalErrorFlag() if x.len > 0: raise newException(ValueError, x) diff --git a/tests/macros/mparsefile.nim b/tests/macros/mparsefile.nim new file mode 100644 index 000000000000..8ac99d5685ee --- /dev/null +++ b/tests/macros/mparsefile.nim @@ -0,0 +1,4 @@ +let a = 1 +let b = 2 +let c = +let d = 4 diff --git a/tests/macros/tparsefile.nim b/tests/macros/tparsefile.nim new file mode 100644 index 000000000000..a41223f803c9 --- /dev/null +++ b/tests/macros/tparsefile.nim @@ -0,0 +1,11 @@ +import macros + +static: + let fn = "mparsefile.nim" + var raised = false + try: + discard parseStmt(staticRead(fn), filename = fn) + except ValueError as e: + raised = true + doAssert e.msg == "mparsefile.nim(4, 1) Error: invalid indentation" + doAssert raised