diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-10-05 11:04:17 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-10-05 11:04:17 +0100 |
| commit | 96b1e6f776ae8ce8910c44a3bbec0b489fd10c88 (patch) | |
| tree | 86658222ef741b1620c1635d3fd98d99452a387b /src/main/java/org/zwobble/couscous/backends/python/ast | |
| parent | cdf51cdb9b3f8cef5896315496f348d9f7220903 (diff) | |
Add the beginnings of a Python backend
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/python/ast')
13 files changed, 274 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBlock.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBlock.java new file mode 100644 index 0000000..8bc7132 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonBlock.java @@ -0,0 +1,25 @@ +package org.zwobble.couscous.backends.python.ast; + +import java.util.Iterator; +import java.util.List; + +import com.google.common.collect.ImmutableList; + +import static java.util.Arrays.asList; + +public class PythonBlock implements Iterable<PythonStatementNode> { + private final List<PythonStatementNode> statements; + + public PythonBlock(List<? extends PythonStatementNode> statements) { + if (statements.isEmpty()) { + this.statements = asList(PythonPassNode.PASS); + } else { + this.statements = ImmutableList.copyOf(statements); + } + } + + @Override + public Iterator<PythonStatementNode> iterator() { + return statements.iterator(); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonClassNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonClassNode.java new file mode 100644 index 0000000..958a21a --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonClassNode.java @@ -0,0 +1,48 @@ +package org.zwobble.couscous.backends.python.ast; + +import java.util.List; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import com.google.common.collect.ImmutableList; + +import lombok.Value; + +@Value(staticConstructor="pythonClass") +public class PythonClassNode implements PythonStatementNode { + public static Builder builder(String name) { + return new Builder(name); + } + + public static class Builder { + private final String name; + private final ImmutableList.Builder<PythonStatementNode> statements; + + public Builder(String name) { + this.name = name; + this.statements = ImmutableList.builder(); + } + + public PythonClassNode build() { + return new PythonClassNode(name, new PythonBlock(statements.build())); + } + + public Builder statement(PythonStatementNode statement) { + statements.add(statement); + return this; + } + } + + public static PythonClassNode pythonClass(String name, List<? extends PythonStatementNode> body) { + return new PythonClassNode(name, new PythonBlock(body)); + } + + String name; + PythonBlock body; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java new file mode 100644 index 0000000..9c8a259 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java @@ -0,0 +1,5 @@ +package org.zwobble.couscous.backends.python.ast; + +public interface PythonExpressionNode extends PythonNode { + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonFunctionDefinitionNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonFunctionDefinitionNode.java new file mode 100644 index 0000000..6d66df8 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonFunctionDefinitionNode.java @@ -0,0 +1,22 @@ +package org.zwobble.couscous.backends.python.ast; + +import java.util.List; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import lombok.Value; + +@Value(staticConstructor="pythonFunctionDefinition") +public class PythonFunctionDefinitionNode implements PythonStatementNode { + public static PythonFunctionDefinitionNode pythonFunctionDefinition(String name, List<PythonStatementNode> body) { + return pythonFunctionDefinition(name, new PythonBlock(body)); + } + + String name; + PythonBlock body; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java new file mode 100644 index 0000000..d8a9358 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java @@ -0,0 +1,15 @@ +package org.zwobble.couscous.backends.python.ast; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import lombok.Value; + +@Value(staticConstructor="pythonIntegerLiteral") +public class PythonIntegerLiteralNode implements PythonExpressionNode { + int value; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonModuleNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonModuleNode.java new file mode 100644 index 0000000..92d63a8 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonModuleNode.java @@ -0,0 +1,18 @@ +package org.zwobble.couscous.backends.python.ast; + +import java.util.List; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import lombok.Value; + +@Value(staticConstructor="pythonModule") +public class PythonModuleNode implements PythonNode { + List<PythonStatementNode> statements; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNode.java new file mode 100644 index 0000000..cdda65d --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonNode.java @@ -0,0 +1,7 @@ +package org.zwobble.couscous.backends.python.ast; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +public interface PythonNode { + <T> T accept(PythonNodeVisitor<T> visitor); +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonPassNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonPassNode.java new file mode 100644 index 0000000..36d6695 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonPassNode.java @@ -0,0 +1,16 @@ +package org.zwobble.couscous.backends.python.ast; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +public class PythonPassNode implements PythonStatementNode { + public static final PythonPassNode PASS = new PythonPassNode(); + + private PythonPassNode() { + // TODO Auto-generated constructor stub + } + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonReturnNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonReturnNode.java new file mode 100644 index 0000000..b204b4d --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonReturnNode.java @@ -0,0 +1,16 @@ +package org.zwobble.couscous.backends.python.ast; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import lombok.Value; + +@Value(staticConstructor="pythonReturn") +public class PythonReturnNode implements PythonStatementNode { + PythonExpressionNode value; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStatementNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStatementNode.java new file mode 100644 index 0000000..c27a7dd --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStatementNode.java @@ -0,0 +1,5 @@ +package org.zwobble.couscous.backends.python.ast; + +public interface PythonStatementNode extends PythonNode { + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java new file mode 100644 index 0000000..82d91db --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java @@ -0,0 +1,15 @@ +package org.zwobble.couscous.backends.python.ast; + +import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor; + +import lombok.Value; + +@Value(staticConstructor="pythonStringLiteral") +public class PythonStringLiteralNode implements PythonExpressionNode { + String value; + + @Override + public <T> T accept(PythonNodeVisitor<T> visitor) { + return visitor.visit(this); + } +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonWriter.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonWriter.java new file mode 100644 index 0000000..4ab04c6 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonWriter.java @@ -0,0 +1,60 @@ +package org.zwobble.couscous.backends.python.ast; + +import com.google.common.base.Strings; + +public class PythonWriter { + private static final int SPACES_PER_INDENT = 4; + private final StringBuilder builder = new StringBuilder(); + private int depth = 0; + + public String asString() { + return builder.toString(); + } + + public void writeInteger(int value) { + builder.append(value); + } + + public void writeStringLiteral(String value) { + builder.append("\""); + builder.append(value); + builder.append("\""); + } + + public void writeKeyword(String keyword) { + builder.append(keyword); + } + + public void writeSpace() { + builder.append(" "); + } + + public void writeIdentifier(String name) { + builder.append(name); + } + + public void writeSymbol(String symbol) { + builder.append(symbol); + } + + public void startBlock() { + depth++; + writeSymbol(":"); + builder.append("\n"); + } + + public void endBlock() { + depth--; + } + + public void startStatement() { + builder.append(Strings.repeat(" ", depth * SPACES_PER_INDENT)); + } + + public void endStatement() { + if (builder.charAt(builder.length() - 1) != '\n') { + builder.append("\n"); + } + } + +} diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java new file mode 100644 index 0000000..0210df6 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java @@ -0,0 +1,22 @@ +package org.zwobble.couscous.backends.python.ast.visitors; + +import org.zwobble.couscous.backends.python.ast.PythonClassNode; +import org.zwobble.couscous.backends.python.ast.PythonFunctionDefinitionNode; +import org.zwobble.couscous.backends.python.ast.PythonIntegerLiteralNode; +import org.zwobble.couscous.backends.python.ast.PythonModuleNode; +import org.zwobble.couscous.backends.python.ast.PythonPassNode; +import org.zwobble.couscous.backends.python.ast.PythonReturnNode; +import org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode; + +public interface PythonNodeVisitor<T> { + T visit(PythonIntegerLiteralNode integerLiteral); + T visit(PythonStringLiteralNode stringLiteral); + + T visit(PythonReturnNode pythonReturn); + T visit(PythonPassNode pass); + T visit(PythonClassNode pythonClass); + T visit(PythonFunctionDefinitionNode functionDefinition); + + T visit(PythonModuleNode module); + +} |
