120 lines
4.9 KiB
Plaintext
120 lines
4.9 KiB
Plaintext
;;;; examples/text-codepoints-loading.flan's other half: the scan, the
|
|
;;;; deduplication and the codepoint walk, with no window and no font.
|
|
;;;;
|
|
;;;; The same split core-input-virtual-controls.flan already has. What makes it
|
|
;;;; available here is that the *interesting* part of that example is not the
|
|
;;;; drawing: it is which codepoints a piece of UTF-8 contains, which of them
|
|
;;;; are distinct, and where each one starts in the bytes. All three are
|
|
;;;; arithmetic, LoadCodepoints needs no GL context, and the example's `main`
|
|
;;;; is not exported — so this runs the same code the window runs, without one.
|
|
;;;;
|
|
;;;; Three things are pinned here and they fail for three different reasons.
|
|
;;;;
|
|
;;;; **1. The text survived.** 49 distinct codepoints out of 54 is a
|
|
;;;; property of the Iroha and of nothing else, so a literal that lost a byte
|
|
;;;; between the reader and the object file changes both numbers. The first
|
|
;;;; five distinct codepoints are printed as well, because a count alone would
|
|
;;;; survive a re-ordering.
|
|
;;;;
|
|
;;;; **2. The walk agrees with itself.** The text is stepped from the first
|
|
;;;; codepoint to the last, and then back from the last to the first, and the
|
|
;;;; two sequences are compared. That is what pins `step-back` — the four lines
|
|
;;;; that replace GetCodepointPrevious, which this language cannot call because
|
|
;;;; a Flan string reaches C as a copy and that function reads backwards out of
|
|
;;;; the pointer it is handed. If the continuation-byte test were wrong the
|
|
;;;; backward walk would land mid-sequence and read a different codepoint, and
|
|
;;;; the two sequences would stop being reverses of each other.
|
|
;;;;
|
|
;;;; **3. The walk agrees with raylib.** The sequence the walk produces is
|
|
;;;; compared against the array LoadCodepoints returned, element for element.
|
|
;;;; Item 2 on its own would pass if both walks were wrong in the same way;
|
|
;;;; this is the outside opinion, and it is raylib's rather than ours.
|
|
;;;;
|
|
;;;; Nothing here draws, so nothing here needs the TTF the example looks for.
|
|
|
|
(import cp "../../examples/text-codepoints-loading.flan")
|
|
(import rl "vendor:raylib")
|
|
|
|
(defconst max-walk 128)
|
|
|
|
(defvar forward [max-walk i32])
|
|
(defvar forward-n i32)
|
|
(defvar backward [max-walk i32])
|
|
(defvar backward-n i32)
|
|
|
|
(defn yes-no [b bool] string (if b "yes" "no"))
|
|
|
|
(defn show [name string n i32] ()
|
|
(print name) (print " ") (println n))
|
|
|
|
;; From the first codepoint to the last. step-forward clamps rather than
|
|
;; running off the end — the C does not, which is a bug it gets away with —
|
|
;; so the walk is over when the offset stops moving.
|
|
(defn walk-forward [] ()
|
|
(set forward-n 0)
|
|
(let [off 0
|
|
size 0
|
|
going true]
|
|
(while going
|
|
(set (at forward forward-n) (cp/codepoint-at off (addr size)))
|
|
(set forward-n (+ forward-n 1))
|
|
(let [next (cp/step-forward off)]
|
|
(if (= next off) (set going false) (set off next))))))
|
|
|
|
;; And back again, from wherever forward stopped. Written as a separate walk
|
|
;; rather than as an index into the first one on purpose: the point is that
|
|
;; step-back finds the lead byte of the previous codepoint out of the bytes
|
|
;; alone, so it has to be asked, not remembered.
|
|
(defn walk-backward [start i32] ()
|
|
(set backward-n 0)
|
|
(let [off start
|
|
size 0
|
|
going true]
|
|
(while going
|
|
(set (at backward backward-n) (cp/codepoint-at off (addr size)))
|
|
(set backward-n (+ backward-n 1))
|
|
(if (= off 0)
|
|
(set going false)
|
|
(set off (cp/step-back off))))))
|
|
|
|
(defn main [] ()
|
|
(let [total 0
|
|
raw (rl/load-codepoints cp/text (addr total))]
|
|
(show "codepoints" total)
|
|
(cp/collect-unique (slice-from-ptr raw total))
|
|
(show "unique" cp/unique-count)
|
|
(dotimes [i 5]
|
|
(print "unique ") (print i) (print " ")
|
|
(println (at cp/unique-codepoints i)))
|
|
|
|
(walk-forward)
|
|
(show "forward" forward-n)
|
|
|
|
;; The last codepoint's offset, recomputed the same way walk-forward found
|
|
;; it, because the walk deliberately keeps no offsets.
|
|
(let [last-off 0
|
|
going true]
|
|
(while going
|
|
(let [next (cp/step-forward last-off)]
|
|
(if (= next last-off) (set going false) (set last-off next))))
|
|
(walk-backward last-off))
|
|
(show "backward" backward-n)
|
|
|
|
;; Item 2: the two walks are reverses of each other.
|
|
(let [mirrored (= forward-n backward-n)]
|
|
(dotimes [i forward-n]
|
|
(when (and mirrored
|
|
(not (= (at forward i) (at backward (- (- backward-n 1) i)))))
|
|
(set mirrored false)))
|
|
(print "walks mirror ") (println (yes-no mirrored)))
|
|
|
|
;; Item 3: and the forward walk is what raylib said the text contains.
|
|
(let [agrees (= forward-n total)
|
|
all (slice-from-ptr raw total)]
|
|
(dotimes [i forward-n]
|
|
(when (and agrees (not (= (at forward i) (at all i))))
|
|
(set agrees false)))
|
|
(print "walk matches raylib ") (println (yes-no agrees)))
|
|
|
|
(rl/unload-codepoints raw)))
|