flan/test/programs/dev-inspect.flan

57 lines
2.0 KiB
Plaintext

;;;; 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. And a local of a package's type,
;;;; which is named as the checker names it everywhere else: qualified.
(import agent "vendor:agent")
(import shape "pkgs/shape")
(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.
(defonce 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})
pk (shape/box 3 4)]
(deeper)))
(defonce 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)