From 295bf079b9d1ae4bb5b441ea3a741b949ff9fa93 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 21 May 2024 12:14:12 +0200 Subject: [PATCH] Add continue and do-while, close #331 --- resources/bytecode/javFiles/While.jav | 9 ++++++++ .../de/dhbwstuttgart/bytecode/Codegen.java | 21 +++++++++++++++++++ .../StatementGenerator.java | 8 +++++-- .../syntaxtree/AbstractASTWalker.java | 5 +++++ .../syntaxtree/StatementVisitor.java | 2 ++ .../syntaxtree/statement/Continue.java | 18 ++++++++++++++++ .../syntaxtree/visual/OutputGenerator.java | 5 +++++ .../generate/StatementToTargetExpression.java | 7 ++++++- .../generate/TracingStatementVisitor.java | 5 +++++ .../target/tree/expression/TargetDo.java | 4 ++++ .../tree/expression/TargetExpression.java | 2 +- .../target/tree/expression/TargetWhile.java | 2 -- .../typeinference/typeAlgo/TYPEStmt.java | 10 ++++++++- src/test/java/TestComplete.java | 9 ++++++++ 14 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java create mode 100644 src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java diff --git a/resources/bytecode/javFiles/While.jav b/resources/bytecode/javFiles/While.jav index df259cf5..cdd41f51 100644 --- a/resources/bytecode/javFiles/While.jav +++ b/resources/bytecode/javFiles/While.jav @@ -9,4 +9,13 @@ public class While { } return x; } + + public m2() { + int i = 0; + do { + ++i; + } while(i < 10); + + return i; + } } \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index b3c1fe20..8df566b9 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -978,6 +978,27 @@ public class Codegen { mv.visitLabel(end); break; } + case TargetDo _do: { + Label start = new Label(); + Label end = new Label(); + Label check = new Label(); + + var env = new BreakEnv(); + env.startLabel = check; + env.endLabel = end; + + mv.visitLabel(start); + state.breakStack.push(env); + generate(state, _do.body()); + state.breakStack.pop(); + + mv.visitLabel(check); + generate(state, _do.cond()); + mv.visitJumpInsn(IFEQ, end); + mv.visitJumpInsn(GOTO, start); + mv.visitLabel(end); + break; + } case TargetIf _if: { generate(state, _if.cond()); Label _else = new Label(); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index abe38580..f4587b6b 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -597,8 +597,12 @@ public class StatementGenerator { } private Statement convert(Java17Parser.ContinuestmtContext stmt) { - // TODO - throw new NotImplementedException(); + Token offset = stmt.getStart(); + if (!Objects.isNull(stmt.identifier())) { + return new Continue(localVars.get(stmt.identifier().getText()), offset); + } else { + return new Continue(TypePlaceholder.fresh(offset), offset); + } } private Statement convert(Java17Parser.SemistmtContext stmt) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index bc963fb3..2b4fff9f 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -236,6 +236,11 @@ public abstract class AbstractASTWalker implements ASTVisitor { aBreak.accept(this); } + @Override + public void visit(Continue aContinue) { + aContinue.accept(this); + } + @Override public void visit(StaticClassName staticClassName) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java index 1f1dc61c..78148964 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/StatementVisitor.java @@ -53,6 +53,8 @@ public interface StatementVisitor { void visit(Break aBreak); + void visit(Continue aContinue); + void visit(Yield aYield); void visit(StaticClassName staticClassName); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java new file mode 100644 index 00000000..7da44743 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Continue.java @@ -0,0 +1,18 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; +import org.antlr.v4.runtime.Token; + +public class Continue extends Statement { + + public Continue(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + } + + @Override + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } + +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java index bb24aae3..7297dd87 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/visual/OutputGenerator.java @@ -333,6 +333,11 @@ public class OutputGenerator implements ASTVisitor { out.append("break"); } + @Override + public void visit(Continue aContinue) { + out.append("continue"); + } + @Override public void visit(StaticClassName staticClassName) { diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 715ece94..7e50585a 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -261,6 +261,11 @@ public class StatementToTargetExpression implements ASTVisitor { result = new TargetBreak(); } + @Override + public void visit(Continue aContinue) { + result = new TargetContinue(); + } + @Override public void visit(StaticClassName staticClassName) { result = new TargetClassName(converter.convert(staticClassName.getType())); @@ -283,7 +288,7 @@ public class StatementToTargetExpression implements ASTVisitor { @Override public void visit(DoStmt whileStmt) { - throw new NotImplementedException(); + result = new TargetDo(converter.convert(whileStmt.expr), converter.convert(whileStmt.loopBlock)); } // TODO These two might not be necessary diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 7b6f2a5f..d26cbbd9 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -124,6 +124,11 @@ public abstract class TracingStatementVisitor implements StatementVisitor { } + @Override + public void visit(Continue aContinue) { + + } + @Override public void visit(StaticClassName staticClassName) { diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java new file mode 100644 index 00000000..7329b2ea --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetDo.java @@ -0,0 +1,4 @@ +package de.dhbwstuttgart.target.tree.expression; + +public record TargetDo(TargetExpression cond, TargetExpression body) implements TargetExpression { +} diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java index e0bbc523..b82cfd79 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetExpression.java @@ -3,7 +3,7 @@ package de.dhbwstuttgart.target.tree.expression; import de.dhbwstuttgart.target.tree.type.*; public sealed interface TargetExpression - permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { + permits TargetBinaryOp, TargetBlock, TargetBreak, TargetCast, TargetClassName, TargetContinue, TargetDo, TargetFieldVar, TargetFor, TargetForEach, TargetIf, TargetInstanceOf, TargetLambdaExpression, TargetLiteral, TargetLocalVar, TargetPattern, TargetReturn, TargetStatementExpression, TargetSuper, TargetSwitch, TargetTernary, TargetThis, TargetThrow, TargetUnaryOp, TargetVarDecl, TargetWhile, TargetYield { default TargetType type() { return null; diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java index e1a3690c..463702bd 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetWhile.java @@ -1,6 +1,4 @@ package de.dhbwstuttgart.target.tree.expression; -import de.dhbwstuttgart.target.tree.type.TargetType; - public record TargetWhile(TargetExpression cond, TargetExpression body) implements TargetExpression { } diff --git a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index be402d08..e068d9b2 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -514,6 +514,11 @@ public class TYPEStmt implements StatementVisitor { } + @Override + public void visit(Continue aContinue) { + + } + @Override public void visit(StaticClassName staticClassName) { // Hier entstehen keine Constraints @@ -569,7 +574,10 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(DoStmt whileStmt) { - throw new NotImplementedException(); + RefType booleanType = new RefType(ASTFactory.createClass(java.lang.Boolean.class).getClassName(), new NullToken()); + whileStmt.expr.accept(this); + constraintsSet.addUndConstraint(new Pair(whileStmt.expr.getType(), booleanType, PairOperator.EQUALSDOT, loc(whileStmt.expr.getOffset()))); + whileStmt.loopBlock.accept(this); } @Override diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index bc844bc0..6b685b92 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -925,6 +925,15 @@ public class TestComplete { assertEquals(clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5), "small"); } + @Test + public void testWhile() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "While.jav"); + var clazz = classFiles.get("While"); + var instance = clazz.getDeclaredConstructor().newInstance(); + assertEquals(clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5), 5); + assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 10); + } + @Test public void testBug122() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav");