             [oxcart.passes :refer :all]
             [oxcart.passes.lambda-lift :refer [lift-lambdas]]
             [oxcart.pattern :as pattern]
+            [clojure.tools.analyzer.ast :refer [postwalk]]
             [clojure.tools.analyzer.passes.jvm.emit-form :refer [emit-form]]))
 
 



(defn munge-symbol
  "Stub subject to change based on what TANAL permits, the issue is
  going to be symbol vs. var type in the AST. Munging vars is gonna be
  a bitch, munging symbols could happen."
  [sym arity vardic]
  (symbol
   (str sym "$arity$"
        (if vardic
          (- arity 2)
          arity)
        (when vardic
          "+"))))


(defn munge-fn-name

  (if-not (pattern/def? ast)
    ast
    (let [top-level-forms (atom [])
          new-ast         (update ast :init
                                  update-through-meta
                                  rewrite-fn
                                      ast
                                      top-level-forms
                                      munged-fns-atom)]

      (-> @top-level-forms
          vec
          (conj new-ast)))))


(defn var-name
  [v]
  (symbol
   (-> v .ns ns-name str)
   (-> v .sym str)))


(defn rewrite-fn-invokes
  "λ AST → (Atom {Var → {(U Number :variadic) → Var}}) → AST

  Walks the argument AST, rewriting invoke nodes where it is possible
  to call a previously emitted single arity function rather than a
  decomposed multiple arity function by doing static arity resolution
  defaulting to the variadic implementation if present and failing
  back to the original unaltered function in all cases. Returns an
  updated top level form."
  [top-ast munged-fns]
  (let [munged-fns @munged-fns]
    (postwalk top-ast
              (fn [{:keys [op fn args env] :as node}]
                (if (and (= op :invoke)
                         (= :var (:op fn)))
                  (if-let [arities (munged-fns (-> fn :var))]
                    (if-let [var (get munged-fns
                                      (count args)
                                      (get munged-fns :variadic))]
                      (assoc node :fn (ast (var-name var) env))
                      node)
                    node)
                  node)))))


(defn reduce-fn-arities
