aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-10-05 13:20:24 +0100
committerMichael Williamson <mike@zwobble.org>2015-10-05 13:20:24 +0100
commit34df0782f05475bf2e9723feb4224e411d13959f (patch)
tree8fdc1746c8a1bc594a0b22284afe78db50b555d5 /src
parentfe4766439c47ea146c37422e86d0ce0367f6c653 (diff)
Support passing arguments to Python runner
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java4
-rw-r--r--src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java8
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java60
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java7
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java15
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/ast/visitors/PythonNodeVisitor.java2
-rw-r--r--src/test/java/org/zwobble/couscous/tests/BackendTests.java14
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java12
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java6
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java11
10 files changed, 99 insertions, 40 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
index cd2cb86..736322e 100644
--- a/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/FormalArgumentNode.java
@@ -11,4 +11,8 @@ public class FormalArgumentNode implements VariableNode {
public TypeReference getType() {
return declaration.getType();
}
+
+ public String getName() {
+ return declaration.getName();
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
index 2410549..afd3918 100644
--- a/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/VariableReferenceNode.java
@@ -7,13 +7,17 @@ import lombok.Value;
@Value
public class VariableReferenceNode implements ExpressionNode {
public static VariableReferenceNode reference(VariableNode variable) {
- return new VariableReferenceNode(variable.getDeclaration().getId());
+ return new VariableReferenceNode(variable.getDeclaration());
}
- int referentId;
+ VariableDeclaration referent;
@Override
public <T> T accept(ExpressionNodeVisitor<T> visitor) {
return visitor.visit(this);
}
+
+ public int getReferentId() {
+ return referent.getId();
+ }
}
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 95e54a5..63fa56b 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonCodeGenerator.java
@@ -24,6 +24,7 @@ import org.zwobble.couscous.backends.python.ast.PythonModuleNode;
import org.zwobble.couscous.backends.python.ast.PythonStatementNode;
import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValueVisitor;
import org.zwobble.couscous.values.StringValue;
import org.zwobble.couscous.values.UnitValue;
@@ -35,6 +36,7 @@ import static org.zwobble.couscous.backends.python.ast.PythonIntegerLiteralNode.
import static org.zwobble.couscous.backends.python.ast.PythonModuleNode.pythonModule;
import static org.zwobble.couscous.backends.python.ast.PythonReturnNode.pythonReturn;
import static org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode.pythonStringLiteral;
+import static org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode.pythonVariableReference;
import lombok.val;
@@ -49,12 +51,41 @@ public class PythonCodeGenerator {
return pythonModule(asList(pythonClass));
}
+ public static PythonExpressionNode generateCode(PrimitiveValue value) {
+ return value.accept(new PrimitiveValueVisitor<PythonExpressionNode>() {
+ @Override
+ public PythonExpressionNode visit(IntegerValue value) {
+ return pythonIntegerLiteral(value.getValue());
+ }
+
+ @Override
+ public PythonExpressionNode visit(StringValue value) {
+ return pythonStringLiteral(value.getValue());
+ }
+
+ @Override
+ public PythonExpressionNode visit(BooleanValue value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public PythonExpressionNode visit(UnitValue unitValue) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ }
+
private static PythonFunctionDefinitionNode generateFunction(MethodNode method) {
+ val argumentNames = method.getArguments().stream()
+ .map(argument -> argument.getName())
+ .collect(Collectors.toList());
+
val pythonBody = method.getBody()
.stream()
.map(PythonCodeGenerator::generateStatement)
.collect(Collectors.toList());
- return pythonFunctionDefinition(method.getName(), asList(), new PythonBlock(pythonBody));
+
+ return pythonFunctionDefinition(method.getName(), argumentNames, new PythonBlock(pythonBody));
}
private static PythonStatementNode generateStatement(StatementNode statement) {
@@ -85,33 +116,12 @@ public class PythonCodeGenerator {
private static class ExpressionGenerator implements ExpressionNodeVisitor<PythonExpressionNode> {
@Override
public PythonExpressionNode visit(LiteralNode literal) {
- return literal.getValue().accept(new PrimitiveValueVisitor<PythonExpressionNode>() {
- @Override
- public PythonExpressionNode visit(IntegerValue value) {
- return pythonIntegerLiteral(value.getValue());
- }
-
- @Override
- public PythonExpressionNode visit(StringValue value) {
- return pythonStringLiteral(value.getValue());
- }
-
- @Override
- public PythonExpressionNode visit(BooleanValue value) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public PythonExpressionNode visit(UnitValue unitValue) {
- throw new UnsupportedOperationException();
- }
- });
+ return generateCode(literal.getValue());
}
@Override
- public PythonExpressionNode visit(
- VariableReferenceNode variableReference) {
- throw new UnsupportedOperationException();
+ public PythonExpressionNode visit(VariableReferenceNode variableReference) {
+ return pythonVariableReference(variableReference.getReferent().getName());
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
index c6cf516..4893cb6 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonSerializer.java
@@ -10,6 +10,7 @@ import org.zwobble.couscous.backends.python.ast.PythonNode;
import org.zwobble.couscous.backends.python.ast.PythonPassNode;
import org.zwobble.couscous.backends.python.ast.PythonReturnNode;
import org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode;
+import org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode;
import org.zwobble.couscous.backends.python.ast.PythonWriter;
import org.zwobble.couscous.backends.python.ast.visitors.PythonNodeVisitor;
@@ -54,6 +55,12 @@ public class PythonSerializer implements PythonNodeVisitor<Void> {
}
@Override
+ public Void visit(PythonVariableReferenceNode reference) {
+ writer.writeIdentifier(reference.getName());
+ return null;
+ }
+
+ @Override
public Void visit(PythonReturnNode pythonReturn) {
writer.startStatement();
writer.writeKeyword("return");
diff --git a/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.java
new file mode 100644
index 0000000..81f26d2
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/backends/python/ast/PythonVariableReferenceNode.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="pythonVariableReference")
+public class PythonVariableReferenceNode implements PythonExpressionNode {
+ String name;
+
+ @Override
+ public <T> T accept(PythonNodeVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+}
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
index 42f97a0..88035c8 100644
--- 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
@@ -8,11 +8,13 @@ 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;
+import org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode;
public interface PythonNodeVisitor<T> {
T visit(PythonIntegerLiteralNode integerLiteral);
T visit(PythonStringLiteralNode stringLiteral);
T visit(PythonBooleanLiteralNode booleanLiteral);
+ T visit(PythonVariableReferenceNode reference);
T visit(PythonReturnNode pythonReturn);
T visit(PythonPassNode pass);
diff --git a/src/test/java/org/zwobble/couscous/tests/BackendTests.java b/src/test/java/org/zwobble/couscous/tests/BackendTests.java
index ce3fc7d..7e7c3bd 100644
--- a/src/test/java/org/zwobble/couscous/tests/BackendTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/BackendTests.java
@@ -6,11 +6,15 @@ import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.ast.ReturnNode;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
+import org.zwobble.couscous.values.StringValue;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
+import static org.zwobble.couscous.ast.FormalArgumentNode.formalArg;
import static org.zwobble.couscous.ast.LiteralNode.literal;
import static org.zwobble.couscous.ast.MethodNode.staticMethod;
+import static org.zwobble.couscous.ast.VariableDeclaration.var;
+import static org.zwobble.couscous.ast.VariableReferenceNode.reference;
import static org.zwobble.couscous.values.PrimitiveValues.value;
import lombok.val;
@@ -32,6 +36,16 @@ public abstract class BackendTests {
assertEquals(value("hello, world!"), result);
}
+ @Test
+ public void canPassValueToMethod() {
+ val arg = formalArg(var(42, "x", StringValue.REF));
+ val method = staticMethod("hello")
+ .argument(arg)
+ .statement(new ReturnNode(reference(arg)));
+ val result = runMethod(method, value("hello, world!"));
+
+ assertEquals(value("hello, world!"), result);
+ }
protected PrimitiveValue runMethod(MethodNode.MethodNodeBuilder methodBuilder, PrimitiveValue... arguments) {
val method = methodBuilder.build();
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
index 6f171c3..2563ff8 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
@@ -7,13 +7,16 @@ import java.nio.file.Files;
import java.util.List;
import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.backends.python.PythonCodeGenerator;
import org.zwobble.couscous.backends.python.PythonCompiler;
+import org.zwobble.couscous.backends.python.PythonSerializer;
import org.zwobble.couscous.tests.BackendTests;
import org.zwobble.couscous.tests.MethodRunner;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
import com.google.common.io.CharStreams;
import static java.lang.Integer.parseInt;
@@ -38,9 +41,14 @@ public class PythonCompilerTests extends BackendTests {
val directoryPath = Files.createTempDirectory(null);
try {
compiler.compile(asList(classNode), directoryPath);
-
+
+ val argumentsString = Joiner.on(", ").join(arguments.stream()
+ .map(PythonCodeGenerator::generateCode)
+ .map(PythonSerializer::serialize)
+ .iterator());
+
val program = "from " + classNode.getName() + " import " + classNode.getLocalName() +
- ";print(repr(" + classNode.getLocalName() + "." + methodName + "()))";
+ ";print(repr(" + classNode.getLocalName() + "." + methodName + "(" + argumentsString + ")))";
val process = new ProcessBuilder("python3.4", "-c", program)
.directory(directoryPath.toFile())
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java
index 65f9074..944c2af 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java
@@ -13,6 +13,7 @@ import static org.zwobble.couscous.backends.python.ast.PythonModuleNode.pythonMo
import static org.zwobble.couscous.backends.python.ast.PythonPassNode.PASS;
import static org.zwobble.couscous.backends.python.ast.PythonReturnNode.pythonReturn;
import static org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode.pythonStringLiteral;
+import static org.zwobble.couscous.backends.python.ast.PythonVariableReferenceNode.pythonVariableReference;
import lombok.val;
@@ -37,6 +38,11 @@ public class PythonSerializerTests {
}
@Test
+ public void variableReferenceIsSerializedAsIdentifier() {
+ assertEquals("blah", serialize(pythonVariableReference("blah")));
+ }
+
+ @Test
public void returnKeywordIsUsedForReturns() {
val output = serialize(pythonReturn(pythonIntegerLiteral(42)));
assertEquals("return 42\n", output);
diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java
index 09c3993..c6e6ce2 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java
@@ -39,17 +39,6 @@ import lombok.val;
public class InterpreterTests extends BackendTests {
@Test
- public void canPassValueToMethod() {
- val arg = formalArg(var(42, "x", StringValue.REF));
- val method = staticMethod("hello")
- .argument(arg)
- .statement(new ReturnNode(reference(arg)));
- val result = runMethod(method, value("hello, world!"));
-
- assertEquals(value("hello, world!"), result);
- }
-
- @Test
public void errorIfWrongNumberOfArgumentsArePassed() {
val method = staticMethod("hello");