;;;; A program that stops on a bad index, for driving the break loop over one. ;;;; ;;;; bounds-condition.flan is the other half of the same change and covers the ;;;; path where a `handler-bind` answers. This one covers the path the change ;;;; is actually *for*: **nothing handles it**, so the signal walks the ;;;; handlers, finds none, and reaches `flan_break_hook` — which is where an ;;;; editor picks up a stopped program with the stack, the locals and the ;;;; globals readable and the restarts on offer. ;;;; ;;;; That is the claim `docs/PORTING.md` said was missing, and it is worth testing ;;;; end to end rather than reasoning about: before this, a bad index called ;;;; exit(134), and with `flan dev` running as one process that took the ;;;; compiler and the session with it. ;;;; ;;;; The shape is a frame loop's: one `restart-case` offering `continue` around ;;;; the work, which is sand.flan's shape and the game's. No restart is ;;;; established at the failing index — nothing a handler could do would make ;;;; index 9 valid for a length-4 array — so `continue` is the *program's* own ;;;; restart, found by the ordinary walk, and taking it is the proof that a ;;;; bounds failure now lands somewhere a session can be recovered from. (import agent "vendor:agent") (defvar grid [4 i32]) (defvar skipped i64) ;;; One frame deep under the restart-case, so the transfer has something to ;;; cross and the backtrace has something to show. (defn touch [i i32] () (set (at grid i) 1)) (defn frame [i i32] () (restart-case (do (touch i) (println "frame done")) (continue [] (set skipped (+ skipped 1))))) (defvar ticks i64) (defn main [] i32 (agent/start "/tmp/flan-dev-break-bounds-fallback.sock") ;; Out of bounds on the first frame, with nothing handling it: the daemon ;; meets a program that has already stopped, which is the state an editor ;; has to cope with and the hardest one to arrange later. (frame 9) ;; 1 once `continue` was taken. Printing it is how the transcript says which ;; way the program left the break, rather than that it left. (print skipped) (println "") ;; And it keeps polling on the far side, because the claim worth testing is ;; that everything still works after a break over a bad index. (dotimes [i 4000] (agent/wait 5) (set ticks (+ ticks 1))) 0)