171 lines
5.3 KiB
Java
171 lines
5.3 KiB
Java
package abstractSyntaxTree.Expression;
|
|
|
|
import TypeCheck.TypeCheckResult;
|
|
import TypeCheck.TypeCheckHelper;
|
|
import TypeCheck.AbstractType;
|
|
import org.objectweb.asm.*;
|
|
|
|
import java.beans.Expression;
|
|
import java.util.Objects;
|
|
|
|
public class BinaryExpression extends AbstractType implements IExpression{
|
|
|
|
public String operator;
|
|
public IExpression left;
|
|
public IExpression right;
|
|
|
|
@Override
|
|
public TypeCheckResult typeCheck() throws Exception {
|
|
TypeCheckHelper helper = new TypeCheckHelper();
|
|
TypeCheckResult result = new TypeCheckResult();
|
|
|
|
TypeCheckResult leftType = left.typeCheck();
|
|
TypeCheckResult rightType = right.typeCheck();
|
|
|
|
switch (operator) {
|
|
|
|
case "&&":
|
|
case "||" :{
|
|
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "bool")){
|
|
result.type = "bool";
|
|
}
|
|
break;
|
|
}
|
|
case "==":
|
|
case "<":
|
|
case ">":
|
|
case "<=":
|
|
case ">=":
|
|
case "!=":
|
|
result.type = helper.upperBound(leftType.type, rightType.type);
|
|
break;
|
|
|
|
case "-":
|
|
case "+":
|
|
case "*":
|
|
case "/":
|
|
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "int")){
|
|
result.type = "int";
|
|
}
|
|
break;
|
|
|
|
//case "&" ist für logisches und auf bit level
|
|
//case "|" ist für logisches oder auf bit level
|
|
}
|
|
|
|
setTypeCheckResult(result);
|
|
return result;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void codeGen(MethodVisitor mv) throws Exception {
|
|
// Label for the jump instruction
|
|
Label operationFalse = new Label(); //Operation is false
|
|
Label operationTrue = new Label(); //Operation is true
|
|
// Labels are placed at the end of this method
|
|
Label expressionEnd = new Label(); //End of the whole expression
|
|
|
|
// Bytecode for the binary operation
|
|
switch (operator) {
|
|
case "&&":
|
|
left.codeGen(mv);
|
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
|
|
|
right.codeGen(mv);
|
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
|
|
|
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
|
break;
|
|
|
|
case "||":
|
|
left.codeGen(mv);
|
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
|
|
|
right.codeGen(mv);
|
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
|
break;
|
|
|
|
case "==":
|
|
// Keep in mind that only primitive types are allowed in this case (at this time)
|
|
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
|
break;
|
|
|
|
case "<":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
|
break;
|
|
|
|
case ">":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
|
break;
|
|
|
|
case "<=":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
|
break;
|
|
|
|
case ">=":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
|
break;
|
|
|
|
case "!=":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
|
|
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
|
break;
|
|
|
|
case "+":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
mv.visitInsn(Opcodes.IADD);
|
|
break;
|
|
|
|
case "-":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
mv.visitInsn(Opcodes.ISUB);
|
|
break;
|
|
|
|
case "*":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
mv.visitInsn(Opcodes.IMUL);
|
|
break;
|
|
|
|
case "/":
|
|
left.codeGen(mv);
|
|
right.codeGen(mv);
|
|
mv.visitInsn(Opcodes.IDIV);
|
|
break;
|
|
|
|
default:
|
|
throw new Exception("Unknown operator: " + operator);
|
|
}
|
|
|
|
mv.visitLabel(operationFalse);
|
|
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
|
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
|
|
|
mv.visitLabel(operationTrue);
|
|
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
|
|
|
mv.visitLabel(expressionEnd);
|
|
}
|
|
}
|