Re-sequence the language queue now that libakgl closed the gaps

The bump in 7f16337 updated sections 3, 7 and 8 but left the section 4 work
queue still marking groups G and I "file it", which is no longer true.

Groups G and I are unblocked outright. Group E splits: GET, GETKEY and SCNCLR
need nothing further, while WINDOW, KEY, SLEEP, WAIT and TI still want the sink
or a clock. LOCATE was listed in both E and G; it belongs to G alone, because in
BASIC 7.0 it moves the graphics pixel cursor DRAW starts from and the text
cursor verb is CHAR, already in group D.

One gap is genuinely outstanding and upstream named it in the same commit that
added the audio API: FILTER has no SDL3 primitive behind it. It is recorded in
section 7 with the behaviour to apply until an akgl_audio_filter() exists --
refuse at execution rather than silently ignore, since a program that asks for a
low-pass and gets an unfiltered square wave has been lied to.

Also records why the libakgl requirement is pinned by commit rather than by
version: 42b60f7 added 22 public symbols across four headers and left both
VERSION 0.1.0 and the libakgl.so.0.1 soname alone, so AKGL_VERSION_AT_LEAST
cannot tell the two trees apart and a binary built against the new headers
resolves against an old .so without complaint.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 08:01:16 -04:00
parent 7f16337a16
commit 5077efc3a7
2 changed files with 44 additions and 8 deletions

46
TODO.md
View File

