diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-11-21 13:40:52 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-11-21 13:40:52 +0000 |
| commit | fa0e5ad5e621fb6a65ecc70a357bb20c14b0e796 (patch) | |
| tree | ec94c60ec657174c3598c6421772fb73d998bbc2 /src | |
| parent | 9f294b76b8b7e5c7eb9bc0a3dff82ba083a4d783 (diff) | |
Support simple for-loops
Diffstat (limited to 'src')
5 files changed, 80 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java index a766cce..97a235e 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java @@ -7,6 +7,7 @@ import org.zwobble.couscous.values.BooleanValue; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import static java.util.Arrays.asList; import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement; @@ -15,6 +16,8 @@ import static org.zwobble.couscous.ast.WhileNode.whileLoop; import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpression; import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpressionWithoutBoxing; import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; +import static org.zwobble.couscous.util.ExtraLists.append; +import static org.zwobble.couscous.util.ExtraLists.concat; import static org.zwobble.couscous.util.ExtraLists.eagerMap; class JavaStatementReader { @@ -41,6 +44,9 @@ class JavaStatementReader { case ASTNode.WHILE_STATEMENT: return asList(readWhileStatement((WhileStatement)statement)); + case ASTNode.FOR_STATEMENT: + return readForStatement((ForStatement)statement); + case ASTNode.VARIABLE_DECLARATION_STATEMENT: return readVariableDeclarationStatement((VariableDeclarationStatement)statement); @@ -78,10 +84,34 @@ class JavaStatementReader { readStatement(statement.getBody())); } + private List<StatementNode> readForStatement(ForStatement statement) { + List javaInitialisers = statement.initializers(); + if (javaInitialisers.size() != 1) { + throw new UnsupportedOperationException(); + } + VariableDeclarationExpression javaDeclaration = (VariableDeclarationExpression) javaInitialisers.get(0); + @SuppressWarnings("unchecked") + List<VariableDeclarationFragment> fragments = javaDeclaration.fragments(); + @SuppressWarnings("unchecked") + List<Expression> updaters = statement.updaters(); + + return append( + readDeclarationFragments(fragments, typeOf(javaDeclaration.getType())), + whileLoop( + readExpression(BooleanValue.REF, statement.getExpression()), + concat( + readStatement(statement.getBody()), + eagerMap(updaters, updater -> expressionStatement(readExpressionWithoutBoxing(updater)))))); + } + private static List<StatementNode> readVariableDeclarationStatement(VariableDeclarationStatement statement) { @SuppressWarnings("unchecked") List<VariableDeclarationFragment> fragments = statement.fragments(); TypeName type = typeOf(statement.getType()); + return readDeclarationFragments(fragments, type); + } + + private static List<StatementNode> readDeclarationFragments(List<VariableDeclarationFragment> fragments, TypeName type) { return eagerMap(fragments, fragment -> localVariableDeclaration( fragment.resolveBinding().getKey(), diff --git a/src/main/java/org/zwobble/couscous/util/ExtraLists.java b/src/main/java/org/zwobble/couscous/util/ExtraLists.java index be8ffb3..8c282e8 100644 --- a/src/main/java/org/zwobble/couscous/util/ExtraLists.java +++ b/src/main/java/org/zwobble/couscous/util/ExtraLists.java @@ -7,6 +7,18 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; public class ExtraLists { + public static <T> List<T> cons(T value, List<T> list) { + return Stream.concat(Stream.of(value), list.stream()).collect(Collectors.toList()); + } + + public static <T> List<T> append(List<T> list, T value) { + return Stream.concat(list.stream(), Stream.of(value)).collect(Collectors.toList()); + } + + public static <T> List<T> concat(List<T> first, List<T> second) { + return Stream.concat(first.stream(), second.stream()).collect(Collectors.toList()); + } + @SuppressWarnings("unchecked") public static <T, R, E extends Exception> List<R> map( Stream<T> stream, diff --git a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java index f17f42b..8c6c3b1 100644 --- a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java +++ b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java @@ -69,6 +69,17 @@ public class JavaToPythonTests { "factorial", asList(value(6)))); } + + @Test + public void forFactorial() throws Exception { + assertEquals( + value(720), + execTestProgram( + "for-factorial", + TypeName.of("com.example.ForFactorial"), + "factorial", + asList(value(6)))); + } private PrimitiveValue execTestProgram( String directoryName, diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java index ad8bcbb..9d21ed2 100644 --- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java +++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java @@ -24,6 +24,7 @@ import static org.zwobble.couscous.ast.FieldAccessNode.fieldAccess; import static org.zwobble.couscous.ast.FieldDeclarationNode.field; import static org.zwobble.couscous.ast.IfStatementNode.ifStatement; import static org.zwobble.couscous.ast.LiteralNode.literal; +import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration; import static org.zwobble.couscous.ast.MethodCallNode.*; import static org.zwobble.couscous.ast.ReturnNode.returns; import static org.zwobble.couscous.ast.StaticMethodCallNode.boxBoolean; @@ -504,6 +505,21 @@ public class JavaReaderTests { asList(returns(literal(1)))), readStatement("int", "while (true) { return 1; }")); } + + @Test + public void canReadForLoops() { + List<StatementNode> statements = readStatements("int", "for (int x = 0; true; ++x) { return 1; }"); + LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0); + assertEquals( + asList( + localVariableDeclaration(declaration.getDeclaration(), literal(0)), + whileLoop( + literal(true), + asList( + returns(literal(1)), + expressionStatement(assign(declaration, integerAdd(reference(declaration), literal(1))))))), + statements); + } @Test public void canDeclareConstructor() { diff --git a/src/test/resources/java/for-factorial/com/example/ForFactorial.java b/src/test/resources/java/for-factorial/com/example/ForFactorial.java new file mode 100644 index 0000000..a5fef50 --- /dev/null +++ b/src/test/resources/java/for-factorial/com/example/ForFactorial.java @@ -0,0 +1,11 @@ +package com.example; + +public class ForFactorial { + public static int factorial(int n) { + int result = 1; + for (int i = 2; i <= n; ++i) { + result *= i; + } + return result; + } +} |
