 (def ^:dynamic *cljs-warn-on-dynamic* true)
 (def ^:dynamic *cljs-warn-on-fn-var* true)
 (def ^:dynamic *unchecked-if* (atom false))
+(def ^:dynamic *position* nil)
 
 (defmacro ^:private debug-prn
   [& args]

                          methods))
              ms (sort-by #(-> % second :params count) (seq mmap))]
          (when (= :return (:context env))
            (print "return "))
          (println "(function() {")
          (println (str "var " name " = null;"))
          (doseq [[n meth] ms]
            (println (str "var " n " = " (with-out-str (if (:variadic meth)
                                                           (emit-variadic-fn-method meth)
                                                           (emit-fn-method meth))) ";")))
          (println (str name " = function(" (comma-sep (if variadic
                                                         (concat (butlast maxparams) ['var_args])
                                                         maxparams)) "){"))
          (when variadic
            (println (str "var " (last maxparams) " = var_args;")))
          (println "switch(arguments.length){")
          (doseq [[n meth] ms]
            (if (:variadic meth)
              (do (println "default:")
                  (println (str "return " n ".apply(this,arguments);")))
              (let [pcnt (count (:params meth))]
                (println "case " pcnt ":")
                (println (str "return " n ".call(this" (if (zero? pcnt) nil
                                                           (str "," (comma-sep (take pcnt maxparams)))) ");")))))
          (println "}")
          (println "throw('Invalid arity: ' + arguments.length);")
          (println "};")
          (when variadic
            (println (str name ".cljs$lang$maxFixedArity = " max-fixed-arity ";"))
            (println (str name ".cljs$lang$applyTo = " (some #(let [[n m] %] (when (:variadic m) n)) ms) ".cljs$lang$applyTo;")))
          (when has-name?
            (doseq [[n meth] ms]
              (let [c (count (:params meth))]
               (println (str name ".__" c " = " n ";")))))
          (println (str "return " name ";"))
          (println "})()")))
      (when loop-locals
        (println (str ";})(" (comma-sep loop-locals) "))"))))))

(defmethod emit :do
  [{:keys [statements ret env]}]
  (let [context (:context env)]
    (when (and statements (= :expr context)) (print "(function (){"))
    ;(when statements (print "{\n"))
    (emit-block context statements ret)
    ;(when statements (print "}"))
    (when (and statements (= :expr context)) (print "})()"))))

(defmethod emit :try*
  [{:keys [env try catch name finally]}]

        subcontext (if (= :expr context) :return context)]
    (if (or name finally)
      (do
        (when (= :expr context) (emits "(function (){"))
        (emits "try{")
        (let [{:keys [statements ret]} try]
          (emit-block subcontext statements ret))
        (emits "}")
        (when name
          (emits "catch (" name "){")
          (when catch
            (let [{:keys [statements ret]} catch]
              (emit-block subcontext statements ret)))
          (emits "}"))
        (when finally
          (let [{:keys [statements ret]} finally]
            (assert (not= :constant (:op ret)) "finally block cannot contain constant")
            (emits "finally {")
            (emit-block subcontext statements ret)
            (emits "}")))
        (when (= :expr context) (emits "})()")))
      (let [{:keys [statements ret]} try]
        (when (and statements (= :expr context)) (emits "(function (){"))
        (emit-block subcontext statements ret)
        (when (and statements (= :expr context)) (emits "})()"))))))

(defmethod emit :let
  [{:keys [bindings statements ret env loop]}]
  (let [context (:context env)]
    (when (= :expr context) (emits "(function (){"))
    (doseq [{:keys [name init]} bindings]
      (emitln "var " name " = " init ";"))
    (when loop (emitln "while(true){"))
    (emit-block (if (= :expr context) :return context) statements ret)
    (when loop
      (emitln "break;")
      (emitln "}"))
    ;(emits "}")
    (when (= :expr context) (emits "})()"))))

(defmethod emit :recur
  [{:keys [frame exprs env]}]
  (let [temps (vec (take (count exprs) (repeatedly gensym)))
        names (:names frame)]
    (emitln "{")
    (dotimes [i (count exprs)]
      (emitln "var " (temps i) " = " (exprs i) ";"))
    (dotimes [i (count exprs)]
      (emitln (names i) " = " (temps i) ";"))
    (emitln "continue;")
    (emitln "}")))

(defmethod emit :invoke
  [{:keys [f args env]}]
