aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Executor.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java6
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/JavaProject.java14
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/MapBackedProject.java23
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Project.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java22
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java (renamed from src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java)162
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java97
-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.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java3
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java6
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java4
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java12
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java7
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java7
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java5
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java6
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java7
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java9
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraMaps.java5
-rw-r--r--src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java18
22 files changed, 244 insertions, 187 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Executor.java b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
index d85013e..75ace0a 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Executor.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Executor.java
@@ -29,10 +29,10 @@ public class Executor implements StatementNodeMapper<Optional<InterpreterValue>>
public static InterpreterValue callConstructor(
Environment environment,
ConstructorNode constructor,
- Optional<InterpreterValue> thisValue,
+ InterpreterValue thisValue,
PositionalArguments actualArguments)
{
- return callMethod(environment, constructor.getArguments(), constructor.getBody(), thisValue, actualArguments);
+ return callMethod(environment, constructor.getArguments(), constructor.getBody(), Optional.of(thisValue), actualArguments);
}
private static InterpreterValue callMethod(
diff --git a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java
index b43e926..b9221de 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java
@@ -2,7 +2,7 @@ package org.zwobble.couscous.interpreter;
import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.interpreter.errors.UnexpectedValueType;
-import org.zwobble.couscous.interpreter.values.ConcreteType;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
import org.zwobble.couscous.interpreter.values.InterpreterValue;
import org.zwobble.couscous.values.ObjectValues;
@@ -11,13 +11,13 @@ public class InterpreterTypes {
checkIsSubType(type, value.getType());
}
- private static void checkIsSubType(TypeName superTypeName, ConcreteType subType) {
+ private static void checkIsSubType(TypeName superTypeName, InterpreterType subType) {
if (!isSubType(superTypeName, subType)) {
throw new UnexpectedValueType(superTypeName, subType.getName());
}
}
- public static boolean isSubType(TypeName superTypeName, ConcreteType subType) {
+ public static boolean isSubType(TypeName superTypeName, InterpreterType subType) {
return
superTypeName.equals(subType.getName()) ||
superTypeName.equals(ObjectValues.OBJECT) ||
diff --git a/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java b/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
index 8038ce1..f96f0c4 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/JavaProject.java
@@ -1,17 +1,17 @@
package org.zwobble.couscous.interpreter;
-import java.util.List;
-
-import org.zwobble.couscous.ast.ClassNode;
+import com.google.common.collect.Iterables;
import org.zwobble.couscous.ast.TypeNode;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
+import org.zwobble.couscous.interpreter.types.UserDefinedInterpreterType;
import org.zwobble.couscous.interpreter.values.BoxedIntegerInterpreterValue;
-import org.zwobble.couscous.interpreter.values.ConcreteType;
import org.zwobble.couscous.interpreter.values.InternalCouscousInterpreterValue;
-import com.google.common.collect.Iterables;
+import java.util.List;
public class JavaProject {
- private static final ConcreteType OBJECT_TYPE = ConcreteType.classBuilder("java.lang.Object")
+ private static final InterpreterType OBJECT_TYPE = IntrinsicInterpreterType.classBuilder("java.lang.Object")
.build();
public static MapBackedProject.Builder builder() {
@@ -22,7 +22,7 @@ public class JavaProject {
}
public static Project of(List<TypeNode> classNodes) {
- Iterable<ConcreteType> concreteTypes = Iterables.transform(classNodes, ConcreteType::fromNode);
+ Iterable<InterpreterType> concreteTypes = Iterables.transform(classNodes, UserDefinedInterpreterType::new);
return builder()
.addClasses(concreteTypes)
.build();
diff --git a/src/main/java/org/zwobble/couscous/interpreter/MapBackedProject.java b/src/main/java/org/zwobble/couscous/interpreter/MapBackedProject.java
index 7f16b8f..eca6ba9 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/MapBackedProject.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/MapBackedProject.java
@@ -1,30 +1,30 @@
package org.zwobble.couscous.interpreter;
-import java.util.Map;
-import org.zwobble.couscous.ast.TypeName;
-import org.zwobble.couscous.interpreter.values.ConcreteType;
import com.google.common.collect.ImmutableMap;
+import org.zwobble.couscous.ast.TypeName;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+
+import java.util.Map;
public class MapBackedProject implements Project {
-
public static Builder builder() {
return new Builder();
}
public static class Builder {
- private final ImmutableMap.Builder<TypeName, ConcreteType> classes;
+ private final ImmutableMap.Builder<TypeName, InterpreterType> classes;
private Builder() {
classes = ImmutableMap.builder();
}
- public Builder addClass(ConcreteType clazz) {
+ public Builder addClass(InterpreterType clazz) {
classes.put(clazz.getName(), clazz);
return this;
}
- public Builder addClasses(Iterable<ConcreteType> classes) {
- for (ConcreteType clazz : classes) {
+ public Builder addClasses(Iterable<InterpreterType> classes) {
+ for (InterpreterType clazz : classes) {
addClass(clazz);
}
return this;
@@ -34,14 +34,15 @@ public class MapBackedProject implements Project {
return new MapBackedProject(classes.build());
}
}
- private Map<TypeName, ConcreteType> classes;
+
+ private Map<TypeName, InterpreterType> classes;
- public MapBackedProject(Map<TypeName, ConcreteType> classes) {
+ public MapBackedProject(Map<TypeName, InterpreterType> classes) {
this.classes = classes;
}
@Override
- public ConcreteType findClass(TypeName name) {
+ public InterpreterType findClass(TypeName name) {
if (classes.containsKey(name)) {
return classes.get(name);
} else {
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Project.java b/src/main/java/org/zwobble/couscous/interpreter/Project.java
index 287ac9c..7e749b4 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Project.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Project.java
@@ -1,8 +1,8 @@
package org.zwobble.couscous.interpreter;
import org.zwobble.couscous.ast.TypeName;
-import org.zwobble.couscous.interpreter.values.ConcreteType;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
public interface Project {
- ConcreteType findClass(TypeName name);
+ InterpreterType findClass(TypeName name);
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java
new file mode 100644
index 0000000..f5316ae
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java
@@ -0,0 +1,22 @@
+package org.zwobble.couscous.interpreter.types;
+
+import org.zwobble.couscous.ast.FieldDeclarationNode;
+import org.zwobble.couscous.ast.MethodSignature;
+import org.zwobble.couscous.ast.StatementNode;
+import org.zwobble.couscous.ast.TypeName;
+import org.zwobble.couscous.interpreter.Environment;
+import org.zwobble.couscous.interpreter.values.InterpreterValue;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+public interface InterpreterType {
+ TypeName getName();
+ Set<TypeName> getSuperTypes();
+ Optional<FieldDeclarationNode> getField(String fieldName);
+ List<StatementNode> getStaticConstructor();
+ InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments);
+ InterpreterValue callMethod(Environment environment, InterpreterValue value, MethodSignature signature, List<InterpreterValue> arguments);
+ InterpreterValue callStaticMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments);
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java
index ed01d59..5fda40c 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java
@@ -1,34 +1,35 @@
-package org.zwobble.couscous.interpreter.values;
+package org.zwobble.couscous.interpreter.types;
import com.google.common.collect.ImmutableMap;
-import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.FieldDeclarationNode;
+import org.zwobble.couscous.ast.MethodSignature;
+import org.zwobble.couscous.ast.StatementNode;
+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.PositionalArguments;
import org.zwobble.couscous.interpreter.errors.NoSuchMethod;
-import org.zwobble.couscous.interpreter.errors.WrongNumberOfArguments;
+import org.zwobble.couscous.interpreter.values.*;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import java.util.function.BiFunction;
-import java.util.stream.Collectors;
-import static java.util.stream.Collectors.toMap;
import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraLists.list;
-import static org.zwobble.couscous.util.ExtraMaps.map;
import static org.zwobble.couscous.util.ExtraSets.set;
-public class ConcreteType {
- public static <T> ConcreteType.Builder<T> builder(Class<T> interpreterValueType, TypeName reference) {
+public class IntrinsicInterpreterType implements InterpreterType {
+ public static <T> Builder<T> builder(Class<T> interpreterValueType, TypeName reference) {
return new Builder<>(interpreterValueType, reference);
}
-
- public static <T> ConcreteType.Builder<T> builder(Class<T> interpreterValueType, String name) {
+
+ public static <T> Builder<T> builder(Class<T> interpreterValueType, String name) {
return builder(interpreterValueType, TypeName.of(name));
}
-
- public static ConcreteType.Builder<ObjectInterpreterValue> classBuilder(String name) {
+
+ public static Builder<ObjectInterpreterValue> classBuilder(String name) {
return builder(ObjectInterpreterValue.class, name);
}
@@ -39,7 +40,7 @@ public class ConcreteType {
private final ImmutableMap.Builder<MethodSignature, StaticMethodValue> staticMethods = ImmutableMap.builder();
private final Class<T> interpreterValueType;
private final TypeName name;
-
+
public Builder(Class<T> interpreterValueType, TypeName name) {
this.interpreterValueType = interpreterValueType;
this.name = name;
@@ -83,158 +84,85 @@ public class ConcreteType {
staticMethods.put(new MethodSignature(name, argumentsTypes, returnType), new StaticMethodValue(argumentsTypes, method));
return this;
}
-
- public ConcreteType build() {
- return new ConcreteType(
+
+ public InterpreterType build() {
+ return new IntrinsicInterpreterType(
name,
- Collections.emptySet(),
fields.build(),
- list(),
constructor,
methods.build(),
staticMethods.build());
}
}
-
- public static ConcreteType fromNode(TypeNode typeNode) {
- return tryCast(ClassNode.class, typeNode)
- .map(ConcreteType::fromNode)
- // TODO: tidy this up -- type hierarchy instead of one ConcreteType?
- .orElseGet(() -> new ConcreteType(
- typeNode.getName(),
- set(),
- map(),
- list(),
- null,
- map(),
- map()));
- }
-
- private static ConcreteType fromNode(ClassNode classNode) {
- Map<String, FieldDeclarationNode> fields = classNode.getFields().stream()
- .collect(toMap(
- field -> field.getName(),
- field -> field));
- MethodValue constructor = new MethodValue(
- getArgumentTypes(classNode.getConstructor().getArguments()),
- (environment, arguments) -> Executor.callConstructor(
- environment,
- classNode.getConstructor(),
- Optional.of(arguments.getReceiver()),
- arguments.getPositionalArguments()));
-
- Map<MethodSignature, MethodValue> methods = classNode.getMethods()
- .stream()
- .filter(method -> !method.isStatic())
- .collect(toMap(method -> method.signature(), 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<MethodSignature, StaticMethodValue> staticMethods = classNode.getMethods()
- .stream()
- .filter(method -> method.isStatic())
- .collect(toMap(method -> method.signature(), method -> {
- List<TypeName> argumentTypes = getArgumentTypes(method.getArguments());
- return new StaticMethodValue(argumentTypes, (environment, arguments) -> {
- return Executor.callMethod(environment, method, Optional.empty(), arguments);
- });
- }));
- return new ConcreteType(
- classNode.getName(),
- classNode.getSuperTypes(),
- fields,
- classNode.getStaticConstructor(),
- constructor,
- methods,
- staticMethods);
- }
- private static List<TypeName> getArgumentTypes(List<FormalArgumentNode> arguments) {
- return arguments.stream().map(arg -> arg.getType()).collect(Collectors.toList());
- }
private final TypeName name;
- private final Set<TypeName> superTypes;
private final Map<String, FieldDeclarationNode> fields;
- private final List<StatementNode> staticConstructor;
private final MethodValue constructor;
private final Map<MethodSignature, MethodValue> methods;
private final Map<MethodSignature, StaticMethodValue> staticMethods;
-
- private ConcreteType(
+
+ private IntrinsicInterpreterType(
TypeName name,
- Set<TypeName> superTypes,
Map<String, FieldDeclarationNode> fields,
- List<StatementNode> staticConstructor,
MethodValue constructor,
Map<MethodSignature, MethodValue> methods,
Map<MethodSignature, StaticMethodValue> staticMethods)
{
this.name = name;
- this.superTypes = superTypes;
this.fields = fields;
- this.staticConstructor = staticConstructor;
this.constructor = constructor;
this.methods = methods;
this.staticMethods = staticMethods;
}
-
+
+ @Override
public TypeName getName() {
return name;
}
+ @Override
public Set<TypeName> getSuperTypes() {
- return superTypes;
+ return set();
}
- public Optional<FieldDeclarationNode> getField(boolean isStatic, String fieldName) {
- return Optional.ofNullable(fields.get(fieldName))
- .filter(field -> field.isStatic() == isStatic);
+ @Override
+ public Optional<FieldDeclarationNode> getField(String fieldName) {
+ return Optional.ofNullable(fields.get(fieldName));
}
+ @Override
public List<StatementNode> getStaticConstructor() {
- return staticConstructor;
+ return list();
}
+ @Override
public InterpreterValue callMethod(Environment environment, InterpreterValue receiver, MethodSignature signature, List<InterpreterValue> arguments) {
- MethodValue method = findMethod(methods, signature, arguments);
+ MethodValue method = findMethod(methods, signature);
return method.apply(environment, MethodCallArguments.of(receiver, new PositionalArguments(arguments)));
}
-
+
+ @Override
public InterpreterValue callStaticMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) {
- StaticMethodValue method = findMethod(staticMethods, signature, arguments);
+ StaticMethodValue method = findMethod(staticMethods, signature);
return method.apply(environment, new PositionalArguments(arguments));
}
-
+
+ @Override
public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) {
- final org.zwobble.couscous.interpreter.values.ObjectInterpreterValue object = new ObjectInterpreterValue(this);
- checkMethodArguments(constructor, arguments);
+ ObjectInterpreterValue object = new ObjectInterpreterValue(this);
constructor.apply(environment, MethodCallArguments.of(object, new PositionalArguments(arguments)));
return object;
}
-
- private static <T extends Callable> T findMethod(Map<MethodSignature, T> methods, MethodSignature signature, List<InterpreterValue> arguments) {
+
+ private static <T extends Callable> T findMethod(Map<MethodSignature, T> methods, MethodSignature signature) {
if (!methods.containsKey(signature)) {
throw new NoSuchMethod(signature);
}
- final T method = methods.get(signature);
- checkMethodArguments(method, arguments);
- return method;
- }
-
- private static void checkMethodArguments(final Callable method, List<InterpreterValue> arguments) {
- if (method.getArgumentTypes().size() != arguments.size()) {
- throw new WrongNumberOfArguments(method.getArgumentTypes().size(), arguments.size());
- }
- for (int index = 0; index < arguments.size(); index++) {
- final org.zwobble.couscous.ast.TypeName formalArgumentType = method.getArgumentTypes().get(index);
- InterpreterTypes.checkIsInstance(formalArgumentType, arguments.get(index));
- }
+ return methods.get(signature);
}
-
+
@Override
public String toString() {
- return "ConcreteType<" + name + ">";
+ return "IntrinsicInterpreterType<" + name + ">";
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
new file mode 100644
index 0000000..a058cc3
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java
@@ -0,0 +1,97 @@
+package org.zwobble.couscous.interpreter.types;
+
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.interpreter.Environment;
+import org.zwobble.couscous.interpreter.Executor;
+import org.zwobble.couscous.interpreter.PositionalArguments;
+import org.zwobble.couscous.interpreter.errors.NoSuchMethod;
+import org.zwobble.couscous.interpreter.values.InterpreterValue;
+import org.zwobble.couscous.interpreter.values.ObjectInterpreterValue;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.collect.Iterables.filter;
+import static org.zwobble.couscous.util.Casts.tryCast;
+import static org.zwobble.couscous.util.ExtraLists.list;
+import static org.zwobble.couscous.util.ExtraMaps.map;
+import static org.zwobble.couscous.util.ExtraMaps.toMapWithKeys;
+
+public class UserDefinedInterpreterType implements InterpreterType {
+ private final TypeNode type;
+ private final Map<String, FieldDeclarationNode> fields;
+ private final Map<MethodSignature, MethodNode> methods;
+
+ public UserDefinedInterpreterType(TypeNode type) {
+ this.type = type;
+ this.fields = tryCast(ClassNode.class, type)
+ .map(classNode -> toMapWithKeys(classNode.getFields(), field -> field.getName()))
+ .orElse(map());
+ this.methods = toMapWithKeys(
+ filter(type.getMethods(), method -> !method.isAbstract()),
+ method -> method.signature());
+ }
+
+ @Override
+ public TypeName getName() {
+ return type.getName();
+ }
+
+ @Override
+ public Set<TypeName> getSuperTypes() {
+ return type.getSuperTypes();
+ }
+
+ @Override
+ public Optional<FieldDeclarationNode> getField(String fieldName) {
+ return Optional.ofNullable(fields.get(fieldName));
+ }
+
+ @Override
+ public List<StatementNode> getStaticConstructor() {
+ return tryCast(ClassNode.class, type)
+ .map(node -> node.getStaticConstructor())
+ .orElse(list());
+ }
+
+ @Override
+ public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) {
+ ConstructorNode constructor = tryCast(ClassNode.class, type)
+ // TODO: add test for this case
+ .orElseThrow(() -> new RuntimeException("Cannot instantiate non-class types"))
+ .getConstructor();
+ InterpreterValue object = new ObjectInterpreterValue(this);
+ Executor.callConstructor(
+ environment,
+ constructor,
+ object,
+ new PositionalArguments(arguments));
+ return object;
+ }
+
+ @Override
+ public InterpreterValue callMethod(Environment environment, InterpreterValue value, MethodSignature signature, List<InterpreterValue> arguments) {
+ return Executor.callMethod(
+ environment,
+ findMethod(signature, false),
+ Optional.of(value),
+ new PositionalArguments(arguments));
+ }
+
+ @Override
+ public InterpreterValue callStaticMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) {
+ return Executor.callMethod(
+ environment,
+ findMethod(signature, true),
+ Optional.empty(),
+ new PositionalArguments(arguments));
+ }
+
+ private MethodNode findMethod(MethodSignature signature, boolean isStatic) {
+ return Optional.ofNullable(methods.get(signature))
+ .filter(method -> method.isStatic() == isStatic)
+ .orElseThrow(() -> new NoSuchMethod(signature));
+ }
+}
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 2ac6e3a..a183206 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/BooleanInterpreterValue.java
@@ -2,6 +2,8 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.Operator;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
@@ -18,7 +20,7 @@ public final class BooleanInterpreterValue implements InterpreterValue {
return value ? TRUE : FALSE;
}
- private static final ConcreteType TYPE = ConcreteType.builder(BooleanInterpreterValue.class, "boolean")
+ private static final InterpreterType TYPE = IntrinsicInterpreterType.builder(BooleanInterpreterValue.class, "boolean")
.method(Operator.BOOLEAN_NOT.getSymbol(), list(), BooleanValue.REF, (environment, arguments) ->
of(!arguments.getReceiver().getValue()))
@@ -46,7 +48,7 @@ public final class BooleanInterpreterValue implements InterpreterValue {
}
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return TYPE;
}
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 951d57d..5c477af 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,7 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.ObjectValues;
@@ -18,7 +20,7 @@ public class BoxedIntegerInterpreterValue {
return obj;
}
- public static final ConcreteType TYPE = ConcreteType.classBuilder("java.lang.Integer")
+ public static final InterpreterType TYPE = IntrinsicInterpreterType.classBuilder("java.lang.Integer")
.field("value", IntegerValue.REF)
.staticMethod("parseInt", list(StringValue.REF), IntegerValue.REF,
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java
index 8179394..cdc2167 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java
@@ -2,6 +2,7 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.MethodSignature;
import org.zwobble.couscous.interpreter.Environment;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
import java.util.List;
@@ -14,7 +15,7 @@ public class InstanceReceiverValue implements ReceiverValue {
@Override
public InterpreterValue callMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) {
- ConcreteType type = value.getType();
+ InterpreterType type = value.getType();
return type.callMethod(environment, value, signature, arguments);
}
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 78da460..f0ce783 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,8 @@ 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.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.BooleanValue;
import org.zwobble.couscous.values.IntegerValue;
import org.zwobble.couscous.values.PrimitiveValue;
@@ -14,7 +16,7 @@ import java.util.function.BiFunction;
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)
+ public static final InterpreterType TYPE = IntrinsicInterpreterType.builder(IntegerInterpreterValue.class, IntegerValue.REF)
.method(Operator.ADD.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
infixReturningInteger((left, right) -> left + right))
.method(Operator.SUBTRACT.getSymbol(), list(IntegerValue.REF), IntegerValue.REF,
@@ -71,7 +73,7 @@ public final class IntegerInterpreterValue implements InterpreterValue {
private final int value;
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return TYPE;
}
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 e39f576..faab2a8 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,14 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
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")
+ public static final InterpreterType TYPE = IntrinsicInterpreterType.classBuilder("_couscous")
.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/InterpreterFields.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
index 1661ee7..50ed24f 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java
@@ -4,24 +4,25 @@ 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;
import java.util.HashMap;
import java.util.Map;
public class InterpreterFields {
- public static InterpreterFields forClass(ConcreteType type) {
+ public static InterpreterFields forClass(InterpreterType type) {
return new InterpreterFields(true, type);
}
- public static InterpreterFields forInstanceOf(ConcreteType type) {
+ public static InterpreterFields forInstanceOf(InterpreterType type) {
return new InterpreterFields(false, type);
}
private final boolean isStatic;
- private final ConcreteType type;
+ private final InterpreterType type;
private final Map<String, InterpreterValue> fields;
- private InterpreterFields(boolean isStatic, ConcreteType type) {
+ private InterpreterFields(boolean isStatic, InterpreterType type) {
this.isStatic = isStatic;
this.type = type;
this.fields = new HashMap<>();
@@ -43,7 +44,8 @@ public class InterpreterFields {
}
private FieldDeclarationNode getFieldDefinition(String fieldName) {
- return type.getField(isStatic, fieldName)
+ return type.getField(fieldName)
+ .filter(field -> field.isStatic() == isStatic)
.orElseThrow(() -> new NoSuchField(fieldName));
}
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
index e02387b..831ba2c 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java
@@ -1,11 +1,12 @@
package org.zwobble.couscous.interpreter.values;
-import java.util.Optional;
-
+import org.zwobble.couscous.interpreter.types.InterpreterType;
import org.zwobble.couscous.values.PrimitiveValue;
+import java.util.Optional;
+
public interface InterpreterValue {
- ConcreteType getType();
+ InterpreterType getType();
Optional<PrimitiveValue> toPrimitiveValue();
InterpreterValue getField(String fieldName);
void setField(String fieldName, InterpreterValue value);
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
index e15c01d..aadf44b 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java
@@ -1,20 +1,21 @@
package org.zwobble.couscous.interpreter.values;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
import org.zwobble.couscous.values.PrimitiveValue;
import java.util.Optional;
public class ObjectInterpreterValue implements InterpreterValue {
- private final ConcreteType type;
+ private final InterpreterType type;
private final InterpreterFields fields;
- public ObjectInterpreterValue(ConcreteType type) {
+ public ObjectInterpreterValue(InterpreterType type) {
this.type = type;
this.fields = InterpreterFields.forInstanceOf(type);
}
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return type;
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
index 2595623..cf2c9b7 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java
@@ -3,14 +3,15 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.MethodSignature;
import org.zwobble.couscous.interpreter.Environment;
import org.zwobble.couscous.interpreter.Executor;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
import java.util.List;
public class StaticReceiverValue implements ReceiverValue {
- private final ConcreteType type;
+ private final InterpreterType type;
private final InterpreterFields fields;
- public StaticReceiverValue(ConcreteType type) {
+ public StaticReceiverValue(InterpreterType type) {
this.type = type;
this.fields = InterpreterFields.forClass(type);
}
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 ae7d141..2fe72d7 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/StringInterpreterValue.java
@@ -2,6 +2,8 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.Operator;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.*;
import java.util.Optional;
@@ -9,7 +11,7 @@ import java.util.Optional;
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)
+ public static final InterpreterType TYPE = IntrinsicInterpreterType.builder(StringInterpreterValue.class, StringValue.REF)
.method("length", list(), IntegerValue.REF, (environment, arguments) ->
new IntegerInterpreterValue(arguments.getReceiver().value.length()))
@@ -49,7 +51,7 @@ public final class StringInterpreterValue implements InterpreterValue {
}
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return TYPE;
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java
index 5938ce3..f221ea0 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/TypeInterpreterValue.java
@@ -2,6 +2,8 @@ package org.zwobble.couscous.interpreter.values;
import org.zwobble.couscous.ast.TypeName;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.ObjectValues;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
@@ -9,7 +11,8 @@ import org.zwobble.couscous.values.PrimitiveValues;
import java.util.Optional;
public class TypeInterpreterValue implements InterpreterValue {
- public static final ConcreteType TYPE = ConcreteType.builder(TypeInterpreterValue.class, ObjectValues.CLASS)
+ public static final InterpreterType TYPE = IntrinsicInterpreterType
+ .builder(TypeInterpreterValue.class, ObjectValues.CLASS)
.build();
public static InterpreterValue of(TypeName type) {
@@ -23,7 +26,7 @@ public class TypeInterpreterValue implements InterpreterValue {
}
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return TYPE;
}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java
index 54f5605..59792c6 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java
@@ -1,19 +1,22 @@
package org.zwobble.couscous.interpreter.values;
-import java.util.Optional;
import org.zwobble.couscous.interpreter.errors.NoSuchField;
+import org.zwobble.couscous.interpreter.types.InterpreterType;
+import org.zwobble.couscous.interpreter.types.IntrinsicInterpreterType;
import org.zwobble.couscous.values.PrimitiveValue;
import org.zwobble.couscous.values.PrimitiveValues;
+import java.util.Optional;
+
public class UnitInterpreterValue implements InterpreterValue {
- private static final ConcreteType TYPE = ConcreteType.builder(UnitInterpreterValue.class, "Unit").build();
+ private static final InterpreterType TYPE = IntrinsicInterpreterType.builder(UnitInterpreterValue.class, "Unit").build();
public static final UnitInterpreterValue UNIT = new UnitInterpreterValue();
private UnitInterpreterValue() {
}
@Override
- public ConcreteType getType() {
+ public InterpreterType getType() {
return TYPE;
}
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraMaps.java b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
index e5d21e9..09339e6 100644
--- a/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
+++ b/src/main/java/org/zwobble/couscous/util/ExtraMaps.java
@@ -2,6 +2,7 @@ package org.zwobble.couscous.util;
import com.google.common.collect.ImmutableMap;
+import java.util.AbstractMap;
import java.util.Map;
import java.util.function.Function;
@@ -31,4 +32,8 @@ public class ExtraMaps {
return builder.build();
}
+
+ 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));
+ }
}
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 fde8646..33d5347 100644
--- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java
@@ -96,24 +96,6 @@ public class EvaluatorTests extends BackendEvalTests {
}
@Test
- public void errorIfConstructorArgumentIsWrongType() {
- FormalArgumentNode argument = formalArg(var(ANY_ID, "x", IntegerValue.REF));
- ClassNode classNode = ClassNode.builder("com.example.Example")
- .constructor(constructor -> constructor
- .argument(argument))
- .build();
-
- UnexpectedValueType exception = assertThrows(UnexpectedValueType.class,
- () -> evalExpression(
- list(classNode),
- constructorCall(
- classNode.getName(),
- list(literal("")))));
-
- assertEquals(new UnexpectedValueType(IntegerValue.REF, StringValue.REF), exception);
- }
-
- @Test
public void cannotGetValueOfUndeclaredField() {
ClassNode classNode = ClassNode.builder("com.example.Example")
.build();