package edu.cmu.cs.l3.translate;

import edu.cmu.cs.l3.absyn.*;
import edu.cmu.cs.l3.frame.*;
import edu.cmu.cs.l3.errormsg.*;
import edu.cmu.cs.l3.tree.*;
import edu.cmu.cs.l3.temp.*;

public class TranslateExpressionOpCx extends TranslateExpressionCx {

    public TranslateExpressionOpCx(Frame curframe, ErrorMsg e,TranslateEnvironment t) {
	super(curframe,e,t);
    }

    public IRStatement asConditional(Label t, Label f) {

	switch (m_op) {
	case ASOpExpression.AND:
	    return procAnd(t,f);
	case ASOpExpression.OR:
	    return procOr(t,f);
	case ASOpExpression.XOR:
	    return procXor(t,f);
	case ASOpExpression.NOT:
	    return procNot(t,f);
        default:
            System.out.println("Did not recog op");
	};

	return null;
    }

    private IRStatement procAnd(Label t, Label f) {

	Label nextlabel = new Label();

	IRSeq rseq = new IRSeq(new IRLabel(nextlabel),m_right.asConditional(t,f));

	return new IRSeq(m_left.asConditional(nextlabel,f), rseq);
    }

    private IRStatement procOr(Label t, Label f) {

	Label nextlabel = new Label();

	IRSeq rseq = new IRSeq(new IRLabel(nextlabel),m_right.asConditional(t,f));

	return new IRSeq(m_left.asConditional(t,nextlabel), rseq);

    }

    private IRStatement procXor(Label t, Label f) {

	Label trueinit = new Label();
	Label falseinit = new Label();

        IRTemp rtemp = new IRTemp(m_curframe.allocLocalTemp());
        IRStatement rmove = new IRMove(rtemp, m_right.asExpression());
        IRStatement ltcond = new IRCJump(IRCJump.EQ,
                                         rtemp, new IRConst(0), new IRLabel(t), new IRLabel(f));
        IRStatement lfcond = new IRCJump(IRCJump.EQ,
                                         rtemp, new IRConst(1), new IRLabel(t), new IRLabel(f));

	IRSeq tseq = new IRSeq(new IRLabel(trueinit), ltcond);
	IRSeq fseq = new IRSeq(new IRLabel(falseinit), lfcond);
	IRSeq rightseq = new IRSeq(tseq,fseq);

	return new IRSeq(rmove, new IRSeq(m_left.asConditional(trueinit,falseinit), rightseq));
    }

    private IRStatement procNot(Label t, Label f) {
	return m_left.asConditional(f,t);
    }

    public void visitResponse(String type, Object obj) {

	if (type.equals("ASOpExpression"))
	    visitBoolExp(obj);
        else
            System.out.println("WARNING: Skipping: " + type);
    }

    public void visitBoolExp(Object e) {

	ASOpExpression ae = (ASOpExpression) e;

	if (ae.getOperatorClass() == ASOpExpression.BOOLOP) {

	    m_left = chooseTranslator(ae.getLeft());

	    if (ae.getRight() != null) {
		m_right = chooseTranslator(ae.getRight());
	    }

	    ae.getLeft().visit(m_left);
	    if (ae.getRight() != null) {
		ae.getRight().visit(m_right);
	    }

	    m_op = ae.getOperator();
	}
	else
	    System.out.println("WARNING: Translating Non Op in Op Translator");
    }

    private int m_op;
    private TranslateExpression m_left,m_right;

}



