aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java12
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Interpreter.java7
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/MethodSignature.java38
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/NoSuchMethod.java43
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java58
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java16
6 files changed, 107 insertions, 67 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index 910cba7..1271d72 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -10,6 +10,8 @@ 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);
@@ -76,14 +78,20 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
InterpreterValue receiver = eval(methodCall.getReceiver());
ConcreteType type = receiver.getType();
List<InterpreterValue> arguments = evalArguments(methodCall.getArguments());
- return type.callMethod(environment, receiver, methodCall.getMethodName(), arguments);
+ MethodSignature signature = new MethodSignature(
+ methodCall.getMethodName(),
+ eagerMap(arguments, argument -> argument.getType().getName()));
+ return type.callMethod(environment, receiver, signature, arguments);
}
@Override
public InterpreterValue visit(StaticMethodCallNode staticMethodCall) {
ConcreteType clazz = environment.findClass(staticMethodCall.getClassName());
List<InterpreterValue> arguments = evalArguments(staticMethodCall.getArguments());
- return clazz.callStaticMethod(environment, staticMethodCall.getMethodName(), arguments);
+ MethodSignature signature = new MethodSignature(
+ staticMethodCall.getMethodName(),
+ eagerMap(arguments, argument -> argument.getType().getName()));
+ return clazz.callStaticMethod(environment, signature, arguments);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
index 95510cd..b506fdf 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Interpreter.java
@@ -9,6 +9,8 @@ import org.zwobble.couscous.interpreter.values.InterpreterValue;
import com.google.common.collect.ImmutableMap;
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
+
public class Interpreter {
private Project project;
@@ -23,6 +25,9 @@ public class Interpreter {
ImmutableMap.of());
ConcreteType clazz = environment.findClass(className);
- return clazz.callStaticMethod(environment, methodName, arguments);
+ MethodSignature signature = new MethodSignature(
+ methodName,
+ eagerMap(arguments, argument -> argument.getType().getName()));
+ return clazz.callStaticMethod(environment, signature, arguments);
}
} \ No newline at end of file
diff --git a/src/main/java/org/zwobble/couscous/interpreter/MethodSignature.java b/src/main/java/org/zwobble/couscous/interpreter/MethodSignature.java
new file mode 100644
index 0000000..708bc9a
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/MethodSignature.java
@@ -0,0 +1,38 @@
+package org.zwobble.couscous.interpreter;
+
+import org.zwobble.couscous.ast.TypeName;
+
+import java.util.List;
+import java.util.Objects;
+
+public class MethodSignature {
+ private String name;
+ private List<TypeName> arguments;
+
+ public MethodSignature(String name, List<TypeName> arguments) {
+ this.name = name;
+ this.arguments = arguments;
+ }
+
+ @Override
+ public String toString() {
+ return "MethodSignature(" +
+ "name='" + name + '\'' +
+ ", arguments=" + arguments +
+ ')';
+ }
+
+ @Override
+ 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);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, arguments);
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/NoSuchMethod.java b/src/main/java/org/zwobble/couscous/interpreter/NoSuchMethod.java
index ddddd71..1bb934e 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/NoSuchMethod.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/NoSuchMethod.java
@@ -2,43 +2,20 @@ package org.zwobble.couscous.interpreter;
public final class NoSuchMethod extends InterpreterException {
private static final long serialVersionUID = 1L;
- private final String methodName;
+ private MethodSignature signature;
- public NoSuchMethod(final String methodName) {
- this.methodName = methodName;
+ public NoSuchMethod(MethodSignature signature) {
+ this.signature = signature;
}
- public String getMethodName() {
- return this.methodName;
+ public MethodSignature getSignature() {
+ return signature;
}
- @java.lang.Override
- public java.lang.String toString() {
- return "NoSuchMethod(methodName=" + this.getMethodName() + ")";
- }
-
- @java.lang.Override
- public boolean equals(final java.lang.Object o) {
- if (o == this) return true;
- if (!(o instanceof NoSuchMethod)) return false;
- final NoSuchMethod other = (NoSuchMethod)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
- final java.lang.Object this$methodName = this.getMethodName();
- final java.lang.Object other$methodName = other.getMethodName();
- if (this$methodName == null ? other$methodName != null : !this$methodName.equals(other$methodName)) return false;
- return true;
- }
-
- protected boolean canEqual(final java.lang.Object other) {
- return other instanceof NoSuchMethod;
- }
-
- @java.lang.Override
- public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- final java.lang.Object $methodName = this.getMethodName();
- result = result * PRIME + ($methodName == null ? 43 : $methodName.hashCode());
- return result;
+ @Override
+ public String toString() {
+ return "NoSuchMethod(" +
+ "signature=" + signature +
+ ") " + super.toString();
}
} \ No newline at end of file
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 157bb41..536aeb3 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
@@ -5,17 +5,14 @@ import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.zwobble.couscous.ast.ClassNode;
import org.zwobble.couscous.ast.FormalArgumentNode;
+import org.zwobble.couscous.ast.MethodNode;
import org.zwobble.couscous.ast.TypeName;
-import org.zwobble.couscous.interpreter.Environment;
-import org.zwobble.couscous.interpreter.Executor;
-import org.zwobble.couscous.interpreter.InterpreterTypes;
-import org.zwobble.couscous.interpreter.NoSuchMethod;
-import org.zwobble.couscous.interpreter.PositionalArguments;
-import org.zwobble.couscous.interpreter.WrongNumberOfArguments;
+import org.zwobble.couscous.interpreter.*;
import org.zwobble.couscous.util.Casts;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import static java.util.stream.Collectors.toMap;
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
public class ConcreteType {
@@ -33,8 +30,8 @@ public class ConcreteType {
public static class Builder<T> {
private final ImmutableMap.Builder<String, FieldValue> fields = ImmutableMap.builder();
- private final ImmutableMap.Builder<String, MethodValue> methods = ImmutableMap.builder();
- private final ImmutableMap.Builder<String, StaticMethodValue> staticMethods = ImmutableMap.builder();
+ private final ImmutableMap.Builder<MethodSignature, MethodValue> methods = ImmutableMap.builder();
+ private final ImmutableMap.Builder<MethodSignature, StaticMethodValue> staticMethods = ImmutableMap.builder();
private final Class<T> interpreterValueType;
private final TypeName name;
@@ -49,14 +46,14 @@ public class ConcreteType {
}
public Builder<T> method(String name, List<TypeName> argumentsTypes, BiFunction<Environment, MethodCallArguments<T>, InterpreterValue> method) {
- methods.put(name, new MethodValue(argumentsTypes, (environment, arguments) -> {
+ methods.put(new MethodSignature(name, argumentsTypes), new MethodValue(argumentsTypes, (environment, arguments) -> {
return Casts.tryCast(interpreterValueType, arguments.getReceiver()).map(typedReceiver -> method.apply(environment, MethodCallArguments.of(typedReceiver, arguments.getPositionalArguments()))).orElseThrow(() -> new RuntimeException("receiver is of wrong type"));
}));
return this;
}
public Builder<T> staticMethod(String name, List<TypeName> argumentsTypes, BiFunction<Environment, PositionalArguments, InterpreterValue> method) {
- staticMethods.put(name, new StaticMethodValue(argumentsTypes, method));
+ staticMethods.put(new MethodSignature(name, argumentsTypes), new StaticMethodValue(argumentsTypes, method));
return this;
}
@@ -74,19 +71,19 @@ public class ConcreteType {
public static ConcreteType fromNode(ClassNode classNode) {
Map<String, FieldValue> fields = classNode.getFields().stream().collect(toMap(field -> field.getName(), field -> new FieldValue(field.getName(), field.getType())));
MethodValue constructor = new MethodValue(getArgumentTypes(classNode.getConstructor().getArguments()), (environment, arguments) -> Executor.callMethod(environment, classNode.getConstructor(), Optional.of(arguments.getReceiver()), arguments.getPositionalArguments()));
- Map<String, MethodValue> methods = classNode.getMethods()
+ Map<MethodSignature, MethodValue> methods = classNode.getMethods()
.stream()
.filter(method -> !method.isStatic())
- .collect(toMap(method -> method.getName(), method -> {
+ .collect(toMap(method -> signature(method), method -> {
List<TypeName> argumentTypes = getArgumentTypes(method.getArguments());
return new MethodValue(argumentTypes, (environment, arguments) -> {
return Executor.callMethod(environment, method, Optional.of(arguments.getReceiver()), arguments.getPositionalArguments());
});
}));
- Map<String, StaticMethodValue> staticMethods = classNode.getMethods()
+ Map<MethodSignature, StaticMethodValue> staticMethods = classNode.getMethods()
.stream()
.filter(method -> method.isStatic())
- .collect(toMap(method -> method.getName(), method -> {
+ .collect(toMap(method -> signature(method), method -> {
List<TypeName> argumentTypes = getArgumentTypes(method.getArguments());
return new StaticMethodValue(argumentTypes, (environment, arguments) -> {
return Executor.callMethod(environment, method, Optional.empty(), arguments);
@@ -94,7 +91,13 @@ public class ConcreteType {
}));
return new ConcreteType(classNode.getName(), classNode.getSuperTypes(), fields, constructor, methods, staticMethods);
}
-
+
+ private static MethodSignature signature(MethodNode method) {
+ return new MethodSignature(
+ method.getName(),
+ eagerMap(method.getArguments(), argument -> argument.getType()));
+ }
+
private static List<TypeName> getArgumentTypes(List<FormalArgumentNode> arguments) {
return arguments.stream().map(arg -> arg.getType()).collect(Collectors.toList());
}
@@ -102,16 +105,17 @@ public class ConcreteType {
private final Set<TypeName> superTypes;
private final Map<String, FieldValue> fields;
private final MethodValue constructor;
- private final Map<String, MethodValue> methods;
- private final Map<String, StaticMethodValue> staticMethods;
+ private final Map<MethodSignature, MethodValue> methods;
+ private final Map<MethodSignature, StaticMethodValue> staticMethods;
private ConcreteType(
TypeName name,
Set<TypeName> superTypes,
Map<String, FieldValue> fields,
MethodValue constructor,
- Map<String, MethodValue> methods,
- Map<String, StaticMethodValue> staticMethods) {
+ Map<MethodSignature, MethodValue> methods,
+ Map<MethodSignature, StaticMethodValue> staticMethods)
+ {
this.name = name;
this.superTypes = superTypes;
this.fields = fields;
@@ -132,13 +136,13 @@ public class ConcreteType {
return Optional.ofNullable(fields.get(fieldName));
}
- public InterpreterValue callMethod(Environment environment, InterpreterValue receiver, String methodName, List<InterpreterValue> arguments) {
- final org.zwobble.couscous.interpreter.values.MethodValue method = findMethod(methods, methodName, arguments);
+ public InterpreterValue callMethod(Environment environment, InterpreterValue receiver, MethodSignature signature, List<InterpreterValue> arguments) {
+ MethodValue method = findMethod(methods, signature, arguments);
return method.apply(environment, MethodCallArguments.of(receiver, new PositionalArguments(arguments)));
}
- public InterpreterValue callStaticMethod(Environment environment, String methodName, List<InterpreterValue> arguments) {
- final org.zwobble.couscous.interpreter.values.StaticMethodValue method = findMethod(staticMethods, methodName, arguments);
+ public InterpreterValue callStaticMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) {
+ StaticMethodValue method = findMethod(staticMethods, signature, arguments);
return method.apply(environment, new PositionalArguments(arguments));
}
@@ -149,11 +153,11 @@ public class ConcreteType {
return object;
}
- private static <T extends Callable> T findMethod(Map<String, T> methods, String methodName, List<InterpreterValue> arguments) {
- if (!methods.containsKey(methodName)) {
- throw new NoSuchMethod(methodName);
+ private static <T extends Callable> T findMethod(Map<MethodSignature, T> methods, MethodSignature signature, List<InterpreterValue> arguments) {
+ if (!methods.containsKey(signature)) {
+ throw new NoSuchMethod(signature);
}
- final T method = methods.get(methodName);
+ final T method = methods.get(signature);
checkMethodArguments(method, arguments);
return method;
}
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 3bcb41a..be58d56 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java
@@ -4,8 +4,7 @@ import java.util.Optional;
import java.util.function.BiFunction;
import org.zwobble.couscous.ast.Operator;
-import org.zwobble.couscous.interpreter.Environment;
-import org.zwobble.couscous.interpreter.NoSuchField;
+import org.zwobble.couscous.interpreter.*;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.ObjectValues;
import org.zwobble.couscous.values.PrimitiveValue;
@@ -29,11 +28,16 @@ public final class IntegerInterpreterValue implements InterpreterValue {
(environment, arguments) -> {
InterpreterValue right = arguments.getPositionalArguments().get(0);
if (right instanceof IntegerInterpreterValue) {
- return new BooleanInterpreterValue(arguments.getReceiver().getValue() == ((IntegerInterpreterValue)right).getValue());
+ return integerEquals(arguments, ((IntegerInterpreterValue)right));
} else {
return new BooleanInterpreterValue(false);
}
})
+ .method(Operator.EQUALS.getMethodName(), asList(IntegerValue.REF),
+ (environment, arguments) -> {
+ IntegerInterpreterValue right = (IntegerInterpreterValue)arguments.getPositionalArguments().get(0);
+ return integerEquals(arguments, right);
+ })
.method(Operator.NOT_EQUALS.getMethodName(), asList(IntegerValue.REF),
infixReturningBoolean((left, right) -> !left.equals(right)))
.method(Operator.GREATER_THAN.getMethodName(), asList(IntegerValue.REF),
@@ -45,7 +49,11 @@ public final class IntegerInterpreterValue implements InterpreterValue {
.method(Operator.LESS_THAN_OR_EQUAL.getMethodName(), asList(IntegerValue.REF),
infixReturningBoolean((left, right) -> left <= right))
.build();
-
+
+ private static BooleanInterpreterValue integerEquals(MethodCallArguments<IntegerInterpreterValue> arguments, IntegerInterpreterValue right) {
+ return new BooleanInterpreterValue(arguments.getReceiver().getValue() == right.getValue());
+ }
+
private static
BiFunction<Environment, MethodCallArguments<IntegerInterpreterValue>, InterpreterValue>
infixReturningInteger(BiFunction<Integer, Integer, Integer> func) {