Permalink
Browse files

CLJS-661: (try ... (catch :default e ...) ...)

  • Loading branch information...
1 parent e89f9ed commit 9feed772a6db1d2697de387f14c05e7e99c9d891 @brandonbloom brandonbloom committed with swannodette Nov 5, 2013
Showing with 32 additions and 13 deletions.
  1. +29 −5 src/clj/cljs/analyzer.clj
  2. +3 −8 test/cljs/cljs/core_test.cljs
View
@@ -386,21 +386,45 @@
[op env [_ & body :as form] name]
(let [catchenv (update-in env [:context] #(if (= :expr %) :return %))
catch? (every-pred seq? #(= (first %) 'catch))
+ default? (every-pred catch? #(= (second %) :default))
finally? (every-pred seq? #(= (first %) 'finally))
- [body tail] (split-with (complement (some-fn catch? finally?)) body)
- [cblocks [fblock]] (split-with catch? tail)
+
+ {:keys [body cblocks dblock fblock]}
+ (loop [parser {:state :start :forms body
+ :body [] :cblocks [] :dblock nil :fblock nil}]
+ (if (seq? (:forms parser))
+ (let [[form & forms*] (:forms parser)
+ parser* (assoc parser :forms forms*)]
+ (case (:state parser)
+ :start (cond
+ (catch? form) (recur (assoc parser :state :catches))
+ (finally? form) (recur (assoc parser :state :finally))
+ :else (recur (update-in parser* [:body] conj form)))
+ :catches (cond
+ (default? form) (recur (assoc parser* :dblock form :state :finally))
+ (catch? form) (recur (update-in parser* [:cblocks] conj form))
+ (finally? form) (recur (assoc parser :state :finally))
+ :else (throw (error env "Invalid try form")))
+ :finally (recur (assoc parser* :fblock form :state :done))
+ :done (throw (error env "Unexpected form after finally"))))
+ parser))
+
finally (when (seq fblock)
(analyze (assoc env :context :statement) `(do ~@(rest fblock))))
- e (when (seq cblocks) (gensym "e"))
- cblock (when e
+ e (when (or (seq cblocks) dblock) (gensym "e"))
+ default (if-let [[_ _ name & cb] dblock]
+ `(cljs.core/let [~name ~e] ~@cb)
+ `(throw ~e))
+ cblock (if (seq cblocks)
`(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)))
+ :else ~default)
+ default)
locals (:locals catchenv)
locals (if e
(assoc locals e
@@ -473,18 +473,13 @@
(assert (empty? e-hmap))
(assert (= {:b :c} (meta e-hmap))))
- ;;this fails in v8 advanced mode - what's e?
- #_(let [a (atom nil)]
- (assert (= 1 (try* 1)))
- (assert (= 2 (try* 1 (throw 3) (catch e 2))))
- (assert (= 3 (try* 1 (throw 3) (catch e e))))
- (assert (= 1 (try* 1 (finally (reset! a 42)))))
- (assert (= 42 (deref a))))
-
(let [a (atom nil)]
(assert (= 1 (try 1)))
(assert (= 2 (try 1 (throw (js/Error.)) (catch js/Error e 2))))
(assert (= 2 (try 1 (throw (js/Error.)) (catch js/Error e 1 2))))
+ (assert (= 2 (try 1 (throw (js/Error.)) (catch js/Error e 2) (catch :default e 3))))
+ (assert (= 3 (try 1 (throw true) (catch js/Error e 2) (catch :default e 3))))
+ (assert (= 2 (try 1 (throw 2) (catch js/Error e 3) (catch :default e e))))
(assert (= 1 (try 1 (finally (reset! a 42)))))
(assert (= 42 (deref a))))

0 comments on commit 9feed77

Please sign in to comment.