 
 (defmethod eval-result nil [_] "")
 
-(defmethod eval-result org.mozilla.javascript.Undefined [_] "")
+(defmethod eval-result Undefined [_] "")
+
+;; =============================================================================
 
 (defn rhino-eval
   [repl-env filename line js]

            [cljs.analyzer :as ana]
            [cljs.repl :as repl]
            [cljs.util :as util])
  (:import java.io.File
           cljs.repl.IJavaScriptEnv
           [org.mozilla.javascript Context ScriptableObject]))

(def current-repl-env (atom nil))

;;todo - move to core.cljs, using js
(def ^String bootjs (str "goog.require = function(rule){"
                         "Packages.clojure.lang.RT[\"var\"](\"cljs.repl.rhino\",\"goog-require\")"
                         ".invoke(___repl_env, __repl_opts, rule);}"))

(defprotocol IEval
  (-eval [this env filename line]))

(extend-protocol IEval
  
  java.lang.String
  (-eval [this {:keys [cx scope]} filename line]
    (.evaluateString cx scope this filename line nil))
  
  java.io.Reader
  (-eval [this {:keys [cx scope]} filename line]
    (.setOptimizationLevel ^Context cx -1)
    (.evaluateReader cx scope this filename line nil))
  )

(defmulti stacktrace class)

(defmethod stacktrace :default [e]
  (apply str (interpose "\n" (map #(str "        " (.toString %)) (.getStackTrace e)))))

(defmethod stacktrace org.mozilla.javascript.RhinoException [e]
  (.getScriptStackTrace e))

(defmulti eval-result class)

            (if-let [res (io/resource js-path)]
              (with-open [reader (io/reader res)]
                (-eval reader repl-env js-path 1))
              (throw
                (Exception.
                  (str "Cannot find " cljs-path
                       " or " js-path " in classpath")))))))
      (swap! (:loaded-libs repl-env) conj rule))))

(defn load-javascript [repl-env ns url]
  (let [missing (remove #(contains? @(:loaded-libs repl-env) %) ns)]
    (when (seq missing)
      (do
        (try
          (with-open [reader (io/reader url)]
            (-eval reader repl-env (.toString url) 1))
          ;; TODO: don't show errors for goog/base.js line number 105
          (catch Throwable ex (println (.getMessage ex))))
        (swap! (:loaded-libs repl-env) (partial apply conj) missing)))))

(defn rhino-setup
  ([repl-env] (rhino-setup repl-env nil))
  ([repl-env opts]
    (let [env   (ana/empty-env)
          scope (:scope repl-env)]
      (ScriptableObject/putProperty scope "__repl_opts"
        (Context/javaToJS opts scope))
      (repl/load-file repl-env "cljs/core.cljs" opts)
      (swap! (:loaded-libs repl-env) conj "cljs.core")
      (repl/evaluate-form repl-env env "<cljs repl>"
        '(ns cljs.user))
      (ScriptableObject/putProperty scope
        "out" (Context/javaToJS *out* scope))
      (binding [ana/*cljs-ns* 'cljs.core]
        (repl/evaluate-form repl-env env "<cljs repl>"
          '(set! *print-fn* (fn [x] (.write js/out x))))))))

(defrecord RhinoEnv [loaded-libs]
