Three example programs are in no test, and all three had rotted #58

Open
opened 2026-08-05 23:24:45 -04:00 by tachikoma · 0 comments
Collaborator

examples/galaga/ is covered by example_galaga and example_galaga_interop. examples/embed.c, hostvars.c and hoststruct.c each have a test. examples/breakout/sprites/breakout.bas, examples/breakout/characters/breakout.bas and examples/megademo/megademo.bas are covered by nothing, and when checked during a submodule bump, all three were broken on main (ae2c702).

Two independent causes, both from changes that landed after the programs were written:

1. RND became a reserved word. ae2c702 ("Add native RND and ASC functions") added RND to the verb table. characters/breakout.bas and megademo.bas both use a variable called RND# to hold their LCG output, and a suffixed identifier that collides with a function name is refused — ? 141 : SYNTAX ERROR Reserved word in variable name. Neither program got past its own PRNG. examples/galaga/ had the same defect in its RND% host field and was caught, by the test it has.

2. The line-length limit. sprites/breakout.bas had seven lines that the reader refuses. Worth knowing the exact ceiling, because it is not the one the message names: src/sink_stdio.c:87 fails when the read filled the buffer without seeing a terminator, so with AKBASIC_MAX_LINE_LENGTH at 80 the message says "exceeds the 79 character limit" and the real maximum is 78 characters — a 79-character line leaves no room for the \n. The commits that swept the corpus for this ("Keep BASIC fixtures within the input line limit", "Rework the megademo to fit the 80-column source line limit") did not reach this file.

All of it is fixed in the submodule-bump PR, which is how it was found — but the fix is not the point. The point is that nothing would have told anyone. These are the programs two tutorial chapters are built around: 17 and 18 teach sprites/breakout.bas line by line, and a reader who copies the chapter gets a program that works while the file in the repository does not.

docs_examples does not close this. It runs the listings in the chapters, which are maintained separately from the files, and the two drifted apart in exactly the way the harness was built to prevent — for documentation, but the checked-in programs are outside its remit.

What would close it

An example_breakout / example_megademo pair alongside example_galaga, running each .bas under the akgl frontend with the dummy video and audio drivers and a bounded step count, asserting a zero exit and no ? line : CLASS on stdout. example_galaga is the model, and AKBASIC_FRONTEND_STEPS_PER_FRAME plus a frame cap is the existing way to bound a game that would otherwise never return.

Cheaper stopgap, if that is too much: a test that reads every .bas under examples/ and asserts no line reaches 79 characters. That catches cause 2 and nothing else, but it is about ten lines.

Also worth deciding separately: the limit reported to the user is off by one from the limit enforced. Either the message should say 78, or the reader should accept a 79-character line and its terminator.

`examples/galaga/` is covered by `example_galaga` and `example_galaga_interop`. `examples/embed.c`, `hostvars.c` and `hoststruct.c` each have a test. **`examples/breakout/sprites/breakout.bas`, `examples/breakout/characters/breakout.bas` and `examples/megademo/megademo.bas` are covered by nothing**, and when checked during a submodule bump, all three were broken on `main` (ae2c702). Two independent causes, both from changes that landed after the programs were written: **1. `RND` became a reserved word.** ae2c702 ("Add native RND and ASC functions") added `RND` to the verb table. `characters/breakout.bas` and `megademo.bas` both use a *variable* called `RND#` to hold their LCG output, and a suffixed identifier that collides with a function name is refused — `? 141 : SYNTAX ERROR Reserved word in variable name`. Neither program got past its own PRNG. `examples/galaga/` had the same defect in its `RND%` host field and *was* caught, by the test it has. **2. The line-length limit.** `sprites/breakout.bas` had seven lines that the reader refuses. Worth knowing the exact ceiling, because it is not the one the message names: `src/sink_stdio.c:87` fails when the read filled the buffer without seeing a terminator, so with `AKBASIC_MAX_LINE_LENGTH` at 80 the message says *"exceeds the 79 character limit"* and the real maximum is **78 characters** — a 79-character line leaves no room for the `\n`. The commits that swept the corpus for this ("Keep BASIC fixtures within the input line limit", "Rework the megademo to fit the 80-column source line limit") did not reach this file. All of it is fixed in the submodule-bump PR, which is how it was found — but the fix is not the point. **The point is that nothing would have told anyone.** These are the programs two tutorial chapters are built around: 17 and 18 teach `sprites/breakout.bas` line by line, and a reader who copies the chapter gets a program that works while the file in the repository does not. `docs_examples` does not close this. It runs the *listings in the chapters*, which are maintained separately from the files, and the two drifted apart in exactly the way the harness was built to prevent — for documentation, but the checked-in programs are outside its remit. ## What would close it An `example_breakout` / `example_megademo` pair alongside `example_galaga`, running each `.bas` under the akgl frontend with the dummy video and audio drivers and a bounded step count, asserting a zero exit and no `? line : CLASS` on stdout. `example_galaga` is the model, and `AKBASIC_FRONTEND_STEPS_PER_FRAME` plus a frame cap is the existing way to bound a game that would otherwise never return. Cheaper stopgap, if that is too much: a test that reads every `.bas` under `examples/` and asserts no line reaches 79 characters. That catches cause 2 and nothing else, but it is about ten lines. Also worth deciding separately: the limit reported to the user is off by one from the limit enforced. Either the message should say 78, or the reader should accept a 79-character line and its terminator.
Sign in to join this conversation.