From 119de6958f47141815de9c13e884b27a08a2b4b3 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 31 Jul 2016 18:22:41 +0100 Subject: Read statement blocks --- .../java/org/zwobble/couscous/ast/NodeTypes.java | 2 + .../zwobble/couscous/ast/StatementBlockNode.java | 51 ++++++++++++++++++++++ .../couscous/frontends/java/JavaReader.java | 7 ++- .../frontends/java/JavaStatementReader.java | 33 ++++++++------ .../tests/frontends/java/JavaReaderTests.java | 12 +++++ 5 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/ast/StatementBlockNode.java (limited to 'src') diff --git a/src/main/java/org/zwobble/couscous/ast/NodeTypes.java b/src/main/java/org/zwobble/couscous/ast/NodeTypes.java index f7f8bf6..82090aa 100644 --- a/src/main/java/org/zwobble/couscous/ast/NodeTypes.java +++ b/src/main/java/org/zwobble/couscous/ast/NodeTypes.java @@ -45,6 +45,7 @@ public class NodeTypes { public static final int VARIABLE_REFERENCE = 10029; public static final int WHILE = 10030; public static final int FOR_EACH = 10034; + public static final int STATEMENT_BLOCK = 10035; private NodeTypes() { } @@ -85,6 +86,7 @@ public class NodeTypes { .put(VariableReferenceNode.class, VARIABLE_REFERENCE) .put(WhileNode.class, WHILE) .put(ForEachNode.class, FOR_EACH) + .put(StatementBlockNode.class, STATEMENT_BLOCK) .put(PrimitiveInstanceMethodCall.class, CsharpNodeTypes.PRIMITIVE_INSTANCE_METHOD_CALL) .put(PrimitiveStaticMethodCall.class, CsharpNodeTypes.PRIMITIVE_STATIC_METHOD_CALL) .build(); diff --git a/src/main/java/org/zwobble/couscous/ast/StatementBlockNode.java b/src/main/java/org/zwobble/couscous/ast/StatementBlockNode.java new file mode 100644 index 0000000..0c24295 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/StatementBlockNode.java @@ -0,0 +1,51 @@ +package org.zwobble.couscous.ast; + +import org.zwobble.couscous.ast.visitors.NodeTransformer; + +import java.util.List; + +public class StatementBlockNode implements StatementNode { + private final List statements; + + public StatementBlockNode(List statements) { + this.statements = statements; + } + + @Override + public int type() { + return NodeTypes.STATEMENT_BLOCK; + } + + @Override + public Iterable childNodes() { + return statements; + } + + @Override + public StatementNode transformSubtree(NodeTransformer transformer) { + return new StatementBlockNode(transformer.transformStatements(statements)); + } + + @Override + public String toString() { + return "StatementBlockNode(" + + "statements=" + statements + + ')'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + StatementBlockNode that = (StatementBlockNode) o; + + return statements.equals(that.statements); + + } + + @Override + public int hashCode() { + return statements.hashCode(); + } +} diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java index 30adff9..1c4ac81 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -367,7 +367,7 @@ public class JavaReader { tryCast(Initializer.class, declaration) .ifPresent(initializer -> body.addInitializer( Modifier.isStatic(initializer.getModifiers()), - readStatement(scope, initializer.getBody()))); + readStatementBody(scope, initializer.getBody()))); tryCast(FieldDeclaration.class, declaration) .ifPresent(field -> readField(body, scope, type, field)); @@ -494,6 +494,11 @@ public class JavaReader { } } + List readStatementBody(Scope scope, Statement statement) { + JavaStatementReader statementReader = new JavaStatementReader(scope, expressionReader(scope), Optional.empty()); + return statementReader.readBody(statement); + } + List readStatement(Scope scope, Statement statement) { JavaStatementReader statementReader = new JavaStatementReader(scope, expressionReader(scope), Optional.empty()); return statementReader.readStatement(statement); 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 df75ec4..72f94d5 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java @@ -10,7 +10,6 @@ import org.zwobble.couscous.types.Types; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import static org.zwobble.couscous.ast.ExceptionHandlerNode.exceptionHandler; import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement; @@ -83,10 +82,9 @@ class JavaStatementReader { private List readBlock(Block block) { @SuppressWarnings("unchecked") - List statements = block.statements(); - return statements.stream() - .flatMap(statement -> readStatement(statement).stream()) - .collect(Collectors.toList()); + List javaStatements = block.statements(); + List statements = eagerFlatMap(javaStatements, this::readStatement); + return list(new StatementBlockNode(statements)); } private StatementNode readReturnStatement(ReturnStatement statement) { @@ -107,10 +105,10 @@ class JavaStatementReader { private StatementNode readIfStatement(IfStatement statement) { List falseBranch = statement.getElseStatement() == null ? list() - : readStatement(statement.getElseStatement()); + : readBody(statement.getElseStatement()); return ifStatement( readExpression(Types.BOOLEAN, statement.getExpression()), - readStatement(statement.getThenStatement()), + readBody(statement.getThenStatement()), falseBranch); } @@ -145,7 +143,7 @@ class JavaStatementReader { @SuppressWarnings("unchecked") List resources = statement.resources(); List resourceDeclarations = eagerFlatMap(resources, this::readVariableDeclarationExpression); - List body = readStatement(statement.getBody()); + List body = readBody(statement.getBody()); for (LocalVariableDeclarationNode resource : Lists.reverse(resourceDeclarations)) { body = list( resource, @@ -155,7 +153,7 @@ class JavaStatementReader { @SuppressWarnings("unchecked") List javaCatchClauses = statement.catchClauses(); List catchClauses = eagerMap(javaCatchClauses, this::readCatchClause); - List finallyBody = statement.getFinally() == null ? list() : readStatement(statement.getFinally()); + List finallyBody = statement.getFinally() == null ? list() : readBody(statement.getFinally()); if (catchClauses.isEmpty() && finallyBody.isEmpty()) { return body; } else { @@ -166,7 +164,7 @@ class JavaStatementReader { private ExceptionHandlerNode readCatchClause(CatchClause clause) { return exceptionHandler( JavaVariableDeclarationReader.read(scope, clause.getException()), - readStatement(clause.getBody())); + readBody(clause.getBody())); } private List readStatements(Iterable statements) { @@ -176,7 +174,7 @@ class JavaStatementReader { private WhileNode readWhileStatement(WhileStatement statement) { return whileLoop( readExpression(Types.BOOLEAN, statement.getExpression()), - readStatement(statement.getBody())); + readBody(statement.getBody())); } private List readForStatement(ForStatement statement) { @@ -193,7 +191,7 @@ class JavaStatementReader { whileLoop( readExpression(Types.BOOLEAN, statement.getExpression()), concat( - readStatement(statement.getBody()), + readBody(statement.getBody()), eagerMap(updaters, updater -> expressionStatement(readExpressionWithoutBoxing(updater)))))); } @@ -207,7 +205,7 @@ class JavaStatementReader { ForEachNode node = new ForEachNode( scope.generateVariable(parameterBinding.getKey(), parameterBinding.getName(), elementType), iterableValue, - readStatement(statement.getBody()) + readBody(statement.getBody()) ); return list(node); } @@ -243,4 +241,13 @@ class JavaStatementReader { private ExpressionNode readExpression(Type targetType, Expression expression) { return expressionReader.readExpression(targetType, expression); } + + List readBody(Statement statement) { + if (statement instanceof Block) { + List javaStatements = ((Block) statement).statements(); + return eagerFlatMap(javaStatements, this::readStatement); + } else { + return readStatement(statement); + } + } } 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 5718dca..4308be7 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 @@ -250,6 +250,18 @@ public class JavaReaderTests { ); } + @Test + public void canReadStatementBlocks() { + List statements = new JavaStatementSourceReader() + .returns("int") + .readStatement("{ return 0; }"); + + assertEquals( + list(new StatementBlockNode(list(returns(literal(0))))), + statements + ); + } + @Test public void canDeclareConstructor() { ClassNode classNode = readClass( -- cgit v1.2.3