Fixed Bug concerning all BinaryOperators which are not booleanExpressions but produce a value.

This commit is contained in:
Jochen Seyfried 2024-06-29 14:02:51 +02:00
parent d1da1c6eee
commit 392fea7d23
3 changed files with 81 additions and 89 deletions

View File

@ -76,97 +76,88 @@ public class BinaryExpression extends AbstractType implements IExpression{
Label expressionEnd = new Label(); //End of the whole expression
// Bytecode for the binary operation
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
switch (operator) {
case "&&":
case "+" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IADD);
}
case "-" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.ISUB);
}
case "*" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IMUL);
}
case "/" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IDIV);
}
}
} else {
switch (operator) {
case "&&" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse);
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
break;
case "||":
}
case "||" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
break;
case "==":
}
case "==" -> {
// Keep in mind that only primitive types are allowed in this case (at this time)
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
break;
case "<":
}
case "<" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
break;
case ">":
}
case ">" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
break;
case "<=":
}
case "<=" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
break;
case ">=":
}
case ">=" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
break;
case "!=":
}
case "!=" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
break;
case "+":
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IADD);
break;
case "-":
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.ISUB);
break;
case "*":
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IMUL);
break;
case "/":
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
mv.visitInsn(Opcodes.IDIV);
break;
default:
throw new TypeCheckException("The operator " + operator + " is not known.");
}
default -> throw new TypeCheckException("The operator " + operator + " is not known.");
}
//TODO: This is only viable for boolean expressions --> structure this file differently
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)
@ -176,6 +167,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
mv.visitLabel(expressionEnd);
}
}
@Override
public boolean equals(Object o) {

View File

@ -54,7 +54,7 @@ public class IfElseStatement extends AbstractType implements IStatement{
}
//TODO: There are 2 NOPs and one athrow on the stack between the if-Block and else-Block execution --> I have no idea why
@Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
@ -67,7 +67,8 @@ public class IfElseStatement extends AbstractType implements IStatement{
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is true, execute the ifBlock
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the else statement
mv.visitLabel(conditionFalse);
elseStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is false, execute the elseBlock

View File

@ -55,7 +55,6 @@ public class WhileStatement extends AbstractType implements IStatement {
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
//statement.codeGen(mv);
//TODO: If the block ends with a return statement, we might have to pop it from the stack
// So the next iteration starts with a clean stack
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop