A breakpoint, which is only error under a restart-case
This commit is contained in:
parent
81d46c342e
commit
4857db1fc4
@ -389,3 +389,22 @@ is stopped inside it, and the new body happens to have the same number of slots
|
||||
of the same types, the frame will show the *new* names against the *old*
|
||||
values. The check that should catch this does not fire. There is a failing test
|
||||
pinned to it, so this is recorded rather than lurking.
|
||||
|
||||
## Stopping on purpose
|
||||
|
||||
`(pause)` stops the program where it stands and hands it to the break loop.
|
||||
`C-c C-b` then shows the stack, `TAB` opens a frame's locals, and taking
|
||||
`continue` resumes at the call as though nothing happened.
|
||||
|
||||
It is spelled `pause` rather than `break` because `break` is reserved for
|
||||
leaving a loop — the same word meaning "exit this loop" and "stop for
|
||||
inspection" in the same position would be the worst available collision.
|
||||
|
||||
Nothing in the compiler implements it. It is an `error` under a `restart-case`,
|
||||
written in the prelude, which is what a breakpoint *is* in a language that
|
||||
already has conditions. One consequence worth knowing: a `handler-bind` above
|
||||
it can intercept a `Pause` and decline to stop, so a release build can neuter
|
||||
every breakpoint in the program without editing any of them.
|
||||
|
||||
**Untested.** It compiles and the shape is right, but nobody has run it into a
|
||||
real break loop yet.
|
||||
|
||||
@ -44,6 +44,28 @@ let source = {flan|
|
||||
;; handler or the break loop, where a working allocator is known.
|
||||
(defstruct StorageExhausted [bytes i64 align i64 allocator i64])
|
||||
|
||||
;; A breakpoint. (pause) stops the program where it stands and hands it to the
|
||||
;; break loop, with the whole stack under it readable — C-c C-b lists the
|
||||
;; frames, TAB opens one, and taking `continue` resumes at the call.
|
||||
;;
|
||||
;; It is spelled `pause` and not `break` because `break` is reserved for
|
||||
;; leaving a loop (parse.ml refuses it by name, with the milestone), and a
|
||||
;; breakpoint and a loop exit in the same word would be the worst kind of
|
||||
;; collision: both are legal in the same place and mean opposite things.
|
||||
;;
|
||||
;; Nothing in the compiler knows about this. It is `error` under a
|
||||
;; `restart-case`, which is exactly what a breakpoint is in a language that
|
||||
;; already has conditions: the break loop is entered because nothing handled
|
||||
;; the condition, and `continue` is an ordinary restart whose body is empty, so
|
||||
;; taking it returns here and the caller carries on. A handler-bind above it
|
||||
;; can therefore also intercept a Pause and decline to stop, which is the
|
||||
;; behaviour a release build wants and gets for free.
|
||||
(defstruct Pause [])
|
||||
|
||||
(defn pause []
|
||||
(restart-case (error (Pause {}))
|
||||
(continue [] (do))))
|
||||
|
||||
;; A seeded PRNG in Flan rather than libc's, because a grid hash is only a
|
||||
;; regression test if the sequence is byte-identical on native and wasm32
|
||||
;; (plan.org, RNG is ours). PCG-XSH-RR 32: one u64 LCG step per draw, folded
|
||||
|
||||
@ -418,6 +418,8 @@
|
||||
col (/ (i32 (.x m)) cell-size)]
|
||||
(paint-at row col)))
|
||||
|
||||
(defstruct Pause [])
|
||||
|
||||
;; Every cross-function call in a dev build routes through an indirection cell,
|
||||
;; so redefining this from the REPL reaches the running loop on the next frame.
|
||||
;; No `varfn` (Janet), no `let update = ref` (OCaml), no var-routing (jank).
|
||||
@ -439,6 +441,7 @@
|
||||
(when (rl/key-released? :space) (next-color) (plink 1.4))
|
||||
(when (rl/mouse-button-pressed? :right) (reset-view) (plink 0.6))
|
||||
(when (rl/mouse-button-pressed? :left) (plink 1.0))
|
||||
(when (rl/key-pressed? :f) (error (Pause {})))
|
||||
(when (rl/key-pressed? :m) (toggle-music))
|
||||
;; The pad, when there is one. Pressed and released are separate events here
|
||||
;; too, for the same reason.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user