Error handling: split stack frames over two lines; adjust more manual examples#6263
Error handling: split stack frames over two lines; adjust more manual examples#6263
Conversation
| gap> dive(100); | ||
| gap> OnBreak:= function() Where(1); end; # shorter traceback | ||
| function( ) ... end | ||
| gap> OnBreak:= function() Where(2); end;; # shorter traceback |
There was a problem hiding this comment.
the "1" showed 2 level due to a bug that I fixed in #6257, so I've now changed it to 2 levels to more closely match was the example showed before
| if (activeContext != Fail) { | ||
| Pr(context == activeContext ? "*[%d] " : " [%d] ", | ||
| INT_INTOBJ(level), 0); | ||
| snprintf(prefix, sizeof(prefix), "%c%*s[%lu] ", |
There was a problem hiding this comment.
We already use fprintf in this file, so I thought it's OK to allow the AI this ...
| Pr("<<compiled GAP function \"%g\">>", (Int)funcname, 0); | ||
| } | ||
| else { | ||
| Pr("<<compiled GAP function>>", 0, 0); |
There was a problem hiding this comment.
We deliberately duplicate some PrintKernelFunction functionality to get a more consistent output
|
|
||
| while (totalDepthInt > 0) { | ||
| prefixWidth++; | ||
| totalDepthInt /= 10; |
There was a problem hiding this comment.
Not sure which part you mean? Whether I like the way this code is written (not particular, but it will be replaced in a follow-up), or the feature it enables (indenting the [1], [2] "prefix" so that if they go double-digits, they keep right aligned) ? That I like (and made it add), it really helps reading the stack trace if it has 10 or more levels.
| gap> | ||
| gap> func( ); | ||
| Error, | ||
| Error, |
There was a problem hiding this comment.
@fingolfin How about removing this whitespace at the end?
There was a problem hiding this comment.
This is genuinely output by Error, so removing it here would cause a test failure. I guess we could try to get rid of it here, but I am not sure it's worth the effort: anyone who writes Error() hopefully only does that in test code, not in something shipping to users...
src/calls.c
Outdated
| Obj body = BODY_FUNC(func); | ||
| Obj filename = body ? GET_FILENAME_BODY(body) : 0; | ||
| if (filename) { | ||
| // A precise location means this is pure kernel code. |
There was a problem hiding this comment.
@fingolfin Do you think these comments are valuable?
There was a problem hiding this comment.
Yes and no. I explained to the AI what these different cases mean (so that it could adjust or copy them as needed); and then asked it to turn my remarks into comments, but it didn't do a good job: the first two are indeed "obvious" from the code context; and the third one is misleading: this is not a "legacy" case, but a matter of some code, here MAKE_BITFIELDS, producing function objects with arguably incomplete metadata.
I'll revise this.
Render visible stack frames with numbered prefixes on one line and an aligned location line below, and give compiled GAP frames a stacktrace-specific format. AI-assisted with Codex for implementation, tests, and documentation. Co-authored-by: Codex <codex@openai.com>
james-d-mitchell
left a comment
There was a problem hiding this comment.
I think this looks really good (in terms of the way the stack traces look, I haven't really looked at the implementation).
| [4] String( record.(nam) ) at GAPROOT/lib/record.gi:LINE called from | ||
| [5] String( record.(nam) ) at GAPROOT/lib/record.gi:LINE called from | ||
| *[1] String( record.(nam) ) | ||
| @ GAPROOT/lib/record.gi:LINE |
There was a problem hiding this comment.
Is this really supposed to be LINE?
There was a problem hiding this comment.
Yes. The script tst/testspecial/run_gap.sh intentionally substitutes the strings GAPROOT and LINE into these files; otherwise we'd constantly get failures caused by e.g. someone inserting a line into lib/record.gi.
| ## <function>( <arguments> ) called from read-eval-loop | ||
| ## Entering break read-eval-print loop ... | ||
| ## Error, the residues must be equal modulo 2 | ||
| ## *[1] Error( "the residues must be equal modulo ", g.gcd ); |
There was a problem hiding this comment.
I find it slightly vexing to see the error message in line 251 and then again in 252, but I understand that this is a necessity.
There was a problem hiding this comment.
Yeah, agreed...
So, there is a way: in other system, we wouldn't print the statement with the error here, we would print the function containing the statement... but I'd rather leave that to a follow-up PR, as I believe it may be controversial...
There was a problem hiding this comment.
I think the idea of follow-up pull request is great.
I fell like @james-d-mitchell, but I see... the controversy. 😼
I would close it.
| *[1] <<compiled GAP code>> from GAPROOT/lib/oper1.g:LINE in function INSTALL_METHOD called from | ||
| [2] <<compiled GAP code>> from GAPROOT/lib/oper1.g:LINE in function InstallMethod called from | ||
| *[1] <<compiled GAP function "INSTALL_METHOD">> | ||
| @ GAPROOT/lib/oper1.g:LINE |
There was a problem hiding this comment.
More instances of "LINE" which should probably be a number no?
8a76023 to
6cc08be
Compare
|
@james-d-mitchell @limakzi thank you for your reviews. I've now tried to address everything. Please user the "Resolve conversation" buttons suitably if you are satisfied; or else please feel free to ask follow-ups |
| ## <function>( <arguments> ) called from read-eval-loop | ||
| ## Entering break read-eval-print loop ... | ||
| ## Error, the residues must be equal modulo 2 | ||
| ## *[1] Error( "the residues must be equal modulo ", g.gcd ); |
There was a problem hiding this comment.
I think the idea of follow-up pull request is great.
I fell like @james-d-mitchell, but I see... the controversy. 😼
I would close it.
|
Thanks again for your feedback, @limakzi, much appreciated. Will auto-merge this now and make a follow-up PR tomorrow or so. |
|
@james-d-mitchell @ChrisJefferson happy with this? feel free to "approve" if you are ;-) |
… examples (gap-system#6263) Render visible stack frames with numbered prefixes on one line and an aligned location line below, and give compiled GAP frames a stacktrace-specific format. AI-assisted with Codex for implementation, tests, and documentation. Co-authored-by: Codex <codex@openai.com>
Render visible stack frames with numbered prefixes on one line and an aligned location line below, and give compiled GAP frames a stacktrace-specific format.
Also update a bunch of examples in the manual and code comments to reflect the new stack trace formatting.
AI-assisted with Codex for implementation, tests, and documentation.
Follow up to PR #6257
There are several aspects to this PR one may wish to discuss
It splits each stack trace line into two; with the file/location on its own line. I borrowed the formatting from Julia, because I know and like it, but am completely open to alternatives. I would also understand if people prefer the more compact old printing; but for me, it is often difficult to weed through a long and complex GAP stack trace, and often what I want most are the file:line pairs (as I just cmd-click on them in my terminal to look at the code they reference).
It updates more examples, and in some cases edits them; in some cases I decided it is best to just delete something. Please have a look if you agree
The implementation: I feel
PRINT_CURRENT_STATEMENTgets more and more complex. I've thought about converting parts of it to GAP code, but this always ends up raising questions about "but won't this need to allocate or cause additional errors, and we can afford neither". So I decided to leave it as it is, to be refactor in a future PR. But feel free to disagree / suggest better alternatives.Further ideas (for follow-up PRs):
WhereDepths(see AddWhereDepthuser preference to control depth of initial stack trace in break loops #6261), something likeUpDownEnvWhereDepths: if set to 0 or negative, then noWhereis executed, any positive value runsWherewith that many levels; if the setting is not set at all, default toWhereDepth?)