aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java28
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerEvalTests.java27
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerMethodTests.java75
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java78
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java10
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java24
6 files changed, 153 insertions, 89 deletions
diff --git a/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java
new file mode 100644
index 0000000..c4a3538
--- /dev/null
+++ b/src/test/java/org/zwobble/couscous/tests/BackendEvalTests.java
@@ -0,0 +1,28 @@
+package org.zwobble.couscous.tests;
+
+import org.junit.Test;
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.TernaryConditionalNode;
+import org.zwobble.couscous.values.PrimitiveValue;
+
+import static org.junit.Assert.assertEquals;
+import static org.zwobble.couscous.ast.LiteralNode.literal;
+import static org.zwobble.couscous.values.PrimitiveValues.value;
+
+import lombok.val;
+
+public abstract class BackendEvalTests {
+ @Test
+ public void whenConditionIsTrueThenValueOfConditionalTernaryIsTrueBranch() {
+ val result = evalExpression(new TernaryConditionalNode(literal(true), literal("T"), literal("F")));
+ assertEquals(value("T"), result);
+ }
+
+ @Test
+ public void whenConditionIsFalseThenValueOfConditionalTernaryIsFalseBranch() {
+ val result = evalExpression(new TernaryConditionalNode(literal(false), literal("T"), literal("F")));
+ assertEquals(value("F"), result);
+ }
+
+ protected abstract PrimitiveValue evalExpression(ExpressionNode expression);
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerEvalTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerEvalTests.java
new file mode 100644
index 0000000..6f19eb3
--- /dev/null
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerEvalTests.java
@@ -0,0 +1,27 @@
+package org.zwobble.couscous.tests.backends.python;
+
+import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.ExpressionNode;
+import org.zwobble.couscous.ast.MethodNode;
+import org.zwobble.couscous.ast.ReturnNode;
+import org.zwobble.couscous.tests.BackendEvalTests;
+import org.zwobble.couscous.values.PrimitiveValue;
+
+import com.google.common.collect.ImmutableList;
+
+import lombok.val;
+
+public class PythonCompilerEvalTests extends BackendEvalTests {
+ @Override
+ protected PrimitiveValue evalExpression(ExpressionNode expression) {
+ val runner = new PythonMethodRunner();
+ return runner.runMethod(
+ ClassNode.builder("Program")
+ .method(MethodNode.staticMethod("run")
+ .statement(new ReturnNode(expression))
+ .build())
+ .build(),
+ "run",
+ ImmutableList.of());
+ }
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerMethodTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerMethodTests.java
index 93c283a..6666ac4 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerMethodTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerMethodTests.java
@@ -1,84 +1,11 @@
package org.zwobble.couscous.tests.backends.python;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-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.BackendMethodTests;
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;
-import static java.util.Arrays.asList;
-import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively;
-import static org.zwobble.couscous.values.PrimitiveValues.value;
-
-import lombok.SneakyThrows;
-import lombok.val;
public class PythonCompilerMethodTests extends BackendMethodTests {
@Override
protected MethodRunner buildMethodRunner() {
- return new MethodRunner() {
- @Override
- @SneakyThrows
- public PrimitiveValue runMethod(
- ClassNode classNode,
- String methodName,
- List<PrimitiveValue> arguments) {
- val compiler = new PythonCompiler();
- 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 + "(" + argumentsString + ")))";
-
- val process = new ProcessBuilder("python3.4", "-c", program)
- .directory(directoryPath.toFile())
- .start();
- val exitCode = process.waitFor();
- val output = readString(process.getInputStream()).trim();
- val stderrOutput = readString(process.getErrorStream());
- if (exitCode != 0) {
- throw new RuntimeException("stderr was: " + stderrOutput);
- } else {
- return readPrimitive(output);
- }
- } finally {
- deleteRecursively(directoryPath.toFile());
- }
- }
-
- private PrimitiveValue readPrimitive(String output) {
- if (output.equals("None")) {
- return PrimitiveValues.UNIT;
- } else if (output.startsWith("'")) {
- return value(output.substring(1, output.length() - 1));
- } else {
- return value(parseInt(output));
- }
- }
-
- private String readString(final InputStream stream) throws IOException {
- return CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
- }
- };
+ return new PythonMethodRunner();
}
}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java
new file mode 100644
index 0000000..fb0e880
--- /dev/null
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java
@@ -0,0 +1,78 @@
+package org.zwobble.couscous.tests.backends.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+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.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;
+import static java.util.Arrays.asList;
+import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively;
+import static org.zwobble.couscous.values.PrimitiveValues.value;
+
+import lombok.SneakyThrows;
+import lombok.val;
+
+public class PythonMethodRunner implements MethodRunner {
+ @Override
+ @SneakyThrows
+ public PrimitiveValue runMethod(
+ ClassNode classNode,
+ String methodName,
+ List<PrimitiveValue> arguments) {
+ val compiler = new PythonCompiler();
+ 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 + "(" + argumentsString + ")))";
+
+ val process = new ProcessBuilder("python3.4", "-c", program)
+ .directory(directoryPath.toFile())
+ .start();
+ val exitCode = process.waitFor();
+ val output = readString(process.getInputStream()).trim();
+ val stderrOutput = readString(process.getErrorStream());
+ if (exitCode != 0) {
+ throw new RuntimeException("stderr was: " + stderrOutput);
+ } else {
+ return readPrimitive(output);
+ }
+ } finally {
+ deleteRecursively(directoryPath.toFile());
+ }
+ }
+
+ private PrimitiveValue readPrimitive(String output) {
+ if (output.equals("None")) {
+ return PrimitiveValues.UNIT;
+ } else if (output.startsWith("'")) {
+ return value(output.substring(1, output.length() - 1));
+ } else {
+ return value(parseInt(output));
+ }
+ }
+
+ private String readString(final InputStream stream) throws IOException {
+ return CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
+ }
+}
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 2835034..60aed36 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
@@ -9,6 +9,7 @@ import static org.junit.Assert.assertEquals;
import static org.zwobble.couscous.backends.python.PythonSerializer.serialize;
import static org.zwobble.couscous.backends.python.ast.PythonAssignmentNode.pythonAssignment;
import static org.zwobble.couscous.backends.python.ast.PythonBooleanLiteralNode.pythonBooleanLiteral;
+import static org.zwobble.couscous.backends.python.ast.PythonConditionalExpressionNode.pythonConditionalExpression;
import static org.zwobble.couscous.backends.python.ast.PythonIntegerLiteralNode.pythonIntegerLiteral;
import static org.zwobble.couscous.backends.python.ast.PythonModuleNode.pythonModule;
import static org.zwobble.couscous.backends.python.ast.PythonPassNode.PASS;
@@ -44,6 +45,15 @@ public class PythonSerializerTests {
}
@Test
+ public void conditionalExpressionIsSerializedUsingParens() {
+ assertEquals("(1) if (True) else (2)", serialize(
+ pythonConditionalExpression(
+ pythonBooleanLiteral(true),
+ pythonIntegerLiteral(1),
+ pythonIntegerLiteral(2))));
+ }
+
+ @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/EvaluatorTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
index 40cdf8f..0a2a947 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
@@ -4,6 +4,7 @@ import org.junit.Test;
import org.zwobble.couscous.JavaProject;
import org.zwobble.couscous.MapBackedProject;
import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.ast.ExpressionNode;
import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.ast.ReturnNode;
import org.zwobble.couscous.ast.TernaryConditionalNode;
@@ -16,7 +17,9 @@ import org.zwobble.couscous.interpreter.WrongNumberOfArguments;
import org.zwobble.couscous.interpreter.values.ConcreteType;
import org.zwobble.couscous.interpreter.values.IntegerInterpreterValue;
import org.zwobble.couscous.interpreter.values.StringInterpreterValue;
+import org.zwobble.couscous.tests.BackendEvalTests;
import org.zwobble.couscous.values.IntegerValue;
+import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.StringValue;
import com.google.common.collect.ImmutableMap;
@@ -34,7 +37,7 @@ import static org.zwobble.couscous.tests.util.ExtraAsserts.assertThrows;
import lombok.val;
-public class EvaluatorTests {
+public class EvaluatorTests extends BackendEvalTests {
@Test
public void valueOfAssignmentExpressionIsNewValue() {
val arg = formalArg(var(42, "x", StringValue.REF));
@@ -46,20 +49,6 @@ public class EvaluatorTests {
}
@Test
- public void whenConditionIsTrueThenValueOfConditionalTernaryIsTrueBranch() {
- val result = eval(emptyEnvironment(),
- new TernaryConditionalNode(literal(true), literal("T"), literal("F")));
- assertEquals(new StringInterpreterValue("T"), result);
- }
-
- @Test
- public void whenConditionIsFalseThenValueOfConditionalTernaryIsFalseBranch() {
- val result = eval(emptyEnvironment(),
- new TernaryConditionalNode(literal(false), literal("T"), literal("F")));
- assertEquals(new StringInterpreterValue("F"), result);
- }
-
- @Test
public void errorIfConditionIsNotBoolean() {
val exception = assertThrows(ConditionMustBeBoolean.class,
() -> eval(emptyEnvironment(),
@@ -134,4 +123,9 @@ public class EvaluatorTests {
JavaProject.builder().build(),
ImmutableMap.of());
}
+
+ @Override
+ protected PrimitiveValue evalExpression(ExpressionNode expression) {
+ return eval(emptyEnvironment(), expression).toPrimitiveValue().get();
+ }
}