     (mul (cst 0) (sym "x") (sym "y"))
     (mul (cst 1) (sym "y") (cst 2))
     (add (cst 0) (sym "x"))))
-
-(def expr-2
-  (add 1 2
-    (mul 0 "x" "y")
-    (mul 1 "y" 2)
-    (add 0 "y")))
 
 ;; ----------------------------------------------------------------------------
 

      )))

(defn- optimize-add [e]
  (cond
    (add? e) (optimize-op e + 0)
    :else e))

(defn- optimize-mul [e]
  (cond
    (mul? e) (if (some #{0} e) (cst 0) (optimize-op e * 1))
    :else e))

(defn optimize
  [e]
  (walk/postwalk
    (comp optimize-mul optimize-add)
    e))


;; ----------------------------------------------------------------------------

(defn add [& args] (into [:add] args))
(defn mul [& args] (into [:mul] args))

(defn rator [e] (first e))
(defn rands [e] (rest e))

(defn cst? [n] (number? n))
(defn sym? [v] (string? v))
(defn op? [e] (vector? e))
(defn add? [e] (and (op? e) (= (rator e) :add)))
(defn mul? [e] (and (op? e) (= (rator e) :mul)))


;; ----------------------------------------------------------------------------
