The reload path had never seen a restart-case or a handler-bind: the acceptance table's dev build proves whole-program codegen with cells, but not Emit.redefinition, where the callees are declares or cell loads and the restart frame is an alloca in a module the process was not built with. Driving it found a hole step 1 left - a lifted clause was numbered by its position in the whole program's lifted list, so the name was neither stable against an unrelated handler-bind being added nor attributable to the function it came out of, and redefining a function that established a handler died in llc with an undefined value. A clause is now named after its parent - handler/step/0/Missing - and carries Tast.fn.fparent, which is what lets a redefinition module emit the clauses belonging to the bodies it is replacing and nothing else. They are hidden for the same reason a redefined body is: taking the address of an interposable symbol would resolve to the host's copy, so the module would install the very handler it was replacing. A clause is reached by address from its parent and from nowhere else, so it is kept out of the cell and registry machinery entirely rather than given a slot nobody uses. test_dev.ml now sends a third evaluation: step redefined to a restart-case whose frame is an alloca in the new module, whose guarded call goes through the host's cell, and whose transfer starts in a handler and crosses probe, which the host was compiled with. The transcript's fourth line is the clause's value.
32 lines
1019 B
Plaintext
32 lines
1019 B
Plaintext
;;;; What [flan dev] launches: a program with a loop, a function to redefine,
|
|
;;;; and a way to stop. The daemon overrides the socket path through the
|
|
;;;; environment, so the one written here is only what it falls back to.
|
|
(import agent "vendor:agent")
|
|
|
|
(defvar ticks i64)
|
|
|
|
;;; A condition and something that signals it, so that a body typed in later
|
|
;;; can establish a handler and transfer past this frame — spec-conditions.md
|
|
;;; §6. It is here rather than in the evaluated form on purpose: the guard that
|
|
;;; forwards the transfer has to be one the *host* was compiled with.
|
|
(defstruct Missing [id i32])
|
|
|
|
(defn probe [] i64
|
|
(signal (Missing {:id 1}))
|
|
0)
|
|
|
|
(defn step [] i64
|
|
(set ticks (+ ticks 1))
|
|
ticks)
|
|
|
|
(defn main [] i32
|
|
(agent/start "/tmp/flan-dev-fallback.sock")
|
|
(print-i64 (step)) (newline)
|
|
(while (= (agent/wait 100) 0) 0)
|
|
(print-i64 (step)) (newline)
|
|
(while (= (agent/wait 100) 0) 0)
|
|
(print-i64 (step)) (newline)
|
|
(while (= (agent/wait 100) 0) 0)
|
|
(print-i64 (step)) (newline)
|
|
0)
|