 
 
 (defn f-symbol
-  [node log env]
-  (cons {:symbol node, 
-         :type "symbol", 
-         :resolution (my-resolve node env)}
-        log))
+  [node log env state]
+  [(cons {:symbol node, 
+          :type "symbol", 
+          :resolution (my-resolve node env state)}
+         log)
+   state])
+
+(defn is-deffed
+  [symbol log bindings]
+  (cons {:type "def-check" :symbol symbol
+         :is-deffed (contains? bindings symbol)} log))
 
 (defn f-def
-  [node log env]
-  ; todo: ... everything! ...
-  log)
-
+  [node log env state]
+  (let [log-2 (is-deffed (node :symbol) log (state :bindings))
+        state-2 {:bindings (conj (state :bindings) (node :symbol))}] ; TODO is there a better way to copy most of a table, changing only 1 key?
+    (f-node (node :value) log-2 env state-2)))
+    
 (defn m-seq
-  [nodes log env]
-  (loop [log-n log node-n nodes]
-    (if (empty? node-n)
-        log-n
-        (recur (f-node (first node-n) log-n env) (rest node-n)))))
+  ([nodes log env state] (m-seq f-node nodes log env state))
+  ([f nodes log env state]
+   (loop [log-n log node-n nodes state-n state]
+     (if (empty? node-n)
+         [log-n state-n]
+         (let [[log-z state-z] (f (first node-n) log-n env state-n)]
+           (recur log-z (rest node-n) state-z))))))
+
+(defn shadowing?
+  [sym log env state]
+  (let [r (my-resolve sym env state)]
+    (if (nil? r)
+        [log state]
+        [(cons {:type "shadowing" :symbol sym :location r} log)
+         state])))
 
 (defn f-let
   "recurs on: value of each binding, form"
   ; todo: unique symbols?
-  [node log env]
-  (let [log-2 (m-seq (map second (node :bindings)) log env)]
-    (f-node (node :body)
-            log-2
-            (new-env (apply hash-set (map first (node :bindings))) env))))
+  [node log env state]
+  (let [syms (map first (node :bindings))
+        [log-1 state-1] (m-seq shadowing? syms log env state)]
+    (let [[log-2 state-2] (m-seq (map second (node :bindings)) log-1 env state-1)]
+      (let [sym-set (apply hash-set syms)
+            log-3 (if (not (= (count syms) (count sym-set)))
+                      (cons {:type "duplicate symbol in let", :symbols syms} log-2)
+                      log-2)]
+        (f-node (node :body)
+                log-3
+                (new-env sym-set env)
+                state-2)))))
 
 (defn f-app
-  [node log env]
-  (let [log2 (f-node (node :function) log env)]
-    (m-seq (node :arguments) log2 env)))
+  [node log env state]
+  (let [[log-2 state-2] (f-node (node :function) log env state)]
+    (m-seq (node :arguments) log-2 env state-2)))
 
 (def actions
  {"symbol"      f-symbol

   :bindings bindings
   :form form})

(defn make-app
  [f args]
  {:type "application"



(def eg1
  [;(make-def 'id (make-fn '(x) 'x))
;   (make-def 'a 'True)
;   (make-def 'b 'False)
;   (make-def 'z (make-app 'a '[a b c]))
   (make-def 'f 'True)
   (make-app 'f '[x y])
   (make-let '[[f g]] (make-let '[[f h]] 'q))
;   (make-let '[[f g] [f h]] 'f)
;   (make-let '[[f g] [x z]] (make-app 'f '[x y]))])
;   (make-def '. (make-fn '(f g x) '(f (g x))))
;   (make-def 'd (make-fn '(x) '(x x)))
;   (make-def 't (make-fn '(f x) '(. f f x)))])
  ])


(defn my-resolve
  [sym env state]
  (cond 
    (nil? env)
      (if (contains? (state :bindings) sym)
          "root state")
    (contains? (env :bindings) sym) (env :depth)
    :else (recur sym (env :parent) state)))

(defn new-env
  [bindings old-env]
