diff --git a/host/chez/reader.ss b/host/chez/reader.ss index de853bb..839da8b 100644 --- a/host/chez/reader.ss +++ b/host/chez/reader.ss @@ -645,8 +645,13 @@ (cond ((eq? tag (keyword #f "#uuid")) (jolt-uuid-from-string form)) ((eq? tag (keyword #f "#inst")) (jolt-inst-from-string form)) - (else (jolt-throw (jolt-ex-info (string-append "No reader function for tag " (jolt-pr-str tag)) - (empty-pmap)))))) + ;; No registered reader: throw a clean, catchable ex-info naming the tag, like + ;; the JVM's "No reader function for tag foobar" (empty-pmap is a VALUE — the + ;; old (empty-pmap) applied it as a procedure and crashed the Chez VM). + (else (let* ((nm (keyword-t-name tag)) + (bare (if (and (> (string-length nm) 0) (char=? (string-ref nm 0) #\#)) + (substring nm 1 (string-length nm)) nm))) + (jolt-throw (jolt-ex-info (string-append "No reader function for tag " bare) empty-pmap)))))) (def-var! "clojure.core" "read-string" jolt-read-string) (def-var! "clojure.core" "__parse-next" jolt-parse-next) diff --git a/test/chez/corpus.edn b/test/chez/corpus.edn index 42b9d69..2bb10c7 100644 --- a/test/chez/corpus.edn +++ b/test/chez/corpus.edn @@ -3063,4 +3063,7 @@ {:suite "interop / java.io streams" :label "BufferedReader over StringReader readLine" :expected "[\"a\" \"b\" nil]" :actual "(let [r (java.io.BufferedReader. (java.io.StringReader. \"a\\nb\\n\"))] [(.readLine r) (.readLine r) (.readLine r)])"} {:suite "interop / java.io streams" :label "instance? InputStream" :expected "true" :actual "(instance? java.io.InputStream (java.io.ByteArrayInputStream. (.getBytes \"x\")))"} {:suite "interop / java.io streams" :label "FileOutputStream then FileInputStream round-trip" :expected "90" :actual "(let [f (java.io.File/createTempFile \"jc\" \".t\") o (java.io.FileOutputStream. f)] (.write o (byte-array [90])) (.close o) (let [in (java.io.FileInputStream. f) b (.read in)] (.close in) (.delete f) b))"} + {:suite "clojure.edn / unknown tags" :label "unknown tag throws naming the tag" :expected "\"No reader function for tag foobar\"" :actual "(do (require (quote [clojure.edn :as e1])) (try (e1/read-string \"#foobar 1\") (catch Exception e (ex-message e))))"} + {:suite "clojure.edn / unknown tags" :label "object tag throws naming the tag" :expected "\"No reader function for tag object\"" :actual "(do (require (quote [clojure.edn :as e2])) (try (e2/read-string \"#object [1 2 3]\") (catch Exception e (ex-message e))))"} + {:suite "clojure.edn / unknown tags" :label ":default opt handles an unknown tag" :expected "[\"foobar\" 9]" :actual "(do (require (quote [clojure.edn :as e3])) (e3/read-string {:default (fn [t v] [(name t) v])} \"#foobar 9\"))"} ]