aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodCallNode.java5
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodNode.java3
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodSignature.java23
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java6
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Interpreter.java12
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java6
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java9
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java18
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java23
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java3
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java10
-rw-r--r--src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java2
-rw-r--r--src/test/java/org/zwobble/couscous/tests/CompilerTests.java74
-rw-r--r--src/test/java/org/zwobble/couscous/tests/JavaToInterpreterTests.java5
-rw-r--r--src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java8
-rw-r--r--src/test/java/org/zwobble/couscous/tests/MethodRunner.java12
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpMethodRunner.java23
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/csharp/JavaToCsharpTests.java5
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonMethodRunner.java10
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java6
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterMethodTests.java24
21 files changed, 167 insertions, 120 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java
index c284d1f..c4e0321 100644
--- a/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/MethodCallNode.java
@@ -78,7 +78,10 @@ public class MethodCallNode implements ExpressionNode {
}
public MethodSignature signature() {
- return new MethodSignature(methodName, eagerMap(arguments, argument -> argument.getType()));
+ return new MethodSignature(
+ methodName,
+ eagerMap(arguments, argument -> argument.getType()),
+ type);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodNode.java b/src/main/java/org/zwobble/couscous/ast/MethodNode.java
index e0b2432..dd970c5 100644
--- a/src/main/java/org/zwobble/couscous/ast/MethodNode.java
+++ b/src/main/java/org/zwobble/couscous/ast/MethodNode.java
@@ -140,7 +140,8 @@ public class MethodNode implements CallableNode {
public MethodSignature signature() {
return new MethodSignature(
name,
- eagerMap(arguments, argument -> argument.getType()));
+ eagerMap(arguments, argument -> argument.getType()),
+ returnType);
}
public MethodNode mapBody(Function<List<StatementNode>, List<StatementNode>> function) {
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
index fb2dc64..d7bc725 100644
--- a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
+++ b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
@@ -1,15 +1,16 @@
package org.zwobble.couscous.ast;
import java.util.List;
-import java.util.Objects;
public class MethodSignature {
- private String name;
- private List<TypeName> arguments;
+ private final String name;
+ private final List<TypeName> arguments;
+ private final TypeName returnType;
- public MethodSignature(String name, List<TypeName> arguments) {
+ public MethodSignature(String name, List<TypeName> arguments, TypeName returnType) {
this.name = name;
this.arguments = arguments;
+ this.returnType = returnType;
}
public String getName() {
@@ -25,6 +26,7 @@ public class MethodSignature {
return "MethodSignature(" +
"name='" + name + '\'' +
", arguments=" + arguments +
+ ", returnType=" + returnType +
')';
}
@@ -32,13 +34,20 @@ public class MethodSignature {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
+
MethodSignature that = (MethodSignature) o;
- return Objects.equals(name, that.name) &&
- Objects.equals(arguments, that.arguments);
+
+ if (!name.equals(that.name)) return false;
+ if (!arguments.equals(that.arguments)) return false;
+ return returnType.equals(that.returnType);
+
}
@Override
public int hashCode() {
- return Objects.hash(name, arguments);
+ int result = name.hashCode();
+ result = 31 * result + arguments.hashCode();
+ result = 31 * result + returnType.hashCode();
+ return result;
}
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index dbb02c8..815bf10 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -12,8 +12,6 @@ import org.zwobble.couscous.values.IntegerValue;
import java.util.List;
import java.util.stream.Collectors;
-import static org.zwobble.couscous.util.ExtraLists.eagerMap;
-
public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
public static InterpreterValue eval(Environment environment, ExpressionNode expression) {
return new Evaluator(environment).eval(expression);
@@ -87,9 +85,7 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
@Override
public InterpreterValue visit(MethodCallNode methodCall) {
List<InterpreterValue> arguments = evalArguments(methodCall.getArguments());
- MethodSignature signature = new MethodSignature(
- methodCall.getMethodName(),
- eagerMap(methodCall.getArguments(), argument -> argument.getType()));
+ MethodSignature signature = methodCall.signature();
return methodCall.getReceiver().accept(new Receiver.Mapper<InterpreterValue>() {
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
index da84de0..5493e52 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
@@ -1,14 +1,13 @@
package org.zwobble.couscous.interpreter;
-import java.util.List;
-import java.util.Optional;
-
+import com.google.common.collect.ImmutableMap;
import org.zwobble.couscous.ast.MethodSignature;
import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.interpreter.values.ConcreteType;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import java.util.Optional;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
@@ -19,7 +18,7 @@ public class Interpreter {
this.project = project;
}
- public InterpreterValue run(TypeName className, String methodName, List<InterpreterValue> arguments) {
+ public InterpreterValue run(TypeName className, String methodName, List<InterpreterValue> arguments, TypeName returnType) {
final Environment environment = new Environment(
project,
Optional.empty(),
@@ -28,7 +27,8 @@ public class Interpreter {
ConcreteType clazz = environment.findClass(className);
MethodSignature signature = new MethodSignature(
methodName,
- eagerMap(arguments, argument -> argument.getType().getName()));
+ eagerMap(arguments, argument -> argument.getType().getName()),
+ returnType);
return clazz.callStaticMethod(environment, signature, arguments);
}
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
index bb60863..2ac6e3a 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
@@ -20,15 +20,15 @@ public final class BooleanInterpreterValue implements InterpreterValue {
private static final ConcreteType TYPE = ConcreteType.builder(BooleanInterpreterValue.class, "boolean")
- .method(Operator.BOOLEAN_NOT.getSymbol(), list(), (environment, arguments) ->
+ .method(Operator.BOOLEAN_NOT.getSymbol(), list(), BooleanValue.REF, (environment, arguments) ->
of(!arguments.getReceiver().getValue()))
- .method(Operator.BOOLEAN_AND.getSymbol(), list(BooleanValue.REF), (environment, arguments) -> {
+ .method(Operator.BOOLEAN_AND.getSymbol(), list(BooleanValue.REF), BooleanValue.REF, (environment, arguments) -> {
BooleanInterpreterValue right = (BooleanInterpreterValue)arguments.get(0);
return of(arguments.getReceiver().getValue() && right.getValue());
})
- .method(Operator.BOOLEAN_OR.getSymbol(), list(BooleanValue.REF), (environment, arguments) -> {
+ .method(Operator.BOOLEAN_OR.getSymbol(), list(BooleanValue.REF), BooleanValue.REF, (environment, arguments) -> {
BooleanInterpreterValue right = (BooleanInterpreterValue)arguments.get(0);
return of(arguments.getReceiver().getValue() || right.getValue());
})
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java
index 2aa7024..951d57d 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java
@@ -1,5 +1,6 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.ObjectValues;
import org.zwobble.couscous.values.StringValue;
@@ -20,19 +21,19 @@ public class BoxedIntegerInterpreterValue {
public static final ConcreteType TYPE = ConcreteType.classBuilder("java.lang.Integer")
.field("value", IntegerValue.REF)
- .staticMethod("parseInt", list(StringValue.REF),
+ .staticMethod("parseInt", list(StringValue.REF), IntegerValue.REF,
(environment, arguments) -> {
StringInterpreterValue value = (StringInterpreterValue)arguments.get(0);
return new IntegerInterpreterValue(Integer.parseInt(value.getValue()));
})
- .staticMethod("valueOf", list(IntegerValue.REF),
+ .staticMethod("valueOf", list(IntegerValue.REF), ObjectValues.BOXED_INT,
(environment, arguments) -> {
IntegerInterpreterValue value = (IntegerInterpreterValue)arguments.get(0);
return of(value);
})
- .method("equals", list(ObjectValues.OBJECT),
+ .method("equals", list(ObjectValues.OBJECT), BooleanValue.REF,
(environment, arguments) -> {
InterpreterValue right = arguments.getPositionalArguments().get(0);
if (right.getType().getName().equals(ObjectValues.BOXED_INT)) {
@@ -44,7 +45,7 @@ public class BoxedIntegerInterpreterValue {
}
})
- .method("toString", list(),
+ .method("toString", list(), StringValue.REF,
(environment, arguments) -> {
IntegerInterpreterValue value = (IntegerInterpreterValue)arguments.getReceiver().getField("value");
return StringInterpreterValue.of(Integer.toString(value.getValue()));
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
index 9a9fde8..41c0445 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
@@ -54,8 +54,13 @@ public class ConcreteType {
return this;
}
- public Builder<T> method(String name, List<TypeName> argumentsTypes, BiFunction<Environment, MethodCallArguments<T>, InterpreterValue> method) {
- methods.put(new MethodSignature(name, argumentsTypes), toMethodValue(argumentsTypes, method));
+ public Builder<T> method(
+ String name,
+ List<TypeName> argumentsTypes,
+ TypeName returnType,
+ BiFunction<Environment, MethodCallArguments<T>, InterpreterValue> method)
+ {
+ methods.put(new MethodSignature(name, argumentsTypes, returnType), toMethodValue(argumentsTypes, method));
return this;
}
@@ -68,8 +73,13 @@ public class ConcreteType {
.orElseThrow(() -> new RuntimeException("receiver is of wrong type")));
}
- public Builder<T> staticMethod(String name, List<TypeName> argumentsTypes, BiFunction<Environment, PositionalArguments, InterpreterValue> method) {
- staticMethods.put(new MethodSignature(name, argumentsTypes), new StaticMethodValue(argumentsTypes, method));
+ public Builder<T> staticMethod(
+ String name,
+ List<TypeName> argumentsTypes,
+ TypeName returnType,
+ BiFunction<Environment, PositionalArguments, InterpreterValue> method)
+ {
+ staticMethods.put(new MethodSignature(name, argumentsTypes, returnType), new StaticMethodValue(argumentsTypes, method));
return this;
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
index 8c6af74..78da460 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
@@ -3,6 +3,7 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.Operator;
import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
+import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
@@ -14,30 +15,30 @@ import static org.zwobble.couscous.util.ExtraLists.list;
public final class IntegerInterpreterValue implements InterpreterValue {
public static final ConcreteType TYPE = ConcreteType.builder(IntegerInterpreterValue.class, IntegerValue.REF)
- .method(Operator.ADD.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.ADD.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left + right))
- .method(Operator.SUBTRACT.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.SUBTRACT.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left - right))
- .method(Operator.MULTIPLY.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.MULTIPLY.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left * right))
- .method(Operator.DIVIDE.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.DIVIDE.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left / right))
- .method(Operator.MOD.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.MOD.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left % right))
- .method(Operator.EQUALS.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.EQUALS.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
(environment, arguments) -> {
IntegerInterpreterValue right = (IntegerInterpreterValue)arguments.getPositionalArguments().get(0);
return integerEquals(arguments, right);
})
- .method(Operator.NOT_EQUALS.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.NOT_EQUALS.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
infixReturningBoolean((left, right) -> !left.equals(right)))
- .method(Operator.GREATER_THAN.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.GREATER_THAN.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
infixReturningBoolean((left, right) -> left > right))
- .method(Operator.GREATER_THAN_OR_EQUAL.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.GREATER_THAN_OR_EQUAL.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
infixReturningBoolean((left, right) -> left >= right))
- .method(Operator.LESS_THAN.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.LESS_THAN.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
infixReturningBoolean((left, right) -> left < right))
- .method(Operator.LESS_THAN_OR_EQUAL.getSymbol(), list(IntegerValue.REF),
+ .method(Operator.LESS_THAN_OR_EQUAL.getSymbol(), list(IntegerValue.REF), BooleanValue.REF,
infixReturningBoolean((left, right) -> left <= right))
.build();
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java
index 75f8af4..e39f576 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java
@@ -1,12 +1,13 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.ObjectValues;
import static org.zwobble.couscous.util.ExtraLists.list;
public class InternalCouscousInterpreterValue {
public static final ConcreteType TYPE = ConcreteType.classBuilder("_couscous")
- .staticMethod("same", list(ObjectValues.OBJECT, ObjectValues.OBJECT),
+ .staticMethod("same", list(ObjectValues.OBJECT, ObjectValues.OBJECT), BooleanValue.REF,
(environment, arguments) ->
BooleanInterpreterValue.of(arguments.get(0) == arguments.get(1)))
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
index 55a17cc..ae7d141 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
@@ -10,24 +10,24 @@ import static org.zwobble.couscous.util.ExtraLists.list;
public final class StringInterpreterValue implements InterpreterValue {
public static final ConcreteType TYPE = ConcreteType.builder(StringInterpreterValue.class, StringValue.REF)
- .method("length", list(), (environment, arguments) ->
+ .method("length", list(), IntegerValue.REF, (environment, arguments) ->
new IntegerInterpreterValue(arguments.getReceiver().value.length()))
- .method("substring", list(IntegerValue.REF, IntegerValue.REF), (environment, arguments) -> {
+ .method("substring", list(IntegerValue.REF, IntegerValue.REF), StringValue.REF, (environment, arguments) -> {
IntegerInterpreterValue startIndex = (IntegerInterpreterValue)arguments.get(0);
IntegerInterpreterValue endIndex = (IntegerInterpreterValue)arguments.get(1);
return of(arguments.getReceiver().value.substring(startIndex.getValue(), endIndex.getValue()));
})
- .method(Operator.ADD.getSymbol(), list(StringValue.REF), (environment, arguments) -> {
+ .method(Operator.ADD.getSymbol(), list(StringValue.REF), StringValue.REF, (environment, arguments) -> {
StringInterpreterValue right = (StringInterpreterValue)arguments.get(0);
return of(arguments.getReceiver().value + right.value);
})
- .method("toLowerCase", list(), (environment, arguments) ->
+ .method("toLowerCase", list(), StringValue.REF, (environment, arguments) ->
of(arguments.getReceiver().value.toLowerCase()))
- .method("equals", list(ObjectValues.OBJECT), (environment, arguments) -> {
+ .method("equals", list(ObjectValues.OBJECT), BooleanValue.REF, (environment, arguments) -> {
InterpreterValue right = arguments.get(0);
if (right instanceof StringInterpreterValue) {
return BooleanInterpreterValue.of(arguments.getReceiver().value.equals(((StringInterpreterValue)right).value));
diff --git a/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java b/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
index d6d35af..c8b2b70 100644
--- a/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/BackendMethodTests.java
@@ -153,7 +153,7 @@ public abstract class BackendMethodTests {
String className = "com.example.Program";
ClassNode classNode = ClassNode.builder(className).method(method).build();
MethodRunner runner = buildMethodRunner();
- return runner.runMethod(list(classNode), classNode.getName(), method.getName(), asList(arguments));
+ return runner.runMethod(list(classNode), classNode.getName(), method.getName(), asList(arguments), method.getReturnType());
}
protected abstract MethodRunner buildMethodRunner();
diff --git a/src/test/java/org/zwobble/couscous/tests/CompilerTests.java b/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
index 5b63a66..f03f6ce 100644
--- a/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
@@ -2,7 +2,10 @@ package org.zwobble.couscous.tests;
import org.junit.Test;
import org.zwobble.couscous.ast.TypeName;
+import org.zwobble.couscous.values.BooleanValue;
+import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.StringValue;
import java.io.File;
import java.io.IOException;
@@ -20,7 +23,7 @@ import static org.zwobble.couscous.values.PrimitiveValues.value;
public abstract class CompilerTests {
@Test
public void canEvaluateLiterals() {
- assertEquals(value("hello"), evalExpression("String", "\"hello\""));
+ assertEquals(value("hello"), evalExpression(StringValue.REF, "\"hello\""));
assertEquals(value(42), evalIntExpression("42"));
}
@@ -38,13 +41,13 @@ public abstract class CompilerTests {
@Test
public void equalityOnReferenceTypesChecksForIdentity() {
assertEquals(value(false), evalBooleanExpression("new Object() == new Object()"));
- assertEquals(value(true), exec("boolean", "Object x = new Object(); return x == x;"));
+ assertEquals(value(true), exec(BooleanValue.REF, "Object x = new Object(); return x == x;"));
}
@Test
public void integersCanBeAssignedToObjectVariable() {
- assertEquals(value(false), exec("boolean", "Object x = 1; return x.equals(new Object());"));
- assertEquals(value(true), exec("boolean", "Object x = 1; return x.equals(1);"));
+ assertEquals(value(false), exec(BooleanValue.REF, "Object x = 1; return x.equals(new Object());"));
+ assertEquals(value(true), exec(BooleanValue.REF, "Object x = 1; return x.equals(1);"));
}
@Test
@@ -55,7 +58,8 @@ public abstract class CompilerTests {
"recursive-factorial",
TypeName.of("com.example.RecursiveFactorial"),
"factorial",
- list(value(6))));
+ list(value(6)),
+ IntegerValue.REF));
}
@Test
@@ -66,7 +70,8 @@ public abstract class CompilerTests {
"while-factorial",
TypeName.of("com.example.WhileFactorial"),
"factorial",
- list(value(6))));
+ list(value(6)),
+ IntegerValue.REF));
}
@Test
@@ -77,7 +82,8 @@ public abstract class CompilerTests {
"for-factorial",
TypeName.of("com.example.ForFactorial"),
"factorial",
- list(value(6))));
+ list(value(6)),
+ IntegerValue.REF));
}
@Test
@@ -88,7 +94,8 @@ public abstract class CompilerTests {
"anonymous-class",
TypeName.of("com.example.AnonymousClass"),
"value",
- list()));
+ list(),
+ IntegerValue.REF));
}
@Test
@@ -99,7 +106,8 @@ public abstract class CompilerTests {
"anonymous-class-capture",
TypeName.of("com.example.AnonymousClass"),
"value",
- list(value(42))));
+ list(value(42)),
+ IntegerValue.REF));
}
@Test
@@ -110,7 +118,8 @@ public abstract class CompilerTests {
"lambda",
TypeName.of("com.example.Lambda"),
"value",
- list()));
+ list(),
+ IntegerValue.REF));
}
@Test
@@ -121,7 +130,8 @@ public abstract class CompilerTests {
"lambda-capture",
TypeName.of("com.example.Lambda"),
"value",
- list(value(2))));
+ list(value(2)),
+ IntegerValue.REF));
}
@Test
@@ -132,7 +142,8 @@ public abstract class CompilerTests {
"lambda-this-capture",
TypeName.of("com.example.Lambda"),
"value",
- list(value(2))));
+ list(value(2)),
+ IntegerValue.REF));
}
@Test
@@ -143,31 +154,33 @@ public abstract class CompilerTests {
"static-method-overloads",
TypeName.of("com.example.StaticMethodOverloads"),
"value",
- list()));
+ list(),
+ IntegerValue.REF));
}
@Test
public void stringAdd() throws Exception {
- assertEquals(value("42"), evalExpression("String", "\"4\" + \"2\""));
+ assertEquals(value("42"), evalExpression(StringValue.REF, "\"4\" + \"2\""));
}
@Test
public void stringToLowerCase() throws Exception {
- assertEquals(value("patrick wolf"), evalExpression("String", "\"Patrick Wolf\".toLowerCase()"));
+ assertEquals(value("patrick wolf"), evalExpression(StringValue.REF, "\"Patrick Wolf\".toLowerCase()"));
}
@Test
public void stringEquals() throws Exception {
- assertEquals(value(true), evalExpression("boolean", "\"a\".equals(\"a\")"));
- assertEquals(value(false), evalExpression("boolean", "\"a\".equals(\"b\")"));
- assertEquals(value(false), evalExpression("boolean", "\"a\".equals(42)"));
+ assertEquals(value(true), evalBooleanExpression("\"a\".equals(\"a\")"));
+ assertEquals(value(false), evalBooleanExpression("\"a\".equals(\"b\")"));
+ assertEquals(value(false), evalBooleanExpression("\"a\".equals(42)"));
}
private PrimitiveValue execTestProgram(
String directoryName,
TypeName type,
String methodName,
- List<PrimitiveValue> arguments) throws IOException, InterruptedException {
+ List<PrimitiveValue> arguments,
+ TypeName returnType) throws IOException, InterruptedException {
Path path = pathForResource(
"/java/" + directoryName + "/" + type.getQualifiedName().replace(".", "/") + ".java");
@@ -176,14 +189,16 @@ public abstract class CompilerTests {
directoryName(path, type.getQualifiedName().split("\\.").length),
type,
methodName,
- arguments);
+ arguments,
+ returnType);
}
protected abstract PrimitiveValue execProgram(
Path directory,
TypeName type,
String methodName,
- List<PrimitiveValue> arguments) throws IOException, InterruptedException;
+ List<PrimitiveValue> arguments,
+ TypeName returnType) throws IOException, InterruptedException;
private Path directoryName(Path path, int length) {
for (int i = 0; i < length; i++) {
@@ -192,12 +207,12 @@ public abstract class CompilerTests {
return path;
}
- private PrimitiveValue exec(String returnType, String source) {
+ private PrimitiveValue exec(TypeName returnType, String source) {
try {
String javaClass =
"package com.example;" +
"public class Example {" +
- " public static " + returnType + " main() {" + source + "}" +
+ " public static " + returnType.getQualifiedName() + " main() {" + source + "}" +
"}";
Path directoryPath = Files.createTempDirectory(null);
try {
@@ -207,7 +222,8 @@ public abstract class CompilerTests {
directoryPath,
TypeName.of("com.example.Example"),
"main",
- list());
+ list(),
+ returnType);
} finally {
deleteRecursively(directoryPath.toFile());
}
@@ -217,18 +233,14 @@ public abstract class CompilerTests {
}
private PrimitiveValue evalBooleanExpression(String expressionSource) {
- return evalExpression("boolean", expressionSource);
+ return evalExpression(BooleanValue.REF, expressionSource);
}
private PrimitiveValue evalIntExpression(String expressionSource) {
- return evalExpression("int", expressionSource);
+ return evalExpression(IntegerValue.REF, expressionSource);
}
- private PrimitiveValue evalObjectExpression(String expressionSource) {
- return evalExpression("Object", expressionSource);
- }
-
- private PrimitiveValue evalExpression(String type, String expressionSource) {
+ private PrimitiveValue evalExpression(TypeName type, String expressionSource) {
return exec(type, "return " + expressionSource + ";");
}
diff --git a/src/test/java/org/zwobble/couscous/tests/JavaToInterpreterTests.java b/src/test/java/org/zwobble/couscous/tests/JavaToInterpreterTests.java
index 59cc6d6..5a6ada1 100644
--- a/src/test/java/org/zwobble/couscous/tests/JavaToInterpreterTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/JavaToInterpreterTests.java
@@ -24,7 +24,8 @@ public class JavaToInterpreterTests extends CompilerTests {
Path directory,
TypeName type,
String methodName,
- List<PrimitiveValue> arguments
+ List<PrimitiveValue> arguments,
+ TypeName returnType
) throws IOException, InterruptedException {
JavaFrontend frontend = new JavaFrontend();
List<ClassNode> classNodes = frontend.readSourceDirectory(list(directory), directory);
@@ -33,7 +34,7 @@ public class JavaToInterpreterTests extends CompilerTests {
Interpreter interpreter = new Interpreter(project);
List<InterpreterValue> argumentValues = ImmutableList.copyOf(transform(arguments, InterpreterValues::value));
- return interpreter.run(type, methodName, argumentValues)
+ return interpreter.run(type, methodName, argumentValues, returnType)
.toPrimitiveValue().get();
}
}
diff --git a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
index a0d1c7e..6b9f6ed 100644
--- a/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/JavaToPythonTests.java
@@ -1,7 +1,5 @@
package org.zwobble.couscous.tests;
-import com.google.common.collect.ImmutableList;
-import org.junit.Test;
import org.zwobble.couscous.CouscousCompiler;
import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.backends.python.PythonBackend;
@@ -10,7 +8,6 @@ import org.zwobble.couscous.tests.backends.python.PythonMethodRunner;
import org.zwobble.couscous.values.PrimitiveValue;
import java.io.IOException;
-import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
@@ -23,7 +20,8 @@ public class JavaToPythonTests extends CompilerTests {
Path directory,
TypeName type,
String methodName,
- List<PrimitiveValue> arguments) throws IOException, InterruptedException {
+ List<PrimitiveValue> arguments,
+ TypeName returnType) throws IOException, InterruptedException {
Path directoryPath = Files.createTempDirectory(null);
try {
@@ -31,7 +29,7 @@ public class JavaToPythonTests extends CompilerTests {
new JavaFrontend(),
new PythonBackend(directoryPath, "couscous"));
compiler.compileDirectory(list(directory), directory);
- return PythonMethodRunner.runFunction(directoryPath, type, methodName, arguments);
+ return PythonMethodRunner.runFunction(directoryPath, type, methodName, arguments, returnType);
} finally {
deleteRecursively(directoryPath.toFile());
}
diff --git a/src/test/java/org/zwobble/couscous/tests/MethodRunner.java b/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
index ed486fc..59b71f9 100644
--- a/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
+++ b/src/test/java/org/zwobble/couscous/tests/MethodRunner.java
@@ -14,7 +14,14 @@ public interface MethodRunner {
List<ClassNode> classNodes,
TypeName className,
String methodName,
- List<PrimitiveValue> arguments);
+ List<PrimitiveValue> arguments, TypeName returnType);
+
+
+ default PrimitiveValue runMethod(List<ClassNode> classNodes, TypeName className, String methodName, List<PrimitiveValue> arguments) {
+ ClassNode classNode = Iterables.find(classNodes, c -> c.getName().equals(className));
+ MethodNode method = Iterables.find(classNode.getMethods(), m -> m.getName().equals(methodName));
+ return runMethod(classNodes, className, methodName, arguments, method.getReturnType());
+ }
default PrimitiveValue evalExpression(List<ClassNode> classes, ExpressionNode expression) {
ClassNode programNode = ClassNode.builder("Program")
@@ -29,6 +36,7 @@ public interface MethodRunner {
list(programNode))),
programNode.getName(),
"run",
- list());
+ list(),
+ expression.getType());
}
}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpMethodRunner.java b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpMethodRunner.java
index d293f84..88cce22 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpMethodRunner.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/csharp/CsharpMethodRunner.java
@@ -1,7 +1,6 @@
package org.zwobble.couscous.tests.backends.csharp;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import org.hamcrest.Matchers;
import org.zwobble.couscous.Backend;
@@ -15,7 +14,10 @@ import org.zwobble.couscous.backends.csharp.CsharpSerializer;
import org.zwobble.couscous.tests.MethodRunner;
import org.zwobble.couscous.tests.backends.Processes;
import org.zwobble.couscous.util.ExtraLists;
-import org.zwobble.couscous.values.*;
+import org.zwobble.couscous.values.PrimitiveValue;
+import org.zwobble.couscous.values.PrimitiveValues;
+import org.zwobble.couscous.values.StringValue;
+import org.zwobble.couscous.values.UnitValue;
import java.io.IOException;
import java.nio.file.Files;
@@ -34,17 +36,13 @@ public class CsharpMethodRunner implements MethodRunner {
private static final String NAMESPACE = "Couscous";
@Override
- public PrimitiveValue runMethod(List<ClassNode> classNodes, TypeName className, String methodName, List<PrimitiveValue> arguments) {
+ public PrimitiveValue runMethod(List<ClassNode> classNodes, TypeName className, String methodName, List<PrimitiveValue> arguments, TypeName returnType) {
try {
Path directoryPath = Files.createTempDirectory(null);
Backend compiler = new CsharpBackend(directoryPath, NAMESPACE);
try {
compiler.compile(classNodes);
- ClassNode classNode = Iterables.find(classNodes, c -> c.getName().equals(className));
- boolean isVoid = Iterables.find(classNode.getMethods(), method -> method.getName().equals(methodName))
- .getReturnType()
- .equals(UnitValue.REF);
- return runFunction(directoryPath, className, methodName, arguments, isVoid);
+ return runFunction(directoryPath, className, methodName, arguments, returnType);
} finally {
deleteRecursively(directoryPath.toFile());
}
@@ -58,21 +56,22 @@ public class CsharpMethodRunner implements MethodRunner {
TypeName className,
String methodName,
List<PrimitiveValue> arguments,
- boolean isVoid)
+ TypeName returnType)
throws IOException, InterruptedException
{
MethodSignature signature = new MethodSignature(
methodName,
- eagerMap(arguments, argument -> argument.getType()));
+ eagerMap(arguments, argument -> argument.getType()),
+ returnType);
String csharpMethodName = Names.toUniqueName(signature);
String value = CsharpSerializer.serialize(
staticMethodCall(
TypeName.of(NAMESPACE + "." + className.getQualifiedName()),
csharpMethodName,
eagerMap(arguments, LiteralNode::literal),
- // TODO: pass in return type
- ObjectValues.OBJECT));
+ returnType));
+ boolean isVoid = returnType.equals(UnitValue.REF);
String body = isVoid
? value + ";"
: "var value = " + value + ";" +
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/csharp/JavaToCsharpTests.java b/src/test/java/org/zwobble/couscous/tests/backends/csharp/JavaToCsharpTests.java
index e578ef3..1ab76bd 100644
--- a/src/test/java/org/zwobble/couscous/tests/backends/csharp/JavaToCsharpTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/backends/csharp/JavaToCsharpTests.java
@@ -47,7 +47,8 @@ public class JavaToCsharpTests extends CompilerTests {
Path directory,
TypeName type,
String methodName,
- List<PrimitiveValue> arguments) throws IOException, InterruptedException
+ List<PrimitiveValue> arguments,
+ TypeName returnType) throws IOException, InterruptedException
{
Path directoryPath = Files.createTempDirectory(null);
try {
@@ -55,7 +56,7 @@ public class JavaToCsharpTests extends CompilerTests {
new JavaFrontend(),
new CsharpBackend(directoryPath, "Couscous"));
compiler.compileDirectory(list(directory), directory);
- return CsharpMethodRunner.runFunction(directoryPath, type, methodName, arguments, false);
+ return CsharpMethodRunner.runFunction(directoryPath, type, methodName, arguments, returnType);
} finally {
deleteRecursively(directoryPath.toFile());
}
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 e541459..a4a57d1 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
@@ -28,13 +28,13 @@ import static org.zwobble.couscous.values.PrimitiveValues.value;
public class PythonMethodRunner implements MethodRunner {
@Override
- public PrimitiveValue runMethod(List<ClassNode> classNodes, TypeName className, String methodName, List<PrimitiveValue> arguments) {
+ public PrimitiveValue runMethod(List<ClassNode> classNodes, TypeName className, String methodName, List<PrimitiveValue> arguments, TypeName returnType) {
try {
Path directoryPath = Files.createTempDirectory(null);
PythonBackend compiler = new PythonBackend(directoryPath, "couscous");
try {
compiler.compile(classNodes);
- return runFunction(directoryPath, className, methodName, arguments);
+ return runFunction(directoryPath, className, methodName, arguments, returnType);
} finally {
deleteRecursively(directoryPath.toFile());
}
@@ -47,13 +47,15 @@ public class PythonMethodRunner implements MethodRunner {
Path directoryPath,
TypeName className,
String methodName,
- List<PrimitiveValue> arguments)
+ List<PrimitiveValue> arguments,
+ TypeName returnType)
throws IOException, InterruptedException {
String argumentsString = Joiner.on(", ").join(arguments.stream().map(PythonCodeGenerator::generateCode).map(PythonSerializer::serialize).iterator());
MethodSignature signature = new MethodSignature(
methodName,
- eagerMap(arguments, argument -> argument.getType()));
+ eagerMap(arguments, argument -> argument.getType()),
+ returnType);
String pythonMethodName = Names.toUniqueName(signature);
String program = "from couscous." + className.getQualifiedName() + " import " + className.getSimpleName() + ";" +
"value = " + className.getSimpleName() + "." + pythonMethodName + "(" + argumentsString + ");" +
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 49b435d..afd0936 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
@@ -66,7 +66,7 @@ public class EvaluatorTests extends BackendEvalTests {
"size",
list(),
IntegerValue.REF)));
- assertEquals(new MethodSignature("size", list()), exception.getSignature());
+ assertEquals(new MethodSignature("size", list(), IntegerValue.REF), exception.getSignature());
}
@Test
@@ -78,7 +78,7 @@ public class EvaluatorTests extends BackendEvalTests {
"substring",
list(literal(1)),
StringValue.REF)));
- assertEquals(new MethodSignature("substring", list(IntegerValue.REF)), exception.getSignature());
+ assertEquals(new MethodSignature("substring", list(IntegerValue.REF), StringValue.REF), exception.getSignature());
}
@Test
@@ -91,7 +91,7 @@ public class EvaluatorTests extends BackendEvalTests {
list(literal(0), literal("")),
StringValue.REF)));
assertEquals(
- new MethodSignature("substring", list(IntegerValue.REF, StringValue.REF)),
+ new MethodSignature("substring", list(IntegerValue.REF, StringValue.REF), StringValue.REF),
exception.getSignature());
}
diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterMethodTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterMethodTests.java
index f9b1f07..499d18c 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterMethodTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterMethodTests.java
@@ -1,11 +1,10 @@
package org.zwobble.couscous.tests.interpreter;
-import java.util.List;
-import java.util.stream.Collectors;
-
import org.junit.Test;
import org.zwobble.couscous.ast.*;
-import org.zwobble.couscous.interpreter.*;
+import org.zwobble.couscous.interpreter.Interpreter;
+import org.zwobble.couscous.interpreter.JavaProject;
+import org.zwobble.couscous.interpreter.Project;
import org.zwobble.couscous.interpreter.errors.NoSuchMethod;
import org.zwobble.couscous.interpreter.errors.UnboundVariable;
import org.zwobble.couscous.interpreter.errors.UnexpectedValueType;
@@ -17,6 +16,10 @@ import org.zwobble.couscous.tests.MethodRunner;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.StringValue;
+import org.zwobble.couscous.values.UnitValue;
+
+import java.util.List;
+import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.zwobble.couscous.ast.AssignmentNode.assign;
@@ -41,7 +44,7 @@ public class InterpreterMethodTests extends BackendMethodTests {
NoSuchMethod exception = assertThrows(NoSuchMethod.class,
() -> runMethod(method, value("hello, world!")));
- assertEquals(new MethodSignature("hello", list(StringValue.REF)), exception.getSignature());
+ assertEquals(new MethodSignature("hello", list(StringValue.REF), UnitValue.REF), exception.getSignature());
}
@Test
@@ -102,10 +105,11 @@ public class InterpreterMethodTests extends BackendMethodTests {
return new MethodRunner() {
@Override
public PrimitiveValue runMethod(
- List<ClassNode> classNodes,
- TypeName className,
- String methodName,
- List<PrimitiveValue> arguments) {
+ List<ClassNode> classNodes,
+ TypeName className,
+ String methodName,
+ List<PrimitiveValue> arguments,
+ TypeName returnType) {
Project project = JavaProject.of(classNodes);
Interpreter interpreter = new Interpreter(project);
@@ -113,7 +117,7 @@ public class InterpreterMethodTests extends BackendMethodTests {
.map(InterpreterValues::value)
.collect(Collectors.toList());
- return interpreter.run(className, methodName, argumentValues)
+ return interpreter.run(className, methodName, argumentValues, returnType)
.toPrimitiveValue().get();
}
};