A GOTO that leaves a FOR or a DO leaks the loop's scope #3

Open
opened 2026-08-02 19:04:10 -04:00 by tachikoma · 0 comments
Collaborator

Source: TODO.md §6 item 37 (at 9151438)

A program that uses the pattern as its main loop stops after the thirty-second time round:

N# = 0
LABEL TOP
DO
  N# = N# + 1
  IF N# < 100 THEN GOTO TOP
LOOP UNTIL N# > 99
PRINT "SURVIVED " + N#
? 3 : PARSE ERROR Environment pool exhausted at line 3 (32 in use)

Thirty-two is AKBASIC_MAX_ENVIRONMENTS (include/akbasic/types.h:31), and the branch that
reports is the DO being entered for the thirty-third time rather than the GOTO that did the
damage.
The FOR form behaves identically.

This is a real pattern rather than a contrivance. A game's main loop is a loop the program
leaves from the middle of: losing a life, clearing a level and quitting are all "stop what you
are doing and go somewhere else". Both Breakout listings in examples/ are built out of
LABEL/GOTO for exactly this reason
-- the shape a reader of chapters 17 and 18 is now told
to copy -- and it is a workaround rather than a preference.

The mechanism: a loop's environment is pushed when the line is parsed and popped by its
NEXT or LOOP, and nothing else pops it. GOTO sets the next line and returns
(akbasic_cmd_goto(), src/runtime_commands.c); it has no idea it has just left a scope.

A fix has to know which scopes the branch target is outside of, which the environment stack can
answer if a loop's environment records the source line that pushed it: on a GOTO, pop every
loop scope whose line is not on the path to the target.

That is more machinery than the two associativity fixes want between them, and it is worth
pricing against simply documenting it
-- chapters 13 and 17 both now say "loop with GOTO,
never jump out of a DO", which is a rule a reader can follow. Wants tests/for_next.c either
way, because the reduction above is four lines and nothing asserts it in either direction.

Files: src/runtime_commands.c (akbasic_cmd_goto), src/runtime.c, tests/for_next.c


Filed by Tachikoma (Claude Code, Opus 5, 1M context)

**Source:** TODO.md §6 item 37 (at 9151438) A program that uses the pattern as its main loop stops after the thirty-second time round: ```basic N# = 0 LABEL TOP DO N# = N# + 1 IF N# < 100 THEN GOTO TOP LOOP UNTIL N# > 99 PRINT "SURVIVED " + N# ``` ```output ? 3 : PARSE ERROR Environment pool exhausted at line 3 (32 in use) ``` Thirty-two is `AKBASIC_MAX_ENVIRONMENTS` (`include/akbasic/types.h:31`), and **the branch that reports is the `DO` being entered for the thirty-third time rather than the `GOTO` that did the damage.** The `FOR` form behaves identically. **This is a real pattern rather than a contrivance.** A game's main loop is a loop the program leaves from the middle of: losing a life, clearing a level and quitting are all "stop what you are doing and go somewhere else". **Both Breakout listings in `examples/` are built out of `LABEL`/`GOTO` for exactly this reason** -- the shape a reader of chapters 17 and 18 is now told to copy -- and it is a workaround rather than a preference. **The mechanism:** a loop's environment is pushed when the line is parsed and popped by its `NEXT` or `LOOP`, and nothing else pops it. `GOTO` sets the next line and returns (`akbasic_cmd_goto()`, `src/runtime_commands.c`); it has no idea it has just left a scope. A fix has to know which scopes the branch target is *outside* of, which the environment stack can answer if a loop's environment records the source line that pushed it: on a `GOTO`, pop every loop scope whose line is not on the path to the target. **That is more machinery than the two associativity fixes want between them, and it is worth pricing against simply documenting it** -- chapters 13 and 17 both now say "loop with `GOTO`, never jump out of a `DO`", which is a rule a reader can follow. Wants `tests/for_next.c` either way, because the reduction above is four lines and nothing asserts it in either direction. **Files:** `src/runtime_commands.c` (`akbasic_cmd_goto`), `src/runtime.c`, `tests/for_next.c` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 0.1.x milestone 2026-08-02 19:04:10 -04:00
tachikoma added the defectblast-radius:highstatus::grooming labels 2026-08-02 19:04:10 -04:00
Sign in to join this conversation.