Skip to content

Commit

Permalink
Improve reporting of errors in vm/vmgen
Browse files Browse the repository at this point in the history
Reporting of guest code related errors was done in an inconsistent
manner via either `stackTrace` or `globalReport`, where `stackTrace` used
`localReport` and an injected `return` statement to terminate the
execution loop. `stackTrace` was sometimes used in nested functions,
thus not terminating execution at all.

## Changes
Both the execution engine and `vmgen` now use exceptions for error
propagation internally, translating them into a result value at their
respective interface edges. In case of an error, the result value stores the
error report. Otherwise, it stores the actual result.

In addition, some usages of `globalReport` are also replaced with the
 new error propagation mechanism.

Depending on whether or not a VM invocation is expected to return
something, errors reported from VM execution and/or `vmgen` are either
 turned into a `nkError` node or handled directly via `handleReport`
  • Loading branch information
zerbina committed Apr 8, 2022
1 parent ec285cc commit 8850e11
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 274 deletions.
2 changes: 1 addition & 1 deletion compiler/ast/reports.nim
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ type
func incl*(s: var ReportSet, id: ReportId) = s.ids.incl uint32(id)
func contains*(s: var ReportSet, id: ReportId): bool = s.ids.contains uint32(id)

func addReport*(list: var ReportList, report: Report): ReportId =
func addReport*(list: var ReportList, report: sink Report): ReportId =
## Add report to the report list
list.list.add report
result = ReportId(uint32(list.list.high) + 1)
Expand Down
27 changes: 15 additions & 12 deletions compiler/sem/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,11 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
c.config.m.errorOutputs = {}
c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here

try:
result = evalConstExpr(c.module, c.idgen, c.graph, e)
if result == nil or result.kind == nkEmpty:
result = nil
else:
result = fixupTypeAfterEval(c, result, e)

except ERecoverableError:
result = evalConstExpr(c.module, c.idgen, c.graph, e)
if result == nil or result.kind in {nkEmpty, nkError}:
result = nil
else:
result = fixupTypeAfterEval(c, result, e)

c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax
Expand All @@ -475,13 +471,20 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
if result == nil:
#if e.kind == nkEmpty: globalReport(n.info, errConstExprExpected)
result = evalConstExpr(c.module, c.idgen, c.graph, e)
if result == nil or result.kind == nkEmpty:
if e.info != n.info:
assert result != nil
case result.kind
of {nkEmpty, nkError}:
let withContext = e.info != n.info
if withContext:
pushInfoContext(c.config, n.info)

if result.kind == nkEmpty:
localReport(c.config, e.info, SemReport(kind: rsemConstExprExpected))
popInfoContext(c.config)
else:
localReport(c.config, e.info, SemReport(kind: rsemConstExprExpected))
localReport(c.config, result)

if withContext:
popInfoContext(c.config)
# error correction:
result = e
else:
Expand Down
Loading

0 comments on commit 8850e11

Please sign in to comment.