NichtHaskell/Source/abstractSyntaxTree/Expression/BinaryExpression.java
2024-05-08 12:56:40 +02:00

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);
}
}