flan/spike/x86/p7-slice-from-ptr.flan
Joseph Ferano a4c6b996ff def re-runs its initialiser, and defvar is renamed defonce
The trio the author decided on 2026-09-20 is now all built: def is CL's
defparameter — its initialiser runs on every daemon re-run, unguarded, so
an edited initialiser repaints the same storage on C-c C-c plus re-run —
defonce (Clojure's name for CL's defvar, per the author) initialises once
behind the .init~once. flag, and defconst stays the image.

One parse arm reads both forms; the difference is Ast.reinit, carried to
Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and
Check.check_global lifts every def initialiser — zero and literal
included — into global/<n>, so the host's startup reaches it through the
function cell and a re-evaluated def swaps it (Session's def_inits;
Emit.redefinition declares the cell for a non-sibling target). The old
defvar spelling is refused with the rename and both compiling spellings,
and every program, test, doc and editor list is swept — except sand.flan,
the author's live WIP, whose seven defvar lines are flagged in FIX.org
and keep its three dependent tests red on this branch.
2026-09-21 07:12:04 +07:00

47 lines
1.7 KiB
Plaintext

;;;; (slice-from-ptr p n) with a length the checker cannot see.
;;;;
;;;; test/programs/slice-from-ptr.flan covers the form itself, but every length
;;;; in it is a literal, and a negative literal is refused by check.ml before
;;;; any code is emitted. So the run-time half of the check -- the one both
;;;; backends plant beside the form -- is walked by nothing in the corpus.
;;;;
;;;; The half that matters here is that the test is *signed*. check_slice's own
;;;; compares are unsigned, and a negative i32 sign-extended to 64 bits is a
;;;; huge unsigned value that an unsigned "hi <= len" waves straight through.
;;;; Getting that wrong yields a slice whose length is about 2^64, which reads
;;;; as a pass and segfaults somewhere else entirely.
;;;;
;;;; Both cases go through a restart-case, so what is compared is the message
;;;; on stderr as well as the fact that something was signalled.
(defonce a [4 i32])
(defn promised [n i32] i32
;; n is a parameter, so the checker has no literal to look at.
(restart-case
(let [s (slice-from-ptr (addr (at a 0)) n)]
(len s))
(give-up [] -1)))
(defn show [name string n i64] ()
(print name)
(print " ")
(println n))
(defn main [] ()
(dotimes [i 4]
(set (at a i) (* (+ i 1) 10)))
(handler-bind
[(BoundsError [c]
(show "low" (.low c))
(show "high" (.high c))
(show "length" (.length c))
(invoke-restart 'give-up))]
(println (promised 4)) ; 4 -- the truth
(println (promised 0)) ; 0 -- empty is not an error
(println (promised 2)) ; 2 -- shorter than the truth is legal
(println (promised -1)) ; -1 -- signalled, and the restart answered
(println (promised -1000000))))