53 lines
2.3 KiB
Plaintext
53 lines
2.3 KiB
Plaintext
;;;; 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 `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)
|