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
|
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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user