From 392fea7d23e81e66bf4f88280524193ce6bdf658 Mon Sep 17 00:00:00 2001 From: Jochen Seyfried Date: Sat, 29 Jun 2024 14:02:51 +0200 Subject: [PATCH] Fixed Bug concerning all BinaryOperators which are not booleanExpressions but produce a value. --- .../Expression/BinaryExpression.java | 164 +++++++++--------- .../Statement/IfElseStatement.java | 5 +- .../Statement/WhileStatement.java | 1 - 3 files changed, 81 insertions(+), 89 deletions(-) diff --git a/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java b/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java index 6b775f6..cbce259 100644 --- a/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java +++ b/src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java @@ -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 diff --git a/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java b/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java index d380fae..b290dcf 100644 --- a/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java @@ -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 localVars, HashMap> typeContext, HashMap>> 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 diff --git a/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java b/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java index 47255ea..a81de81 100644 --- a/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java +++ b/src/main/java/abstractSyntaxTree/Statement/WhileStatement.java @@ -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