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.
This commit is contained in:
Joseph Ferano 2026-09-11 07:53:35 +07:00
parent 0fea971771
commit 7f803db0b0

45
NEXT.md
View File

@ -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