;;;; A stopped stack whose OUTER frame holds a local the evaluator cannot see. ;;;; ;;;; dev-locals.flan is about what one frame holds; this one is about which ;;;; frame the answer came from. The whole of the bug the `inspect' verb ;;;; exists for is that an expression is evaluated where the evaluator stands, ;;;; so a local's *name* reaches the right storage only when the frame is the ;;;; innermost one. `mark' below is a global AND a local of the outer frame, ;;;; holding different things of different types: evaluating the name answers ;;;; the global, and rooting at the frame and slot answers the frame. ;;;; ;;;; The other locals are the shapes a path step has to walk and that an ;;;; expression cannot reach at all: an option's payload, which has no ;;;; accessor form in the language, and a union case's field, whose offset ;;;; depends on which case the value is in. (import agent "vendor:agent") (defstruct Point [x f32 y f32]) (defstruct Boom [why i32]) (defdata Shape [Empty (Dot [x f64 y f64]) (Rect [w i32 h i32])]) ;; The discriminator. `outer' binds a local of this name to something else, so ;; every claim about which frame answered is visible in the value itself. (defvar mark i64) ;; The innermost frame, and it is deliberately dull: it holds nothing worth ;; inspecting, so that the frame worth inspecting is not the one an expression ;; would have found by luck. (defn deeper [] i64 (restart-case (do (error (Boom {.why 7})) 1) (carry-on [] 5))) (defn outer [] i64 (let [mark (Point {.x 1.5 .y 2.5}) xs [10 20 30] box (Some (Point {.x 4.5 .y 5.5})) s (Shape.Rect {.w 3 .h 6})] (deeper))) (defvar ticks i64) (defn main [] i32 (set mark 99) (agent/start "/tmp/flan-dev-inspect-fallback.sock") (print (outer)) (println "") (dotimes [i 4000] (agent/wait 5) (set ticks (+ ticks 1))) 0)