flan/test/programs/dev-stale.flan
Joseph Ferano ed8dbbcd62 A handler-bind clause runs with only the handlers outside its own form in force, and a stale call in main's running loop stays listed until the callee changes back or the program re-runs
The first is CLHS 9.1.4.1: a clause that signalled the condition it handles used to re-enter itself until the stack ran out. The stale list now names a lifted clause by the function it is written in, and BUILT.md's cost line is measured against master.
2026-09-25 11:15:52 +07:00

47 lines
1.6 KiB
Plaintext

;;;; A program whose callers go stale, for the signature word a dev cell
;;;; carries (docs/BUILT.md, "A signature change installs").
;;;;
;;;; [scale] is the function whose signature the tests change. [step] calls it
;;;; every frame and [pick] takes it as a value, so both are callers compiled
;;;; against the signature it starts with — two sites the session has to name
;;;; after the change, and one the running program has to stop at rather than
;;;; call. [lonely] has no caller at all, so changing its signature leaves
;;;; nothing behind.
;;;;
;;;; The frame loop's `skip-frame' restart is what the break buffer resumes
;;;; with once [step] is compiled again. Without it a stale call would have
;;;; nowhere to go but the exit.
(import agent "vendor:agent")
(defonce ticks i64)
(defonce seen i64)
(defn scale [x i64] i64 (* x 2))
(defn step [] i64
(set ticks (+ ticks 1))
(set seen (scale ticks))
seen)
(defn pick [] (Fn [i64] i64) scale)
(defn lonely [x i64] i64 x)
(defn main [] i32
(agent/start "/tmp/flan-dev-stale-fallback.sock")
(dotimes [i 6000]
(agent/wait 5)
(restart-case (step)
(skip-frame [] 0)))
0)
;;; A stale call inside a handler-bind clause that handles StaleCall. The body's
;;; call to [scale] signals, the clause runs, and the clause's own call to
;;; [scale] signals again — which reaches the handlers outside this
;;; handler-bind and not the clause itself, so it stops in the break buffer
;;; rather than recursing until the stack runs out. The clause is a lifted
;;; function, and the stale list names it as [guarded].
(defn guarded [] i64
(handler-bind [(StaleCall [c] (set seen (scale 1)))]
(scale 5)))