package zinara.ast.expression; import zinara.ast.type.*; import zinara.code_generator.*; import zinara.exceptions.TypeClashException; import zinara.exceptions.InvalidCodeException; import zinara.parser.sym; import zinara.parser.parser; import java.io.IOException; public class BinaryBooleanExp extends BooleanExp { public int operator; public Expression left; public Expression right; public BinaryBooleanExp (int o, Expression l, Expression r) throws TypeClashException { type = parser.operators.check(o, l.getType(), r.getType()); operator=o; left = l; right = r; } public Type getType() { return type; } public String toString() { return "("+left + " " + operator + " " + right+")" ; } public void tox86(Genx86 generator) throws IOException,InvalidCodeException{ switch(operator) { case sym.AND: conjuntionToX86(generator, true); break; case sym.SAND: conjuntionToX86(generator, false); break; case sym.OR: disjunctionToX86(generator, true); break; case sym.SOR: disjunctionToX86(generator, false); break; case sym.XOR: xorToX86(generator); } } public void conjuntionToX86(Genx86 generator, boolean shortCircuit) throws IOException,InvalidCodeException{ left.yesLabel = generator.newLabel(); left.noLabel = (shortCircuit ? noLabel : left.yesLabel); right.yesLabel = yesLabel; right.noLabel = noLabel; left.register = register; right.register = register + 1; String leftReg = generator.regName(left.register,left.type); String rightReg = generator.regName(right.register,left.type); left.tox86(generator); generator.write(generator.add(leftReg,"0")); generator.write(generator.jz(left.noLabel)); generator.writeLabel(left.yesLabel); //save generator.write(generator.save(register+1)); right.tox86(generator); generator.write(generator.add(rightReg,"0")); //restore generator.write(generator.restore(register+1)); generator.write(generator.jz(left.noLabel)); } public void disjunctionToX86(Genx86 generator, boolean shortCircuit) throws IOException,InvalidCodeException{ left.noLabel = generator.newLabel(); left.yesLabel = (shortCircuit ? yesLabel : left.noLabel); right.yesLabel = yesLabel; right.noLabel = noLabel; left.register = register; right.register = register + 1; String leftReg = generator.regName(left.register,type); String rightReg = generator.regName(right.register,type); // saving and restoring register missing left.tox86(generator); generator.write(generator.add(leftReg,"0")); generator.write(generator.jnz(left.yesLabel)); generator.writeLabel(left.noLabel); //save generator.write(generator.save(register+1)); right.tox86(generator); generator.write(generator.add(rightReg,"0")); //restore generator.write(generator.restore(register+1)); generator.write(generator.jnz(left.yesLabel)); } public void xorToX86(Genx86 generator) throws IOException,InvalidCodeException{ left.register = register; right.register = register + 1; String leftReg = generator.regName(left.register,type); String rightReg = generator.regName(right.register,type); //save generator.write(generator.save(register+1)); left.tox86(generator); right.tox86(generator); generator.write(generator.xor(leftReg,rightReg)); //restore generator.write(generator.restore(register+1)); generator.write(generator.add(leftReg,"0")); generator.write(generator.jnz(yesLabel)); generator.write(generator.jump(noLabel)); } public boolean isStaticallyKnown() { return left.isStaticallyKnown() && right.isStaticallyKnown(); } public Object staticValue() { switch(operator) { case sym.AND: return new Boolean(((Boolean)left.staticValue()).booleanValue() && ((Boolean)right.staticValue()).booleanValue()); case sym.SAND: return new Boolean(((Boolean)left.staticValue()).booleanValue() & ((Boolean)right.staticValue()).booleanValue()); case sym.OR: return new Boolean(((Boolean)left.staticValue()).booleanValue() || ((Boolean)right.staticValue()).booleanValue()); case sym.SOR: return new Boolean(((Boolean)left.staticValue()).booleanValue() | ((Boolean)right.staticValue()).booleanValue()); case sym.XOR: return new Boolean(((Boolean)left.staticValue()).booleanValue() ^ ((Boolean)right.staticValue()).booleanValue()); } return null; } }