Commit the generated bindings, and say that a restart is not a transaction

This commit is contained in:
Joseph Ferano 2026-09-13 07:50:57 +07:00
parent 54027ca942
commit 82cf429906

40
NEXT.md
View File

@ -1,3 +1,43 @@
## Queued: commit the generated bindings, with a config beside them
**Decided.** `flan import-c` already exists and prints the lines; kebab-casing is already implemented and reversible
(the C symbol is kept verbatim in `Ast.DeclareC`, so the rule never has to be undone).
**Generate once, commit the result, regenerate when raylib moves.** What changes against today's opt-in header read:
no header is needed by anyone, so the `?${FLAN_RAYLIB_H}` split disappears and every build gets all 428 bindings; the
bindings become greppable and diffable in the repo; and the hand-written 172 stop being a separate set to maintain.
Caching is not the argument — the dump is already cached on disk and in memory.
**What is given up, and it is the real cost:** the build-time check against the real header stops being automatic and
becomes something run at regeneration. That check earned its place — it verified all 172 hand-written declarations and
all 16 struct layouts against raylib 5.5 and found them exactly right, and against a 5.1-dev header on the same
machine it found ten genuine differences. Keep it as a step, and make regeneration run it.
**A config file beside `headers`**, because the generated file is committed and therefore any hand-edit is destroyed by
the next regeneration — the config is what survives. Wanted: **exclude patterns**, and **name overrides** where
kebab-casing gives something ugly. A postprocessing transform pass was considered and rejected: it is a second program
to understand and the config covers the real cases.
**Document it on the web page.** `web/index.html` has no section on the FFI's generated half.
**Later, not now: an idiomatic layer.** Thin Flan-shaped wrappers *over* the generated bindings, not instead of them —
the generated set stays honest to C, and the layer is where a Flan-shaped API lives.
## Queued: a restart is not a transaction, and the docs must say so
Raised by the author, and it is a real sharp edge rather than a gap. **If a frame mutates a global and then signals,
taking a `retry` re-runs the mutation.** Nothing rolls back. Common Lisp has exactly this property and offers no help
either — restarts are explicitly not transactional.
The discipline is that **the author chooses where the retry boundary is**: a `restart-case` at the top of a frame
re-runs everything including mutations already applied; one placed after the mutations re-runs only what follows. So
either put the restart before anything mutates, make the retried section idempotent, or snapshot what will be
re-applied.
This matters more here than in most Lisps because the intended use is a **game loop**, where the author's plan is to
skip a frame and carry on rather than die — exactly the case where a non-idempotent mutation bites. Write it into
`conditions.org` and `spec-conditions.md`'s prose, and into `web/index.html` beside the restart documentation.
## Picked up first, 2026-09-13
Three things, in order. The first two are one line each and unblock a real game.