             [cljs.compiler :as comp]
             [cljs.tools.reader :as r]
             [cljs.tools.reader.reader-types :as rt]
-            [cljs.tagged-literals :as tags]))
+            [cljs.tagged-literals :as tags])
+  (:import [goog.string StringBuffer]))
 
 (js/goog.require "cljs.core$macros")
 

;; -----------------------------------------------------------------------------
;; Analyze

(declare compile*)

(def *loaded* (atom #{}))


;; Compile

(defn compile* [bound-vars source opts cb]
  (let [rdr  (rt/string-push-back-reader source)
        eof  (js-obj)
        aenv (ana/empty-env)
        sb   (StringBuffer.)]
    ((fn compile-loop []
       (binding [env/*compiler*   (:*compiler* bound-vars)
                 *eval-fn*        (:*eval-fn* bound-vars)
                 ana/*cljs-ns*    (:*cljs-ns* bound-vars)
                 *ns*             (:*ns* bound-vars)
                 r/*data-readers* (:*data-readers* bound-vars)]
         (let [form (r/read {:eof eof} rdr)]
           (if-not (identical? eof form)
             (let [aenv (assoc aenv :ns (ana/get-namespace ana/*cljs-ns*))
                   ast  (.append sb (comp/emit (ana/analyze aenv form)))]
               (if (= :ns (:op ast))
                 (ns-side-effects bound-vars aenv ast opts
                   (fn [_] (compile-loop)))
                 (recur)))
             (cb (.toString cb)))))))))

(defn compile
  ([env source cb] (compile env source cb))
