a9600c3fcc89e79bdac56d65f34865bd561c1c34
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
1fb808f480
|
Rewrite the two game tutorials as instructions rather than commentary
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m21s
akbasic CI Build / sanitizers (push) Failing after 4m32s
akbasic CI Build / coverage (push) Failing after 3m37s
akbasic CI Build / akgl_build (push) Failing after 22s
akbasic CI Build / mutation_test (push) Failing after 3m30s
Chapters 17 and 18 read as a code review of a finished listing: they explained why each decision had been made, walked through the project's own history, and led with what had once been broken. A reader who wanted to build the game got the reasoning and had to reconstruct the program. Both are now step-by-step. Each opens with a picture of the finished game and a bullet list of the steps, each bullet is a section, and each section states its goal, shows the code, and says how to check it. Chapter 17 is sixteen steps and Chapter 18 is thirteen, and the last of each is the assembly: the order of the file, the full declaration block, and the routines the earlier steps referred to. Project history is gone -- it belongs in Chapter 14 and in git -- and where a listing has to do something awkward, the tutorial shows how first and names the `TODO.md` item that will make it unnecessary second. **Three defects had no entry anywhere**, which the rewrite found by trying to state each rule as a rule. §6 item 35: `a - b + c` computes `a - (b + c)`, because `subtraction()` sits above `addition()` as its own precedence level and the inner loop eats the `+`. Item 36: only one unparenthesised `AND` or `OR` is matched, which is item 12's `if`-where-`while` on the one operator pair item 12 did not reach. Item 37: a `GOTO` out of a `FOR` or a `DO` leaks the loop's scope, so a main loop written that way stops on the thirty-second lost life -- which is why both games are built out of `LABEL` and `GOTO`, and it is a workaround rather than a preference. Chapter 3 gains the identifier rule the third trial ran into: there is no underscore in a name, and the error says `UNKNOWN TOKEN _`. **`tools/screenshot.c` learned to draw the text layer**, behind a new `text=1` fence attribute, because Chapter 17's game is characters in the grid and a figure without that layer is two sprites on black. It opens the bundled font at the size the standalone frontend uses, so a figure's cell size is the reader's cell size, and it uses the akgl sink alone rather than a tee so the program's output lands in the picture instead of on the stdout the caller reads to decide a figure failed. Both new figures -- `breakout-game.png` and `breakout-game-artwork.png` -- are generated from listings in the chapters like every other one. Verified by handing each chapter, alone, to an agent on a much smaller model and telling it to build the game from the tutorial text with the `examples/` tree off limits. The first pass scored 3.5 and 3 out of 10 and named what was missing: routines referred to but never shown, the third level layout, the sprite `DATA`, the font table, edits to earlier routines that were never marked as edits. Those are now in. The second pass built a 658-line Chapter 17 game that plays itself for ninety seconds with the score at 1890 and no error line, and the third built a 1053-line Chapter 18 game with 61 labels, no invented routines, no gaps found, and forty seconds clean. 9/10 and 8/10. One real bug in the new prose, caught in review: Chapter 18's `HITBAR` did not set the `HIT#` that `BALLPADDLE` reads to decide whether the paddle already caught the ball. Both suites green in both configurations, `docs_examples` and `docs_screenshots --check` pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwxGB6TdoVvZ11KQQME9cL |
|||
|
ad76889292
|
State where a scalar lives in the three chapters that describe the pool
Chapter 13's limits table said 4096 array elements "in total", Chapter 16 said an instance's fields come out of the same pool and nothing is reclaimed, and Chapter 14's pool table listed `AKBASIC_MAX_ARRAY_VALUES` with no note about what does and does not draw from it. All three were written when a scalar drew from that pool, and all three now understate what a program may do. Each gains the same two facts in the register it is written in. Chapter 13: a scalar does not come out of the 4096, so creating one inside a `GOSUB` or a `FOR` -- the loop counter included -- costs nothing, while a `DIM` inside a scope does and is not given back. Chapter 16: scalars are the exception, and "nothing is reclaimed" is what lets a pointer into a record stay sound after its scope has gone -- which is the reason arrays and structures still spend. Chapter 14: a row for the variable's own storage, and a paragraph on why the value pool is the one budget that needs a second sentence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
|
c3d9e91bbd
|
Write down that a redraw has to fit inside one batch
"Drawing does not persist across frames; redraw it every frame" was the advice, and it is not sufficient on its own. The host runs a fixed number of source lines and then presents, and presenting discards the drawing buffer -- so a run of drawing verbs longer than one budget is **torn**, not merely transient, and an `SSHAPE` at the end of it captures only what was issued since the present, over whatever the frame before left behind. Measured against the standalone frontend's 256: after synchronising to a jiffy edge, 220 lines of drawing survive a capture and 250 do not. There is no fix available that does not change what a host owns -- the budget is the host's and so is the present -- so this is documentation, in the three places it belongs. Chapter 13 beside the note it qualifies, with the numbers. Chapter 6 where `SSHAPE` is introduced, which is where a program meets it. Chapter 14 from the step loop's side, naming `AKBASIC_FRONTEND_STEPS_PER_FRAME` and explaining the one thing a script can do about it: `settime()` is called once a frame, so `TI#` changes on the first step of a batch and nowhere else, and spinning until it changes is the only frame synchronisation this dialect has. **Untested, deliberately.** Reproducing it needs the real frontend, a clock and a timing window, and a test that reproduced it would be reproducing a race. Recorded in TODO.md rather than left looking like an oversight. TODO.md section 9 item 5, struck as a documentation outcome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
|
28ea99a638
|
Document optional line numbers
Chapter 2 gets the rule and the refusal, chapter 4 gets the payoff for LABEL, chapter 9 says DSAVE writes the numbers it handed out and to RENUMBER first if you want gaps, chapter 10 shows a host loading numberless source, chapter 13 gets the QuickBASIC-shaped divergence, and chapter 14's source[] passage gets its second half. Chapter 14 said "two prescans" and listed two; there were three before this and there are four now, so it lists all four and says which of them reports against the right line. TODO.md section 6 records four things found on the way and deliberately not fixed: set_label() filing into the active scope rather than the root, three prescans reporting the wrong line number, duplicate written line numbers still replacing silently, and renumber.c's file-scope scratch arrays. examples/embed.c runs the same program twice, numbered and not, so the example compiles the feature rather than describing it. Its header pointed at ./build/examples/embed, which is not where the binary lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
|
6bac929901
|
Document structures: a chapter, the architecture, and the differences
docs/16-structures.md is the feature: records, nesting, copy-on-assign, strict pointers, lists, what is checked and what is not, and how a host shares its own C structs. Every example in it is executed by docs_examples and byte-compared, including the refusals -- so a message that changes fails the suite rather than quietly making the chapter wrong. The chapter makes one contrast explicitly, because it is the question a reader will actually have: a misspelled *field* is refused and a misspelled *variable* still prints zero. The rule underneath is that what the program declared gets checked and what it did not gets shrugged at -- a variable's name is never declared, a TYPE's field list is. Structures end up the strictest thing in the language, not from a higher standard but because they are the only named thing whose valid spellings are written down. Chapter 14 gains the layout: an instance is a contiguous run of value slots with a diagram of where the fields sit, the three-pass prescan and why each pass exists, why the copy cannot live in akbasic_value_clone(), and why the render depth bound is four rather than eight. Chapter 3 gains the @ suffix, chapter 13 records that all of this is an addition BASIC 7.0 has nothing like, and the verb reference gains TYPE, POINT and DIM ... AS. MAINTENANCE.md gains the two rules that are on a maintainer rather than on a test: a structure copy must not go through clone, and a field chain gets its own leaf field. TODO.md section 5 records what was invented and the three limits that are ours, and section 8 records the two defects the work exposed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
|||
|
23ccb66f69
|
Document the interpreter's architecture as chapter fourteen
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m2s
akbasic CI Build / sanitizers (push) Successful in 3m50s
akbasic CI Build / coverage (push) Failing after 3m22s
akbasic CI Build / akgl_build (push) Failing after 20s
akbasic CI Build / mutation_test (push) Successful in 12m19s
Chapters 1 through 13 describe the language. Nothing described the machine that runs it, and the answers were spread across header comments, TODO.md sections written for a different purpose, and the source itself. Somebody embedding the interpreter, debugging something it did, or adding a verb had to reconstruct the shape from all three. docs/14-architecture.md is that shape, and only that: the three targets and the driver, the single akbasic_Runtime and why nothing is file-scope, akbasic_runtime_step() unrolled with the reason each stage sits where it does, the four modes and what set_mode() does beyond assigning, a line's journey from text through tokens and leaves to a verb handler, the dispatch table, the pool map with what each exhaustion actually says, environments doubling as block state, the two kinds of error, devices, and interrupts. It defers rather than restates. The headers are the authority on every function's contract and the chapter says so up front; where a rule is subtle the header comment already states it at more length than a chapter should. MAINTENANCE.md keeps the conventions and now points here for the mechanism, so there is still one copy of each. Two sections are the reason it exists at all. Debugging: reading a TRON trace as evidence about the loop rather than the lines, reading an akerror stack trace and what it is not, four breakpoints and the expressions worth printing at them, narrowing with ctest -R and the mock devices, and a symptom-to-cause table. Changing it: the verb recipe end to end including the private src/verbs.h prototype that is easy to miss, the rule that a missing dependency capability gets filed upstream rather than worked around, and the five constraints goal 3 puts on any change. A `text` fence tag comes with it. Every fenced block in docs/ is executed and an untagged one is a hard error, so six block diagrams had nowhere to live. The tag means never executed, it is counted in the skip line like `cmake`, and MAINTENANCE.md documents it -- the alternative was an indented block the extractor never sees, and a picture nobody decided about is indistinguishable from a test nobody ran. tests/docs_examples.sh now makes --root and --basic absolute before it starts. Both are used from inside a sandbox directory it cd's into, so the invocation MAINTENANCE.md itself documents -- --root . --basic ./build/basic -- failed every example with "exited 127" and every setup= with "setup failed". CTest passes absolute paths and never saw it; running one document by hand hits it immediately. Writing the error section turned up a defect and TODO.md section 8 records it. The ATTEMPT blocks that turn a script's mistake into an error line wrap parsing and interpretation but not scanning, so a line with more than 32 tokens escapes as an interpreter error: stack trace, exit 1, and at a prompt the REPL is gone. That is the same shape as section 8 item 2, on a path that fix did not cover. Not fixed here -- it is a behaviour change and wants its own tests -- but written down with the three call sites and what would cover them. Both configurations stay green: 95/95 and 94/94. docs_examples now runs 37 programs, 9 transcripts, 45 output comparisons, 3 C snippets, 2 excerpts and 2 shell blocks, and skips 9 text blocks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |