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 BinaryExp extends Expression { public int operator; public Expression left; public Expression right; public BinaryExp (int o, Expression l, Expression r) throws TypeClashException { operator=o; left=l; right=r; type = parser.operators.check(this.operator, this.left.getType(), this.right.getType()); if ((l.getType().getType() instanceof IntType) && (r.getType().getType() instanceof FloatType)) left = new CastedExp(new FloatType(), l); else if ((l.getType().getType() instanceof FloatType) && (r.getType().getType() instanceof IntType)) right = new CastedExp(new FloatType(), r); } public Type getType() { return type; } public String toString() { return "("+left + " " + operator + " " + right+")" ; } public void tox86(Genx86 generate) throws IOException,InvalidCodeException{ String save; String restore; left.register = register; right.register = register + 1; left.tox86(generate); //save generate.write(generate.save(register+1)); right.tox86(generate); if (type instanceof IntType) generate.write(intOps(generate)); else if (type instanceof FloatType) generate.write(realOps(generate)); else{ System.out.println("Tipo no implementado en BinaryExp: "+type); System.exit(1); } //restore generate.write(generate.restore(register+1)); } private String intOps(Genx86 generate) throws InvalidCodeException{ String code = ""; String leftReg = generate.regName(left.register,left.type); String rightReg = generate.regName(right.register,right.type); if (operator == sym.PLUS){ code += generate.add(leftReg,rightReg); } else if (operator == sym.MINUS){ code += generate.sub(leftReg,rightReg); } else if (operator == sym.TIMES){ code += generate.imul(leftReg,rightReg); } else if (operator == sym.DIVIDE){ code += generate.idiv(leftReg,rightReg); } else if (operator == sym.MOD){ code += generate.imod(leftReg,rightReg); } else{ System.out.println("Operacion no implementada para enteros: "+operator); System.exit(1); } return code; } private String realOps(Genx86 generate) throws InvalidCodeException{ String code = ""; String leftReg = generate.regName(left.register,left.type); String rightReg = generate.regName(right.register,right.type); if (operator == sym.PLUS){ code += generate.fadd(leftReg,rightReg); } else if (operator == sym.MINUS){ code += generate.fsub(leftReg,rightReg); } else if (operator == sym.TIMES){ code += generate.fmul(leftReg,rightReg); } else if (operator == sym.DIVIDE){ code += generate.fdiv(leftReg,rightReg); } else{ System.out.println("Operacion no implementada para reales: "+operator); System.exit(1); } return code; } public boolean isStaticallyKnown() { return left.isStaticallyKnown() && right.isStaticallyKnown(); } public Object staticValue() { if (left.staticValue() instanceof Integer && right.staticValue() instanceof Integer) { int leftInt = ((Integer)left.staticValue()).intValue(); int rightInt = ((Integer)right.staticValue()).intValue(); if (operator == sym.PLUS) return new Integer(leftInt + rightInt); else if (operator == sym.MINUS) return new Integer(leftInt - rightInt); else if (operator == sym.TIMES) return new Integer(leftInt * rightInt); else if (operator == sym.DIVIDE) return new Integer(leftInt / rightInt); else if (operator == sym.MOD) return new Integer(leftInt % rightInt); } else if (left.staticValue() instanceof Float || right.staticValue() instanceof Float) { float leftFloat = ((Float)left.staticValue()).floatValue(); float rightFloat = ((Float)right.staticValue()).floatValue(); if (operator == sym.PLUS) return new Float(leftFloat + rightFloat); else if (operator == sym.MINUS) return new Float(leftFloat - rightFloat); else if (operator == sym.TIMES) return new Float(leftFloat * rightFloat); else if (operator == sym.DIVIDE) return new Float(leftFloat / rightFloat); else if (operator == sym.MOD) return new Float(leftFloat % rightFloat); } else if (left.staticValue() instanceof Integer || right.staticValue() instanceof Float) { int leftInt = ((Integer)left.staticValue()).intValue(); float rightFloat = ((Float)right.staticValue()).floatValue(); if (operator == sym.PLUS) return new Float(leftInt + rightFloat); else if (operator == sym.MINUS) return new Float(leftInt - rightFloat); else if (operator == sym.TIMES) return new Float(leftInt * rightFloat); else if (operator == sym.DIVIDE) return new Float(leftInt / rightFloat); else if (operator == sym.MOD) return new Float(leftInt % rightFloat); } else if (left.staticValue() instanceof Float || right.staticValue() instanceof Float) { float leftFloat = ((Float)left.staticValue()).floatValue(); int rightInt = ((Integer)right.staticValue()).intValue(); if (operator == sym.PLUS) return new Float(leftFloat + rightInt); else if (operator == sym.MINUS) return new Float(leftFloat - rightInt); else if (operator == sym.TIMES) return new Float(leftFloat * rightInt); else if (operator == sym.DIVIDE) return new Float(leftFloat / rightInt); else if (operator == sym.MOD) return new Float(leftFloat % rightInt); } return null; } }