From 8a7cb643ac9b0e895123c176803af15b75f90cf1 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 14 Nov 2015 14:30:50 +0000 Subject: Parse while loops --- .../org/zwobble/couscous/ast/StatementNode.java | 6 ++ .../java/org/zwobble/couscous/ast/WhileNode.java | 55 +++++++++++++ .../zwobble/couscous/ast/visitors/NodeVisitor.java | 18 +--- .../ast/visitors/NodeVisitorWithEmptyDefaults.java | 21 ++--- .../couscous/ast/visitors/NodeVisitors.java | 24 ++---- .../couscous/ast/visitors/StatementNodeMapper.java | 6 +- .../couscous/backends/python/PythonBackend.java | 2 +- .../backends/python/PythonCodeGenerator.java | 25 ++---- .../couscous/frontends/java/JavaReader.java | 95 +++++++--------------- .../org/zwobble/couscous/interpreter/Executor.java | 19 +++-- 10 files changed, 125 insertions(+), 146 deletions(-) create mode 100644 src/main/java/org/zwobble/couscous/ast/WhileNode.java (limited to 'src/main/java') diff --git a/src/main/java/org/zwobble/couscous/ast/StatementNode.java b/src/main/java/org/zwobble/couscous/ast/StatementNode.java index 1186619..6ba198f 100644 --- a/src/main/java/org/zwobble/couscous/ast/StatementNode.java +++ b/src/main/java/org/zwobble/couscous/ast/StatementNode.java @@ -33,6 +33,12 @@ public interface StatementNode extends Node { visitor.visit(ifStatement); return null; } + + @Override + public Void visit(WhileNode whileLoop) { + visitor.visit(whileLoop); + return null; + } }); } } diff --git a/src/main/java/org/zwobble/couscous/ast/WhileNode.java b/src/main/java/org/zwobble/couscous/ast/WhileNode.java new file mode 100644 index 0000000..0a67aef --- /dev/null +++ b/src/main/java/org/zwobble/couscous/ast/WhileNode.java @@ -0,0 +1,55 @@ +package org.zwobble.couscous.ast; + +import com.google.common.base.Objects; +import org.zwobble.couscous.ast.visitors.StatementNodeMapper; + +import java.util.List; + +public class WhileNode implements StatementNode { + public static WhileNode whileLoop(ExpressionNode condition, List body) { + return new WhileNode(condition, body); + } + + private final ExpressionNode condition; + private final List body; + + public WhileNode(ExpressionNode condition, List body) { + this.condition = condition; + this.body = body; + } + + public ExpressionNode getCondition() { + return condition; + } + + public List getBody() { + return body; + } + + @Override + public T accept(StatementNodeMapper visitor) { + return visitor.visit(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WhileNode whileNode = (WhileNode) o; + return Objects.equal(condition, whileNode.condition) && + Objects.equal(body, whileNode.body); + } + + @Override + public int hashCode() { + return Objects.hashCode(condition, body); + } + + @Override + public String toString() { + return "WhileNode(" + + "condition=" + condition + + ", body=" + body + + ')'; + } +} diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java index ce6bb52..8d42f5c 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitor.java @@ -1,21 +1,6 @@ package org.zwobble.couscous.ast.visitors; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ConstructorNode; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.MethodNode; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; public interface NodeVisitor { void visit(LiteralNode literal); @@ -32,6 +17,7 @@ public interface NodeVisitor { void visit(ExpressionStatementNode expressionStatement); void visit(LocalVariableDeclarationNode localVariableDeclaration); void visit(IfStatementNode ifStatement); + void visit(WhileNode whileLoop); void visit(ClassNode classNode); void visit(MethodNode methodNode); diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitorWithEmptyDefaults.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitorWithEmptyDefaults.java index fe57a28..c8dd2cf 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitorWithEmptyDefaults.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitorWithEmptyDefaults.java @@ -1,21 +1,6 @@ package org.zwobble.couscous.ast.visitors; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ConstructorNode; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.MethodNode; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; public interface NodeVisitorWithEmptyDefaults extends NodeVisitor { @Override @@ -69,6 +54,10 @@ public interface NodeVisitorWithEmptyDefaults extends NodeVisitor { @Override default void visit(IfStatementNode ifStatement) { } + + @Override + default void visit(WhileNode whileLoop) { + } @Override default void visit(ClassNode classNode) { diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitors.java b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitors.java index 1bcc226..78a8254 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitors.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/NodeVisitors.java @@ -2,23 +2,7 @@ package org.zwobble.couscous.ast.visitors; import java.util.List; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ConstructorNode; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.MethodNode; -import org.zwobble.couscous.ast.Node; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; public class NodeVisitors { public static void visitAll(Node node, NodeVisitor visitor) { @@ -102,6 +86,12 @@ public class NodeVisitors { visitAll(ifStatement.getFalseBranch()); } + @Override + public void visit(WhileNode whileLoop) { + whileLoop.getCondition().accept(visitor); + visitAll(whileLoop.getBody()); + } + @Override public void visit(ClassNode classNode) { visitor.visit(classNode); diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/StatementNodeMapper.java b/src/main/java/org/zwobble/couscous/ast/visitors/StatementNodeMapper.java index fe639bd..33fbbd3 100644 --- a/src/main/java/org/zwobble/couscous/ast/visitors/StatementNodeMapper.java +++ b/src/main/java/org/zwobble/couscous/ast/visitors/StatementNodeMapper.java @@ -1,13 +1,11 @@ package org.zwobble.couscous.ast.visitors; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.ReturnNode; +import org.zwobble.couscous.ast.*; public interface StatementNodeMapper { T visit(ReturnNode returnNode); T visit(ExpressionStatementNode expressionStatement); T visit(LocalVariableDeclarationNode localVariableDeclaration); T visit(IfStatementNode ifStatement); + T visit(WhileNode whileLoop); } diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java index ca5fe34..39bd058 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java @@ -35,7 +35,7 @@ public class PythonBackend implements Backend { for (ClassNode classNode : classes) { compileClass(classNode); } - for (String runtimeFile : RUNTIME_FILES) { + for (String runtimeFile : RUNTIME_FILES) { String path = relativePathForModule(runtimeFile); writeModule( runtimeFile, diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java index 9131fb2..ca1c706 100644 --- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java +++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java @@ -7,25 +7,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ConstructorNode; -import org.zwobble.couscous.ast.ExpressionNode; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.MethodNode; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StatementNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.TypeName; -import org.zwobble.couscous.ast.VariableReferenceNode; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; import org.zwobble.couscous.ast.visitors.NodeVisitorWithEmptyDefaults; import org.zwobble.couscous.ast.visitors.NodeVisitors; @@ -214,6 +196,11 @@ public class PythonCodeGenerator { generateStatements(ifStatement.getTrueBranch()), generateStatements(ifStatement.getFalseBranch())); } + + @Override + public PythonStatementNode visit(WhileNode whileLoop) { + throw new UnsupportedOperationException(); + } } private static PythonExpressionNode generateExpression(ExpressionNode expression) { 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 c75205d..97474c4 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -6,56 +6,10 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BooleanLiteral; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.IAnnotationBinding; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.InfixExpression; +import org.eclipse.jdt.core.dom.*; import org.eclipse.jdt.core.dom.InfixExpression.Operator; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.zwobble.couscous.ast.AssignableExpressionNode; -import org.zwobble.couscous.ast.AssignmentNode; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.ClassNodeBuilder; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.ClassNodeBuilder.MethodBuilder; -import org.zwobble.couscous.ast.ConstructorCallNode; -import org.zwobble.couscous.ast.ExpressionNode; -import org.zwobble.couscous.ast.FieldAccessNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LiteralNode; -import org.zwobble.couscous.ast.MethodCallNode; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StatementNode; -import org.zwobble.couscous.ast.StaticMethodCallNode; -import org.zwobble.couscous.ast.TernaryConditionalNode; -import org.zwobble.couscous.ast.ThisReferenceNode; -import org.zwobble.couscous.ast.TypeName; import org.zwobble.couscous.values.BooleanValue; import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.ObjectValues; @@ -66,6 +20,7 @@ import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariabl import static org.zwobble.couscous.ast.MethodCallNode.methodCall; import static org.zwobble.couscous.ast.VariableDeclaration.var; import static org.zwobble.couscous.ast.VariableReferenceNode.reference; +import static org.zwobble.couscous.ast.WhileNode.whileLoop; import static org.zwobble.couscous.util.ExtraLists.eagerMap; public class JavaReader { @@ -131,24 +86,26 @@ public class JavaReader { private static List readStatement(Statement statement) { switch (statement.getNodeType()) { - case ASTNode.BLOCK: - return readBlock((Block)statement); - - case ASTNode.RETURN_STATEMENT: - return asList(readReturnStatement((ReturnStatement)statement)); - - case ASTNode.EXPRESSION_STATEMENT: - return asList(readExpressionStatement((ExpressionStatement)statement)); - - case ASTNode.IF_STATEMENT: - return asList(readIfStatement((IfStatement)statement)); - - case ASTNode.VARIABLE_DECLARATION_STATEMENT: - return readVariableDeclarationStatement((VariableDeclarationStatement)statement); - - default: - throw new RuntimeException("Unsupported statement: " + statement.getClass()); - + case ASTNode.BLOCK: + return readBlock((Block)statement); + + case ASTNode.RETURN_STATEMENT: + return asList(readReturnStatement((ReturnStatement)statement)); + + case ASTNode.EXPRESSION_STATEMENT: + return asList(readExpressionStatement((ExpressionStatement)statement)); + + case ASTNode.IF_STATEMENT: + return asList(readIfStatement((IfStatement)statement)); + + case ASTNode.WHILE_STATEMENT: + return asList(readWhileStatement((WhileStatement)statement)); + + case ASTNode.VARIABLE_DECLARATION_STATEMENT: + return readVariableDeclarationStatement((VariableDeclarationStatement)statement); + + default: + throw new RuntimeException("Unsupported statement: " + statement.getClass()); } } @@ -176,6 +133,12 @@ public class JavaReader { readStatement(statement.getElseStatement())); } + private static WhileNode readWhileStatement(WhileStatement statement) { + return whileLoop( + readExpression(BooleanValue.REF, statement.getExpression()), + readStatement(statement.getBody())); + } + private static List readVariableDeclarationStatement(VariableDeclarationStatement statement) { @SuppressWarnings("unchecked") List fragments = statement.fragments(); diff --git a/src/main/java/org/zwobble/couscous/interpreter/Executor.java b/src/main/java/org/zwobble/couscous/interpreter/Executor.java index 6f33b4d..9e34c42 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Executor.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Executor.java @@ -4,13 +4,7 @@ import java.util.List; import java.util.Optional; import java.util.stream.Stream; -import org.zwobble.couscous.ast.CallableNode; -import org.zwobble.couscous.ast.ExpressionStatementNode; -import org.zwobble.couscous.ast.IfStatementNode; -import org.zwobble.couscous.ast.LocalVariableDeclarationNode; -import org.zwobble.couscous.ast.ReturnNode; -import org.zwobble.couscous.ast.StatementNode; -import org.zwobble.couscous.ast.VariableNode; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.ast.visitors.StatementNodeMapper; import org.zwobble.couscous.interpreter.values.BooleanInterpreterValue; import org.zwobble.couscous.interpreter.values.InterpreterValue; @@ -61,6 +55,12 @@ public class Executor implements StatementNodeMapper> // TODO: Handle declarations in branches return Stream.empty(); } + + @Override + public Stream visit(WhileNode whileLoop) { + // TODO: Handle declarations in branches + return Stream.empty(); + } })); } @@ -100,6 +100,11 @@ public class Executor implements StatementNodeMapper> return Optional.empty(); } + @Override + public Optional visit(WhileNode whileLoop) { + throw new UnsupportedOperationException(); + } + private Optional exec(List statements) { for (StatementNode statement : statements) { Optional result = exec(environment, statement); -- cgit v1.2.3