From 7f16337a16e039c77ff5261ae71df454847bd8b9 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Fri, 31 Jul 2026 07:56:02 -0400 Subject: [PATCH] Bump libakgl to 42b60f7: every gap this port filed is now closed All four capability gaps filed against libakgl have landed upstream, so nothing in this repository is waiting on that library any more. text measurement -> akgl_text_measure, akgl_text_measure_wrapped immediate drawing -> akgl_draw_point/_line/_rect/_filled_rect/_circle/ _flood_fill/_copy_region/_paste_region audio -> akgl_audio_init/_tone/_envelope/_waveform/_volume/ _stop/_voice_active/_mix console input -> akgl_controller_poll_key, akgl_controller_flush_keys The signatures came back close to what was filed, and two details are worth recording for whoever writes src/sink_akgl.c next. The draw calls take an akgl_RenderBackend * as their first argument rather than reaching for a global renderer, which fits goal 3's rule that the interpreter draws through whatever renderer the host already initialized. And the audio API is a synthesised-voice one -- a tone on a numbered voice plus a separate ADSR envelope -- which is the shape PLAY and ENVELOPE actually need, rather than the sample playback SDL3_mixer would have offered. Checked rather than assumed: libakgl's status band is still 256-260, so the coordinated range map in CLAUDE.md is unaffected and akbasic's 512-767 does not move. Documentation that described these as open is corrected in the same commit -- section 7's gap list, section 3's "known gap" note, the priority list, the dependency table, and the README's unimplemented-verbs section all said blocked and no longer are. Section 3 also gains the thing that replaced the gap: the character grid comes from akgl_text_measure(font, "A", &w, &h), the direct equivalent of the font.SizeUTF8("A") at basicruntime.go:96, and akgl_text_measure_wrapped takes the same wraplength argument akgl_text_rendertextat does so the measurement and the draw cannot disagree about where a line breaks. One caveat recorded rather than papered over: -DAKBASIC_WITH_AKGL=ON has never been configured in this repository, because until now there was nothing to build against. The akbasic_akgl target is unproven and needs libakgl's own submodules present. Expect to fix something there on the first attempt. Default build unaffected: ctest 61/61, doxygen exits 0, no warnings. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 2 +- TODO.md | 71 ++++++++++++++++++++++++++++++++++++---------------- deps/libakgl | 2 +- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 0bbf11f..8801270 100644 --- a/README.md +++ b/README.md @@ -410,7 +410,7 @@ Plus six more the original already carried: a leading `0` selects base 8, so `PR * `USING`, `VERIFY`, `VOL`, `WAIT`, `WIDTH`, `WINDOW` * The I/O-channel variants (`GETIO`, `INPUTIO`, `OPENIO`, `PRINTIO`, `RECORDIO`) -Four of those are blocked on capabilities `libakgl` does not have yet — text measurement, immediate-mode drawing, audio, and a non-blocking keystroke read. Rather than work around them here, they are filed in [`deps/libakgl/TODO.md`](deps/libakgl/TODO.md) under "API gaps blocking akbasic", with the entry point each one wants. +None of those is blocked on a missing `libakgl` capability any more. Four were — text measurement, immediate-mode drawing, audio, and a non-blocking keystroke read — and rather than work around them here they were filed in [`deps/libakgl/TODO.md`](deps/libakgl/TODO.md) under "API gaps blocking akbasic". All four have since landed upstream (`akgl_text_measure`, the `akgl_draw_*` family, `akgl_audio_*`, and `akgl_controller_poll_key`), so what is left is akbasic-side work. ## Deliberately out of scope diff --git a/TODO.md b/TODO.md index a466612..6058358 100644 --- a/TODO.md +++ b/TODO.md @@ -371,9 +371,18 @@ such ceiling because it called `make()`. ## 3. Remaining work: the akgl text sink -**`src/sink_akgl.c`.** Implement the §1.5 vtable against `akgl_text_loadfont` and -`akgl_text_rendertextat`. Owns the cursor, the wrap, and the scroll — everything in -`basicruntime_graphics.go` except `Write`/`Println`, which are now the sink interface itself. +**Unblocked as of `libakgl` 42b60f7** — the text-measurement call this waited on now exists. + +**`src/sink_akgl.c`.** Implement the §1.5 vtable against `akgl_text_loadfont`, +`akgl_text_rendertextat` and `akgl_text_measure`. Owns the cursor, the wrap, and the scroll — +everything in `basicruntime_graphics.go` except `Write`/`Println`, which are now the sink +interface itself. + +The character grid comes from `akgl_text_measure(font, "A", &w, &h)`, which is the direct +equivalent of the `font.SizeUTF8("A")` at `basicruntime.go:96` that the reference derives +`maxCharsW`/`maxCharsH` from. For wrapping, `akgl_text_measure_wrapped` takes the same +`wraplength` argument `akgl_text_rendertextat` already does, so the measurement and the draw +cannot disagree about where a line breaks. **The interpreter does not own the window, the renderer, or the game loop.** The sink draws through whatever renderer the host already initialized. `akbasic_sink_init_akgl()` takes the @@ -389,13 +398,15 @@ guaranteed to be unnamed. It is idempotent, so calling it from both `akbasic_sin and a host that already did is harmless. `PASS` its result; a range collision is an initialization failure, not a warning. -**Known gap:** `libakgl` has no text-measurement call — the Go code needs -`font.SizeUTF8("A")` (`basicruntime.go:96`) to compute `maxCharsW`/`maxCharsH`, and there is no -`akgl_text_*` equivalent. **File it in `deps/libakgl/TODO.md`** before writing a workaround. -See §7. +**Still to check before starting:** `-DAKBASIC_WITH_AKGL=ON` has never been configured in this +repository, because until now there was nothing to build against. It needs `libakgl`'s own +submodules present (`git submodule update --init --recursive` pulls SDL and friends), and the +`akbasic_akgl` target in `CMakeLists.txt` has therefore never been compiled. Expect to fix +something there on the first attempt. -*Acceptance:* `tests/sink_akgl.c` against the offscreen renderer harness, or — if that harness -does not exist yet — a known-failing test plus a `libakgl` TODO entry saying so. +*Acceptance:* `tests/sink_akgl.c` against the offscreen renderer harness described in +`deps/libakgl/TODO.md` under "Remaining work". If that harness still does not exist, a +known-failing test plus a `libakgl` TODO entry saying so. --- @@ -595,15 +606,29 @@ When phase 7 or phase 8 needs something `libakgl` does not have, **stop and file the `akgl_*` entry point should look like, and what tests would cover it. Growing `libakgl` to serve the interpreter is a wanted outcome, not a detour. -Known gaps, to be filed as they are reached: +**All four gaps filed so far are now closed upstream**, at `libakgl` 42b60f7. Nothing here is +blocked on `libakgl` any more; what remains is akbasic-side work. -1. **Text measurement.** No `akgl_text_*` call returns the pixel size of a string in a font. - `PRINT` wrapping, the cursor, and `WIDTH` all need it. Blocks 7.1. -2. **Immediate-mode drawing.** `src/draw.c` is at 0% coverage and there is no public API for - lines, boxes, circles or flood fill. Blocks group G. -3. **Audio.** There is no mixer-backed API at all. Blocks group I entirely. -4. **Console input.** `GET`/`GETKEY` need a non-blocking keystroke read that does not require - the interpreter to own the SDL event loop. Blocks part of group E. +| Was blocking | Closed by | +|---|---| +| Text measurement (§3, the akgl sink) | `akgl_text_measure`, `akgl_text_measure_wrapped` | +| Immediate-mode drawing (§4 group G) | `akgl_draw_point`/`_line`/`_rect`/`_filled_rect`/`_circle`/`_flood_fill`/`_copy_region`/`_paste_region` | +| Audio (§4 group I) | `akgl_audio_init`/`_tone`/`_envelope`/`_waveform`/`_volume`/`_stop`/`_voice_active`/`_mix` | +| Console input (§4 group E) | `akgl_controller_poll_key`, `akgl_controller_flush_keys` | + +Two notes for whoever picks up §3 next. The draw calls take an `akgl_RenderBackend *` as their +first argument rather than reaching for a global renderer, which fits the rule that the +interpreter draws through whatever renderer the host already initialized. And the audio API is +a synthesised-voice one — `akgl_audio_tone(voice, hz, ms)` with a separate ADSR envelope — +which is the shape `PLAY` and `ENVELOPE` need, rather than the sample playback SDL3_mixer +would have given. + +Building against any of it needs `-DAKBASIC_WITH_AKGL=ON`, which pulls in `libakgl`'s own +submodules (SDL and friends). Those are not initialized in a default clone; `git submodule +update --init --recursive` gets them. + +No gaps are currently outstanding. When the next one turns up, file it there rather than +working around it here. --- @@ -660,11 +685,13 @@ keeping: What remains, in priority order: -1. **§3 — the akgl text sink.** Blocked on `libakgl` having no text-measurement call; that gap - needs filing in `deps/libakgl/TODO.md` before any workaround is written. -2. **§4 — the language completion work queue.** Groups A, B, D, F and J need nothing from - `libakgl` and can start immediately. Multiple statements per line (the `COLON` token exists - and nothing consumes it) should come first, because `DO`/`LOOP` reads badly without it. +1. **§3 — the akgl text sink.** No longer blocked: `libakgl` 42b60f7 landed + `akgl_text_measure`, so this is now ordinary work. Note that `-DAKBASIC_WITH_AKGL=ON` has + never been configured here, so the `akbasic_akgl` target is unproven. +2. **§4 — the language completion work queue.** Nothing in it is blocked on `libakgl` any more: + groups G, I and part of E were, and `libakgl` 42b60f7 closed all three. Multiple statements + per line (the `COLON` token exists and nothing consumes it) should still come first, because + `DO`/`LOOP` reads badly without it. 3. **§6 items 12–17** — the defects the port uncovered. Item 12 is the one that produces a *wrong answer* rather than a refused one, and should be fixed first. 4. **Mutation survivors in `src/value.c`.** The harness is in place (`scripts/mutation_test.py`, diff --git a/deps/libakgl b/deps/libakgl index 5f03475..42b60f7 160000 --- a/deps/libakgl +++ b/deps/libakgl @@ -1 +1 @@ -Subproject commit 5f03475e0fa81ec2fbd966526f5ba2800faf3b9d +Subproject commit 42b60f725dbbe8450ee07995bb3eb175adc88e4f