errors: reader errors carry file:line:col (jolt-2o7.5)

Syntax errors were positionless ('Unterminated list', no idea where).
Now they use Clojure's shape:

    Error: Syntax error reading source at (src/app/syn.clj:3:8): Unmatched delimiter: ]
      at src/app/top.clj:1

The reader's 15 error sites raise a {:jolt/reader-error :msg :pos}
struct carrying the byte offset (every site already had pos in scope).
The parse entry points convert offset -> line:col on demand and
re-raise the formatted message: parse-string against its own string
(no file), parse-all-positioned against the full source with the
file threaded in from the loaders — rebasing slice-relative offsets
onto the original source so positions stay absolute. No per-token
cost; nothing is tracked until an error actually happens.

Unmatched-delimiter messages match Clojure's 'Unmatched delimiter: )'
wording. cli-test rows assert positions for unterminated string/list,
unmatched delimiter through a require (composing with round 4's
'while loading' chain), and bad ## tokens. Gate green, suite 4718
steady, bench within noise.
This commit is contained in:
Yogthos 2026-06-12 10:55:42 -04:00
parent 2a3dfd223d
commit 026ad888cd
5 changed files with 88 additions and 24 deletions

View file

@ -86,6 +86,25 @@
(run-err "-e" `(+ 1 "a")`)
(fn [s] (nil? (string/find "<eval>" s))))
# --- round 5: reader errors carry file:line:col ------------------------------
(check "unterminated string positions in -e"
(run-err "-e" `(+ 1 "abc`)
(has "Syntax error reading source at (<eval>:1:10): Unterminated string"))
(check "unterminated list names script file:line:col"
(do (spit (string r4 "/syn.clj") "(ns syn)\n\n(defn f [x]\n (+ x 1\n")
(run-err (string r4 "/syn.clj")))
(has ":5:1): Unterminated list"))
(check "unmatched delimiter positioned"
(do (spit (string r4 "/app/synreq.clj") "(ns app.synreq)\n\n(def x ])\n")
(spit (string r4 "/app/top2.clj") "(ns app.top2 (:require [app.synreq :as q]))\n(defn -main [& a] nil)\n")
(os/setenv "JOLT_PATH" r4)
(run-err "-m" "app.top2"))
(fn [s] (and (string/find "/app/synreq.clj:3:8): Unmatched delimiter: ]" s)
(string/find "/app/top2.clj:1" s))))
(check "bad token positioned"
(run-err "-e" "(def x ##Huh)")
(has "Invalid symbolic value: ##Huh"))
(check "JOLT_DEBUG restores the raw trace"
(do (os/setenv "JOLT_DEBUG" "1")
(def r (run-err "-e" `(+ 1 "a")`))