 								arg2 (if (not (= :minijava.ir/Call (type (:exp2 s)))) (:exp2 s)
 											;;;exp2 is a call, so wrap it in an eseq  
 											(let [t (tm/temp)] (ExpSeq (Move (:exp2 s) t) t)))]
-								(canon (Conditional (:op s) arg1 arg2 (:t s) (:f s))));;ok; now create a new binop with these arguments, and run canon on it		
+								(canon-local (Conditional (:op s) arg1 arg2 (:t s) (:f s))));;ok; now create a new binop with these arguments, and run canon-local on it		
 			(= :minijava.ir/Mem (type s))
 					;;s is an Mem, and its adress is a call	
-					(canon (Mem (let [t (tm/temp)] (ExpSeq (Move (:exp s) t) t))))
+					(canon-local (Mem (let [t (tm/temp)] (ExpSeq (Move (:exp s) t) t))))
 
 				:else s
 ))

(ns minijava.canon
  "Implementation of the canonicalization algorithms for IR."
  (:use (minijava ir)
        clojure.contrib.seq)
  (:require [minijava.temp :as tm]))

(declare canon)

(defn remove-double-eseq
  "(ExpSeq s1 (ExpSeq s2 e)) -> [s1 s2 e]"
  [tree]
  (let [s1 (canon (:seqs tree ))
        s2 (canon (get-in tree [:exp :seqs]))
        e  (canon  (get-in tree [:exp :exp]))]
    (conj (vec (concat s1 s2))
          e)))

(defn remove-eseq-left
  "(BinaryOp op (ExpSeq stmt expr) e2) -> [stmt (BinaryOp op expr e2)]"
  [tree] 
  (let [stmt (canon (get-in tree [:exp1 :seqs]))
        expr (canon (get-in tree [:exp1 :exp]))]
    (conj (vec stmt)
          (merge tree [:exp1 expr]))))

 ;; is this correct for CJumps, or just for Binops? As seen in figure
 ;; 8.1 (3), if a Cjump is fed into this, it should end up with no
 ;; ESeqs, just Seqs.
(defn remove-eseq-commute
  "(BinaryOp op e1 (ExpSeq s2 e2)) -> [s2 (BinaryOp op e1 e2)]"
  [tree]
  (let [e1 (canon (get tree :exp1))
        s2 (canon (get-in tree [:exp2 :seqs]))
        e2 (canon (get-in tree [:exp2 :exp]))]
    (conj (vec s2)
          (merge tree [:exp2 e2]))))

(defn remove-eseq-no-commute
  "(BinaryOp op e1 (ExpSeq s2 e2))
     -> [(Move e1 (Temp t)) s2 (BinaryOp op (Temp t e2))]"
  [tree]
  (let [e1 (canon (get tree :exp1))
        s1 (canon (get-in tree [:exp2 :seqs]))
        e2 (canon (get-in tree [:exp2 :exp]))
        t  (tm/temp)]
    (concat [(Move e1 (Temp t))]
            s1
            [(merge tree [:exp1 (Temp t)]
                    [:exp2 e2])])))

(defn matches-double-eseq?
  [s]
  (and (= :minijava.ir/ExpSeq (type s))
       (= :minijava.ir/ExpSeq (type (:exp s)))))

(defn matches-eseq-left?
  [s]
  (or (and (= :minijava.ir/BinaryOp (type s)) ;; see figure 8.1
           (= :minijava.ir/ExpSeq (type (:exp1 s))))
      (and (= :minijava.ir/Mem (type s))
           (= :minijava.ir/ExpSeq (type (:adr s))))
      (and (= :minijava.ir/Jump (type s))
           (= :minijava.ir/ExpSeq (type (:lbl s))))
      (and (= :minijava.ir/Conditional (type s))
           (= :minijava.ir/ExpSeq (type (:exp1 s))))))


(defn matches-eseq-commute?
  [s]
  (or (and (= :minijava.ir/BinaryOp (type s)) ;; see figure 8.1
           (= :minijava.ir/ExpSeq (type (:exp2 s))))
      (and (= :minijava.ir/Conditional (type s))
           (= :minijava.ir/ExpSeq (type (:exp2 s))))))

(defn isit? [x t]
  (= (type x) t))

;; support function for Commutes, taken from Canon.java
(defn isNop [a]
  (and (isit? a :minijava.ir/Statement) (isit? (:exp a) :minijava.ir/Const)))

;; commutes, translated from Canon.java
(defn commutes
  [a b]
  (or (isNop a) (isit? b :minijava.ir/Name) (isit? b :minijava.ir/Const)))

								arg2 (if (not (= :minijava.ir/Call (type (:exp2 s)))) (:exp2 s)
											;;;exp2 is a call, so wrap it in an eseq  
											(let [t (tm/temp)] (ExpSeq (Move (:exp2 s) t) t)))]
								(canon-local (BinaryOp (:op s) arg1 arg2)));;ok; now create a new binop with these arguments, and run canon-local on it		
				(= :minijava.ir/ExpSeq (type s))
					;;s is an expseq, and its expression is a call	
					(canon-local (ExpSeq (:seqs s) 	
								 (let [t (tm/temp)] (ExpSeq (Move (:exp s) t) t))))
			(= :minijava.ir/Conditional (type s))
							;;s is an conditional, and one or both arguments are calls
