diff options
| -rw-r--r-- | .classpath | 5 | ||||
| -rw-r--r-- | .project | 10 | ||||
| -rw-r--r-- | .settings/org.eclipse.core.resources.prefs | 1 | ||||
| -rw-r--r-- | src/main/java/org/zwobble/couscous/CouscousCompiler.java | 23 | ||||
| -rw-r--r-- | src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java | 55 | ||||
| -rw-r--r-- | src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java | 36 | ||||
| -rw-r--r-- | src/test/resources/java/recursive-factorial/com/example/RecursiveFactorial.java | 15 |
7 files changed, 132 insertions, 13 deletions
@@ -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> @@ -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); + } + } +} |
