From 8b9ba81801530e67232d006612f84e80d9d71f02 Mon Sep 17 00:00:00 2001 From: Wes Brown Date: Wed, 23 Apr 2014 17:57:59 -0400 Subject: [PATCH 1/3] Fix to namespace handling of try/catch to accept `js` as namespace. --- src/clj/cljs/analyzer.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/clj/cljs/analyzer.clj b/src/clj/cljs/analyzer.clj index f1cfd4ab2e..b5b9470a62 100644 --- a/src/clj/cljs/analyzer.clj +++ b/src/clj/cljs/analyzer.clj @@ -281,7 +281,9 @@ body (if name (pop body) body) try (when body (analyze-block (if (or name finally) catchenv env) body))] - (when name (assert (not (namespace name)) "Can't qualify symbol in catch")) + (when name (assert (not (or (namespace name) + (= (namespace name) "js"))) + "Can't qualify symbol in catch")) {:env env :op :try* :form form :try try :finally finally From dd9c5d66de9e364af62d8ef5cc05734892d025ba Mon Sep 17 00:00:00 2001 From: Wes Brown Date: Wed, 23 Apr 2014 18:45:50 -0400 Subject: [PATCH 2/3] Fixed logic issue in fix. --- src/clj/cljs/analyzer.clj | 4 ++-- src/cljs/cljs/analyzer.cljs | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/clj/cljs/analyzer.clj b/src/clj/cljs/analyzer.clj index b5b9470a62..0245a96727 100644 --- a/src/clj/cljs/analyzer.clj +++ b/src/clj/cljs/analyzer.clj @@ -281,8 +281,8 @@ body (if name (pop body) body) try (when body (analyze-block (if (or name finally) catchenv env) body))] - (when name (assert (not (or (namespace name) - (= (namespace name) "js"))) + (when name (assert (not (and (namespace name) + (not= (namespace name) "js"))) "Can't qualify symbol in catch")) {:env env :op :try* :form form :try try diff --git a/src/cljs/cljs/analyzer.cljs b/src/cljs/cljs/analyzer.cljs index 6e7a28e036..b272f10e09 100644 --- a/src/cljs/cljs/analyzer.cljs +++ b/src/cljs/cljs/analyzer.cljs @@ -274,7 +274,9 @@ body (if name (pop body) body) try (when body (analyze-block (if (or name finally) catchenv env) body))] - (when name (assert (not (namespace name)) "Can't qualify symbol in catch")) + (when name (assert (not (and (namespace name) + (not= (namespace name) "js"))) + "Can't qualify symbol in catch")) {:env env :op :try* :form form :try try :finally finally From 4b9990f99888dccd4ca24645841e5c3e5f63571e Mon Sep 17 00:00:00 2001 From: Wes Brown Date: Thu, 24 Apr 2014 14:29:24 -0400 Subject: [PATCH 3/3] Update cljs-in-cljs to CLJS613, applying changes from https://github.com/clojure/clojurescript/commit/24bb5b75403e7b52898cf0565930ccbaa4961fd7 -- some functions added to satisfy line number errors. --- src/clj/cljs/analyzer.clj | 66 ++++++++++++++++++++----------------- src/clj/cljs/compiler.clj | 34 +++++++------------ src/clj/cljs/core.clj | 30 ----------------- src/cljs/cljs/analyzer.cljs | 66 ++++++++++++++++++++----------------- src/cljs/cljs/compiler.cljs | 34 +++++++------------ web/vendor/jq-console | 2 +- 6 files changed, 95 insertions(+), 137 deletions(-) diff --git a/src/clj/cljs/analyzer.clj b/src/clj/cljs/analyzer.clj index 0245a96727..aa18f63670 100644 --- a/src/clj/cljs/analyzer.clj +++ b/src/clj/cljs/analyzer.clj @@ -208,7 +208,7 @@ (declare analyze analyze-symbol analyze-seq) -(def specials '#{if def fn* do let* loop* letfn* throw try* recur new set! ns deftype* defrecord* . js* & quote}) +(def specials '#{if def fn* do let* loop* letfn* throw try recur new set! ns deftype* defrecord* . js* & quote}) (def ^:dynamic *recur-frames* nil) (def ^:dynamic *loop-lets* nil) @@ -255,42 +255,48 @@ (defn- block-children [{:keys [statements ret] :as block}] (when block (conj (vec statements) ret))) -(defmethod parse 'try* +(defn get-line [x env] + (or (-> x meta :line) (:line env))) + +(defn get-col [x env] + (or (-> x meta :column) (:column env))) + +(defmethod parse 'try [op env [_ & body :as form] name] - (let [body (vec body) - catchenv (update-in env [:context] #(if (= :expr %) :return %)) - tail (peek body) - fblock (when (and (seq? tail) (= 'finally (first tail))) - (rest tail)) - finally (when fblock - (analyze-block - (assoc env :context :statement) - fblock)) - body (if finally (pop body) body) - tail (peek body) - cblock (when (and (seq? tail) - (= 'catch (first tail))) - (rest tail)) - name (first cblock) + (let [catchenv (update-in env [:context] #(if (= :expr %) :return %)) + catch? (every-pred seq? #(= (first %) 'catch)) + finally? (every-pred seq? #(= (first %) 'finally)) + [body tail] (split-with (complement (some-fn catch? finally?)) body) + [cblocks [fblock]] (split-with catch? tail) + finally (when (seq fblock) + (analyze (assoc env :context :statement) `(do ~@(rest fblock)))) + e (when (seq cblocks) (gensym "e")) + cblock (when e + `(cljs.core/cond + ~@(mapcat + (fn [[_ type name & cb]] + (when name (assert (not (namespace name)) "Can't qualify symbol in catch")) + `[(cljs.core/instance? ~type ~e) + (cljs.core/let [~name ~e] ~@cb)]) + cblocks) + :else (throw ~e))) locals (:locals catchenv) - locals (if name - (assoc locals name {:name name}) + locals (if e + (assoc locals e + {:name e + :line (get-line e env) + :column (get-col e env)}) locals) catch (when cblock - (analyze-block (assoc catchenv :locals locals) (rest cblock))) - body (if name (pop body) body) - try (when body - (analyze-block (if (or name finally) catchenv env) body))] - (when name (assert (not (and (namespace name) - (not= (namespace name) "js"))) - "Can't qualify symbol in catch")) - {:env env :op :try* :form form + (analyze (assoc catchenv :locals locals) cblock)) + try (analyze (if (or e finally) catchenv env) `(do ~@body))] + + {:env env :op :try :form form :try try :finally finally - :name name + :name e :catch catch - :children (vec (mapcat block-children - [try catch finally]))})) + :children [try catch finally]})) (defmethod parse 'def [op env form name] diff --git a/src/clj/cljs/compiler.clj b/src/clj/cljs/compiler.clj index d3b9b11e99..05b0a3d321 100644 --- a/src/clj/cljs/compiler.clj +++ b/src/clj/cljs/compiler.clj @@ -523,34 +523,22 @@ ;(when statements (emits "}")) (when (and statements (= :expr context)) (emits "})()")))) -(defmethod emit :try* +(defmethod emit :try [{:keys [env try catch name finally]}] - (let [context (:context env) - subcontext (if (= :expr context) :return context)] + (let [context (:context env)] (if (or name finally) (do - (when (= :expr context) (emits "(function (){")) - (emits "try{") - (let [{:keys [statements ret]} try] - (emit-block subcontext statements ret)) - (emits "}") + (when (= :expr context) + (emits "(function (){")) + (emits "try{" try "}") (when name - (emits "catch (" (munge name) "){") - (when catch - (let [{:keys [statements ret]} catch] - (emit-block subcontext statements ret))) - (emits "}")) + (emits "catch (" (munge name) "){" catch "}")) (when finally - (let [{:keys [statements ret]} finally] - (assert (not= :constant (:op ret)) "finally block cannot contain constant") - (emits "finally {") - (emit-block subcontext statements ret) - (emits "}"))) - (when (= :expr context) (emits "})()"))) - (let [{:keys [statements ret]} try] - (when (and statements (= :expr context)) (emits "(function (){")) - (emit-block subcontext statements ret) - (when (and statements (= :expr context)) (emits "})()")))))) + (assert (not= :constant (:op finally)) "finally block cannot contain constant") + (emits "finally {" finally "}")) + (when (= :expr context) + (emits "})()"))) + (emits try)))) (defmethod emit :let [{:keys [bindings statements ret env loop]}] diff --git a/src/clj/cljs/core.clj b/src/clj/cljs/core.clj index c0d943814e..d2f6ea2e1f 100644 --- a/src/clj/cljs/core.clj +++ b/src/clj/cljs/core.clj @@ -853,36 +853,6 @@ ~@(mapcat (fn [[m c]] `((cljs.core/= ~m ~esym) ~c)) pairs) :else ~default)))) -(defmacro try - "(try expr* catch-clause* finally-clause?) - - Special Form - - catch-clause => (catch protoname name expr*) - finally-clause => (finally expr*) - - Catches and handles JavaScript exceptions." - [& forms] - (let [catch? #(and (list? %) (= (first %) 'catch)) - [body catches] (split-with (complement catch?) forms) - [catches fin] (split-with catch? catches) - e (gensym "e")] - (assert (every? #(clojure.core/> (count %) 2) catches) "catch block must specify a prototype and a name") - (if (seq catches) - `(~'try* - ~@body - (catch ~e - (cond - ~@(mapcat - (fn [[_ type name & cb]] - `[(instance? ~type ~e) (let [~name ~e] ~@cb)]) - catches) - :else (throw ~e))) - ~@fin) - `(~'try* - ~@body - ~@fin)))) - (defmacro assert "Evaluates expr and throws an exception if it does not evaluate to logical true." diff --git a/src/cljs/cljs/analyzer.cljs b/src/cljs/cljs/analyzer.cljs index b272f10e09..ef6d221c7a 100644 --- a/src/cljs/cljs/analyzer.cljs +++ b/src/cljs/cljs/analyzer.cljs @@ -199,7 +199,7 @@ (declare analyze analyze-symbol analyze-seq) -(def specials '#{if def fn* do let* loop* letfn* throw try* recur new set! ns deftype* defrecord* . js* & quote}) +(def specials '#{if def fn* do let* loop* letfn* throw try recur new set! ns deftype* defrecord* . js* & quote}) (def ^:dynamic *recur-frames* nil) (def ^:dynamic *loop-lets* nil) @@ -248,42 +248,48 @@ (defn- block-children [{:keys [statements ret] :as block}] (when block (conj (vec statements) ret))) -(defmethod parse 'try* +(defn get-line [x env] + (or (-> x meta :line) (:line env))) + +(defn get-col [x env] + (or (-> x meta :column) (:column env))) + +(defmethod parse 'try [op env [_ & body :as form] name] - (let [body (vec body) - catchenv (update-in env [:context] #(if (= :expr %) :return %)) - tail (peek body) - fblock (when (and (seq? tail) (= 'finally (first tail))) - (rest tail)) - finally (when fblock - (analyze-block - (assoc env :context :statement) - fblock)) - body (if finally (pop body) body) - tail (peek body) - cblock (when (and (seq? tail) - (= 'catch (first tail))) - (rest tail)) - name (first cblock) + (let [catchenv (update-in env [:context] #(if (= :expr %) :return %)) + catch? (every-pred seq? #(= (first %) 'catch)) + finally? (every-pred seq? #(= (first %) 'finally)) + [body tail] (split-with (complement (some-fn catch? finally?)) body) + [cblocks [fblock]] (split-with catch? tail) + finally (when (seq fblock) + (analyze (assoc env :context :statement) `(do ~@(rest fblock)))) + e (when (seq cblocks) (gensym "e")) + cblock (when e + `(cljs.core/cond + ~@(mapcat + (fn [[_ type name & cb]] + (when name (assert (not (namespace name)) "Can't qualify symbol in catch")) + `[(cljs.core/instance? ~type ~e) + (cljs.core/let [~name ~e] ~@cb)]) + cblocks) + :else (throw ~e))) locals (:locals catchenv) - locals (if name - (assoc locals name {:name name}) + locals (if e + (assoc locals e + {:name e + :line (get-line e env) + :column (get-col e env)}) locals) catch (when cblock - (analyze-block (assoc catchenv :locals locals) (rest cblock))) - body (if name (pop body) body) - try (when body - (analyze-block (if (or name finally) catchenv env) body))] - (when name (assert (not (and (namespace name) - (not= (namespace name) "js"))) - "Can't qualify symbol in catch")) - {:env env :op :try* :form form + (analyze (assoc catchenv :locals locals) cblock)) + try (analyze (if (or e finally) catchenv env) `(do ~@body))] + + {:env env :op :try :form form :try try :finally finally - :name name + :name e :catch catch - :children (vec (mapcat block-children - [try catch finally]))})) + :children [try catch finally]})) (defmethod parse 'def [op env form name] diff --git a/src/cljs/cljs/compiler.cljs b/src/cljs/cljs/compiler.cljs index 9d6e79e743..b4c428f798 100644 --- a/src/cljs/cljs/compiler.cljs +++ b/src/cljs/cljs/compiler.cljs @@ -566,34 +566,22 @@ ;(when statements (emits "}")) (when (and statements (= :expr context)) (emits "})()")))) -(defmethod emit :try* +(defmethod emit :try [{:keys [env try catch name finally]}] - (let [context (:context env) - subcontext (if (= :expr context) :return context)] + (let [context (:context env)] (if (or name finally) (do - (when (= :expr context) (emits "(function (){")) - (emits "try{") - (let [{:keys [statements ret]} try] - (emit-block subcontext statements ret)) - (emits "}") + (when (= :expr context) + (emits "(function (){")) + (emits "try{" try "}") (when name - (emits "catch (" (munge name) "){") - (when catch - (let [{:keys [statements ret]} catch] - (emit-block subcontext statements ret))) - (emits "}")) + (emits "catch (" (munge name) "){" catch "}")) (when finally - (let [{:keys [statements ret]} finally] - (assert (not= :constant (:op ret)) "finally block cannot contain constant") - (emits "finally {") - (emit-block subcontext statements ret) - (emits "}"))) - (when (= :expr context) (emits "})()"))) - (let [{:keys [statements ret]} try] - (when (and statements (= :expr context)) (emits "(function (){")) - (emit-block subcontext statements ret) - (when (and statements (= :expr context)) (emits "})()")))))) + (assert (not= :constant (:op finally)) "finally block cannot contain constant") + (emits "finally {" finally "}")) + (when (= :expr context) + (emits "})()"))) + (emits try)))) (defmethod emit :let [{:keys [bindings statements ret env loop]}] diff --git a/web/vendor/jq-console b/web/vendor/jq-console index 19e247d6f5..309fa621f1 160000 --- a/web/vendor/jq-console +++ b/web/vendor/jq-console @@ -1 +1 @@ -Subproject commit 19e247d6f546c64596073faed3ff7b0747f5d6b3 +Subproject commit 309fa621f107bccced6b461c0c703fbc64b24167