                    [cljs.analyzer.macros :refer [no-warn]]
                    [lumo.repl :refer [with-err-str]])
   (:require [cljs.analyzer :as ana]
+            [cljs.compiler :as comp]
             [cljs.env :as env]
             [cljs.js :as cljs]
             [cljs.reader :as reader]


(defn- ^:export execute
  [type source-or-path expression? print-nil-result? setNS session-id]
  (when setNS
    (vreset! current-ns (symbol setNS)))
  (execute-source source-or-path {:type type

                      (map #(symbol ns-name (str %))
                           (filter matches? (public-syms ns)))))
                  (all-ns)))))

;; Taken from planck eval implementation
;; The following atoms and fns set up a scheme to
;; emit function values into JavaScript as numeric
;; references that are looked up.

(defonce ^:private fn-index (volatile! 0))
(defonce ^:private fn-refs (volatile! {}))

(defn- clear-fns!
  "Clears saved functions."
  []
  (vreset! fn-refs {}))

(defn- put-fn
  "Saves a function, returning a numeric representation."
  [f]
  (let [n (vswap! fn-index inc)]
    (vswap! fn-refs assoc n f)
    n))

(defn- get-fn
  "Gets a function, given its numeric representation."
  [n]
  (get @fn-refs n))

(defn- emit-fn [f]
  (print "lumo.repl.get_fn(" (put-fn f) ")"))

(defmethod comp/emit-constant js/Function
  [f]
  (emit-fn f))

(defmethod comp/emit-constant cljs.core/Var
  [f]
  (emit-fn f))

(defn eval
  ([form]
   (eval form (.-name *ns*)))
  ([form ns]
   (let [result (volatile! nil)]
     (cljs/eval st form
       {:ns            ns
        :context       :expr
        :def-emits-var true}
       (fn [{:keys [value error]}]
         (if error
           (handle-error error true)
           (vreset! result value))))
     @result)))

;; --------------------
;; Code evaluation
