Files
akbasic/tests/unnumbered.c
Andrew Kesterson 6273be580a Refuse a branch to a line the program did not number
GOTO 100 in a script written without line numbers finds the hundredth line
and branches there. Silent, plausible and wrong: the test for it loops
forever printing the second line when the check is removed.

akbasic_runtime_check_targets() is a fourth prescan beside the label, DATA
and TYPE ones, run on every entry into MODE_RUN -- the earliest the check
can be made and the only place all four ways a program arrives pass
through. A target naming an empty line is still allowed, for the same
reason RENUMBER leaves one alone, and a fully numbered program is
unaffected, which is every program that existed before this.

It shares RENUMBER's walk rather than repeating it. renumber.c grows an
akbasic_TargetWalk -- a self pointer and a visit function -- and
rewrite_line() takes one. RENUMBER's visitor substitutes the number a line
moved to; the check's substitutes the number unchanged and raises. One
walk, so the two cannot disagree about what a branch target is.

The check points environment->lineno at the line being walked so the "? N :"
prefix names the offending line. The other three prescans do not and report
whichever line the loader stopped on; TODO.md section 5 item 64 records it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:38:54 -04:00

13 KiB