aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java1
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java9
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java22
-rw-r--r--src/main/resources/python/runtime/_couscous.py4
-rw-r--r--src/main/resources/python/runtime/java/lang/Boolean.py13
-rw-r--r--src/main/resources/python/runtime/java/lang/Integer.py6
-rw-r--r--src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java101
7 files changed, 111 insertions, 45 deletions
diff --git a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
index 39bd058..5cd55d2 100644
--- a/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
+++ b/src/main/java/org/zwobble/couscous/backends/python/PythonBackend.java
@@ -19,6 +19,7 @@ import static org.zwobble.couscous.backends.python.PythonSerializer.serialize;
public class PythonBackend implements Backend {
private static final List<String> RUNTIME_FILES = asList(
"java.lang.Object",
+ "java.lang.Boolean",
"java.lang.Integer",
"_couscous");
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
index a54ca55..4f07149 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -4,11 +4,12 @@ import org.eclipse.jdt.core.dom.*;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.ast.ClassNodeBuilder;
import org.zwobble.couscous.ast.StatementNode;
+import org.zwobble.couscous.ast.TypeName;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.Optional;
-import static org.zwobble.couscous.frontends.java.JavaStatementReader.readStatement;
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
public class JavaReader {
@@ -63,8 +64,12 @@ public class JavaReader {
SingleVariableDeclaration parameter = (SingleVariableDeclaration)parameterObject;
builder.argument(parameter.resolveBinding().getKey(), parameter.getName().getIdentifier(), typeOf(parameter.resolveBinding()));
}
+ Optional<TypeName> returnType = method.getReturnType2() == null
+ ? Optional.empty()
+ : Optional.of(typeOf(method.getReturnType2()));
+ JavaStatementReader statementReader = new JavaStatementReader(returnType);
for (Object statement : method.getBody().statements()) {
- for (StatementNode intermediateStatement : readStatement((Statement)statement)) {
+ for (StatementNode intermediateStatement : statementReader.readStatement((Statement)statement)) {
builder.statement(intermediateStatement);
}
}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
index c5194b4..a766cce 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java
@@ -5,6 +5,7 @@ import org.zwobble.couscous.ast.*;
import org.zwobble.couscous.values.BooleanValue;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
@@ -16,8 +17,14 @@ import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpre
import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
-public class JavaStatementReader {
- static List<StatementNode> readStatement(Statement statement) {
+class JavaStatementReader {
+ private final Optional<TypeName> returnType;
+
+ JavaStatementReader(Optional<TypeName> returnType) {
+ this.returnType = returnType;
+ }
+
+ List<StatementNode> readStatement(Statement statement) {
switch (statement.getNodeType()) {
case ASTNode.BLOCK:
return readBlock((Block)statement);
@@ -42,7 +49,7 @@ public class JavaStatementReader {
}
}
- private static List<StatementNode> readBlock(Block block) {
+ private List<StatementNode> readBlock(Block block) {
@SuppressWarnings("unchecked")
List<Statement> statements = block.statements();
return statements.stream()
@@ -50,23 +57,22 @@ public class JavaStatementReader {
.collect(Collectors.toList());
}
- private static StatementNode readReturnStatement(ReturnStatement statement) {
- // TODO: set target type
- return ReturnNode.returns(readExpressionWithoutBoxing(statement.getExpression()));
+ private StatementNode readReturnStatement(ReturnStatement statement) {
+ return ReturnNode.returns(readExpression(returnType.get(), statement.getExpression()));
}
private static StatementNode readExpressionStatement(ExpressionStatement statement) {
return expressionStatement(readExpressionWithoutBoxing(statement.getExpression()));
}
- private static StatementNode readIfStatement(IfStatement statement) {
+ private StatementNode readIfStatement(IfStatement statement) {
return IfStatementNode.ifStatement(
readExpression(BooleanValue.REF, statement.getExpression()),
readStatement(statement.getThenStatement()),
readStatement(statement.getElseStatement()));
}
- private static WhileNode readWhileStatement(WhileStatement statement) {
+ private WhileNode readWhileStatement(WhileStatement statement) {
return whileLoop(
readExpression(BooleanValue.REF, statement.getExpression()),
readStatement(statement.getBody()));
diff --git a/src/main/resources/python/runtime/_couscous.py b/src/main/resources/python/runtime/_couscous.py
index 70d9a97..aa108a5 100644
--- a/src/main/resources/python/runtime/_couscous.py
+++ b/src/main/resources/python/runtime/_couscous.py
@@ -1,4 +1,5 @@
from .java.lang.Integer import Integer
+from .java.lang.Boolean import Boolean
def _div_round_to_zero(a, b):
@@ -9,3 +10,6 @@ def _mod_round_to_zero(a, b):
def boxInt(value):
return Integer(value)
+
+def boxBoolean(value):
+ return Boolean(value) \ No newline at end of file
diff --git a/src/main/resources/python/runtime/java/lang/Boolean.py b/src/main/resources/python/runtime/java/lang/Boolean.py
new file mode 100644
index 0000000..6e08f29
--- /dev/null
+++ b/src/main/resources/python/runtime/java/lang/Boolean.py
@@ -0,0 +1,13 @@
+class Boolean(object):
+ def __init__(self, value):
+ self._value = value
+
+ def equals(self, other):
+ # TODO: test this properly
+ return isinstance(other, Boolean) and other._value == self._value
+
+ def __str__(self):
+ return str(self._value)
+
+ def __repr__(self):
+ return str(self) \ No newline at end of file
diff --git a/src/main/resources/python/runtime/java/lang/Integer.py b/src/main/resources/python/runtime/java/lang/Integer.py
index e16e7bb..8ea30a4 100644
--- a/src/main/resources/python/runtime/java/lang/Integer.py
+++ b/src/main/resources/python/runtime/java/lang/Integer.py
@@ -9,3 +9,9 @@ class Integer(object):
def equals(self, other):
# TODO: test this properly
return isinstance(other, Integer) and other._value == self._value
+
+ def __str__(self):
+ return str(self._value)
+
+ def __repr__(self):
+ return str(self) \ No newline at end of file
diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
index ad2f755..ad8bcbb 100644
--- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java
@@ -40,10 +40,10 @@ import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively;
public class JavaReaderTests {
@Test
public void canReadLiterals() {
- assertEquals(literal("hello"), readExpression("\"hello\""));
- assertEquals(literal(true), readExpression("true"));
- assertEquals(literal(false), readExpression("false"));
- assertEquals(literal(42), readExpression("42"));
+ assertEquals(literal("hello"), readObjectExpression("\"hello\""));
+ assertEquals(literal(true), readBooleanExpression("true"));
+ assertEquals(literal(false), readBooleanExpression("false"));
+ assertEquals(literal(42), readIntExpression("42"));
}
@Test
@@ -93,9 +93,9 @@ public class JavaReaderTests {
public void canReadInstanceMethodCalls() {
assertEquals(
methodCall(literal("hello"), "startsWith", asList(literal("h")), BooleanValue.REF),
- readExpression("\"hello\".startsWith(\"h\")"));
+ readBooleanExpression("\"hello\".startsWith(\"h\")"));
- List<StatementNode> statements = readStatements("Object x = 1; return x.hashCode();");
+ List<StatementNode> statements = readStatements("int", "Object x = 1; return x.hashCode();");
LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0);
ReturnNode returnNode = (ReturnNode) statements.get(1);
assertEquals(
@@ -128,7 +128,7 @@ public class JavaReaderTests {
"parseInt",
asList(literal("42")),
IntegerValue.REF),
- readExpression("Integer.parseInt(\"42\")"));
+ readIntExpression("Integer.parseInt(\"42\")"));
}
@Test
@@ -152,12 +152,12 @@ public class JavaReaderTests {
public void canReadConstructorCalls() {
assertEquals(
constructorCall(TypeName.of("java.lang.String"), asList(literal("_"))),
- readExpression("new String(\"_\")"));
+ readObjectExpression("new String(\"_\")"));
}
@Test
public void argumentIsBoxedIfNecessary() {
- StaticMethodCallNode expression = (StaticMethodCallNode)readExpression(
+ StaticMethodCallNode expression = (StaticMethodCallNode) readObjectExpression(
"java.util.Objects.toString(42)");
assertEquals(
boxInt(literal(42)),
@@ -170,51 +170,51 @@ public class JavaReaderTests {
same(
constructorCall(TypeName.of("java.lang.Object"), emptyList()),
constructorCall(TypeName.of("java.lang.Object"), emptyList())),
- readExpression("new Object() == new Object()"));
+ readBooleanExpression("new Object() == new Object()"));
assertEquals(
not(same(
constructorCall(TypeName.of("java.lang.Object"), emptyList()),
constructorCall(TypeName.of("java.lang.Object"), emptyList()))),
- readExpression("new Object() != new Object()"));
+ readBooleanExpression("new Object() != new Object()"));
}
@Test
public void canUseOperatorsOnIntegers() {
assertEquals(
integerAdd(literal(1), literal(2)),
- readExpression("1 + 2"));
+ readIntExpression("1 + 2"));
assertEquals(
integerSubtract(literal(1), literal(2)),
- readExpression("1 - 2"));
+ readIntExpression("1 - 2"));
assertEquals(
integerMultiply(literal(1), literal(2)),
- readExpression("1 * 2"));
+ readIntExpression("1 * 2"));
assertEquals(
integerDivide(literal(1), literal(2)),
- readExpression("1 / 2"));
+ readIntExpression("1 / 2"));
assertEquals(
integerMod(literal(1), literal(2)),
- readExpression("1 % 2"));
+ readIntExpression("1 % 2"));
assertEquals(
equal(literal(1), literal(2)),
- readExpression("1 == 2"));
+ readBooleanExpression("1 == 2"));
assertEquals(
notEqual(literal(1), literal(2)),
- readExpression("1 != 2"));
+ readBooleanExpression("1 != 2"));
assertEquals(
greaterThan(literal(1), literal(2)),
- readExpression("1 > 2"));
+ readBooleanExpression("1 > 2"));
assertEquals(
greaterThanOrEqual(literal(1), literal(2)),
- readExpression("1 >= 2"));
+ readBooleanExpression("1 >= 2"));
assertEquals(
lessThan(literal(1), literal(2)),
- readExpression("1 < 2"));
+ readBooleanExpression("1 < 2"));
assertEquals(
lessThanOrEqual(literal(1), literal(2)),
- readExpression("1 <= 2"));
+ readBooleanExpression("1 <= 2"));
}
@Test
@@ -223,13 +223,13 @@ public class JavaReaderTests {
equal(
literal(1),
unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))))),
- readExpression("1 == new Integer(1)"));
+ readBooleanExpression("1 == new Integer(1)"));
assertEquals(
notEqual(
literal(1),
unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))))),
- readExpression("1 != new Integer(1)"));
+ readBooleanExpression("1 != new Integer(1)"));
}
@Test
@@ -238,13 +238,13 @@ public class JavaReaderTests {
same(
constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))),
constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2)))),
- readExpression("new Integer(1) == new Integer(2)"));
+ readBooleanExpression("new Integer(1) == new Integer(2)"));
assertEquals(
not(same(
constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1))),
constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2))))),
- readExpression("new Integer(1) != new Integer(2)"));
+ readBooleanExpression("new Integer(1) != new Integer(2)"));
}
@Test
@@ -253,14 +253,14 @@ public class JavaReaderTests {
integerAdd(
unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(1)))),
unboxInt(constructorCall(TypeName.of("java.lang.Integer"), asList(literal(2))))),
- readExpression("new Integer(1) + new Integer(2)"));
+ readIntExpression("new Integer(1) + new Integer(2)"));
}
@Test
public void canReadTernaryConditionals() {
assertEquals(
ternaryConditional(literal(true), literal(1), literal(2)),
- readExpression("true ? 1 : 2"));
+ readIntExpression("true ? 1 : 2"));
}
@Test
@@ -303,7 +303,7 @@ public class JavaReaderTests {
@Test
public void canDeclareAndReferenceLocalVariables() {
- List<StatementNode> statements = readStatements("int x = 4; return x;");
+ List<StatementNode> statements = readStatements("int", "int x = 4; return x;");
LocalVariableDeclarationNode declaration = (LocalVariableDeclarationNode) statements.get(0);
assertEquals("x", declaration.getName());
@@ -360,7 +360,7 @@ public class JavaReaderTests {
@Test
public void canDeclareAndReferenceArguments() {
ClassNode classNode = readClass(
- "public String identity(int value) {" +
+ "public int identity(int value) {" +
" return value;" +
"}");
@@ -493,7 +493,7 @@ public class JavaReaderTests {
literal(true),
asList(returns(literal(1))),
asList(returns(literal(2)))),
- readStatement("if (true) { return 1; } else { return 2; }"));
+ readStatement("int", "if (true) { return 1; } else { return 2; }"));
}
@Test
@@ -502,7 +502,7 @@ public class JavaReaderTests {
whileLoop(
literal(true),
asList(returns(literal(1)))),
- readStatement("while (true) { return 1; }"));
+ readStatement("int", "while (true) { return 1; }"));
}
@Test
@@ -538,6 +538,17 @@ public class JavaReaderTests {
method.getAnnotations());
}
+ @Test
+ public void returnValueHandlesBoxing() {
+ ClassNode classNode = readClass(
+ "public Integer one() { return 1; }");
+
+ MethodNode method = classNode.getMethods().get(0);
+ assertEquals(
+ asList(returns(boxInt(literal(1)))),
+ method.getBody());
+ }
+
private ExpressionNode readExpressionInInstanceMethod(String expressionSource) {
String javaClass =
"public Object main() {" +
@@ -549,8 +560,20 @@ public class JavaReaderTests {
return returnStatement.getValue();
}
- private ExpressionNode readExpression(String expressionSource) {
- ReturnNode returnStatement = (ReturnNode) readStatement("return " + expressionSource + ";");
+ private ExpressionNode readObjectExpression(String expressionSource) {
+ return readExpression("Object", expressionSource);
+ }
+
+ private ExpressionNode readBooleanExpression(String expressionSource) {
+ return readExpression("boolean", expressionSource);
+ }
+
+ private ExpressionNode readIntExpression(String expressionSource) {
+ return readExpression("int", expressionSource);
+ }
+
+ private ExpressionNode readExpression(String returnType, String expressionSource) {
+ ReturnNode returnStatement = (ReturnNode) readStatement(returnType, "return " + expressionSource + ";");
return returnStatement.getValue();
}
@@ -558,9 +581,17 @@ public class JavaReaderTests {
return readStatements(statementSource).get(0);
}
+ private StatementNode readStatement(String returnType, String statementSource) {
+ return readStatements(returnType, statementSource).get(0);
+ }
+
private List<StatementNode> readStatements(String statementsSource) {
+ return readStatements("Object", statementsSource);
+ }
+
+ private List<StatementNode> readStatements(String returnType, String statementsSource) {
String javaClass =
- "public static Object main() {" +
+ "public static " + returnType + " main() {" +
statementsSource +
"}";