compiler: resolve :as aliases in macro detection; fix analyzer compile-ns

- compiler/resolve-macro now resolves :as aliases (like resolve-var), so aliased
  macro calls (t/is) are recognized and compiled via expansion instead of falling
  back. Compile-mode suite holds at 3932.
- host/current-ns reads a backend-stashed :compile-ns rather than ctx-current-ns:
  the interpreter rebinds current-ns to a fn's defining ns while it runs, so the
  interpreted analyzer (defined in jolt.analyzer) would otherwise mis-resolve the
  user's compile ns. Fixes def/intern targeting the wrong namespace.

Analyzer stays interpreted (compiling it needs qualified-ref compilation, which
regresses the clojure.test shim — jolt-4xc). Self-host pipeline correct (218/218),
full suite green.
This commit is contained in:
Yogthos 2026-06-06 09:48:52 -04:00
parent b3a80507cc
commit 98bf389f82
3 changed files with 22 additions and 7 deletions

View file

@ -157,10 +157,10 @@
(defn- ensure-analyzer [ctx]
# Load jolt.analyzer (and transitively jolt.ir) once; jolt.host is pre-installed
# by host/install! so its require is a no-op. The analyzer currently runs
# INTERPRETED — compiling it via the bootstrap is blocked by bootstrap
# miscompilation bugs on the constructs it uses (tracked); correctness is fine,
# speed is the open item.
# by host/install! so its require is a no-op. The analyzer runs INTERPRETED:
# compiling it via the bootstrap needs qualified-ref compilation, which
# regresses compile mode (the clojure.test shim breaks) — tracked in jolt-4xc.
# Correctness is unaffected (218/218 conformance); speed is the open item.
(when (= 0 (length ((ctx-find-ns ctx "jolt.analyzer") :mappings)))
(eval-form ctx @{} (r/parse-string "(require '[jolt.analyzer])"))))
@ -169,8 +169,14 @@
returning host-neutral IR."
[ctx form]
(ensure-analyzer ctx)
# Capture the real compile ns: the analyzer runs interpreted (defined in
# jolt.analyzer), and the interpreter rebinds current-ns to a fn's defining ns
# while it runs — so h/current-ns must read this instead of ctx-current-ns.
(put (ctx :env) :compile-ns (ctx-current-ns ctx))
(def av (ns-find (ctx-find-ns ctx "jolt.analyzer") "analyze"))
((var-get av) ctx form))
(def r ((var-get av) ctx form))
(put (ctx :env) :compile-ns nil)
r)
(defn compile-and-eval
"Self-hosted compile path: analyze (portable Clojure) -> IR -> Janet -> eval.

View file

@ -184,7 +184,12 @@
(let [name (sym-s :name)
ns-sym (sym-s :ns)]
(if ns-sym
(let [target-ns (ctx-find-ns ctx ns-sym)
# Resolve :as aliases (e.g. (t/is …) where t aliases clojure.test) so
# aliased macros are recognized as macros — matching the interpreter's
# resolve-var — rather than miscompiled as a value ref to the macro var.
(let [cur (ctx-find-ns ctx (ctx-current-ns ctx))
aliased (ns-import-lookup cur ns-sym)
target-ns (ctx-find-ns ctx (or aliased ns-sym))
v (ns-find target-ns name)]
(if (and v (var-macro? v)) v))
(let [current-ns-name (ctx-current-ns ctx)

View file

@ -74,7 +74,11 @@
(defn h-special? [name] (if (get special-names name) true false))
(defn h-current-ns [ctx] (ctx-current-ns ctx))
# The namespace being compiled. NOT ctx-current-ns directly: the interpreter
# rebinds current-ns to a fn's defining ns while that fn runs, so an interpreted
# analyzer (defined in jolt.analyzer) would otherwise see jolt.analyzer. The back
# end stashes the real compile ns in :compile-ns before invoking the analyzer.
(defn h-current-ns [ctx] (or (get (ctx :env) :compile-ns) (ctx-current-ns ctx)))
(defn h-macro? [ctx sym]
(let [v (resolve-var ctx @{} sym)]