From 82cf4299066cc1419506601a830033a6d7ee0891 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sun, 13 Sep 2026 07:50:57 +0700 Subject: [PATCH] Commit the generated bindings, and say that a restart is not a transaction --- NEXT.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/NEXT.md b/NEXT.md index 70ec092..53ea38d 100644 --- a/NEXT.md +++ b/NEXT.md @@ -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.