diff --git a/jolt-core/jolt/analyzer.clj b/jolt-core/jolt/analyzer.clj index ba187a3..0f11042 100644 --- a/jolt-core/jolt/analyzer.clj +++ b/jolt-core/jolt/analyzer.clj @@ -38,7 +38,7 @@ (swap! gensym-counter inc) (str "_r$" prefix n))) -(defn- empty-env [] {:locals #{} :recur nil}) +(defn- empty-env [] {:locals #{}}) (defn- local? [env nm] (contains? (:locals env) nm)) (defn- add-locals [env names] (update env :locals #(reduce conj % names))) (defn- with-recur [env name] (assoc env :recur name)) @@ -82,9 +82,12 @@ ;; is a self-call carrying the rest seq directly — Clojure semantics. rname (gen-name "arity") names (cond-> (vec fixed) rst (conj rst) fn-name (conj fn-name)) - env* (-> (add-locals env names) (with-recur rname))] - {:params fixed :rest rst :recur-name rname - :body (analyze-seq ctx body env*)})) + env* (-> (add-locals env names) (with-recur rname)) + arity {:params fixed :recur-name rname + :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] (let [named (form-sym? (nth items 1)) diff --git a/jolt-core/jolt/ir.clj b/jolt-core/jolt/ir.clj index 0624810..af34cdb 100644 --- a/jolt-core/jolt/ir.clj +++ b/jolt-core/jolt/ir.clj @@ -30,15 +30,22 @@ (defn invoke [f args] {:op :invoke :fn f :args args}) ;; 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 - ([ns name init] {:op :def :ns ns :name name :init init :meta nil}) - ([ns name init meta] {:op :def :ns ns :name name :init init :meta meta})) + ([ns name init] {:op :def :ns ns :name name :init init}) + ([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}) -;; A fn is one or more arities. Each arity: {:params [..] :rest name|nil :body ir}. -(defn fn-node [name arities] {:op :fn :name name :arities arities}) +;; A fn is one or more arities. Each arity: {:params [..] :body ir}, plus :rest +;; 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 map-node [pairs] {:op :map :pairs pairs})