;;;; 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)))