diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-02-06 17:38:26 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-02-06 17:38:26 +0000 |
| commit | 2e7d1bb669e3ee26efe060ca5ea92ef73cebff83 (patch) | |
| tree | 204c038ed8dff909f3bed79145144749b266d107 /src | |
| parent | a063cdcec0ecfe449a22f0134dc559a40583fc09 (diff) | |
Add return type to MethodSignature
Diffstat (limited to 'src')
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(); } }; |
