Permalink
Browse files

Analyze quoted collections

Added :quoted? to env
Quoted forms now preserve metadata
Fixed bug with quoted namespaced keywords
Elimited emit-constant cases for collections
  • Loading branch information...
brandonbloom authored and swannodette committed May 19, 2013
1 parent b13caaf commit f80956d90f455810be140cfec1632f55254385a5
Showing with 48 additions and 67 deletions.
  1. +39 −25 src/clj/cljs/analyzer.clj
  2. +7 −42 src/clj/cljs/compiler.clj
  3. +2 −0 test/cljs/cljs/ns_test/foo.cljs
View
@@ -546,7 +546,7 @@
(defmethod parse 'quote
[_ env [_ x] _]
- {:op :constant :env env :form x})
+ (analyze (assoc env :quoted? true) x))
(defmethod parse 'new
[_ env [_ ctor & args :as form] _]
@@ -872,13 +872,15 @@
(defn analyze-symbol
"Finds the var associated with sym"
[env sym]
- (let [ret {:env env :form sym}
- lb (-> env :locals sym)]
- (if lb
- (assoc ret :op :var :info lb)
- (if-not (:def-var env)
- (assoc ret :op :var :info (resolve-existing-var env sym))
- (assoc ret :op :var :info (resolve-var env sym))))))
+ (if (:quoted? env)
+ {:op :constant :env env :form sym}
+ (let [ret {:env env :form sym}
+ lb (-> env :locals sym)]
+ (if lb
+ (assoc ret :op :var :info lb)
+ (if-not (:def-var env)
+ (assoc ret :op :var :info (resolve-existing-var env sym))
+ (assoc ret :op :var :info (resolve-var env sym)))))))
(defn get-expander [sym env]
(let [mvar
@@ -919,22 +921,26 @@
:else form))
form)))))
+(declare analyze-list)
+
(defn analyze-seq
[env form name]
- (let [env (assoc env
- :line (or (-> form meta :line)
- (:line env))
- :column (or (-> form meta :column)
- (:column env)))]
- (let [op (first form)]
- (assert (not (nil? op)) "Can't call nil")
- (let [mform (macroexpand-1 env form)]
- (if (identical? form mform)
- (wrapping-errors env
- (if (specials op)
- (parse op env form name)
- (parse-invoke env form)))
- (analyze env mform name))))))
+ (if (:quoted? env)
+ (analyze-list env form name)
+ (let [env (assoc env
+ :line (or (-> form meta :line)
+ (:line env))
+ :column (or (-> form meta :column)
+ (:column env)))]
+ (let [op (first form)]
+ (assert (not (nil? op)) "Can't call nil")
+ (let [mform (macroexpand-1 env form)]
+ (if (identical? form mform)
+ (wrapping-errors env
+ (if (specials op)
+ (parse op env form name)
+ (parse-invoke env form)))
+ (analyze env mform name)))))))
(declare analyze-wrap-meta)
@@ -948,6 +954,12 @@
:children (vec (interleave ks vs))}
name)))
+(defn analyze-list
+ [env form name]
+ (let [expr-env (assoc env :context :expr)
+ items (disallowing-recur (doall (map #(analyze expr-env % name) form)))]
+ (analyze-wrap-meta {:op :list :env env :form form :items items :children items} name)))
+
(defn analyze-vector
[env form name]
(let [expr-env (assoc env :context :expr)
@@ -961,11 +973,12 @@
(analyze-wrap-meta {:op :set :env env :form form :items items :children items} name)))
(defn analyze-wrap-meta [expr name]
- (let [form (:form expr)]
- (if (meta form)
+ (let [form (:form expr)
+ m (dissoc (meta form) :line :column)]
+ (if (seq m)
(let [env (:env expr) ; take on expr's context ourselves
expr (assoc-in expr [:env :context] :expr) ; change expr to :expr
- meta-expr (analyze-map (:env expr) (meta form) name)]
+ meta-expr (analyze-map (:env expr) m name)]
{:op :meta :env env :form form
:meta meta-expr :expr expr :children [meta-expr expr]})
expr)))
@@ -991,6 +1004,7 @@
(vector? form) (analyze-vector env form name)
(set? form) (analyze-set env form name)
(keyword? form) (analyze-keyword env form)
+ (= form ()) (analyze-list env form name)
:else {:op :constant :env env :form form})))))
(defn analyze-file
View
@@ -188,48 +188,6 @@
(emit-constant nil)
(emits ")")))
-(defn- emit-meta-constant [x & body]
- (if (meta x)
- (do
- (emits "cljs.core.with_meta(" body ",")
- (emit-constant (meta x))
- (emits ")"))
- (emits body)))
-
-(defmethod emit-constant clojure.lang.PersistentList$EmptyList [x]
- (emit-meta-constant x "cljs.core.List.EMPTY"))
-
-(defmethod emit-constant clojure.lang.PersistentList [x]
- (emit-meta-constant x
- (concat ["cljs.core.list("]
- (comma-sep (map #(fn [] (emit-constant %)) x))
- [")"])))
-
-(defmethod emit-constant clojure.lang.Cons [x]
- (emit-meta-constant x
- (concat ["cljs.core.list("]
- (comma-sep (map #(fn [] (emit-constant %)) x))
- [")"])))
-
-(defmethod emit-constant clojure.lang.IPersistentVector [x]
- (emit-meta-constant x
- (concat ["cljs.core.vec(["]
- (comma-sep (map #(fn [] (emit-constant %)) x))
- ["])"])))
-
-(defmethod emit-constant clojure.lang.IPersistentMap [x]
- (emit-meta-constant x
- (concat ["cljs.core.hash_map("]
- (comma-sep (map #(fn [] (emit-constant %))
- (apply concat x)))
- [")"])))
-
-(defmethod emit-constant clojure.lang.PersistentHashSet [x]
- (emit-meta-constant x
- (concat ["cljs.core.set(["]
- (comma-sep (map #(fn [] (emit-constant %)) x))
- ["])"])))
-
(defmacro emit-wrap [env & body]
`(let [env# ~env]
(when (= :return (:context env#)) (emits "return "))
@@ -297,6 +255,13 @@
(comma-sep vals)
"])")))))
+(defmethod emit :list
+ [{:keys [items env]}]
+ (emit-wrap env
+ (if (empty? items)
+ (emits "cljs.core.List.EMPTY")
+ (emits "cljs.core.list(" (comma-sep items) ")"))))
+
(defmethod emit :vector
[{:keys [items env]}]
(emit-wrap env
@@ -3,5 +3,7 @@
(defn baz [] 123)
(def kw ::foo)
+(def qkw '::foo)
(assert (= (str kw) ":cljs.ns-test.foo/foo"))
+(assert (= (str qkw) ":cljs.ns-test.foo/foo"))

0 comments on commit f80956d

Please sign in to comment.