aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/backends/python/ast
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-10-05 11:04:17 +0100
committerMichael Williamson <mike@zwobble.org>2015-10-05 11:04:17 +0100
commit96b1e6f776ae8ce8910c44a3bbec0b489fd10c88 (patch)
tree86658222ef741b1620c1635d3fd98d99452a387b /src/main/java/org/zwobble/couscous/backends/python/ast
parentcdf51cdb9b3f8cef5896315496f348d9f7220903 (diff)
Add the beginnings of a Python backend
Diffstat (limited to 'src/main/java/org/zwobble/couscous/backends/python/ast')
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonBlock.java25
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonClassNode.java48
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonExpressionNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonFunctionDefinitionNode.java22
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonIntegerLiteralNode.java15
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonModuleNode.java18
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonNode.java7
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonPassNode.java16
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonReturnNode.java16
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonStatementNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonStringLiteralNode.java15
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonWriter.java60
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java22
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);
+
+}