@@ -424,13 +424,18 @@ Order by what unblocks the most, and by what does not need `libakgl` to grow fir
| B. Housekeeping | `NEW`, `CLR`, `CONT`, `RESTORE`, `RENUMBER`, `SWAP`, `TRON`, `TROFF`, `HELP` | nothing |
| C. Errors | `TRAP`, `RESUME`, `ER`, `ERR` | needs a BASIC-visible error object |
| D. Strings/format | `USING`, `PUDEF`, `WIDTH`, `CHAR` | nothing |
| E. Console | `GET`, `GETKEY`, `SCNCLR`, `LOCATE`, `WINDOW`, `KEY`, `SLEEP`, `WAIT`, `TI` | sink + `libakgl` input |
| E. Console | `GET`, `GETKEY`, `SCNCLR`, `WINDOW`, `KEY`, `SLEEP`, `WAIT`, `TI` | `GET`/`GETKEY`/`SCNCLR` nothing; the rest want the sink or a clock |
| F. Disk | `DOPEN`, `DCLOSE`, `APPEND`, `RECORD`, `HEADER`, `COLLECT`, `BACKUP`, `COPY`, `CONCAT`, `RENAME`, `SCRATCH`, `DIRECTORY`, `CATALOG`, `DCLEAR`, `DVERIFY`, `SAVE`, `LOAD`, `VERIFY`, `BLOAD`, `BSAVE`, `BOOT` | `aksl_f*` only; no new akgl |
| G. Graphics | `GRAPHIC`, `DRAW`, `BOX`, `CIRCLE`, `PAINT`, `COLOR`, `SCALE`, `SSHAPE`, `GSHAPE`, `LOCATE` | **`libakgl` immediate-mode draw API — file it** |
| G. Graphics | `GRAPHIC`, `DRAW`, `BOX`, `CIRCLE`, `PAINT`, `COLOR`, `SCALE`, `SSHAPE`, `GSHAPE`, `LOCATE` | nothing — `akgl_draw_*` landed at 42b60f7 |
| H. Sprites | `SPRITE`, `MOVSPR`, `SPRCOLOR`, `SPRDEF`, `SPRSAV`, `COLLISION` | `libakgl` sprite/actor API — check before filing |
| I. Audio | `PLAY`, `SOUND`, `ENVELOPE`, `FILTER`, `VOL`, `TEMPO` | **`libakgl` has no mixer-backed audio API — file it** |
| I. Audio | `PLAY`, `SOUND`, `ENVELOPE`, `VOL`, `TEMPO` | nothing — `akgl_audio_*` landed at 42b60f7 |
| I. Audio, still gapped | `FILTER`, `SOUND`'s sweep arguments | `libakgl` has neither; see §7 |
| J. Machine | `SYS`, `FETCH`, `STASH`, `POKE`/`PEEK` variants | nothing |
`LOCATE` used to appear in both E and G. It belongs to G alone: in BASIC 7.0 `LOCATE` moves the
*graphics* pixel cursor that `DRAW` starts from, and the text cursor verb is `CHAR`, which is
already in group D.
**Out of scope, and staying that way** — the reference marks these as incompatible with a
modern PC and that reasoning stands: `BANK` (no bank switching), `FAST` (irrelevant CPU speed
control), `MONITOR` (no machine-language monitor).
@@ -627,8 +632,21 @@ Building against any of it needs `-DAKBASIC_WITH_AKGL=ON`, which pulls in `libak
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.
**One gap is outstanding, and upstream named it itself.** The commit that added the audio API
says plainly what it does not cover: *"Still missing for a complete BASIC sound vocabulary:
`FILTER` (SDL3 has no filter primitive; this would need writing), `TEMPO` and the `PLAY`
note-string parser, both of which belong in the interpreter rather than here."*
- **`TEMPO` and the `PLAY` parser are ours**, not a gap. They are group I work in this
repository and nothing upstream is waiting on.
- **`FILTER` is a real gap.** BASIC 7.0's `FILTER freq, lp, bp, hp, res` sets the SID's
filter cutoff, the three band-pass switches and the resonance. `akgl_audio_*` synthesises
raw waveforms and mixes them; there is no filter stage to configure and SDL3 supplies no
primitive to build one from. Until an `akgl_audio_filter()` exists, `FILTER` is accepted by
the parser and refused at execution with `AKBASIC_ERR_DEVICE` rather than silently ignored —
a program that asks for a low-pass and gets an unfiltered square wave has been lied to.
When the next gap turns up, file it there rather than working around it here.
---
@@ -659,7 +677,23 @@ Dependency baseline:
|---|---|---|
| `deps/libakerror` | 1.0.0 | Private ownership-enforced status registry. akbasic reserves 512767 in `akbasic_error_register()`. Does not namespace its `coverage` target when embedded — worked around in our `CMakeLists.txt`. |
| `deps/libakstdlib` | 0.1.0 | soname `libakstdlib.so.0.1`. `AKSL_VERSION_CHECK()` asserted in `tests/version_check.c`. Its `aksl_ato*` family is banned here — see §1.9. |
| `deps/libakgl` | 0.1.0 | Migrated to the 1.0.0 registry and owns 256260. Not yet linked: `AKBASIC_WITH_AKGL` defaults OFF and `src/sink_akgl.c` does not exist. |
| `deps/libakgl` | 0.1.0, **pinned at commit 42b60f7** | Migrated to the 1.0.0 registry and owns 256260. Not yet linked: `AKBASIC_WITH_AKGL` defaults OFF and `src/sink_akgl.c` does not exist. The version number cannot carry this requirement — see below. |
**The `libakgl` requirement is pinned by commit, not by version, and that is a defect
upstream.** 42b60f7 added 22 public symbols across four headers — `akgl_draw_*` (8),
`akgl_audio_*` (10), `akgl_controller_poll_key`/`_flush_keys`, and `akgl_text_measure`/
`_measure_wrapped` — and left `project(akgl VERSION 0.1.0)` and the `libakgl.so.0.1` soname
unchanged. By that repository's own stated rule, *"0.1 and 0.2 are different ABIs"*, this
should have been 0.2.0. Two consequences land here:
- A binary compiled against the new headers links happily against an installed
`libakgl.so.0.1` built from the old tree, and fails at symbol resolution rather than at
configure time.
- `AKGL_VERSION_AT_LEAST(0, 1, 0)` is true for both trees, so nothing here can feature-test
for the new API. The submodule pointer is the only thing that expresses the requirement.
Filed in `deps/libakgl/TODO.md`. When it is fixed, add the floor to the `find_package` call
and say so here.
CI is split in two. `.gitea/workflows/ci.yaml` runs on push -- the suite, ASan+UBSan, coverage
and a two-file mutation run -- and `.gitea/workflows/release.yaml` is manual