aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-11-07 15:15:21 +0000
committerMichael Williamson <mike@zwobble.org>2015-11-07 15:15:21 +0000
commit5579d7b84fbfbaecb953d0a7a720eafe521f8bc7 (patch)
tree2624d0778580395407084f3fd3d637efb9f9d5bf
parentd8e0031c6d73ba960505601d8e4b3c1933e584ea (diff)
Add WIP test for recursive factorial program
-rw-r--r--.classpath5
-rw-r--r--.project10
-rw-r--r--.settings/org.eclipse.core.resources.prefs1
-rw-r--r--src/main/java/org/zwobble/couscous/CouscousCompiler.java23
-rw-r--r--src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java55
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java36
-rw-r--r--src/test/resources/java/recursive-factorial/com/example/RecursiveFactorial.java15
7 files changed, 132 insertions, 13 deletions
diff --git a/.classpath b/.classpath
index 1a8c6f1..8433ca6 100644
--- a/.classpath
+++ b/.classpath
@@ -27,5 +27,10 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
diff --git a/.project b/.project
index b727570..f9f2ddd 100644
--- a/.project
+++ b/.project
@@ -20,4 +20,14 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
+ <filteredResources>
+ <filter>
+ <id>0</id>
+ <name>src/test/resources/java/recursive-factorial/com</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ </matcher>
+ </filter>
+ </filteredResources>
</projectDescription>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
index 839d647..29abf99 100644
--- a/.settings/org.eclipse.core.resources.prefs
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -2,4 +2,5 @@ eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8
diff --git a/src/main/java/org/zwobble/couscous/CouscousCompiler.java b/src/main/java/org/zwobble/couscous/CouscousCompiler.java
new file mode 100644
index 0000000..8c303b0
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/CouscousCompiler.java
@@ -0,0 +1,23 @@
+package org.zwobble.couscous;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.backends.python.PythonCompiler;
+import org.zwobble.couscous.frontends.java.JavaFrontend;
+
+public class CouscousCompiler {
+ private final PythonCompiler backend;
+
+ public CouscousCompiler(PythonCompiler backend) {
+ this.backend = backend;
+ }
+
+ public void compileDirectory(Path path) throws IOException {
+ List<ClassNode> classes = JavaFrontend.readSourceDirectory(path);
+ backend.compile(classes);
+ }
+
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
index b639c6f..e5d810e 100644
--- a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
@@ -1,12 +1,19 @@
package org.zwobble.couscous.tests;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
+import org.junit.Ignore;
import org.junit.Test;
+import org.zwobble.couscous.CouscousCompiler;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.ast.TypeName;
+import org.zwobble.couscous.backends.python.PythonCompiler;
import org.zwobble.couscous.frontends.java.JavaFrontend;
import org.zwobble.couscous.tests.backends.python.PythonMethodRunner;
import org.zwobble.couscous.values.PrimitiveValue;
@@ -42,6 +49,45 @@ public class JavaToPythonTests {
assertEquals(value(false), exec("Object x = 1; return x.equals(new Object());"));
}
+ @Test
+ @Ignore
+ public void recursiveFactorial() throws Exception {
+ assertEquals(
+ value(120),
+ execProgram(
+ "recursive-factorial",
+ TypeName.of("com.example.RecursiveFactorial"),
+ "factorial",
+ asList(value(6))));
+ }
+
+ private PrimitiveValue execProgram(
+ String directory,
+ TypeName type,
+ String methodName,
+ List<PrimitiveValue> arguments) throws IOException, InterruptedException {
+
+ Path path = pathForResource(
+ "/java/" + directory + "/" + type.getQualifiedName().replace(".", "/") + ".java");
+
+ Path directoryPath = Files.createTempDirectory(null);
+ try {
+ CouscousCompiler compiler = new CouscousCompiler(
+ new PythonCompiler(directoryPath, "couscous"));
+ compiler.compileDirectory(directoryName(path, type.getQualifiedName().split(".").length));
+ return PythonMethodRunner.runFunction(directoryPath, type, methodName, arguments);
+ } finally {
+ deleteRecursively(directoryPath.toFile());
+ }
+ }
+
+ private Path directoryName(Path path, int length) {
+ for (int i = 0; i < length; i++) {
+ path = path.getParent();
+ }
+ return path;
+ }
+
private PrimitiveValue exec(String source) {
try {
String javaClass =
@@ -66,4 +112,13 @@ public class JavaToPythonTests {
private PrimitiveValue evalExpression(String expressionSource) {
return exec("return " + expressionSource + ";");
}
+
+ private static Path pathForResource(String name) {
+ try {
+ URI uri = JavaToPythonTests.class.getResource(name).toURI();
+ return new File(uri).toPath();
+ } catch (URISyntaxException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
} \ No newline at end of file
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
index 1fc0d03..d559e09 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java
@@ -29,17 +29,7 @@ public class PythonMethodRunner implements MethodRunner {
PythonCompiler compiler = new PythonCompiler(directoryPath, "couscous");
try {
compiler.compile(classNodes);
- String argumentsString = Joiner.on(", ").join(arguments.stream().map(PythonCodeGenerator::generateCode).map(PythonSerializer::serialize).iterator());
- String program = "from couscous." + className.getQualifiedName() + " import " + className.getSimpleName() + ";print(repr(" + className.getSimpleName() + "." + methodName + "(" + argumentsString + ")))";
- Process process = new ProcessBuilder("python3.4", "-c", program).directory(directoryPath.toFile()).start();
- int exitCode = process.waitFor();
- String output = readString(process.getInputStream()).trim();
- String stderrOutput = readString(process.getErrorStream());
- if (exitCode != 0) {
- throw new RuntimeException("stderr was: " + stderrOutput);
- } else {
- return readPrimitive(output);
- }
+ return runFunction(directoryPath, className, methodName, arguments);
} finally {
deleteRecursively(directoryPath.toFile());
}
@@ -47,8 +37,28 @@ public class PythonMethodRunner implements MethodRunner {
throw new RuntimeException($ex);
}
}
+
+ public static PrimitiveValue runFunction(
+ Path directoryPath,
+ TypeName className,
+ String methodName,
+ List<PrimitiveValue> arguments)
+ throws IOException, InterruptedException {
+
+ String argumentsString = Joiner.on(", ").join(arguments.stream().map(PythonCodeGenerator::generateCode).map(PythonSerializer::serialize).iterator());
+ String program = "from couscous." + className.getQualifiedName() + " import " + className.getSimpleName() + ";print(repr(" + className.getSimpleName() + "." + methodName + "(" + argumentsString + ")))";
+ Process process = new ProcessBuilder("python3.4", "-c", program).directory(directoryPath.toFile()).start();
+ int exitCode = process.waitFor();
+ String output = readString(process.getInputStream()).trim();
+ String stderrOutput = readString(process.getErrorStream());
+ if (exitCode != 0) {
+ throw new RuntimeException("stderr was: " + stderrOutput);
+ } else {
+ return readPrimitive(output);
+ }
+ }
- private PrimitiveValue readPrimitive(String output) {
+ private static PrimitiveValue readPrimitive(String output) {
if (output.equals("None")) {
return PrimitiveValues.UNIT;
} else if (output.startsWith("\'")) {
@@ -62,7 +72,7 @@ public class PythonMethodRunner implements MethodRunner {
}
}
- private String readString(final InputStream stream) throws IOException {
+ private static String readString(final InputStream stream) throws IOException {
return CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
}
} \ No newline at end of file
diff --git a/src/test/resources/java/recursive-factorial/com/example/RecursiveFactorial.java b/src/test/resources/java/recursive-factorial/com/example/RecursiveFactorial.java
new file mode 100644
index 0000000..eeafcd2
--- /dev/null
+++ b/src/test/resources/java/recursive-factorial/com/example/RecursiveFactorial.java
@@ -0,0 +1,15 @@
+package com.example;
+
+/**
+ *
+ *
+ */
+public class RecursiveFactorial {
+ public static int factorial(int n) {
+ if (n == 1) {
+ return 1;
+ } else {
+ return n * factorial(n - 1);
+ }
+ }
+}