Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLJS613 application #43

Open
wants to merge 3 commits into
base: cljs_in_cljs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions src/clj/cljs/analyzer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -255,40 +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 (namespace name)) "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]
Expand Down
34 changes: 11 additions & 23 deletions src/clj/cljs/compiler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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]}]
Expand Down
30 changes: 0 additions & 30 deletions src/clj/cljs/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down
64 changes: 36 additions & 28 deletions src/cljs/cljs/analyzer.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -248,40 +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 (namespace name)) "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]
Expand Down
34 changes: 11 additions & 23 deletions src/cljs/cljs/compiler.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -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]}]
Expand Down
2 changes: 1 addition & 1 deletion web/vendor/jq-console