A GOTO that leaves a FOR or a DO leaks the loop's scope
#3
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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:
Thirty-two is
AKBASIC_MAX_ENVIRONMENTS(include/akbasic/types.h:31), and the branch thatreports is the
DObeing entered for the thirty-third time rather than theGOTOthat did thedamage. The
FORform 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 ofLABEL/GOTOfor exactly this reason -- the shape a reader of chapters 17 and 18 is now toldto 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
NEXTorLOOP, and nothing else pops it.GOTOsets 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 everyloop 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. Wantstests/for_next.ceitherway, 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.cFiled by Tachikoma (Claude Code, Opus 5, 1M context)