(defn emit-variadic-fn-method
[{:keys [type name variadic params expr env recurs max-fixed-arity] :as f}]
(emit-wrap env
(let [name (or name (gensym))
mname (munge name)
delegate-name (str mname "__delegate")]
(emitln "(function() { ")
(emits "var " delegate-name " = function (")
(doseq [param params]
(emit param)
(when-not (= param (last params)) (emits ",")))
(emitln "){")
(when type
(emitln "var self__ = this;"))
(when recurs (emitln "while(true){"))
(emits expr)
(when recurs
(emitln "break;")
(emitln "}"))
(emitln "};")
(emitln "var " mname " = function (" (comma-sep
(if variadic
(concat (butlast params) ['var_args])
params)) "){")
(when type
(emitln "var self__ = this;"))
(when variadic
(emits "var ")
(emit (last params))
(emitln " = null;")
(emitln "if (arguments.length > " (dec (count params)) ") {")
(let [a (emit-arguments-to-array (dec (count params)))]
(emitln " " (last params) " = new cljs.core.IndexedSeq(" a ",0,null);"))
(emitln "} "))
(emits "return " delegate-name ".call(this,")
(doseq [param params]
(emit param)
(when-not (= param (last params)) (emits ",")))
(emits ");")
(emitln "};")
(emitln mname ".cljs$lang$maxFixedArity = " max-fixed-arity ";")
(emits mname ".cljs$lang$applyTo = ")
(emit-apply-to (assoc f :name name))
(emitln ";")
(emitln mname ".cljs$core$IFn$_invoke$arity$variadic = " delegate-name ";")
(emitln "return " mname ";")
(emitln "})()"))))