 ;; -----------------------------------------------------------------------------
 ;; Analyze
 
+(declare compile*)
+
 (def *loaded* (atom #{}))
 
 (defn require
-  ([name cb]
+  ([bound-vars name opts cb]
    (when-not (contains? @*loaded* name)
      (*load-fn* name
        (fn [source]
-         (*eval-fn* source)
-         (cb true)))))
-  ([name reload cb]
+         (compile* bound-vars source opts (fn [ret] (cb true)))))))
+  ([bound-vars name reload opts cb]
    (when (= :reload reload)
      (swap! *loaded* disj name))
    (when (= :reload-all reload)

             (*load-fn* name
               (fn [source]
                 (if-not (nil? source)
                   (analyze* env bound-vars source opts
                     (fn []
                       (analyze-deps lib (next deps) env bound-vars opts cb)))
                   (throw
                     (ana/error env
                       (ana/error-message :undeclared-ns
                         {:ns-sym dep :js-provide (name dep)}))))))))
         (cb))))))

(defn load-macros [k macros reload reloads bound-vars cb]
  (if (seq macros)
    (let [nsym (first (vals macros))]
      (let [k (or (k reload)
                  (get-in reloads [k nsym])
                  (and (= nsym name) (:*reload-macros* bound-vars) :reload))]
        (if k
          (require nsym k
            (fn []
              (load-macros k (next macros) reload reloads bound-vars cb)))
          (require nsym
            (fn []
              (load-macros k (next macros) reload reloads bound-vars cb))))
        ;(intern-macros nsym k)
        ))
    (cb)))

(defn ns-side-effects
  [env {:keys [op] :as ast} opts bound-vars cb]
  (if (= :ns op)
    (let [{:keys [deps uses require-macros use-macros reload reloads]} ast]
      (letfn [(check-uses-and-load-macros []
                (when (and (:*analyze-deps* bound-vars) (seq uses))
                  (ana/check-uses uses env))
                (when (:*load-macros* bound-vars)
                  (load-macros :use-macros use-macros reload reloads bound-vars
                    (fn []
                      (load-macros :require-macros require-macros reloads reloads bound-vars
                        (fn []
                          (when (seq use-macros)
                            (ana/check-use-macros use-macros env))
                          (cb ast)))))))]
        (if (and (:*analyze-deps* bound-vars) (seq deps))
          (analyze-deps name deps env (dissoc opts :macros-ns)
            check-uses-and-load-macros)
          (check-uses-and-load-macros))))
    (cb ast)))

  "Given a lib, a namespace, deps, its dependencies, env, an analysis environment
   and opts, compiler options - analyze all of the dependencies. Required to
   correctly analyze usage of other namespaces."
  ([bound-vars ana-env lib deps cb] (analyze-deps bound-vars lib deps nil cb))
  ([bound-vars ana-env lib deps opts cb]
   (let [compiler @(:*compiler* bound-vars)]
     (binding [ana/*cljs-dep-set* (vary-meta (conj (:*cljs-dep-set* bound-vars) lib)
                                    update-in [:dep-path] conj lib)]
