Five fixes off the independent review, plus the author's u8 ruling.
x86 parity: the bad-index block always ran x86 (it is flan dev's
default) and now says so with an explicit --x86; the condition render
gets an assertion under the x86 backend too, beside the LLVM one, and
a user error is pinned as carrying no site on both.
ArithError's layout is now pinned: {i32 op; i64 lhs, rhs} in C against
the prelude's defstruct, read field by field through the break loop's
render, driven from the editor through a divide under a restart-case.
That also covers condition and site on LLVM.
Three refusals that were wrong: trap_site tested the prefix "err"
and so ate any site whose path began with those letters; source_line
let Sys_error from input_line escape and take the whole break reply
with it, leaking the handle; and a condition with no fields was
reported as a name no struct has. The daemon now sends its own field
count and the buffer tells the two empties apart.
Nits taken: an over-long site is dropped rather than silently
truncated into a plausible one; the caret pads with the source line's
own tabs; the headline says when it has cut the field list;
flan-cnr-layout is live again as the single spelling of that request
rather than dead beside an inlined copy.
And the ruling: a u8 renders as 97 (\a) where a person is inspecting
and stays 97 where the program is printing.
51 lines
2.3 KiB
Plaintext
51 lines
2.3 KiB
Plaintext
;;;; A program that stops with something worth looking at in the frame.
|
|
;;;;
|
|
;;;; dev-break.flan proves an editor can find out *that* a program stopped and
|
|
;;;; choose a restart; this one is about what the frame holds while it is
|
|
;;;; stopped. One local of each shape the structural printer has an arm for —
|
|
;;;; a parameter, a string, a struct, a fixed array, a bool — plus one that is
|
|
;;;; bound only *after* the error, which is the case that must come back
|
|
;;;; refused rather than rendered: its slot is storage nothing has written yet.
|
|
(import agent "vendor:agent")
|
|
|
|
(defstruct Point [x f32 y f32])
|
|
(defstruct Boom [why i32])
|
|
|
|
(defn look [n i64 label string] i64
|
|
(let [p (Point {.x 1.5 .y 2.5})
|
|
xs [10 20 30]
|
|
flag (> n 0)
|
|
;; Three bytes, for the three answers the character half has. A [u8]
|
|
;; already renders as text, so a lone byte showing only its number is
|
|
;; the one place the same data reads two ways — but only where a
|
|
;; person is inspecting. [println] of a u8 stays a number.
|
|
byte (u8 97) ; printable: 97 (\a)
|
|
gap (u8 32) ; one the reader names: 32 (\space)
|
|
ctl (u8 7)] ; no spelling: the number alone
|
|
;; A loop, for its hidden bound: [dotimes] allocates a slot nobody named,
|
|
;; and the listing must *hide* it rather than refuse it by an invented
|
|
;; name — [s6] is not a variable anyone can find in this file.
|
|
(dotimes [hop 0] (print ""))
|
|
;; And a shadowing rebind. The checker suffixes the repeat as [label~2]
|
|
;; so the debug info never claims one binding is the other; the listing
|
|
;; keeps both raw spellings, because two rows both called [label] with
|
|
;; nothing to tell them apart would be worse.
|
|
(let [label "inner"]
|
|
(restart-case
|
|
(do (error (Boom {.why 7}))
|
|
;; Never reached before the break, so [after] is a slot with nothing
|
|
;; in it: the frame records a null for it and this is what "not bound
|
|
;; yet" has to mean.
|
|
(let [after (i64 99)] after))
|
|
(carry-on [] 5)))))
|
|
|
|
(defvar ticks i64)
|
|
|
|
(defn main [] i32
|
|
(agent/start "/tmp/flan-dev-locals-fallback.sock")
|
|
(print (look 3 "hello")) (println "")
|
|
(dotimes [i 4000]
|
|
(agent/wait 5)
|
|
(set ticks (+ ticks 1)))
|
|
0)
|