|
1249 | 1249 |
|
1250 | 1250 | (def BOOLEAN_OR_SEQ '#{boolean seq})
|
1251 | 1251 |
|
| 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 | + |
1252 | 1258 | (defn infer-if [env e]
|
1253 |
| - (let [{{:keys [op form]} :test} e |
| 1259 | + (let [{:keys [op form]} (unwrap-quote (:test e)) |
1254 | 1260 | then-tag (infer-tag env (:then e))]
|
1255 | 1261 | (if (and #?(:clj (= op :const)
|
1256 | 1262 | :cljs (keyword-identical? op :const))
|
|
1314 | 1320 | true BOOLEAN_SYM
|
1315 | 1321 | false BOOLEAN_SYM
|
1316 | 1322 | ANY_SYM)
|
| 1323 | + :quote (infer-tag env (:expr e)) |
1317 | 1324 | :var (if-some [init (:init e)]
|
1318 | 1325 | (infer-tag env init)
|
1319 | 1326 | (infer-tag env (:info e)))
|
|
1522 | 1529 |
|
1523 | 1530 | (defn constant-value?
|
1524 | 1531 | [{: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) |
1527 | 1534 | (every? constant-value? (ast-children ast)))))
|
1528 | 1535 |
|
| 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 | + |
1529 | 1545 | (defmethod parse 'def
|
1530 | 1546 | [op env form _ _]
|
1531 | 1547 | (when (> (count form) 4)
|
|
2062 | 2078 | :exprs exprs
|
2063 | 2079 | :children [:exprs])))
|
2064 | 2080 |
|
| 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 | + |
2065 | 2092 | (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]})) |
2068 | 2103 |
|
2069 | 2104 | (defmethod parse 'new
|
2070 | 2105 | [_ env [_ ctor & args :as form] _ _]
|
|
3466 | 3501 | :children [:keys :vals]
|
3467 | 3502 | :tag 'cljs.core/IMap})))
|
3468 | 3503 |
|
| 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. |
3469 | 3506 | (defn analyze-list
|
3470 | 3507 | [env form]
|
3471 | 3508 | (let [expr-env (assoc env :context :expr)
|
|
3533 | 3570 | (defn elide-analyzer-meta [m]
|
3534 | 3571 | (dissoc m ::analyzed))
|
3535 | 3572 |
|
| 3573 | +(defn elide-irrelevant-meta [m] |
| 3574 | + (-> m elide-reader-meta elide-analyzer-meta)) |
| 3575 | + |
3536 | 3576 | (defn analyze-wrap-meta [expr]
|
3537 | 3577 | (let [form (:form expr)
|
3538 |
| - m (-> (meta form) elide-reader-meta elide-analyzer-meta)] |
| 3578 | + m (elide-irrelevant-meta (meta form))] |
3539 | 3579 | (if (some? (seq m))
|
3540 | 3580 | (let [env (:env expr) ; take on expr's context ourselves
|
3541 | 3581 | expr (assoc-in expr [:env :context] :expr) ; change expr to :expr
|
|
3636 | 3676 | (set? form) (analyze-set env form)
|
3637 | 3677 | (keyword? form) (analyze-keyword env form)
|
3638 | 3678 | (instance? JSValue form) (analyze-js-value env form)
|
3639 |
| - (= () form) (analyze-list env form) |
3640 | 3679 | :else
|
3641 | 3680 | (let [tag (cond
|
3642 | 3681 | (nil? form) 'clj-nil
|
3643 | 3682 | (number? form) 'number
|
3644 | 3683 | (string? form) 'string
|
3645 | 3684 | (instance? Character form) 'string
|
3646 | 3685 | (true? form) 'boolean
|
3647 |
| - (false? form) 'boolean)] |
| 3686 | + (false? form) 'boolean |
| 3687 | + (= () form) 'cljs.core/IList)] |
3648 | 3688 | (cond-> {:op :const :val form :env env :form form}
|
3649 | 3689 | tag (assoc :tag tag))))))
|
3650 | 3690 |
|
|
3659 | 3699 | (cljs-set? form) (analyze-set env form)
|
3660 | 3700 | (keyword? form) (analyze-keyword env form)
|
3661 | 3701 | (instance? cljs.tagged-literals/JSValue form) (analyze-js-value env form)
|
3662 |
| - (= () form) (analyze-list env form) |
3663 | 3702 | :else
|
3664 | 3703 | (let [tag (cond
|
3665 | 3704 | (nil? form) CLJ_NIL_SYM
|
3666 | 3705 | (number? form) NUMBER_SYM
|
3667 | 3706 | (string? form) STRING_SYM
|
3668 | 3707 | (true? form) BOOLEAN_SYM
|
3669 |
| - (false? form) BOOLEAN_SYM)] |
| 3708 | + (false? form) BOOLEAN_SYM |
| 3709 | + (= () form) 'cljs.core/IList)] |
3670 | 3710 | (cond-> {:op :const :val form :env env :form form}
|
3671 | 3711 | tag (assoc :tag tag))))))
|
3672 | 3712 |
|
|
0 commit comments