Give a loaded line a number when it arrives without one

A script written against LABEL and GOTO NAME never names a line number, so
the numbers it had to carry were decoration. akbasic_runtime_load(),
RUNSTREAM and DLOAD now file an unnumbered line one slot after the last one
filed; a numbered line is filed under its number and moves the cursor, so
the two mix. akbasic_runtime_file_line() is the one implementation of that
rule, so the three paths cannot drift.

The prompt is untouched. A line typed without a number is still direct mode
and still runs now -- that is the only thing separating program text from a
statement at a REPL, and it is why this is a loading feature.

What this replaces was silent data loss: an unnumbered line was filed under
the cursor unchanged, on top of the line before it. A blank line therefore
erased whatever preceded it, and RUNSTREAM did not skip blank lines the way
the other two paths did.

That moves one golden file, and the reference had the same defect.
language/arithmetic/integer.bas has four PRINT statements, an expectation
with three values, and a trailing blank line that erased 40 PRINT 4 - 2
before the program ran. The expectation is now 4 4 2 2.
tests/reference/README.md records the divergence and TODO.md section 5 item
63 says why.

akbasic_SourceLine grows a `numbered` flag so an assigned number can be told
from a written one. RENUMBER sets it on every line it touches; NEW, DELETE
and DLOAD clear it. hadlinenumber moves to akbasic_scanner_scan(), so it
always describes the line just scanned rather than only the REPL's.

Two lines carrying the same written number still keep the last, as they
always have. That is a separate decision.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-01 16:33:27 -04:00
parent d2ae0d75de
commit 8bc253ebbf
12 changed files with 428 additions and 14 deletions

30
TODO.md
View File

@@ -1355,6 +1355,36 @@ deviations from the reference's *program*: `main.go` and the SDL half of
it had not been used for, and both were filed rather than worked around silently. One came
back fixed.
63. **Line numbers are optional in a loaded program, and a blank line is not a program line.**
**This one moved a golden file.** A line with no number used to be filed under the loader's
cursor unchanged — that is, on top of the line before it — so two unnumbered lines in a row
silently lost the first, and a *blank* line erased whatever preceded it. The reference does
the same, and `tests/reference/language/arithmetic/integer.bas` is the proof: four `PRINT`
statements, an expectation with three values, and a trailing blank line that erased
`40 PRINT 4 - 2` before the program ran. The expectation is now `4 4 2 2` and
`tests/reference/README.md` records it.
In its place: `akbasic_runtime_file_line()` (`src/runtime.c`) is the one implementation of
the rule, shared by `akbasic_runtime_load()`, RUNSTREAM and `DLOAD`. A numbered line is
filed under its number and moves the cursor; an unnumbered one takes the slot after it;
blank lines are skipped by all three. A collision involving an assigned number is refused
with `AKBASIC_ERR_BOUNDS` rather than overwriting. `akbasic_SourceLine` grew a `numbered`
flag so deviation 64 can tell the two apart.
**The prompt is deliberately untouched.** A line typed without a number is direct mode and
runs now; that is the only thing separating program text from a statement at a REPL, and it
is why this is a *loading* feature rather than a language-wide one. `AUTO` remains the way
to enter program text without typing numbers.
Consequence worth stating: an unnumbered program is capped at 9998 lines, the cap that
already existed, and its assigned numbers are increment-1 — so `LIST` and `DSAVE` show a
listing with no gaps to insert into. `RENUMBER` before `DSAVE` gives the gaps back, and
marks every line numbered.
**Not changed:** two lines that both carry the *same* written number still silently keep
the last, as they always have. That is a separate decision with its own corpus risk and it
is not this one.
---
---