(defn emit-source [src dest ext opts]
(with-open [out ^java.io.Writer (io/make-writer dest {})]
(binding [*out* out
ana/*cljs-ns* 'cljs.user
ana/*cljs-file* (.getPath ^File src)
reader/*alias-map* (or reader/*alias-map* {})
ana/*checked-arrays* (or ana/*checked-arrays* (:checked-arrays opts))
ana/*cljs-static-fns* (or ana/*cljs-static-fns* (:static-fns opts))
*source-map-data* (when (:source-map opts)
(atom
{:source-map (sorted-map)
:gen-col 0
:gen-line 0}))]
(emitln (compiled-by-string opts))
(with-open [rdr (io/reader src)]
(let [env (ana/empty-env)]
(loop [forms (ana/forms-seq* rdr (util/path src))
ns-name nil
deps nil]
(if (seq forms)
(let [env (assoc env :ns (ana/get-namespace ana/*cljs-ns*))
{:keys [op] :as ast} (ana/analyze env (first forms) nil opts)]
(cond
(= op :ns)
(let [ns-name (:name ast)
ns-name (if (and (= 'cljs.core ns-name)
(= "cljc" ext))
'cljs.core$macros
ns-name)]
(emit ast)
(recur (rest forms) ns-name (merge (:uses ast) (:requires ast))))
(= :ns* (:op ast))
(let [ns-emitted? (some? ns-name)
ns-name (ana/gen-user-ns src)]
(if-not ns-emitted?
(emit (assoc ast :name ns-name :op :ns))
(emit ast))
(recur (rest forms) ns-name (merge deps (:uses ast) (:requires ast))))
:else
(let [ns-emitted? (some? ns-name)
ns-name (if-not ns-emitted?
(ana/gen-user-ns src)
ns-name)]
(when-not ns-emitted?
(emit {:op :ns
:name ns-name}))
(emit ast)
(recur (rest forms) ns-name deps))))
(let [sm-data (when *source-map-data* @*source-map-data*)
ret (merge
{:ns (or ns-name 'cljs.user)
:macros-ns (:macros-ns opts)
:provides [ns-name]
:requires (if (= ns-name 'cljs.core)
(set (vals deps))
(cond-> (conj (set (vals deps)) 'cljs.core)
(get-in @env/*compiler* [:options :emit-constants])
(conj ana/constants-ns-sym)))
:file dest
:out-file dest
:source-file src}
(when sm-data
{:source-map (:source-map sm-data)}))]
(when (and sm-data (= :none (:optimizations opts)))
(emit-source-map src dest sm-data
(merge opts {:ext ext :provides [ns-name]})))
(let [path (.getPath (.toURL ^File dest))]
(swap! env/*compiler* assoc-in [::compiled-cljs path] ret))
(let [{:keys [output-dir cache-analysis]} opts]
(when (and (true? cache-analysis) output-dir)
(ana/write-analysis-cache ns-name
(ana/cache-file src (ana/parse-ns src) output-dir :write)
src))
ret)))))))))