From 5d0d7a6d948f2b50b84160a38bfa63bb81916fb8 Mon Sep 17 00:00:00 2001 From: Daniel Holle Date: Tue, 24 Oct 2023 17:34:06 +0200 Subject: [PATCH] Translate for loop --- resources/bytecode/javFiles/For.jav | 28 +++++------ .../de/dhbwstuttgart/bytecode/Codegen.java | 13 +++-- .../StatementGenerator.java | 48 +++++-------------- .../syntaxtree/AbstractASTWalker.java | 2 +- .../syntaxtree/statement/ForStmt.java | 25 ++++++---- .../generate/StatementToTargetExpression.java | 3 +- .../generate/TracingStatementVisitor.java | 2 +- .../target/tree/expression/TargetFor.java | 4 +- .../typeinference/typeAlgo/TYPEStmt.java | 41 ++-------------- src/test/java/TestComplete.java | 11 ++++- src/test/java/targetast/TestCodegen.java | 2 +- 11 files changed, 71 insertions(+), 108 deletions(-) diff --git a/resources/bytecode/javFiles/For.jav b/resources/bytecode/javFiles/For.jav index c4bd6677..2d967f97 100644 --- a/resources/bytecode/javFiles/For.jav +++ b/resources/bytecode/javFiles/For.jav @@ -4,20 +4,20 @@ import java.lang.Boolean; class For{ Integer m(Integer x){ var c = x + 2; -// Boolean b = true; -// c = 5; -// c++; -// ++c; -// c--; -// --c; -// while(x<2){ -// x = x +1; -// b = false; -// } - return c; -// for(int i = 0;i<10;i++) { -// x = x + 5; -// } + Boolean b = true; + c = 5; + c++; + ++c; + c--; + --c; + while(x<2){ + x = x +1; + b = false; + } + for(int i = 0; i<10; i++) { + x = x + 5; + } + return x; } // m2(Integer x){ diff --git a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java index 83c019c5..0462255a 100644 --- a/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java +++ b/src/main/java/de/dhbwstuttgart/bytecode/Codegen.java @@ -866,7 +866,8 @@ public class Codegen { state.enterScope(); var localCounter = state.localCounter; if (_for.init() != null) - generate(state, _for.init()); + _for.init().forEach(e -> generate(state, e)); + Label start = new Label(); Label end = new Label(); mv.visitLabel(start); @@ -885,10 +886,12 @@ public class Codegen { state.breakStack.pop(); if (_for.increment() != null) { - generate(state, _for.increment()); - if (_for.increment().type() != null) { - popValue(state, _for.increment().type()); - } + _for.increment().forEach(e -> { + generate(state, e); + if (e.type() != null) { + popValue(state, e.type()); + } + }); } mv.visitJumpInsn(GOTO, start); mv.visitLabel(end); diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 31e5d8ed..3611f003 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -11,6 +11,7 @@ import java.util.stream.Collectors; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.syntaxtree.*; +import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.Void; import org.antlr.v4.runtime.Token; @@ -96,40 +97,6 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.YieldstmtContext; import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; -import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; -import de.dhbwstuttgart.syntaxtree.statement.Block; -import de.dhbwstuttgart.syntaxtree.statement.BoolExpression; -import de.dhbwstuttgart.syntaxtree.statement.Break; -import de.dhbwstuttgart.syntaxtree.statement.CastExpr; -import de.dhbwstuttgart.syntaxtree.statement.DoStmt; -import de.dhbwstuttgart.syntaxtree.statement.Expression; -import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; -import de.dhbwstuttgart.syntaxtree.statement.FieldVar; -import de.dhbwstuttgart.syntaxtree.statement.IfStmt; -import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; -import de.dhbwstuttgart.syntaxtree.statement.Literal; -import de.dhbwstuttgart.syntaxtree.statement.LocalVar; -import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; -import de.dhbwstuttgart.syntaxtree.statement.MethodCall; -import de.dhbwstuttgart.syntaxtree.statement.NewClass; -import de.dhbwstuttgart.syntaxtree.statement.Receiver; -import de.dhbwstuttgart.syntaxtree.statement.Return; -import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; -import de.dhbwstuttgart.syntaxtree.statement.Statement; -import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; -import de.dhbwstuttgart.syntaxtree.statement.Super; -import de.dhbwstuttgart.syntaxtree.statement.Switch; -import de.dhbwstuttgart.syntaxtree.statement.SwitchBlock; -import de.dhbwstuttgart.syntaxtree.statement.SwitchLabel; -import de.dhbwstuttgart.syntaxtree.statement.This; -import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; -import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; -import de.dhbwstuttgart.syntaxtree.statement.Yield; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; @@ -522,7 +489,18 @@ public class StatementGenerator { } private Statement convert(Java17Parser.ForloopContext stmt) { - throw new NotImplementedException(); + var control = stmt.forControl(); + var block = convert(stmt.statement()); + if (control.enhancedForControl() != null) + throw new NotImplementedException(); + else { + return new ForStmt( + stmt.getStart(), + convert(control.forInit().localVariableDeclaration()), + convert(control.expression()), control.forUpdate.expression().stream().map(this::convert).toList(), + block + ); + } } private ArgumentList convertArguments(Java17Parser.ExpressionListContext arglist) { diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java index 0b7d9e67..9b8d5286 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/AbstractASTWalker.java @@ -163,7 +163,7 @@ public abstract class AbstractASTWalker implements ASTVisitor { @Override public void visit(ForStmt forStmt) { - forStmt.body_Loop_block.accept(this); + forStmt.block.accept(this); } @Override diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java index 1f933366..cb73f322 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/ForStmt.java @@ -2,24 +2,29 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.exceptions.NotImplementedException; +import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.Void; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; +import org.antlr.v4.runtime.Token; + +import java.util.List; public class ForStmt extends Statement { - - private Expression head_Initializer_1; - private Expression head_Condition_1; - private Expression head_Loop_expr_1; - private Expression head_Initializer; - private Expression head_Condition; - private Expression head_Loop_expr; - public Block body_Loop_block; + public final List initializer; + public final Expression condition; + public final List loopExpr; + public final Statement block; - public ForStmt(int offset, int variableLength) + public ForStmt(Token offset, List initializer, Expression condition, List loopExpr, Statement block) { - super(null,null); + super(new Void(new NullToken()), offset); + this.initializer = initializer; + this.condition = condition; + this.loopExpr = loopExpr; + this.block = block; } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index 880d02a3..0cfc0a2f 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -139,8 +139,7 @@ public class StatementToTargetExpression implements ASTVisitor { @Override public void visit(ForStmt forStmt) { - // TODO Doesn't seem to be fully implemented yet - throw new NotImplementedException(); + result = new TargetFor(forStmt.initializer.stream().map(converter::convert).toList(), converter.convert(forStmt.condition), forStmt.loopExpr.stream().map(converter::convert).toList(), converter.convert(forStmt.block)); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java index 81aa824e..f7feb9f4 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/TracingStatementVisitor.java @@ -63,7 +63,7 @@ public abstract class TracingStatementVisitor implements StatementVisitor { @Override public void visit(ForStmt forStmt) { - forStmt.body_Loop_block.accept(this); + forStmt.block.accept(this); } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java index 0efdd61d..b3ce4676 100644 --- a/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java +++ b/src/main/java/de/dhbwstuttgart/target/tree/expression/TargetFor.java @@ -1,6 +1,6 @@ package de.dhbwstuttgart.target.tree.expression; -import de.dhbwstuttgart.target.tree.type.TargetType; +import java.util.List; -public record TargetFor(TargetExpression init, TargetExpression termination, TargetExpression increment, TargetExpression body) implements TargetExpression { +public record TargetFor(List init, TargetExpression termination, List increment, 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 a9d1051c..154beca8 100644 --- a/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/main/java/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -12,41 +12,7 @@ import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; -import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; -import de.dhbwstuttgart.syntaxtree.statement.Assign; -import de.dhbwstuttgart.syntaxtree.statement.AssignToField; -import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; -import de.dhbwstuttgart.syntaxtree.statement.Block; -import de.dhbwstuttgart.syntaxtree.statement.BoolExpression; -import de.dhbwstuttgart.syntaxtree.statement.Break; -import de.dhbwstuttgart.syntaxtree.statement.CastExpr; -import de.dhbwstuttgart.syntaxtree.statement.DoStmt; -import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt; -import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; -import de.dhbwstuttgart.syntaxtree.statement.FieldVar; -import de.dhbwstuttgart.syntaxtree.statement.ForStmt; -import de.dhbwstuttgart.syntaxtree.statement.IfStmt; -import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; -import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; -import de.dhbwstuttgart.syntaxtree.statement.Literal; -import de.dhbwstuttgart.syntaxtree.statement.LocalVar; -import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl; -import de.dhbwstuttgart.syntaxtree.statement.MethodCall; -import de.dhbwstuttgart.syntaxtree.statement.NewArray; -import de.dhbwstuttgart.syntaxtree.statement.NewClass; -import de.dhbwstuttgart.syntaxtree.statement.Return; -import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; -import de.dhbwstuttgart.syntaxtree.statement.Statement; -import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; -import de.dhbwstuttgart.syntaxtree.statement.Super; -import de.dhbwstuttgart.syntaxtree.statement.SuperCall; -import de.dhbwstuttgart.syntaxtree.statement.Switch; -import de.dhbwstuttgart.syntaxtree.statement.SwitchBlock; -import de.dhbwstuttgart.syntaxtree.statement.SwitchLabel; -import de.dhbwstuttgart.syntaxtree.statement.This; -import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; -import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; -import de.dhbwstuttgart.syntaxtree.statement.Yield; +import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType; import de.dhbwstuttgart.syntaxtree.type.GenericRefType; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -156,7 +122,10 @@ public class TYPEStmt implements StatementVisitor { @Override public void visit(ForStmt forStmt) { - throw new NotImplementedException(); + forStmt.initializer.forEach(s -> s.accept(this)); + forStmt.condition.accept(this); + forStmt.loopExpr.forEach(e -> e.accept(this)); + forStmt.block.accept(this); } @Override diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 7935960b..dbdfff2d 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -725,6 +725,15 @@ public class TestComplete { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Static.jav"); var clazz = classFiles.get("Static"); var m = clazz.getDeclaredMethod("m"); - assertEquals(m.invoke(null), 30); + assertEquals(m.invoke(null), 50); + } + + @Test + public void testFor() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "For.jav"); + var clazz = classFiles.get("For"); + var instance = clazz.getDeclaredConstructor().newInstance(); + var m = clazz.getDeclaredMethod("m", Integer.class); + assertEquals(m.invoke(instance, 10), 60); } } diff --git a/src/test/java/targetast/TestCodegen.java b/src/test/java/targetast/TestCodegen.java index 8e0a5553..716e4d6b 100644 --- a/src/test/java/targetast/TestCodegen.java +++ b/src/test/java/targetast/TestCodegen.java @@ -192,7 +192,7 @@ public class TestCodegen { @Test public void testFor() throws Exception { var targetClass = new TargetClass(Opcodes.ACC_PUBLIC, new JavaClassName("For")); - targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), new TargetFor(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0)), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1))), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum"))))); + targetClass.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "forLoop", List.of(), TargetType.Integer, new TargetBlock(List.of(new TargetVarDecl(TargetType.Integer, "sum", new TargetLiteral.IntLiteral(0)), new TargetFor(List.of(new TargetVarDecl(TargetType.Integer, "i", new TargetLiteral.IntLiteral(0))), new TargetBinaryOp.Less(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(10)), List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "i"), new TargetLiteral.IntLiteral(1)))), new TargetBlock(List.of(new TargetAssign(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetBinaryOp.Add(TargetType.Integer, new TargetLocalVar(TargetType.Integer, "sum"), new TargetLocalVar(TargetType.Integer, "i")))))), new TargetReturn(new TargetLocalVar(TargetType.Integer, "sum"))))); var clazz = generateClass(targetClass, new ByteArrayClassLoader()); assertEquals(clazz.getDeclaredMethod("forLoop").invoke(null), 45); }