Enter a TRAP handler when the variable table is full
Two separable faults, both on the path a program takes when it is already in trouble. `akbasic_trap_set_error_variables()` reached `ER#` and `EL#` through `akbasic_runtime_global()`, which *creates* a name the program never used -- and creating one takes a variable slot. So a program that had filled the 128-slot table could not have its handler entered at all, and because the failure happened inside the error path rather than raising, nothing was reported and the program carried on with the failing statement's effect quietly missing. A wrong answer delivered as a right one, which is worse than an abort. `akbasic_runtime_reserve_globals()` now creates both at runtime init, where there is always room, and `clear_variables()` puts them back after `CLR` and `NEW` empty the table. Second: `report_and_reraise()` used a plain `PASS` around the report, so a failure while reporting *replaced* the error the program had actually made -- "Maximum runtime variables reached" in place of the subscript that was out of range. The secondary failure is now logged and the original is re-raised, which is what a user needs to hear. **The reduction in TODO.md no longer reproduces, and not because of this.** The value-pool fix in the previous commit made a scalar free, so the pool can no longer be emptied by creating names. The defect was still live through the variable table: 124 names and a TRAP armed, and the handler was silently skipped. That is what the new test in tests/trap_verbs.c pins, together with the invariant -- both globals present before a program runs. Verified by reverting the fix against the new tests: both fail, and the second prints the log line the swallow used to eat, "could not report a BASIC error 515 (Out Of Bounds): Maximum runtime variables reached". TODO.md section 6 item 33, struck. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
This commit is contained in:
@@ -72,6 +72,12 @@ static akerr_ErrorContext AKERR_NOIGNORE *clear_variables(akbasic_Runtime *obj)
|
||||
FAIL_ZERO_RETURN(errctx, (root != NULL), AKERR_NULLPOINTER, "Runtime has no root environment");
|
||||
PASS(errctx, akbasic_symtab_init(&root->variables, AKBASIC_MAX_VARIABLES));
|
||||
PASS(errctx, akbasic_symtab_init(&root->functions, AKBASIC_MAX_FUNCTIONS));
|
||||
/*
|
||||
* Put the reserved globals back. They were in the table this just emptied,
|
||||
* and the `TRAP` dispatch relies on never having to create them -- so a CLR
|
||||
* that left them gone would reopen item 33 for the rest of the session.
|
||||
*/
|
||||
PASS(errctx, akbasic_runtime_reserve_globals(obj));
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user