Implement the housekeeping verbs, and stop the REPL spinning after an error
NEW, CLR, CONT, SWAP, TRON, TROFF and HELP. None is in the Go reference, so what each means here is recorded beside it. Testing CONT turned up a hang that predates this: the runtime's error class is deliberately sticky, and with run_finished_mode REPL every later step re-entered REPL and printed READY -- overwriting the QUIT that end of input had just set. An interactive session that hit one runtime error printed READY forever instead of exiting. RESTORE and RENUMBER are deferred with reasons; RESTORE turns out to need a DATA pointer this port does not have, which is a defect in its own right. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -253,6 +253,9 @@ akerr_ErrorContext *akbasic_runtime_error(akbasic_Runtime *obj, akbasic_ErrorCla
|
||||
FAIL_ZERO_RETURN(errctx, (obj != NULL && message != NULL), AKERR_NULLPOINTER,
|
||||
"NULL argument in runtime error");
|
||||
obj->errclass = errclass;
|
||||
/* Where HELP will look. Recorded before the message is built, so a report
|
||||
* that itself fails still leaves the line behind. */
|
||||
obj->errorline = obj->environment->lineno;
|
||||
/*
|
||||
* The format, the trailing \n inside the string, and the second newline
|
||||
* writeln adds are all part of the acceptance contract --
|
||||
@@ -779,6 +782,17 @@ akerr_ErrorContext *akbasic_runtime_process_line_run(akbasic_Runtime *obj)
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* TRON. Inline and with no newline, which is what a C128 prints: a traced
|
||||
* program's output reads `[10][20]HELLO`. Blank lines are skipped above, so
|
||||
* a trace shows only the lines that actually hold something.
|
||||
*/
|
||||
if ( obj->trace ) {
|
||||
char tracemark[32];
|
||||
snprintf(tracemark, sizeof(tracemark), "[%" PRId64 "]", obj->environment->lineno);
|
||||
PASS(errctx, akbasic_runtime_write(obj, tracemark));
|
||||
}
|
||||
|
||||
PASS(errctx, akbasic_scanner_scan(obj, line, NULL, 0));
|
||||
PASS(errctx, akbasic_parser_init(&parser, obj));
|
||||
obj->skiprestofline = false;
|
||||
@@ -929,9 +943,21 @@ akerr_ErrorContext *akbasic_runtime_step(akbasic_Runtime *obj)
|
||||
* ends the program: in a file run, run_finished_mode is QUIT. Reproduced
|
||||
* deliberately -- tests/language/array_outofbounds.txt depends on exactly one
|
||||
* error line being printed and nothing after it.
|
||||
*
|
||||
* The clear on the way back to the REPL is *not* the reference's, and it is
|
||||
* a fix rather than a deviation. A sticky errclass with run_finished_mode
|
||||
* REPL means every later step re-enters REPL mode and prints READY again --
|
||||
* so an interactive session that hits one runtime error and then reaches end
|
||||
* of input spins forever printing READY instead of quitting, because the
|
||||
* QUIT that process_line_repl() set on EOF is overwritten right here. A
|
||||
* fresh prompt is a fresh statement; the error has been reported and acted
|
||||
* on and there is nothing left for it to do.
|
||||
*/
|
||||
if ( obj->errclass != AKBASIC_ERRCLASS_NONE ) {
|
||||
PASS(errctx, akbasic_runtime_set_mode(obj, obj->run_finished_mode));
|
||||
if ( obj->mode == AKBASIC_MODE_REPL ) {
|
||||
obj->errclass = AKBASIC_ERRCLASS_NONE;
|
||||
}
|
||||
}
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user