       (= (first form) 'quote)
       (concat (mapcat #(compile-form vars fns %) (second form))
               (repeat (dec (count form)) [:cons]))
+
+      ;; Variable declaration
+      (= (first form) 'def)
+      (let [[_ var-name val] form]
+        (if (neg? (.indexOf @locals var-name))
+          (swap! locals conj var-name))
+        (concat
+         (compile-form vars fns val)
+         [[:st 0 (.indexOf @locals var-name) (format "; store %s" var-name)]]))
 
       ;; function call
       :else

  (let [labeled (conj stmt (format "; #%s" label))]
    (vec (concat [labeled] stmts))))

(defn load-var
  [vars name]
  (let [index (.indexOf vars name)]
    (if-not (neg? index)
      [:ld 0 index (format "; load var %s" name)])))

(defn load-fn
  ([name]
   (load-fn 1 name))
  ([frame name]
   [:ld frame (format "^%s" name) (format "; load fn %s" name)]))


  (:require [clojure.java.io]
            [clojure.string :as string]
            [spyscope.core :as spy]))

(def ^:dynamic locals (atom []))

(def macros
  {'up    [[:ldc 0 "; up"]]
