Skip to content

Commit 7c99d37

Browse files
frenchy64swannodette
authored andcommitted
CLJS-2801: Add :quote AST op and remove :list op
1. add :quote AST op - This moves a lot more logic into handling :const in the emitter. We rename emit-constant -> emit-constant* and turn emit-constant into a function that emits metadata for each form before delegating to emit-constant*. - Some emit* defmethods are factored out into higher-order function helpers (:{map,list,vector,set} -> emit-{map,list,vector,set}) and are now called from both emit and emit-constant. - analyze-const now registers constants, but throws away the analysis results. 2. remove :list :op - subsumed by :quote'd :const. analyze-list still used to register constants.
1 parent ea53fd0 commit 7c99d37

File tree

7 files changed

+212
-99
lines changed

7 files changed

+212
-99
lines changed

src/main/cljs/cljs/js.cljs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,11 +1229,11 @@
12291229
(defn- emit-fn [f]
12301230
(print "cljs.js.get_fn(" (put-fn f) ")"))
12311231

1232-
(defmethod comp/emit-constant js/Function
1232+
(defmethod comp/emit-constant* js/Function
12331233
[f]
12341234
(emit-fn f))
12351235

1236-
(defmethod comp/emit-constant cljs.core/Var
1236+
(defmethod comp/emit-constant* cljs.core/Var
12371237
[f]
12381238
(emit-fn f))
12391239

src/main/clojure/cljs/analyzer.cljc

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,8 +1249,14 @@
12491249

12501250
(def BOOLEAN_OR_SEQ '#{boolean seq})
12511251

1252+
(defn unwrap-quote [{:keys [op] :as expr}]
1253+
(if #?(:clj (= op :quote)
1254+
:cljs (keyword-identical? op :quote))
1255+
(:expr expr)
1256+
expr))
1257+
12521258
(defn infer-if [env e]
1253-
(let [{{:keys [op form]} :test} e
1259+
(let [{:keys [op form]} (unwrap-quote (:test e))
12541260
then-tag (infer-tag env (:then e))]
12551261
(if (and #?(:clj (= op :const)
12561262
:cljs (keyword-identical? op :const))
@@ -1314,6 +1320,7 @@
13141320
true BOOLEAN_SYM
13151321
false BOOLEAN_SYM
13161322
ANY_SYM)
1323+
:quote (infer-tag env (:expr e))
13171324
:var (if-some [init (:init e)]
13181325
(infer-tag env init)
13191326
(infer-tag env (:info e)))
@@ -1522,10 +1529,19 @@
15221529

15231530
(defn constant-value?
15241531
[{:keys [op] :as ast}]
1525-
(or (= :const op)
1526-
(and (#{:map :set :vector :list} op)
1532+
(or (#{:quote :const} op)
1533+
(and (#{:map :set :vector} op)
15271534
(every? constant-value? (ast-children ast)))))
15281535

1536+
(defn const-expr->constant-value [{:keys [op] :as e}]
1537+
(case op
1538+
:quote (const-expr->constant-value (:expr e))
1539+
:const (:val e)
1540+
:map (zipmap (map const-expr->constant-value (:keys e))
1541+
(map const-expr->constant-value (:vals e)))
1542+
:set (into #{} (map const-expr->constant-value (:items e)))
1543+
:vector (into [] (map const-expr->constant-value (:items e)))))
1544+
15291545
(defmethod parse 'def
15301546
[op env form _ _]
15311547
(when (> (count form) 4)
@@ -2062,9 +2078,28 @@
20622078
:exprs exprs
20632079
:children [:exprs])))
20642080

2081+
(defn analyze-const
2082+
[env form]
2083+
(let [;; register constants
2084+
{:keys [tag]} (analyze (assoc env :quoted? true) form)]
2085+
{:op :const
2086+
:env env
2087+
:literal? true
2088+
:val form
2089+
:tag tag
2090+
:form form}))
2091+
20652092
(defmethod parse 'quote
2066-
[_ env [_ x] _ _]
2067-
(analyze (assoc env :quoted? true) x))
2093+
[_ env [_ x :as form] _ _]
2094+
(when (not= 2 (count form))
2095+
(throw (error env "Wrong number of args to quote")))
2096+
(let [expr (analyze-const env x)]
2097+
{:op :quote
2098+
:expr expr
2099+
:env env
2100+
:form form
2101+
:tag (:tag expr)
2102+
:children [:expr]}))
20682103

20692104
(defmethod parse 'new
20702105
[_ env [_ ctor & args :as form] _ _]
@@ -3466,6 +3501,8 @@
34663501
:children [:keys :vals]
34673502
:tag 'cljs.core/IMap})))
34683503

3504+
;; :list is not used in the emitter any more, but analyze-list is called from analyze-const
3505+
;; to hit the `register-constant!` cases for symbols and keywords.
34693506
(defn analyze-list
34703507
[env form]
34713508
(let [expr-env (assoc env :context :expr)
@@ -3533,9 +3570,12 @@
35333570
(defn elide-analyzer-meta [m]
35343571
(dissoc m ::analyzed))
35353572

3573+
(defn elide-irrelevant-meta [m]
3574+
(-> m elide-reader-meta elide-analyzer-meta))
3575+
35363576
(defn analyze-wrap-meta [expr]
35373577
(let [form (:form expr)
3538-
m (-> (meta form) elide-reader-meta elide-analyzer-meta)]
3578+
m (elide-irrelevant-meta (meta form))]
35393579
(if (some? (seq m))
35403580
(let [env (:env expr) ; take on expr's context ourselves
35413581
expr (assoc-in expr [:env :context] :expr) ; change expr to :expr
@@ -3636,15 +3676,15 @@
36363676
(set? form) (analyze-set env form)
36373677
(keyword? form) (analyze-keyword env form)
36383678
(instance? JSValue form) (analyze-js-value env form)
3639-
(= () form) (analyze-list env form)
36403679
:else
36413680
(let [tag (cond
36423681
(nil? form) 'clj-nil
36433682
(number? form) 'number
36443683
(string? form) 'string
36453684
(instance? Character form) 'string
36463685
(true? form) 'boolean
3647-
(false? form) 'boolean)]
3686+
(false? form) 'boolean
3687+
(= () form) 'cljs.core/IList)]
36483688
(cond-> {:op :const :val form :env env :form form}
36493689
tag (assoc :tag tag))))))
36503690

@@ -3659,14 +3699,14 @@
36593699
(cljs-set? form) (analyze-set env form)
36603700
(keyword? form) (analyze-keyword env form)
36613701
(instance? cljs.tagged-literals/JSValue form) (analyze-js-value env form)
3662-
(= () form) (analyze-list env form)
36633702
:else
36643703
(let [tag (cond
36653704
(nil? form) CLJ_NIL_SYM
36663705
(number? form) NUMBER_SYM
36673706
(string? form) STRING_SYM
36683707
(true? form) BOOLEAN_SYM
3669-
(false? form) BOOLEAN_SYM)]
3708+
(false? form) BOOLEAN_SYM
3709+
(= () form) 'cljs.core/IList)]
36703710
(cond-> {:op :const :val form :env env :form form}
36713711
tag (assoc :tag tag))))))
36723712

src/main/clojure/cljs/closure.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,8 @@
12151215
(defn- const-expr-form
12161216
"Returns the :const-expr form for `sym` from `compiler-state`."
12171217
[compiler-state sym]
1218-
(get-in compiler-state [::ana/namespaces (symbol (namespace sym)) :defs (symbol (name sym)) :const-expr :form]))
1218+
(let [const-expr (get-in compiler-state [::ana/namespaces (symbol (namespace sym)) :defs (symbol (name sym)) :const-expr])]
1219+
(some-> const-expr ana/const-expr->constant-value)))
12191220

12201221
(defn compile-loader
12211222
"Special compilation pass for cljs.loader namespace. cljs.loader must be

0 commit comments

Comments
 (0)