Macros receive &form and &env
A macro body can now read &form (the call form) and &env (a map of the in-scope local symbols), like Clojure. This is what core.logic's matche/defne use to tell a pattern symbol that names an enclosing local from a fresh pattern var — so locals-membero and the recursive checko in `matches` now compute correctly. The suite reaches 535/2/0 (the last two are constraint reification ORDER, where the constraint set is right but it is spliced from a set whose iteration order differs from the JVM — a host set-ordering divergence, not a bug). &form/&env are clojure.core dynamic vars bound around each expander call rather than prepended params, so the macro calling convention is unchanged and the mint stays consistent (the seed prelude is byte-identical; only the analyzer carries the env into form-expand-1). macroexpand-1 passes an empty env. corpus.edn: the ~@ unquote row is now a boolean compare (a bare clojure.core/ unquote-splicing symbol evaluates to an unbound var, not the symbol).
This commit is contained in:
parent
f46772d576
commit
438742702a
4 changed files with 57 additions and 39 deletions
|
|
@ -52,6 +52,11 @@
|
|||
(defn- empty-env [] {:locals #{} :hints {}})
|
||||
(defn- local? [env nm] (contains? (:locals env) nm))
|
||||
(defn- add-locals [env names] (update env :locals #(reduce conj % names)))
|
||||
;; &env value handed to a macro: a map of each in-scope local SYMBOL to nil
|
||||
;; (Clojure's &env maps locals to compiler binding objects; consumers like
|
||||
;; core.logic's matche only read its keys to tell locals from fresh pattern vars).
|
||||
(defn- amp-env-map [env]
|
||||
(reduce (fn [m n] (assoc m (symbol n) nil)) {} (:locals env)))
|
||||
(defn- with-recur [env name] (assoc env :recur name))
|
||||
|
||||
;; Type hints. The reader keeps ^hint metadata on the binding symbol.
|
||||
|
|
@ -632,7 +637,7 @@
|
|||
;; defn/defn- expand to (def name (fn …)); carry the ORIGINAL form's
|
||||
;; source offset onto the resulting def, since the macro builds a fresh
|
||||
;; (def …) with no metadata. So the back end can register fn defs.
|
||||
(let [node (analyze ctx (form-expand-1 ctx form) env)
|
||||
(let [node (analyze ctx (form-expand-1 ctx form (amp-env-map env)) env)
|
||||
p (form-position form)]
|
||||
(if (and p (= :def (:op node))) (assoc node :pos p) node))
|
||||
;; jolt.ffi/__cfn — the foreign-function special form (always emitted
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue