diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-03-31 19:50:44 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-03-31 19:50:44 +0100 |
| commit | 73fd96aa67f29e2cce3ac5d0042a4446c08eb034 (patch) | |
| tree | 78dddaa11bcb9f61b2fb2b49d74b4f4e49d75b76 /src/main/java/org/zwobble | |
| parent | d4c5596cc4c20d884e33d0eb0faab87505483e46 (diff) | |
Create parameterised types with correct interpreter type
Diffstat (limited to 'src/main/java/org/zwobble')
6 files changed, 93 insertions, 16 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java index 8c3d355..64f28ad 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java @@ -6,13 +6,17 @@ import org.zwobble.couscous.ast.visitors.ExpressionNodeMapper; import org.zwobble.couscous.interpreter.errors.ConditionMustBeBoolean; import org.zwobble.couscous.interpreter.errors.InvalidCast; import org.zwobble.couscous.interpreter.values.*; +import org.zwobble.couscous.types.ParameterizedType; import org.zwobble.couscous.types.ScalarType; +import org.zwobble.couscous.types.Type; import org.zwobble.couscous.types.Types; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static org.zwobble.couscous.types.Types.erasure; +import static org.zwobble.couscous.util.Casts.tryCast; import static org.zwobble.couscous.util.ExtraLists.eagerMap; public class Evaluator implements ExpressionNodeMapper<InterpreterValue> { @@ -105,7 +109,9 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> { public InterpreterValue visit(ConstructorCallNode call) { StaticReceiverValue clazz = environment.findClass(erasure(call.getType())); List<InterpreterValue> arguments = evalArguments(call.getArguments()); - return clazz.callConstructor(environment, arguments); + Optional<List<Type>> typeParameters = tryCast(ParameterizedType.class, call.getType()) + .map(type -> type.getParameters()); + return clazz.callConstructor(environment, typeParameters, arguments); } @Override diff --git a/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java index 8c5bdb9..7ffe5d5 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/types/InterpreterType.java @@ -16,7 +16,7 @@ public interface InterpreterType { Set<Type> getSuperTypes(); Optional<FieldDeclarationNode> getField(String fieldName); List<StatementNode> getStaticConstructor(); - InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments); + void callConstructor(Environment environment, InterpreterValue thisValue, 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/types/IntrinsicInterpreterType.java b/src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java index 190908b..29b4fe1 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/types/IntrinsicInterpreterType.java @@ -156,10 +156,8 @@ public class IntrinsicInterpreterType implements InterpreterType { } @Override - public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) { - ObjectInterpreterValue object = new ObjectInterpreterValue(this); - constructor.apply(environment, MethodCallArguments.of(object, new PositionalArguments(arguments))); - return object; + public void callConstructor(Environment environment, InterpreterValue thisValue, List<InterpreterValue> arguments) { + constructor.apply(environment, MethodCallArguments.of(thisValue, new PositionalArguments(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 new file mode 100644 index 0000000..f890fb1 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/interpreter/types/ParameterizedInterpreterType.java @@ -0,0 +1,65 @@ +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.interpreter.Environment; +import org.zwobble.couscous.interpreter.values.InterpreterValue; +import org.zwobble.couscous.types.ScalarType; +import org.zwobble.couscous.types.Type; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static org.zwobble.couscous.types.ParameterizedType.parameterizedType; + +public class ParameterizedInterpreterType implements InterpreterType { + private final InterpreterType rawType; + private final List<Type> parameters; + + public ParameterizedInterpreterType(InterpreterType rawType, List<Type> parameters) { + this.rawType = rawType; + this.parameters = parameters; + } + + @Override + public Type getType() { + return parameterizedType((ScalarType) rawType.getType(), parameters); + } + + // TODO: implement the other methods properly. + // Possibly worth splitting off a separate notion of interpreter type. + // For instance, callConstructor is arguably not relevant here. + // (Or that we should be instantiating this type before the call to callConstructor) + + @Override + public Set<Type> getSuperTypes() { + throw new UnsupportedOperationException(); + } + + @Override + public Optional<FieldDeclarationNode> getField(String fieldName) { + throw new UnsupportedOperationException(); + } + + @Override + public List<StatementNode> getStaticConstructor() { + throw new UnsupportedOperationException(); + } + + @Override + public void callConstructor(Environment environment, InterpreterValue thisValue, List<InterpreterValue> arguments) { + throw new UnsupportedOperationException(); + } + + @Override + public InterpreterValue callMethod(Environment environment, InterpreterValue value, MethodSignature signature, List<InterpreterValue> arguments) { + throw new UnsupportedOperationException(); + } + + @Override + public InterpreterValue callStaticMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) { + throw new UnsupportedOperationException(); + } +} 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 cc072bf..d702720 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/types/UserDefinedInterpreterType.java @@ -1,8 +1,6 @@ package org.zwobble.couscous.interpreter.types; import org.zwobble.couscous.ast.*; -import org.zwobble.couscous.types.ScalarType; -import org.zwobble.couscous.types.Type; import org.zwobble.couscous.interpreter.Environment; import org.zwobble.couscous.interpreter.Executor; import org.zwobble.couscous.interpreter.InterpreterTypes; @@ -10,9 +8,13 @@ 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.InterpreterValue; -import org.zwobble.couscous.interpreter.values.ObjectInterpreterValue; +import org.zwobble.couscous.types.ScalarType; +import org.zwobble.couscous.types.Type; -import java.util.*; +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; @@ -59,7 +61,7 @@ public class UserDefinedInterpreterType implements InterpreterType { } @Override - public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) { + public void callConstructor(Environment environment, InterpreterValue thisValue, List<InterpreterValue> arguments) { ConstructorNode constructor = tryCast(ClassNode.class, type) // TODO: add test for this case .orElseThrow(() -> new RuntimeException("Cannot instantiate non-class types")) @@ -68,13 +70,11 @@ public class UserDefinedInterpreterType implements InterpreterType { constructor.getArguments(), FormalArgumentNode::getType); checkMethodArguments(formalArgumentTypes, arguments); - InterpreterValue object = new ObjectInterpreterValue(this); Executor.callConstructor( environment, constructor, - object, + thisValue, new PositionalArguments(arguments)); - return object; } private static void checkMethodArguments(final List<Type> argumentTypes, List<InterpreterValue> arguments) { 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 cf2c9b7..deca938 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java @@ -4,8 +4,11 @@ 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 org.zwobble.couscous.interpreter.types.ParameterizedInterpreterType; +import org.zwobble.couscous.types.Type; import java.util.List; +import java.util.Optional; public class StaticReceiverValue implements ReceiverValue { private final InterpreterType type; @@ -35,7 +38,12 @@ public class StaticReceiverValue implements ReceiverValue { Executor.exec(environment, type.getStaticConstructor()); } - public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) { - return type.callConstructor(environment, arguments); + public InterpreterValue callConstructor(Environment environment, Optional<List<Type>> typeParameters, List<InterpreterValue> arguments) { + InterpreterType objectType = typeParameters + .<InterpreterType>map(parameters -> new ParameterizedInterpreterType(type, parameters)) + .orElse(type); + ObjectInterpreterValue value = new ObjectInterpreterValue(objectType); + type.callConstructor(environment, value, arguments); + return value; } } |
