Skip to content

Commit 24bb5b7

Browse files
bronsaswannodette
authored andcommitted
CLJS-613: unify the try special form signature between clojure and clojurescript
1 parent 56848c7 commit 24bb5b7

File tree

4 files changed

+31
-59
lines changed

4 files changed

+31
-59
lines changed

src/clj/cljs/analyzer.clj

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@
253253

254254
(declare analyze analyze-symbol analyze-seq)
255255

256-
(def specials '#{if def fn* do let* loop* letfn* throw try* recur new set! ns deftype* defrecord* . js* & quote})
256+
(def specials '#{if def fn* do let* loop* letfn* throw try recur new set! ns deftype* defrecord* . js* & quote})
257257

258258
(def ^:dynamic *recur-frames* nil)
259259
(def ^:dynamic *loop-lets* nil)
@@ -290,38 +290,40 @@
290290
:throw throw-expr
291291
:children [throw-expr]}))
292292

293-
(defmethod parse 'try*
293+
(defmethod parse 'try
294294
[op env [_ & body :as form] name]
295-
(let [body (vec body)
296-
catchenv (update-in env [:context] #(if (= :expr %) :return %))
297-
tail (peek body)
298-
fblock (when (and (seq? tail) (= 'finally (first tail)))
299-
(rest tail))
300-
finally (when fblock
301-
(analyze (assoc env :context :statement) `(do ~@fblock)))
302-
body (if finally (pop body) body)
303-
tail (peek body)
304-
cblock (when (and (seq? tail)
305-
(= 'catch (first tail)))
306-
(rest tail))
307-
name (first cblock)
295+
(let [catchenv (update-in env [:context] #(if (= :expr %) :return %))
296+
catch? (every-pred seq? #(= (first %) 'catch))
297+
finally? (every-pred seq? #(= (first %) 'finally))
298+
[body tail] (split-with (complement (some-fn catch? finally?)) body)
299+
[cblocks [fblock]] (split-with catch? tail)
300+
finally (when (seq fblock)
301+
(analyze (assoc env :context :statement) `(do ~@(rest fblock))))
302+
e (when (seq cblocks) (gensym "e"))
303+
cblock (when e
304+
`(cljs.core/cond
305+
~@(mapcat
306+
(fn [[_ type name & cb]]
307+
(when name (assert (not (namespace name)) "Can't qualify symbol in catch"))
308+
`[(cljs.core/instance? ~type ~e)
309+
(cljs.core/let [~name ~e] ~@cb)])
310+
cblocks)
311+
:else (throw ~e)))
308312
locals (:locals catchenv)
309-
locals (if name
310-
(assoc locals name
311-
{:name name
312-
:line (get-line name env)
313-
:column (get-col name env)})
313+
locals (if e
314+
(assoc locals e
315+
{:name e
316+
:line (get-line e env)
317+
:column (get-col e env)})
314318
locals)
315319
catch (when cblock
316-
(analyze (assoc catchenv :locals locals) `(do ~@(rest cblock))))
317-
body (if name (pop body) body)
318-
try (analyze (if (or name finally) catchenv env) `(do ~@body))]
319-
(when (and name (namespace name))
320-
(throw (error env "Can't qualify symbol in catch")))
321-
{:env env :op :try* :form form
320+
(analyze (assoc catchenv :locals locals) cblock))
321+
try (analyze (if (or e finally) catchenv env) `(do ~@body))]
322+
323+
{:env env :op :try :form form
322324
:try try
323325
:finally finally
324-
:name name
326+
:name e
325327
:catch catch
326328
:children [try catch finally]}))
327329

src/clj/cljs/compiler.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@
571571
(emit ret)
572572
(when (and statements (= :expr context)) (emits "})()"))))
573573

574-
(defmethod emit :try*
574+
(defmethod emit :try
575575
[{:keys [env try catch name finally]}]
576576
(let [context (:context env)]
577577
(if (or name finally)

src/clj/cljs/core.clj

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,36 +1001,6 @@
10011001
~@(mapcat (fn [[m c]] `((cljs.core/= ~m ~esym) ~c)) pairs)
10021002
:else ~default))))
10031003

1004-
(defmacro try
1005-
"(try expr* catch-clause* finally-clause?)
1006-
1007-
Special Form
1008-
1009-
catch-clause => (catch protoname name expr*)
1010-
finally-clause => (finally expr*)
1011-
1012-
Catches and handles JavaScript exceptions."
1013-
[& forms]
1014-
(let [catch? #(and (seq? %) (= (first %) 'catch))
1015-
[body catches] (split-with (complement catch?) forms)
1016-
[catches fin] (split-with catch? catches)
1017-
e (gensym "e")]
1018-
(assert (every? #(clojure.core/> (count %) 2) catches) "catch block must specify a prototype and a name")
1019-
(if (seq catches)
1020-
`(~'try*
1021-
~@body
1022-
(catch ~e
1023-
(cond
1024-
~@(mapcat
1025-
(fn [[_ type name & cb]]
1026-
`[(instance? ~type ~e) (let [~name ~e] ~@cb)])
1027-
catches)
1028-
:else (throw ~e)))
1029-
~@fin)
1030-
`(~'try*
1031-
~@body
1032-
~@fin))))
1033-
10341004
(defmacro assert
10351005
"Evaluates expr and throws an exception if it does not evaluate to
10361006
logical true."

src/cljs/cljs/core.cljs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7524,6 +7524,6 @@ Maps become Objects. Arbitrary keys are encoded to by key->js."
75247524

75257525
(defn ^boolean special-symbol? [x]
75267526
(contains?
7527-
'#{if def fn* do let* loop* letfn* throw try*
7527+
'#{if def fn* do let* loop* letfn* throw try
75287528
recur new set! ns deftype* defrecord* . js* & quote}
75297529
x))

0 commit comments

Comments
 (0)