From 7f803db0b061a749f0d35ce221b31c56ada3e4ee Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 11 Sep 2026 07:53:35 +0700 Subject: [PATCH] A place for the next session to start The dev loop is done and conditions are one step of four in, so NEXT.md leads with what to pick up rather than with how things got here. Everything step 2 needs has been decided and none of it is written: the channel is an out-parameter, every function is transfer-transparent for now with escape analysis left as an optimisation, restarts take no parameters in v1, and a transfer target is a static clause id because unwinding stops at the innermost frame carrying it. --- NEXT.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/NEXT.md b/NEXT.md index 982fbc8..7049068 100644 --- a/NEXT.md +++ b/NEXT.md @@ -1,5 +1,50 @@ # Where this is +## Start here — next session + +**Branch `dev-loop`, 14 commits, working tree clean, `dune test` green.** + +The dev loop works end to end: `flan dev program.flan`, then `C-c C-c`, +`C-x C-e` and `C-c C-r` in Emacs against the running process. Conditions are +one step in of four. + +**The next task is conditions step 2: `restart-case` and `invoke-restart`.** +Everything it needs has been decided; nothing has been written. + +- Read `spec-conditions.md` §3–§6. §6 was amended in `0fea971` and now names + both the reason transfer is lowered explicitly and the channel it uses. +- **The channel is an out-parameter**: a `ptr` appended to every Flan + function's signature, written by a transfer and checked after each call. Not + a discriminated return value, and not a global — a global is not re-entrant + because §5 runs defers *during* a transfer. +- **Scope v1 deliberately smaller than the spec**, and reject the rest by name + as the house rule requires: + - **every Flan function is transfer-transparent**, in release too. §6's + escape analysis is an optimisation for later; uniform is correct and + simple now. + - **restarts take no parameters.** That covers the spec's own `load-texture` + example, and skips argument marshalling and §3's runtime arity check. +- **A transfer target is a static clause id.** It can be static even though a + `restart-case` may be re-entered, because unwinding stops at the first frame + carrying that id — walking outward, the first is the innermost, which is the + activation §4's lookup found. +- A caught transfer must pop the restart frames and run the defers between + (§5) before the clause body starts. `errdefer` must *not* run: a restart is a + chosen recovery, not a failure. +- Sand has no raylib callback, so nothing in the demo path hits §6's "a + transfer cannot cross a foreign frame" wall. + +After step 2: the dev-build break loop (§2), which is where **"a crash kills +the program"** finally gets fixed; then restarts offered in the Emacs +minibuffer, which wants `compute-restarts` plus two protocol ops. SBCL's +restart struct carries `report-function` and `interactive-function` for exactly +that prompt and `spec-conditions.md` mentions neither — worth adding before +that step. + +Read SBCL for what restarts should *mean* and ignore how it moves control: it +transfers with `block`/`return-from`, which §6 rules out. + + **The dev loop is closed.** `C-c C-c` in Emacs recompiles the top-level form at point and installs it in a running program, at that program's next frame boundary. Verified against sand: an unsaved buffer edit to `game-draw`, and 240