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