ir/analyzer: omit absent fields instead of writing nil
def-node carried :meta nil when a def had no metadata, fn-node carried :name nil for anonymous fns, analyze-arity carried :rest nil for fixed arities, and empty-env carried :recur nil. These all mean genuine absence, and every consumer reads an absent key back as nil — so writing the nil is gratuitous. Dropping them keeps the common nodes (defs, fns, fixed arities) nil-free, so once user maps preserve nil they stay plain structs instead of becoming phm. Faithful nil values (a nil const :val) are left as-is; the back end handles those. No-op today since structs already drop nil: suite, conformance 218/218 x3, fixpoint, fib all unchanged.
This commit is contained in:
parent
22ff737f8b
commit
b2ff65972b
2 changed files with 19 additions and 9 deletions
|
|
@ -38,7 +38,7 @@
|
||||||
(swap! gensym-counter inc)
|
(swap! gensym-counter inc)
|
||||||
(str "_r$" prefix n)))
|
(str "_r$" prefix n)))
|
||||||
|
|
||||||
(defn- empty-env [] {:locals #{} :recur nil})
|
(defn- empty-env [] {:locals #{}})
|
||||||
(defn- local? [env nm] (contains? (:locals env) nm))
|
(defn- local? [env nm] (contains? (:locals env) nm))
|
||||||
(defn- add-locals [env names] (update env :locals #(reduce conj % names)))
|
(defn- add-locals [env names] (update env :locals #(reduce conj % names)))
|
||||||
(defn- with-recur [env name] (assoc env :recur name))
|
(defn- with-recur [env name] (assoc env :recur name))
|
||||||
|
|
@ -82,9 +82,12 @@
|
||||||
;; is a self-call carrying the rest seq directly — Clojure semantics.
|
;; is a self-call carrying the rest seq directly — Clojure semantics.
|
||||||
rname (gen-name "arity")
|
rname (gen-name "arity")
|
||||||
names (cond-> (vec fixed) rst (conj rst) fn-name (conj fn-name))
|
names (cond-> (vec fixed) rst (conj rst) fn-name (conj fn-name))
|
||||||
env* (-> (add-locals env names) (with-recur rname))]
|
env* (-> (add-locals env names) (with-recur rname))
|
||||||
{:params fixed :rest rst :recur-name rname
|
arity {:params fixed :recur-name rname
|
||||||
:body (analyze-seq ctx body env*)}))
|
:body (analyze-seq ctx body env*)}]
|
||||||
|
;; :rest only when variadic — an absent :rest reads back nil, same as before,
|
||||||
|
;; but keeps a fixed arity a nil-free struct rather than a phm.
|
||||||
|
(if rst (assoc arity :rest rst) arity)))
|
||||||
|
|
||||||
(defn- analyze-fn [ctx items env]
|
(defn- analyze-fn [ctx items env]
|
||||||
(let [named (form-sym? (nth items 1))
|
(let [named (form-sym? (nth items 1))
|
||||||
|
|
|
||||||
|
|
@ -30,15 +30,22 @@
|
||||||
(defn invoke [f args] {:op :invoke :fn f :args args})
|
(defn invoke [f args] {:op :invoke :fn f :args args})
|
||||||
|
|
||||||
;; meta is the var metadata (e.g. {:dynamic true} / {:redef true}) the back end
|
;; meta is the var metadata (e.g. {:dynamic true} / {:redef true}) the back end
|
||||||
;; applies to the cell; nil when the def name carried none.
|
;; applies to the cell; absent when the def name carried none.
|
||||||
(defn def-node
|
(defn def-node
|
||||||
([ns name init] {:op :def :ns ns :name name :init init :meta nil})
|
([ns name init] {:op :def :ns ns :name name :init init})
|
||||||
([ns name init meta] {:op :def :ns ns :name name :init init :meta meta}))
|
([ns name init meta]
|
||||||
|
(if meta
|
||||||
|
{:op :def :ns ns :name name :init init :meta meta}
|
||||||
|
{:op :def :ns ns :name name :init init})))
|
||||||
|
|
||||||
(defn let-node [bindings body] {:op :let :bindings bindings :body body})
|
(defn let-node [bindings body] {:op :let :bindings bindings :body body})
|
||||||
|
|
||||||
;; A fn is one or more arities. Each arity: {:params [..] :rest name|nil :body ir}.
|
;; A fn is one or more arities. Each arity: {:params [..] :body ir}, plus :rest
|
||||||
(defn fn-node [name arities] {:op :fn :name name :arities arities})
|
;; name when variadic. :name is absent for an anonymous fn.
|
||||||
|
(defn fn-node [name arities]
|
||||||
|
(if name
|
||||||
|
{:op :fn :name name :arities arities}
|
||||||
|
{:op :fn :arities arities}))
|
||||||
|
|
||||||
(defn vector-node [items] {:op :vector :items items})
|
(defn vector-node [items] {:op :vector :items items})
|
||||||
(defn map-node [pairs] {:op :map :pairs pairs})
|
(defn map-node [pairs] {:op :map :pairs pairs})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue