flan/test/programs/edn-provide.flan

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 (length (.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 (length (.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 (length (.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 str
"{: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 str "{: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)