Fixed Bug concerning all BinaryOperators which are not booleanExpressions but produce a value.
This commit is contained in:
parent
d1da1c6eee
commit
392fea7d23
@ -76,105 +76,97 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
Label expressionEnd = new Label(); //End of the whole expression
|
||||
|
||||
// Bytecode for the binary operation
|
||||
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
|
||||
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
|
||||
switch (operator) {
|
||||
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
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
break;
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
}
|
||||
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 "||":
|
||||
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);
|
||||
}
|
||||
case "==" -> {
|
||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||
break;
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
case "==":
|
||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||
}
|
||||
case "<" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
break;
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||
}
|
||||
case "<=" -> {
|
||||
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_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||
}
|
||||
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;
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||
}
|
||||
case "!=" -> {
|
||||
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_ICMPNE, operationTrue); // Checks on not equal
|
||||
}
|
||||
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
|
||||
break;
|
||||
mv.visitLabel(operationTrue);
|
||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||
|
||||
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 ">=":
|
||||
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(expressionEnd);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user