Conversation
Error contexts so far marked the single token or instruction which failed, which left the reader to reconstruct the statement around it: for `return o.missing.deep;` the caret sat under the failing member access and said nothing about which expression the VM had been evaluating. The offset info already records where each statement begins and ends, but only the debugger consulted it. Resolve that extent for the failing instruction now and underline it, keeping the caret at the failing position and dropping the "Near here" label, which the underline makes redundant. Where no statement can be resolved, the previous caret rendering is kept. Statement spans nest, but an inner span always closes before its enclosing one, so the first closed span covering the instruction is the innermost match and remembering a single parent suffices to walk out of a non-matching one. The few instructions which fall through - loop back-edges, function return tails and the like, none of which can be a failing expression - are left to the caller to render as a plain position marker. While wiring this up, two flaws in the span lookup came to light. Abandoning the search after the remembered parent was exhausted made the walk come up empty one level too early, and the byte and instruction deltas of a span-start entry were accumulated alike, although the byte delta leads up to the statement start while the instruction delta counts instructions emitted after it. Since the extent of the failing statement is useful to editors and debug clients as well, stacktrace entries now carry it as a `statement` member holding the start and end line and byte of the statement, and syntax errors are reported against the innermost statement compilation was inside of, whose end marker the error prevented from being emitted. The expected error output of the test suite is adjusted to the new marker rendering. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
When a call fails because its left-hand side isn't a function, the message "left-hand side is not a function" identifies nothing the user can see. Recover the text of the invoked expression from the source and name it instead, falling back to the generic message whenever the expression cannot be recovered with confidence. The instruction of a failing call refers to the closing parenthesis of its argument list, so the source in front of it is scanned backwards over that balanced pair, which marks the end of the invoked expression, and then over the spine of the expression itself. Subscripts, nested calls and literal values are taken as a whole so that their contents cannot be mistaken for part of the surrounding expression, and whitespace which does not surround a member access operator is dropped, since it separates the expression from whatever precedes it. The source is read one character at a time, and how far back the scan may reach is limited, since only the arguments passed to the failing call can be arbitrarily wide. What is recovered goes into a fixed size buffer which is filled from its end towards its beginning, so no second pass is needed to put the characters in order; expressions which do not fit are cut short, and only their tails are shown, marked with an ellipsis. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Assigning to a forward-declared function fails after the right-hand side has already emitted its closure instruction, so the interrupted statement resolves to a non-empty extent and the error context now underlines it instead of pointing at the failing byte with a "Near here" marker. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Improve runtime and syntax error reporting in two ways:
Underline the failing statement
Error contexts previously marked only the single token/instruction which failed, leaving the reader to reconstruct the statement around it. The statement start/end offsets are now resolved from the offset info and underlined, keeping the caret at the failing position and dropping the now-redundant "Near here" label.
statementmember (start/end line and byte), useful for editors and debug clients.Name the offending expression in call failures
When a call fails because its left-hand side isn't a function, the message now includes the recovered source text of the invoked expression, falling back to the generic message whenever it cannot be recovered with confidence. Expressions which do not fit are cut short, marked with an ellipsis.
Example
Before:
After: