         fields (-> params meta ::fields)
         variadic (some '#{&} params)
         params (remove '#{&} params)
+        fixed-arity (count (if variadic (butlast params) params))
         body (next meth)
         gthis (and fields (gensym "this__"))
         locals (reduce (fn [m fld] (assoc m fld {:name (symbol (str gthis "." (munge fld)))})) locals fields)

    (print (str " = " (emits init)))
    (when-not (= :expr (:context env)) (print ";\n"))))

(defn emit-fn-method
  [{:keys [gthis name variadic params statements ret env recurs]}]
  (emit-wrap env
             (print (str "(function " name "(" (comma-sep params) "){\n"))
             (when gthis
               (println (str "var " gthis " = this;")))
             (when variadic
               (println (str (last params) " = Array.prototype.slice.call(arguments, " (dec (count params)) ");")))
             (when recurs (print "while(true){\n"))
             (emit-block :return statements ret)
             (when recurs (print "break;\n}\n"))
             (print "})")))

(defmethod emit :fn
  [{:keys [name env methods]}]
  ;;fn statements get erased, serve no purpose and can pollute scope if named
  (when-not (= :statement (:context env))
    (if (= 1 (count methods))
      (emit-fn-method (assoc (first methods) :name name))
      (let [name (or name (gensym))

                                                         (str "," (comma-sep (take pcnt maxparams)))) ");")))))
        (println "}")
        (println "throw('Invalid arity: ' + arguments.length);")
        (println "};")
        (println (str "return " name ";"))
        (println "})()")))
    (emit-fn-postfix name max-fixed-arity)))

(defmethod emit :do
  [{:keys [statements ret env]}]
