Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parseExpr/parseStmt accept filename, fixes #13540 #19182

Merged
merged 1 commit into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

## Standard library additions and changes

- `macros.parseExpr` and `macros.parseStmt` now accept an optional
filename argument for more informative errors.

## `std/smtp`

- Sends `ehlo` first. If the mail server does not understand, it sends `helo` as a fallback.
Expand Down
9 changes: 4 additions & 5 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1748,11 +1748,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))
Expand All @@ -1764,10 +1763,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))
Expand Down
4 changes: 2 additions & 2 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1225,9 +1225,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)
Expand Down
14 changes: 8 additions & 6 deletions lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions tests/macros/mparsefile.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
let a = 1
let b = 2
let c =
let d = 4
11 changes: 11 additions & 0 deletions tests/macros/tparsefile.nim
Original file line number Diff line number Diff line change
@@ -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