         (-> fns
             (generate-main)
             (generate-prelude)
-            (assign-addresses)
-            (emit-code))))))
+            (emit-code)
+            (resolve-references)
+            (#(string/join "\n" %)))))))

    :else
    (throw (IllegalArgumentException. (format "Don't know how to compile %s which is %s" form (type form))))))

(defn assign-addresses
  [fns]
  {:pre [(vector? fns)
         (every? map? fns)]
   :post [(every? (comp integer? :address) %)]}
  (loop [funcs fns
         index 0
         address 0]
    (if-let [func (get funcs index)]
      (let [new-funcs (update-in funcs [index] assoc :address address)
                           address (+ address (:length func))]
                       (recur new-funcs (inc index) address))
      funcs)))

(defn code->str
  [fn-addrs line]
  {:pre [(map? fn-addrs)]
   :post [(string? %)]}
  (condp = (first line)
    :ldf
    (format "LDF %d ; load function %s"
            (fn-addrs (second line))
            (second line))

    (let [[op & args] line]
      (string/join " " (cons (string/upper-case (name op)) args)))))

(defn generate-main
  [fns]
  ;; This depends on the initial state we want
  (let [code [[:ldc 0 "; define main"]
              (load-fn 0 fns 'step)
              [:cons]
              [:rtn]]

(defn generate-prelude
  [fns]
  (let [loads  (for [func fns]
                 [:ldf (format "@%s" (:name func))])
        code (concat [[:dum (count fns) "; #prelude"]]
                     loads
                     [[:ldf "@main"]
                      [:rap (count fns)]
                      [:rtn]])
        prelude {:name 'prelude
