From ad092d7d02ec758e493b32b7e3cedc583fee22bf Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 11 Sep 2026 20:04:29 +0700 Subject: [PATCH] The fixed stack needs a case, and .5 needs a decision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit err-too-deep was the one error code nothing observed. The message is the least of it: the plausible wrong version is `>` where the guard wants `>=`, which writes one element past a [32 i32] and traps at exit 134 rather than answering anything. 33 opening brackets is the input that separates them, and it is the whole justification for a fixed array instead of a growable stack — the place this lane pushes hardest against having no allocator. `.5` reads as a float here and does not in EDN, where a number must start with a digit and `.` is a legal symbol-start byte. That makes it a reinterpretation of a token that is already legal as something else, which is exactly what the house rule says to name rather than leave to be discovered, so it is written beside the refusals. Also: every symbol in the table was lowercase, so the A-Z half of alpha? was unexercised and a version missing it passed. Enemy/Goblin in an existing dump rather than a new case. And a line under "Internal helpers" saying the heading is intent and not enforcement — a package has no visibility, so edn/scan-atom is as callable as edn/next, the same way rl/get-color-raw is. Both new cases verified by mutation: the depth guard traps, and alpha? without its uppercase range fails Enemy/Goblin. --- test/programs/edn.flan | 9 ++++++++- test/test_acceptance.ml | 3 ++- vendor/edn/edn.flan | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/test/programs/edn.flan b/test/programs/edn.flan index d54739a..a1d7b2c 100644 --- a/test/programs/edn.flan +++ b/test/programs/edn.flan @@ -145,7 +145,9 @@ (dump "-1 +2 0") ; the signs are part of the number (dump "1.5 -2.5e3 .5") ; f, and a leading dot is a float (dump "true false nil") ; b b n — and not three symbols - (dump "foo foo/bar -") ; `-` alone is a symbol; `foo/bar` is NOT a ratio + ;; `-` alone is a symbol, `foo/bar` is NOT a ratio, and the uppercase half + ;; of the alphabet test is only exercised by a name that has one in it. + (dump "foo Enemy/Goblin -") (dump ":a :foo/bar") ; k, text without the colon (newline) @@ -215,6 +217,11 @@ (refusal "[1 2}") ; the wrong closer (refusal "]") ; a closer with nothing open (refusal "[1 2") ; end of input with something still open + ;; 33 opening brackets against a 32-deep stack. The error message is the + ;; least of what this checks: a `>` where the guard needs `>=` writes one + ;; past the end of a fixed array, and the answer is a bounds trap rather + ;; than a wrong message. The offset is the 33rd bracket. + (refusal "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[") (newline) ;; ── The struct reader ───────────────────────────────────────────── diff --git a/test/test_acceptance.ml b/test/test_acceptance.ml index ccfd5cf..9ea3694 100644 --- a/test/test_acceptance.ml +++ b/test/test_acceptance.ml @@ -404,7 +404,7 @@ let () = i<-1>i<+2>i<0> f<1.5>f<-2.5e3>f<.5> bbn -yyy<-> +yyy<-> kk [<>i<1>]<> @@ -452,6 +452,7 @@ s 4 unbalanced: this closing delimiter does not match the one that is open 0 unbalanced: this closing delimiter does not match the one that is open 4 unbalanced: this closing delimiter does not match the one that is open +32 nesting is too deep: the balance stack is a fixed array and it is full [goblin] hp=12 speed=1.5 boss=no [dragon] hp=40 speed=0 boss=yes diff --git a/vendor/edn/edn.flan b/vendor/edn/edn.flan index eb41be4..72df9df 100644 --- a/vendor/edn/edn.flan +++ b/vendor/edn/edn.flan @@ -53,6 +53,17 @@ ;;;; a byte once anything is non-ASCII, and there is no ;;;; code point type. ;;;; +;;;; ── One place this is not EDN, on the record ──────────────────────── +;;;; +;;;; `.5` is a float here. In EDN a number must begin with a digit and `.` is +;;;; a legal symbol-start byte, so strictly `.5` is the *symbol* `.5` — which +;;;; makes this a reinterpretation of a legal token and not an extension, and +;;;; therefore the kind of thing that gets written down rather than discovered. +;;;; It is this way because number-start? runs before the symbol case and +;;;; parse-f64 accepts a leading dot; a caller who needs the symbol reading +;;;; should not be writing `.5` at all. `-`, by contrast, is a symbol, because +;;;; number-start? requires a digit after the sign. +;;;; ;;;; ── Errors ────────────────────────────────────────────────────────── ;;;; ;;;; On the cursor, not in the return type. `next` answers a Token whose kind @@ -221,6 +232,10 @@ (= b \/))) ;; ── Internal helpers ──────────────────────────────────────────────── +;; +;; "Internal" by intent and not by enforcement: a package has no visibility +;; yet, so edn/scan-atom and edn/push-open are as callable as edn/next is. +;; Nothing below is part of the API and none of it will keep its shape. (defn at-end? [c (Ptr Cursor)] bool (>= (.pos c) (len (.src c))))