The map dedup is asserted by the case that can only pass if it works

#{{:a 1} {:a 1} {:a 2}} answers 2 whether tables=? compares anything or
compares nothing, so it was proving the count and not the compare. The
pair beside it isolates both halves: one map twice must collapse to 1,
and two maps of one entry each with different keys must stay 2, which is
what a size-only compare would get wrong.

And read's comment stops implying a property it does not have: empty
input answers (Some Value.Nil), indistinguishable from the document that
is nil. Empty is not malformed and the reader is not the thing that gets
to decide it is.
This commit is contained in:
Joseph Ferano 2026-09-18 23:03:56 +07:00
parent cc2cfa175b
commit 51df451e7b
3 changed files with 19 additions and 2 deletions

View File

@ -110,6 +110,13 @@
(set-size "#{[0 0] [0 0] [0 1]}")
(set-size "#{\"a\" \"a\" :a :a}")
(set-size "#{#{1 2} #{2 1}}")
;; Three map cases and not one, because #{{:a 1} {:a 1} {:a 2}} answers 2
;; whether tables=? works or does nothing at all — two merge and one does
;; not, or none merge and there were only ever three. The pair below
;; isolates it: the first must be 1, and the second must be 2 on the
;; *keys*, which a size compare alone would get wrong.
(set-size "#{{:a 1} {:a 1}}")
(set-size "#{{:a 1} {:b 1}}")
(set-size "#{{:a 1} {:a 1} {:a 2}}")
(set-size "#{1 1.0}") ; an int and a float are two values
(set-size "#{true false true}")

View File

@ -592,7 +592,11 @@ let () =
#{#{1 2} #{2 1}} needs set equality to ignore order, 2 for #{1 1.0}
needs an int and a float to stay two values, and 2 for #{[0 0] [0 0]
[0 1]} is the one a dedup written with `=` gets wrong, because two Vec
headers over two blocks are never equal.
headers over two blocks are never equal. The three map sizes are three
and not one because #{{:a 1} {:a 1} {:a 2}} answers 2 whether the map
compare works or does nothing: 1 for #{{:a 1} {:a 1}} is the one that
says it works, and 2 for #{{:a 1} {:b 1}} is the one that says a size
compare alone is not it.
Then "level-1", which is the whole of the copy contract: the document is
read out of a (Vec u8) and every byte of that buffer is then overwritten
@ -607,7 +611,7 @@ let () =
"./source-assets/Sprout Lands Premium/Objects/Mushrooms, Flowers, \
Stones.png\n\
54\ntrue\ntrue\ntrue\nfalse\n\n\
0\n2\n2\n2\n1\n2\n2\n2\n\n\
0\n2\n2\n2\n1\n1\n2\n2\n2\n2\n\n\
level-1\nmalformed\nread\n"
in
outputs "edn/read over the tileset" "programs/edn-read.flan" edn_read_out;

View File

@ -222,6 +222,12 @@
;; document that is literally `nil`, which is the class of quiet wrongness the
;; package's refusals exist to avoid. A caller who needs the byte offset builds
;; the Cursor itself and calls read-value; that is the three lines below.
;;
;; One collision the Option does NOT resolve, said here rather than discovered:
;; empty input answers (Some Value.Nil), the same as the document `nil`. Empty
;; is not malformed — a tokenizer over no bytes reports no error, correctly —
;; and the alternative is this function deciding that an empty file is a
;; failure, which is the caller's question and not the reader's.
(defn read [src [u8]] (Option Value)
(let [c (cursor src)
t (next (addr c))