spec-conditions.md §3's remaining half: a clause binds parameters, an invoke-restart supplies them, and what a restart takes is compared at run time because a restart is found by name on a dynamic stack — neither end of the transfer can see the other. The parameters live in a buffer the restart-case owns, not the invoker's frame. A clause runs after every frame between the two has returned (§5), so anything on the invoking side is gone by then; the invoker stores into the target frame while both are still alive, which is the one moment they are. The frame carries the parameter count and a hash of how the types are spelled, and every frame carries them whether it takes parameters or not: a clause taking none has to refuse arguments as loudly as one taking two of the wrong type. The count is not redundant with the hash — it is what makes a 32-bit collision between two different signatures harmless — and the spelling itself rides along so that a mismatch can say what was wanted and what was given, which neither end alone knows. The arguments are evaluated into slots before the invoke node rather than hanging off it. An argument that transfers on its own is then guarded before anything aims the channel, and a call written in an argument is on the ordinary walk Reach and Load already do — a node they treat as a leaf would have dropped the function and failed to link. The other way a transfer starts is the break loop, which chooses by position and has nothing to fill parameters in with. It reaches a clause through the same channel, so nothing downstream could tell the two apart: the frame is pushed with the buffer marked unfilled and a clause with parameters checks that mark before reading it. Refused with the reason rather than run on values no one supplied. runtime/flan_rt.c gains two message functions and nothing else; the restart frame's first four fields, which are the ones C declares, do not move.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%