               ;; save the var ast
               (swap! locals->vars assoc (pattern/binding->symbol b) ret)))
 
-          (-> ast
-              (assoc :bindings (mapv #(ast/prewalk %1
-                                        (partial rewrite-locals-to-vars
-                                                 @locals->vars))
-                                     bindings))
-
-              (collect-closed-overs {:what #{:closed-overs} :where #{:fn}})
-
-              ;; force to a let form
-              (assoc :op :let)))
+
+          ;; compute the fixed point over the local bindings
+          (swap! locals->closed-overs
+                 (fn [locals->closed-overs]
+                   (fix merge-deps
+                        locals->closed-overs)))
+
+          (println @locals->closed-overs)
+
+          (let [;; rewrite the bindings to share closed-over information
+                bindings' (mapv (partial rewrite-closed-overs
+                                         locals->closed-overs)
+                                bindings)
+
+                fns       (zipmap (map pattern/binding->symbol bindings')
+                                  (map pattern/binding->value  bindings'))
+
+                ;; compute the mapping from symbols to partial applications
+                fns'      (map-vals fns
+                                    (partial lift-fns defs-atom))]
+            (println fns')
+
+            (-> ast
+                (assoc :bindings (->> bindings'
+                                      (mapv (fn [binding]
+                                              (ast/prewalk binding
+                                                           (partial rewrite-locals
+                                                                    fns'))))
+                                      (mapv #(ast/prewalk %1
+                                                          (partial rewrite-locals
+                                                                   @locals->vars)))))
+                
+                ;; force to a let form
+                (assoc :op :let))))
 
 
         true

        ;;
        ;; 2. Create a (declare <fns>) in the defs atom.
        ;;
        ;; 3. For each fn in the letfn rewrite the letfn bodies using
        ;;    the mapping from 1 and emit lifted defs as would be
        ;;    normal for lambda lifting.
        ;;
        ;; 4. Replace the letfn* with a simple let* that binds the
        ;;    partials appropriately so that I don't have to rewrite
        ;;    all the locals of the body expression.

        (let [bindings     (:bindings ast)
              locals->vars (atom {})
              env          (:env ast)]

          ;; create the forward defs
          (doseq [b bindings]
            (let [sym (-> b
                          pattern/binding->value 
                          pattern/fn->name
                          symbol)
                  {:keys [statements ret]} (util/ast `(do (def ~sym)
                                                          ~sym)
                                                     env)
                  def-ast (first statements)]

              ;; save the def ast
              (swap! defs-atom conj def-ast)

    [nil seq]))


(defn map-vals
  [m f & args]
  (->> (for [[k v] m]
         [k (apply f v args)])
       (into {})))


(defn fn*->cannonical-fn*
  [[_fn* & more]]
  (let [[_sym more] (take-when symbol? more)]
