aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/zwobble/couscous/ast/MethodSignature.java10
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java28
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java16
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java4
-rw-r--r--src/main/java/org/zwobble/couscous/types/Types.java55
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraIterables.java54
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraMaps.java16
8 files changed, 169 insertions, 18 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
index 060d2bc..715dade 100644
--- a/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
+++ b/src/main/java/org/zwobble/couscous/ast/MethodSignature.java
@@ -1,9 +1,12 @@
package org.zwobble.couscous.ast;
import org.zwobble.couscous.types.Type;
+import org.zwobble.couscous.types.Types;
import java.util.List;
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
+
public class MethodSignature {
public static MethodSignature signature(String name, List<Type> arguments, Type returnType) {
return new MethodSignature(name, arguments, returnType);
@@ -31,6 +34,13 @@ public class MethodSignature {
return returnType;
}
+ public MethodSignature generic() {
+ return new MethodSignature(
+ name,
+ eagerMap(arguments, Types::generic),
+ Types.generic(returnType));
+ }
+
@Override
public String toString() {
return "MethodSignature(" +
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index bbc41d1..4c2a8c3 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -52,7 +52,7 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
public InterpreterValue visit(ThisReferenceNode reference) {
InterpreterValue thisValue = environment.getThis().get();
// TODO: add a test for this
- InterpreterTypes.checkIsInstance(reference.getType(), thisValue);
+ //InterpreterTypes.checkIsInstance(reference.getType(), thisValue);
return thisValue;
}
@@ -102,7 +102,7 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
MethodSignature signature = methodCall.signature();
return evalReceiver(methodCall.getReceiver())
- .callMethod(environment, signature, new Arguments(list(), arguments));
+ .callMethod(environment, signature.generic(), new Arguments(list(), arguments));
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java
index 52ec6e1..0d82e6c 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java
@@ -6,27 +6,33 @@ import org.zwobble.couscous.ast.StatementNode;
import org.zwobble.couscous.interpreter.Arguments;
import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.types.ScalarType;
+import org.zwobble.couscous.types.ParameterizedType;
import org.zwobble.couscous.types.Type;
+import org.zwobble.couscous.types.TypeParameter;
+import org.zwobble.couscous.types.Types;
+import org.zwobble.couscous.util.ExtraIterables;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import static org.zwobble.couscous.types.ParameterizedType.parameterizedType;
+import static org.zwobble.couscous.util.ExtraMaps.toMap;
public class ParameterizedInterpreterType implements InterpreterType {
- private final InterpreterType rawType;
+ private final InterpreterType genericType;
private final List<Type> parameters;
- public ParameterizedInterpreterType(InterpreterType rawType, List<Type> parameters) {
- this.rawType = rawType;
+ public ParameterizedInterpreterType(InterpreterType genericType, List<Type> parameters) {
+ this.genericType = genericType;
this.parameters = parameters;
}
@Override
public Type getType() {
- return parameterizedType((ScalarType) rawType.getType(), parameters);
+ return parameterizedType(((ParameterizedType) genericType.getType()).getRawType(), parameters);
}
// TODO: implement the other methods properly.
@@ -36,12 +42,18 @@ public class ParameterizedInterpreterType implements InterpreterType {
@Override
public Set<Type> getSuperTypes() {
- throw new UnsupportedOperationException();
+ Map<TypeParameter, Type> replacements = toMap(
+ ExtraIterables.cast(TypeParameter.class, ((ParameterizedType) genericType.getType()).getParameters()),
+ parameters);
+ return genericType.getSuperTypes()
+ .stream()
+ .map(type -> Types.substitute(type, replacements))
+ .collect(Collectors.toSet());
}
@Override
public Optional<FieldDeclarationNode> getField(String fieldName) {
- throw new UnsupportedOperationException();
+ return genericType.getField(fieldName);
}
@Override
@@ -56,7 +68,7 @@ public class ParameterizedInterpreterType implements InterpreterType {
@Override
public InterpreterValue callMethod(Environment environment, InterpreterValue value, MethodSignature signature, Arguments arguments) {
- throw new UnsupportedOperationException();
+ return genericType.callMethod(environment, value, signature.generic(), arguments);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
index 3b056f1..c26fb32 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
@@ -1,15 +1,15 @@
package org.zwobble.couscous.interpreter.types;
import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.interpreter.Arguments;
import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.Executor;
import org.zwobble.couscous.interpreter.InterpreterTypes;
-import org.zwobble.couscous.interpreter.Arguments;
import org.zwobble.couscous.interpreter.errors.NoSuchMethod;
import org.zwobble.couscous.interpreter.errors.WrongNumberOfArguments;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
-import org.zwobble.couscous.types.ScalarType;
import org.zwobble.couscous.types.Type;
+import org.zwobble.couscous.types.TypeParameter;
import java.util.List;
import java.util.Map;
@@ -17,6 +17,7 @@ import java.util.Optional;
import java.util.Set;
import static com.google.common.collect.Iterables.filter;
+import static org.zwobble.couscous.types.ParameterizedType.parameterizedType;
import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
import static org.zwobble.couscous.util.ExtraLists.list;
@@ -35,12 +36,17 @@ public class UserDefinedInterpreterType implements InterpreterType {
.orElse(map());
this.methods = toMapWithKeys(
filter(type.getMethods(), method -> !method.isAbstract()),
- method -> method.signature());
+ method -> method.signature().generic());
}
@Override
- public ScalarType getType() {
- return type.getName();
+ public Type getType() {
+ List<Type> parameters = eagerMap(
+ type.getTypeParameters(),
+ parameter -> new TypeParameter(type.getName(), parameter.getName()));
+ return parameters.isEmpty()
+ ? type.getName()
+ : parameterizedType(type.getName(), parameters);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
index 50ed24f..b0b7992 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
@@ -1,7 +1,6 @@
package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.FieldDeclarationNode;
-import org.zwobble.couscous.interpreter.InterpreterTypes;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
import org.zwobble.couscous.interpreter.errors.UnboundField;
import org.zwobble.couscous.interpreter.types.InterpreterType;
@@ -39,7 +38,8 @@ public class InterpreterFields {
public void setField(String fieldName, InterpreterValue value) {
FieldDeclarationNode field = getFieldDefinition(fieldName);
- InterpreterTypes.checkIsInstance(field.getType(), value);
+ // TODO: re-enable this
+ //InterpreterTypes.checkIsInstance(field.getType(), value);
fields.put(fieldName, value);
}
diff --git a/src/main/java/org/zwobble/couscous/types/Types.java b/src/main/java/org/zwobble/couscous/types/Types.java
index 02f7672..89e88a6 100644
--- a/src/main/java/org/zwobble/couscous/types/Types.java
+++ b/src/main/java/org/zwobble/couscous/types/Types.java
@@ -1,5 +1,8 @@
package org.zwobble.couscous.types;
+import java.util.Map;
+
+import static org.zwobble.couscous.util.ExtraLists.eagerMap;
import static org.zwobble.couscous.util.ExtraLists.list;
public class Types {
@@ -40,4 +43,56 @@ public class Types {
}
});
}
+
+ public static Type substitute(Type type, Map<TypeParameter, Type> replacements) {
+ return type.accept(new Type.Visitor<Type>() {
+ @Override
+ public Type visit(ScalarType type) {
+ return type;
+ }
+
+ @Override
+ public Type visit(TypeParameter type) {
+ return replacements.getOrDefault(type, type);
+ }
+
+ @Override
+ public Type visit(ParameterizedType type) {
+ return new ParameterizedType(
+ type.getRawType(),
+ eagerMap(type.getParameters(), parameter -> parameter.accept(this)));
+ }
+
+ @Override
+ public Type visit(BoundTypeParameter type) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ }
+
+ public static Type generic(Type type) {
+ return type.accept(new Type.Visitor<Type>() {
+ @Override
+ public Type visit(ScalarType type) {
+ return type;
+ }
+
+ @Override
+ public Type visit(TypeParameter parameter) {
+ return parameter;
+ }
+
+ @Override
+ public Type visit(ParameterizedType type) {
+ return new ParameterizedType(
+ type.getRawType(),
+ eagerMap(type.getParameters(), parameter -> parameter.accept(this)));
+ }
+
+ @Override
+ public Type visit(BoundTypeParameter type) {
+ return type.getParameter();
+ }
+ });
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraIterables.java b/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
index 9cdb0f0..1fd9fca 100644
--- a/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
+++ b/src/main/java/org/zwobble/couscous/util/ExtraIterables.java
@@ -1,6 +1,7 @@
package org.zwobble.couscous.util;
import java.util.Iterator;
+import java.util.function.BiFunction;
public class ExtraIterables {
private ExtraIterables() {}
@@ -15,4 +16,57 @@ public class ExtraIterables {
throw new RuntimeException("Iterables not of same length");
}
}
+
+ public static <T1, T2, R> Iterable<R> map(Iterable<T1> iterable1, Iterable<T2> iterable2, BiFunction<T1, T2, R> function) {
+ return new Iterable<R>() {
+ @Override
+ public Iterator<R> iterator() {
+ Iterator<T1> iterator1 = iterable1.iterator();
+ Iterator<T2> iterator2 = iterable2.iterator();
+ return map(iterator1, iterator2, function);
+ }
+ };
+ }
+
+ private static <R, T1, T2> Iterator<R> map(Iterator<T1> iterator1, Iterator<T2> iterator2, BiFunction<T1, T2, R> function) {
+ return new Iterator<R>() {
+ @Override
+ public boolean hasNext() {
+ return iterator1.hasNext() && iterator2.hasNext();
+ }
+
+ @Override
+ public R next() {
+ return function.apply(iterator1.next(), iterator2.next());
+ }
+ };
+ }
+
+ public static <T> Iterable<T> cast(Class<T> type, Iterable<?> iterable) {
+ return new Iterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return cast(type, iterable.iterator());
+ }
+ };
+ }
+
+ private static <T> Iterator<T> cast(Class<T> type, Iterator<?> iterator) {
+ return new Iterator<T>() {
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public T next() {
+ Object next = iterator.next();
+ if (type.isInstance(next)) {
+ return (T) next;
+ } else {
+ throw new ClassCastException();
+ }
+ }
+ };
+ }
}
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraMaps.java b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
index 55829cf..f25f06f 100644
--- a/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
+++ b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
@@ -28,6 +28,16 @@ public class ExtraMaps {
return Optional.ofNullable(map.get(key));
}
+ public static <T, K, V> Map<K, V> toMap(Iterable<K> keys, Iterable<V> values) {
+ return toMap(ExtraIterables.map(keys, values, ExtraMaps::entry));
+ }
+
+ public static <T, K, V> Map<K, V> toMap(Iterable<Map.Entry<K, V>> entries) {
+ ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
+ entries.forEach(builder::put);
+ return builder.build();
+ }
+
public static <T, K, V> Map<K, V> toMap(Iterable<T> iterable, Function<T, Map.Entry<K, V>> function) {
ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
@@ -39,6 +49,10 @@ public class ExtraMaps {
}
public static <T, K> Map<K, T> toMapWithKeys(Iterable<T> iterable, Function<T, K> function) {
- return toMap(iterable, value -> new AbstractMap.SimpleImmutableEntry<K, T>(function.apply(value), value));
+ return toMap(iterable, value -> entry(function.apply(value), value));
+ }
+
+ public static <K, V> Map.Entry<K, V> entry(K key, V value) {
+ return new AbstractMap.SimpleImmutableEntry<>(key, value);
}
}