35 lines
1.3 KiB
Plaintext
35 lines
1.3 KiB
Plaintext
;;;; What a handler for a parent reads as the message, and that it is still
|
|
;;;; there after the unwind. The clause below runs after the signalling frames
|
|
;;;; are gone, and [scribble] reuses their stack before the message is
|
|
;;;; printed, so a message left pointing into them prints as garbage.
|
|
|
|
(defstruct IoError :parent Error)
|
|
(defstruct Empty :parent Error [])
|
|
(defstruct MyErr :parent Error [code i32 why str])
|
|
|
|
(defonce zero i64)
|
|
|
|
;; Deep enough, and wide enough, to overwrite what the signal left below.
|
|
(defn scribble [n i32] i64
|
|
(let [junk (array-fill [64] (i64 n))]
|
|
(if (= n 0) (at junk 3) (+ (at junk 5) (scribble (- n 1))))))
|
|
|
|
(defn caught [thunk (Fn [] i32)] i32
|
|
(handler-case (thunk)
|
|
[(Error [e]
|
|
(scribble 40)
|
|
(println (.name e))
|
|
(println (.message e))
|
|
-1)]))
|
|
|
|
(defn main [] i32
|
|
;; A category the program filled in is its own name and message.
|
|
(caught (fn [] (do (error (IoError {.name "io" .message "disk gone"})) 0)))
|
|
;; An empty field vector is the same category.
|
|
(caught (fn [] (do (error (Empty {.name "empty" .message "nothing"})) 0)))
|
|
;; A program's own condition is printed with its values.
|
|
(caught (fn [] (do (error (MyErr {.code 3 .why "bad"})) 0)))
|
|
;; A runtime condition carries the sentence with its values.
|
|
(caught (fn [] (i32 (/ 7 zero))))
|
|
0)
|