Re-attempt of the deferred gap, now unblocked. The earlier uberscript break wasn't qualification itself but an aliased-ref resolution bug it exposed: resolve-var looked up ns-aliases (e.g. g/foo) against the analyzer's REBOUND ctx-current-ns (jolt.analyzer, since the analyzer runs interpreted in its own ns) instead of the namespace being compiled. A user's aliased refs failed mid-compile (g/hello -> nil in the bundled standalone). - resolve-var resolves aliases against :compile-ns when set (same ns h-current-ns uses), falling back to ctx-current-ns — correct for both modes. - sq-symbol qualifies a resolved clojure.core name to clojure.core/<name> (Clojure hygiene); special forms stay bare; unresolved syms -> current ns. Tests updated to the qualified behavior (features-test, reader-forms-spec). Co-authored-by: Yogthos <yogthos@gmail.com>
50 lines
2.6 KiB
Text
50 lines
2.6 KiB
Text
# Specification: reader forms + syntax-quote + metadata.
|
|
#
|
|
# Adapted from the jank test corpus (test/jank/{syntax-quote,metadata,reader-macro,
|
|
# call}); we keep our own copies since jank may diverge. Syntax-quoted symbols are
|
|
# qualified to clojure.core (matching jank/Clojure). Platform-specific reader forms
|
|
# (#uuid, #inst, ##Inf/##NaN, bigdecimal/biginteger/ratio) are omitted.
|
|
(use ../support/harness)
|
|
|
|
(defspec "reader / anonymous fn #()"
|
|
["no args" "3" "(#(+ 1 2))"]
|
|
["one arg %" "6" "(#(* % 2) 3)"]
|
|
["positional %1 %2" "[1 2]" "(#(do [%1 %2]) 1 2)"]
|
|
["rest %&" "[1 2 3]" "(#(do %&) 1 2 3)"]
|
|
["fixed + rest" "[2 3]" "(#(do % %&) 1 2 3)"]
|
|
["%2 + rest" "[3]" "(#(do %2 %&) 1 2 3)"]
|
|
["%2 only (placeholder p1)" "20" "(#(* %2 2) 1 10)"]
|
|
["% and %1 same" "10" "(#(+ % %1) 5)"])
|
|
|
|
(defspec "reader / var-quote #'"
|
|
["var-quote = var" "true" "(= (var str) #'str)"]
|
|
["is a var" "true" "(var? #'str)"]
|
|
["deref var-quote" "5" "(do (def w 5) (deref #'w))"])
|
|
|
|
(defspec "reader / metadata ^"
|
|
["meta on map" "true" "(:foo (meta ^:foo {}))"]
|
|
["meta on vector" "true" "(:foo (meta ^:foo [1 2]))"]
|
|
["meta on set" "true" "(:foo (meta ^:foo #{}))"]
|
|
["meta map form" "1" "(:a (meta ^{:a 1} {}))"]
|
|
["meta on quoted sym" "true" "(:foo (meta (quote ^:foo bar)))"]
|
|
["with-meta map" "true" "(:k (meta (with-meta {} {:k true})))"]
|
|
["with-meta vector" "true" "(:k (meta (with-meta [] {:k true})))"]
|
|
["non-metadatable num" "nil" "(meta 100)"]
|
|
["non-metadatable str" "nil" "(meta \"\")"]
|
|
["non-metadatable bool" "nil" "(meta true)"])
|
|
|
|
(defspec "reader / syntax-quote"
|
|
["plain literal" "[1 2 3]" "`[1 2 3]"]
|
|
["gensym distinct" "true" "(not= `meow# `meow#)"]
|
|
["gensym stable" "true" "(let [s `[meow# meow#]] (= (first s) (second s)))"]
|
|
["qualifies unresolved" "(quote user/foo)" "`foo"]
|
|
# jolt-265 (fixed): resolved core symbols fully-qualify to clojure.core/.
|
|
["qualifies core sym" "(quote clojure.core/str)" "`str"]
|
|
["unquote value" "[1 2 3]" "(let [a [1 2 3]] `~a)"]
|
|
["unquote in call" "(quote (clojure.core/str [1 2 3]))" "(let [a [1 2 3]] `(str ~a))"]
|
|
["splice empty" "(quote (clojure.core/str))" "(let [e []] `(str ~@e))"]
|
|
["splice values" "(quote (clojure.core/str 1 2 3))" "(let [a [1 2 3]] `(str ~@a))"]
|
|
["splice in vector" "[1 2 3 0 1 2 3]" "(let [b [0] a [1 2 3] e []] `[~@e ~@a ~@b ~@a ~@e])"]
|
|
# jolt-edb (fixed): ~/~@ inside set literals.
|
|
["splice in set" "#{0 1 2 3}" "(let [b [0] a [1 2 3] e []] `#{~@e ~@a ~@b})"]
|
|
["unquote in set" "#{5 9}" "(let [x 5] `#{~x 9})"])
|