The INSERTIONSORT crash, all three rulings (FIX.org 2026-09-20): - (bytes s) allocates a writable copy through the allocator surface — context or (bytes s a), StorageExhausted with retry, a registry note in dev builds (flan_bytes_dup, lowered like vec-new). (bytes-view s) is the old zero-cost reinterpret, renamed, read-only by convention; every in-repo reader swept over to it. (string b) unchanged. - String constants were already read-only on both backends at -O0; now pinned — bytes-copy.flan rows on LLVM/-O0/--x86, and dies_segv rows asserting the write-through-view trap on both backends. - A dev build installs a SIGSEGV/SIGBUS handler by the same dev-only constructor slot that arms the registry: one line naming the address and the innermost frame, then the trap-hook park — stopped, not dead, the daemon serving. No agent: message and re-raise. Release builds untouched. Pinned by trap_park over dev-segv.flan.
121 lines
5.4 KiB
Plaintext
121 lines
5.4 KiB
Plaintext
;;;; defedn over two real files, and the condition a drifted one signals.
|
|
;;;;
|
|
;;;; The first half is the claim the feature is for: `(.texture-path t)` here
|
|
;;;; is a field load off a struct nobody declared, and the same numbers
|
|
;;;; edn-read.flan prints through the dynamic reader come out of it. Two
|
|
;;;; readers over one file agreeing is what says the derived one is right —
|
|
;;;; either alone could be self-consistently wrong.
|
|
;;;;
|
|
;;;; The second half is the shape matrix: a string, an integer, a float, a
|
|
;;;; boolean, a vector, and a map inside a map, each read back.
|
|
;;;;
|
|
;;;; The third is drift. The struct was derived from the file as it was when
|
|
;;;; this was compiled; the bytes read at run time are a later version of it,
|
|
;;;; with one key gone and one arrived. Both are named by SchemaDrift, which is
|
|
;;;; the whole reason the reader carries one: a missing key otherwise leaves a
|
|
;;;; field at zero and the program draws nothing for a reason nothing reports.
|
|
|
|
(import edn "vendor:edn")
|
|
|
|
;; Both derived at compile time, from the files as they sit beside this one.
|
|
;; The path is the (embed "...") path — relative to this file — and not the
|
|
;; path the run-time reads below use, which is relative to the process.
|
|
(edn/defedn Tileset "assets/edn/tileset.edn")
|
|
(edn/defedn Tuning "assets/edn/tuning.edn")
|
|
|
|
;; The same file the dynamic reader in edn-read.flan walks. Embedded rather
|
|
;; than read, so this half asserts the reader and not the filesystem.
|
|
(defconst tileset (embed "assets/edn/tileset.edn"))
|
|
(defconst tuning (embed "assets/edn/tuning.edn"))
|
|
|
|
(defn show-tileset [a Allocator] ()
|
|
(let [t (Tileset-of-bytes tileset a)]
|
|
;; The line edn-read.flan prints first, off a struct field this time.
|
|
(println (.texture-path t))
|
|
;; 54 pairs, and the same three memberships and one miss. A derivation
|
|
;; that flattened the pairs into 108 integers would have a different count
|
|
;; and would answer no to every one of these.
|
|
(println (len (.selected-cells t)))
|
|
(println (has-key? (.selected-cells t) [3 4]))
|
|
(println (has-key? (.selected-cells t) [0 0]))
|
|
(println (has-key? (.selected-cells t) [4 11]))
|
|
(println (has-key? (.selected-cells t) [9 9]))))
|
|
|
|
(defn show-tuning [a Allocator] ()
|
|
(let [t (Tuning-of-bytes tuning a)]
|
|
(println (.name t))
|
|
(println (.hp t))
|
|
(println (.speed t))
|
|
(println (if (.boss? t) "yes" "no"))
|
|
(println (len (.drops t)))
|
|
;; 3 + 1 + 4 + 1 + 5. A vector read that stopped at the first element would
|
|
;; still have a plausible length from a zeroed Vec, so the sum is the claim.
|
|
(let [total (i64 0)]
|
|
(dotimes [i (len (.drops t))]
|
|
(set total (+ total (at (.drops t) i))))
|
|
(println total))
|
|
;; The nested structs, by the names the paths give them: Tuning-hitbox and
|
|
;; Tuning-hitbox-offset. Both are ordinary field loads, two deep.
|
|
(println (.w (.hitbox t)))
|
|
(println (.h (.hitbox t)))
|
|
(println (.x (.offset (.hitbox t))))
|
|
(println (.y (.offset (.hitbox t))))))
|
|
|
|
;; ── Drift ───────────────────────────────────────────────────────────
|
|
;;
|
|
;; The struct says :name :hp :speed :boss? :drops :hitbox. These bytes have no
|
|
;; :speed and have a :level the struct has never heard of, which is what a
|
|
;; tuning file looks like a month after the program was built.
|
|
(defconst drifted string
|
|
"{:name \"imp\" :hp 3 :level 7 :boss? true :drops [1] :hitbox {:w 1 :h 1 :offset {:x 0 :y 0}}}")
|
|
|
|
(defn show-drift [a Allocator] ()
|
|
(handler-bind
|
|
[(edn/SchemaDrift [d]
|
|
(do (print (if (.extra? d) "extra " "missing "))
|
|
(print (.field d))
|
|
(print " in ")
|
|
(println (.struct d))))]
|
|
(let [t (Tuning-of-bytes (bytes-view drifted) a)]
|
|
;; The fields that were there are read, which is the other half of the
|
|
;; contract: a drifted file is reported, not refused. :speed is the one
|
|
;; that was missing and is zero.
|
|
(println (.name t))
|
|
(println (.hp t))
|
|
(println (.speed t)))))
|
|
|
|
;; ── A file that does not parse ──────────────────────────────────────
|
|
;;
|
|
;; The louder failure, and the one that had the quieter answer until ReadFailed
|
|
;; existed: a generated reader accumulates errors on the cursor, and the cursor
|
|
;; is made and dropped inside the entry point, so a stray brace gave back a
|
|
;; zeroed struct with nothing said. The rest of this package refuses to do
|
|
;; that — read-file answers an Option so that a malformed document is
|
|
;; distinguishable from one that is literally nil — and a derived reader has to
|
|
;; be at least as honest.
|
|
(defconst broken string "{:name \"orc\" :hp }")
|
|
|
|
(defn show-broken [a Allocator] ()
|
|
(handler-bind
|
|
[(edn/ReadFailed [e]
|
|
(do (print "unreadable ")
|
|
(print (.struct e))
|
|
(print ": ")
|
|
(println (edn/error-message (.code e)))))]
|
|
(let [t (Tuning-of-bytes (bytes-view broken) a)]
|
|
;; Read anyway, and zeroed, which is the half a handler that carries on
|
|
;; is choosing. Printed so that "it signalled" and "it gave back nothing
|
|
;; usable" are two claims rather than one.
|
|
(println (.hp t)))))
|
|
|
|
(defn main [] i32
|
|
(let [a (heap-allocator)]
|
|
(show-tileset a)
|
|
(println "")
|
|
(show-tuning a)
|
|
(println "")
|
|
(show-drift a)
|
|
(println "")
|
|
(show-broken a))
|
|
0)
|