From e3c3f741c96869f7ea8e4d30667fb4b9f29e8856 Mon Sep 17 00:00:00 2001 From: Brandon Bloom Date: Wed, 28 Nov 2012 16:00:38 -0800 Subject: [PATCH] CLJS-432: Include file/line in error messages --- src/clj/cljs/analyzer.clj | 58 +++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/clj/cljs/analyzer.clj b/src/clj/cljs/analyzer.clj index 50cce63..38c3471 100644 --- a/src/clj/cljs/analyzer.clj +++ b/src/clj/cljs/analyzer.clj @@ -87,11 +87,17 @@ [& args] `(.println System/err (str ~@args))) +(defn message [env s] + (str s (when (:line env) + (str " at line " (:line env) " " *cljs-file*)))) + (defn warning [env s] (binding [*out* *err*] - (println - (str s (when (:line env) - (str " at line " (:line env) " " *cljs-file*)))))) + (println (message env s)))) + +(defn error + ([env s] (error env s nil)) + ([env s cause] (ex-info (message env s) {:env env} cause))) (defn confirm-var-exists [env prefix suffix] (when *cljs-warn-on-undeclared* @@ -206,9 +212,17 @@ (analyze (assoc env :context (if (= :statement (:context env)) :statement :return)) (last exprs)))] {:statements statements :ret ret})) -(defmulti parse (fn [op & rest] op)) +(defmulti parse-form (fn [op & rest] op)) + +(defn parse [op env & rest] + (try + (apply parse-form op env rest) + (catch Throwable err + (if (:env (ex-data err)) + (throw err) + (throw (error env (.getMessage err) err)))))) -(defmethod parse 'if +(defmethod parse-form 'if [op env [_ test then else :as form] name] (let [test-expr (disallowing-recur (analyze (assoc env :context :expr) test)) then-expr (analyze env then) @@ -218,7 +232,7 @@ :unchecked @*unchecked-if* :children [test-expr then-expr else-expr]})) -(defmethod parse 'throw +(defmethod parse-form 'throw [op env [_ throw :as form] name] (let [throw-expr (disallowing-recur (analyze (assoc env :context :expr) throw))] {:env env :op :throw :form form @@ -228,7 +242,7 @@ (defn- block-children [{:keys [statements ret] :as block}] (when block (conj (vec statements) ret))) -(defmethod parse 'try* +(defmethod parse-form 'try* [op env [_ & body :as form] name] (let [body (vec body) catchenv (update-in env [:context] #(if (= :expr %) :return %)) @@ -263,7 +277,7 @@ :children (vec (mapcat block-children [try catch finally]))})) -(defmethod parse 'def +(defmethod parse-form 'def [op env form name] (let [pfn (fn ([_ sym] {:sym sym}) @@ -352,7 +366,7 @@ :type type :form form :recurs @(:flag recur-frame)} block))) -(defmethod parse 'fn* +(defmethod parse-form 'fn* [op env [_ & args :as form] name] (let [[name meths] (if (symbol? (first args)) [(first args) (next args)] @@ -403,7 +417,7 @@ :children (vec (mapcat block-children methods))})) -(defmethod parse 'letfn* +(defmethod parse-form 'letfn* [op env [_ bindings & exprs :as form] name] (assert (and (vector? bindings) (even? (count bindings))) "bindings must be vector of even number of elements") (let [n->fexpr (into {} (map (juxt first second) (partition 2 bindings))) @@ -429,7 +443,7 @@ :children (into (vec (map :init bes)) (conj (vec statements) ret))})) -(defmethod parse 'do +(defmethod parse-form 'do [op env [_ & exprs :as form] _] (let [block (analyze-block env exprs)] (merge {:env env :op :do :form form :children (block-children block)} block))) @@ -477,15 +491,15 @@ :children (into (vec (map :init bes)) (conj (vec statements) ret))})) -(defmethod parse 'let* +(defmethod parse-form 'let* [op encl-env form _] (analyze-let encl-env form false)) -(defmethod parse 'loop* +(defmethod parse-form 'loop* [op encl-env form _] (analyze-let encl-env form true)) -(defmethod parse 'recur +(defmethod parse-form 'recur [op env [_ & exprs :as form] _] (let [context (:context env) frame (first *recur-frames*) @@ -498,11 +512,11 @@ :exprs exprs :children exprs))) -(defmethod parse 'quote +(defmethod parse-form 'quote [_ env [_ x] _] {:op :constant :env env :form x}) -(defmethod parse 'new +(defmethod parse-form 'new [_ env [_ ctor & args :as form] _] (assert (symbol? ctor) "First arg to new must be a symbol") (disallowing-recur @@ -518,7 +532,7 @@ {:env env :op :new :form form :ctor ctorexpr :args argexprs :children (into [ctorexpr] argexprs)}))) -(defmethod parse 'set! +(defmethod parse-form 'set! [_ env [_ target val alt :as form] _] (let [[target val] (if alt ;; (set! o -prop val) @@ -569,7 +583,7 @@ (when (io/resource relpath) (analyze-file relpath)))))) -(defmethod parse 'ns +(defmethod parse-form 'ns [_ env [_ name & args :as form] _] (let [docstring (if (string? (first args)) (first args) nil) args (if docstring (next args) args) @@ -659,7 +673,7 @@ {:env env :op :ns :form form :name name :doc docstring :uses uses :requires requires :imports imports :uses-macros uses-macros :requires-macros requires-macros :excludes excludes})) -(defmethod parse 'deftype* +(defmethod parse-form 'deftype* [_ env [_ tsym fields pmasks :as form] _] (let [t (:name (resolve-var (dissoc env :locals) tsym))] (swap! namespaces update-in [(-> env :ns :name) :defs tsym] @@ -675,7 +689,7 @@ :line line}))))) {:env env :op :deftype* :form form :t t :fields fields :pmasks pmasks})) -(defmethod parse 'defrecord* +(defmethod parse-form 'defrecord* [_ env [_ tsym fields pmasks :as form] _] (let [t (:name (resolve-var (dissoc env :locals) tsym))] (swap! namespaces update-in [(-> env :ns :name) :defs tsym] @@ -744,7 +758,7 @@ [dot-form] (throw (Error. (str "Unknown dot form of " (list* '. dot-form) " with classification " (classify-dot-form dot-form))))) -(defmethod parse '. +(defmethod parse-form '. [_ env [_ target & [field & member+] :as form] _] (disallowing-recur (let [{:keys [dot-action target method field args]} (build-dot-form [target field member+]) @@ -764,7 +778,7 @@ :children (into [targetexpr] argexprs) :tag (-> form meta :tag)}))))) -(defmethod parse 'js* +(defmethod parse-form 'js* [op env [_ jsform & args :as form] _] (assert (string? jsform)) (if args -- 1.8.0