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,105 +76,97 @@ public class BinaryExpression extends AbstractType implements IExpression{
Label expressionEnd = new Label(); //End of the whole expression Label expressionEnd = new Label(); //End of the whole expression
// Bytecode for the binary operation // Bytecode for the binary operation
switch (operator) { if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
case "&&": switch (operator) {
left.codeGen(mv, localVars, typeContext, methodContext); case "+" -> {
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false 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); 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 mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
break; }
case "||" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
case "||": right.codeGen(mv, localVars, typeContext, methodContext);
left.codeGen(mv, localVars, typeContext, methodContext); mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true }
case "==" -> {
// Keep in mind that only primitive types are allowed in this case (at this time)
right.codeGen(mv, localVars, typeContext, methodContext); left.codeGen(mv, localVars, typeContext, methodContext);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); right.codeGen(mv, localVars, typeContext, methodContext);
break;
case "==": mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
// Keep in mind that only primitive types are allowed in this case (at this time) }
case "<" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
left.codeGen(mv, localVars, typeContext, methodContext); mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
right.codeGen(mv, localVars, typeContext, methodContext); }
case ">" -> {
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 mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
break; }
case "<=" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
case "<": mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
left.codeGen(mv, localVars, typeContext, methodContext); }
right.codeGen(mv, localVars, typeContext, methodContext); 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 mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
break; }
case "!=" -> {
left.codeGen(mv, localVars, typeContext, methodContext);
right.codeGen(mv, localVars, typeContext, methodContext);
case ">": mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
left.codeGen(mv, localVars, typeContext, methodContext); }
right.codeGen(mv, localVars, typeContext, methodContext); 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)
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal mv.visitLabel(operationTrue);
break; mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
case "<=": mv.visitLabel(expressionEnd);
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 ">=":
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 "!=":
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.");
} }
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);
} }
@Override @Override

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 @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 { 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) 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 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); mv.visitLabel(conditionFalse);
elseStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is false, execute the elseBlock 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) mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
statement.codeGen(mv, blockLocalVars, typeContext, methodContext); 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 //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 // So the next iteration starts with a clean stack
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop