     (hash-set :void :int :string :boolean)
     ))
 
-(defn vars-map
-  []
-  (list (hash-map)))
-
-(defn add-var
-  [map var type]
-  (let
-    [curr-scope (peek map)
-     new-scope (conj curr-scope [var type])
-     ]
-    (conj (pop map) new-scope)
-    )
-  )
-
 (defn print-var
   [var]
   (match/match var
     [:ident name] (str name)))
 
+(defn vars-map
+  []
+  [(list (hash-map)) 0 0 (hash-map)])
+
+(defn add-var
+  [[map num-vars num-strings strings] var type]
+  (let
+    [curr-scope (peek map)
+     new-scope (conj curr-scope [var [type num-vars]])
+     ]
+    (if (contains? curr-scope var)
+      (util/err (str "var " (print-var var) " already declared in " (util/ip-meta var)))
+      (util/succ [num-vars [(conj (pop map) new-scope) (+ num-vars 1) num-strings strings]]))
+    )
+  )
+
+(defn add-string
+  [[map num-vars num-strings strings] string]
+  (if (contains? strings string)
+    [(second (find strings string)) [map num-vars num-strings strings]]
+    [(+ num-strings 1) [map num-vars (+ num-strings 1) (assoc (assoc strings string (+ num-strings 1)) (+ num-strings 1) string)]]
+    )
+  )
+
+(defn add-arg-var
+  [[map num-vars num-strings strings] var type]
+  (let
+    [curr-scope (peek map)
+     new-scope (conj curr-scope [var [type (- num-vars)]])
+     ]
+    (if (contains? curr-scope var)
+      (util/err (str "var " (print-var var) " already declared in " (util/ip-meta var)))
+      (util/succ [(- num-vars) [(conj (pop map) new-scope) (+ num-vars 1) num-strings strings]]))
+    )
+  )
+
 (defn lookup-var
-  [map var location]
+  [[map a b c] var location]
   (if (empty? map)
     (do (println "starem") (util/err (str "var " (print-var var) " not found in: " location)))
     (let
       [type (find (peek map) var)]
       (if (nil? type)
-        (recur (pop map) var location)
+        (recur [(pop map) a b c] var location)
         (util/succ (second type))
         )
       )

(defn get-type
  [obj]
  (second (find (meta obj) "_type")))

(defn annotate-expr
  [glob-state vars expr]
  (let [location (util/ip-meta expr)]
    (match/match (first expr)
      :elitint (util/succ (with-type expr [:int]))
      :elittrue (util/succ (with-type expr [:bool]))
      :elitfalse (util/succ (with-type expr [:bool]))
      :estring (util/succ (with-type expr [:string]))
      :evar (m/domonad util/phase-m
              [type (lookup-var vars (second expr) (util/ip-meta expr))]
              (with-type expr type))
      :neg (m/domonad util/phase-m
             [inside-expr (annotate-expr glob-state vars (second expr))
              res (if (= (get-type inside-expr) [:int])
                    (util/succ (with-type [:neg inside-expr] [:int]))
                    (util/err (str "expected int, found " (print-type (get-type inside-expr)) " in: " location))
                    )]
             res
             )
      :not (m/domonad util/phase-m
             [inside-expr (annotate-expr glob-state vars (second expr))
              res (if (= (get-type inside-expr) [:bool])
                    (util/succ (with-type [:not inside-expr] [:bool]))
                    (util/err (str "expected bool, found " (print-type (get-type inside-expr)) " in: " location))
                    )]
             res
             )
      :eor (m/domonad util/phase-m
             [lexpr (annotate-expr glob-state vars (second expr))
              rexpr (annotate-expr glob-state vars (third expr))
              res (if (and
                        (= (get-type lexpr) [:bool])
                        (= (get-type rexpr) [:bool]))
                    (util/succ (with-type [:eor lexpr rexpr] [:bool]))
                    )
              ]
             res)
      :eand (m/domonad util/phase-m
              [lexpr (annotate-expr glob-state vars (second expr))
               rexpr (annotate-expr glob-state vars (third expr))
               res (if (and
                         (= (get-type lexpr) [:bool])
                         (= (get-type rexpr) [:bool]))
                     (util/succ (with-type [:eand lexpr rexpr] [:bool]))
                     (util/err (str "expected bool, bool, found " (print-type (get-type lexpr)) ", " (print-type (get-type rexpr)) " in: " location))
                     )
               ]
              res)
      :erel (m/domonad util/phase-m
              [lexpr (annotate-expr glob-state vars (second expr))
               rexpr (annotate-expr glob-state vars (fourth expr))
               op (m-result (third expr))
               res (if (and
                         (= (get-type lexpr) [:int])
                         (= (get-type rexpr) [:int]))
                     (util/succ (with-type [:erel lexpr op rexpr] [:bool]))
                     (util/err (str "expected int,int, found " (print-type (get-type lexpr)) ", " (print-type (get-type rexpr)) " in: " location))
                     )
               ]
              res)
      :emul (m/domonad util/phase-m
              [lexpr (annotate-expr glob-state vars (second expr))
               rexpr (annotate-expr glob-state vars (fourth expr))
               op (m-result (third expr))
               res (if (and
                         (= (get-type lexpr) [:int])
                         (= (get-type rexpr) [:int]))
                     (util/succ (with-type [:emul lexpr op rexpr] [:int]))
                     (util/err (str "expected int,int, found " (print-type (get-type lexpr)) ", " (print-type (get-type rexpr)) " in: " location))
                     )
               ]

  )

(defn new-scope
  [[map num-vars num-strings strings]]
  (println map)
  (println num-vars)
  (println num-strings)
  (println strings)
  [(conj map (hash-map)) num-vars num-strings strings])

(defn rm-scope
  [[map num-vars num-strings strings]]
  [(pop map) num-vars num-strings strings])

(defn makeclassdefmap
  [glob-state startmap name classdefs]
