diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-02-11 21:33:25 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-02-11 21:33:25 +0000 |
| commit | a34a00ba19f6ffb61762da4629b53b8a633f9d17 (patch) | |
| tree | 6ae34a92c0dfe9a24df0b7e90da2da263a61f708 /src/main/java/org/zwobble/couscous/interpreter/values | |
| parent | 6d02b3e3e6f8da9837a46efda4733bdd89e38aaf (diff) | |
Implement static constructor and fields in interpreter
Diffstat (limited to 'src/main/java/org/zwobble/couscous/interpreter/values')
6 files changed, 94 insertions, 27 deletions
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 41c0445..3a4443f 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java @@ -1,10 +1,7 @@ package org.zwobble.couscous.interpreter.values; import com.google.common.collect.ImmutableMap; -import org.zwobble.couscous.ast.ClassNode; -import org.zwobble.couscous.ast.FormalArgumentNode; -import org.zwobble.couscous.ast.MethodSignature; -import org.zwobble.couscous.ast.TypeName; +import org.zwobble.couscous.ast.*; import org.zwobble.couscous.interpreter.*; import org.zwobble.couscous.interpreter.errors.NoSuchMethod; import org.zwobble.couscous.interpreter.errors.WrongNumberOfArguments; @@ -18,7 +15,6 @@ import static java.util.stream.Collectors.toMap; import static org.zwobble.couscous.util.ExtraLists.list; public class ConcreteType { - public static <T> ConcreteType.Builder<T> builder(Class<T> interpreterValueType, TypeName reference) { return new Builder<>(interpreterValueType, reference); } @@ -30,7 +26,7 @@ public class ConcreteType { public static ConcreteType.Builder<ObjectInterpreterValue> classBuilder(String name) { return builder(ObjectInterpreterValue.class, name); } - + public static class Builder<T> { private final ImmutableMap.Builder<String, FieldValue> fields = ImmutableMap.builder(); private MethodValue constructor = new MethodValue(list(), (environment, arguments) -> InterpreterValues.UNIT); @@ -88,6 +84,7 @@ public class ConcreteType { name, Collections.emptySet(), fields.build(), + list(), constructor, methods.build(), staticMethods.build()); @@ -115,7 +112,14 @@ public class ConcreteType { return Executor.callMethod(environment, method, Optional.empty(), arguments); }); })); - return new ConcreteType(classNode.getName(), classNode.getSuperTypes(), fields, constructor, methods, staticMethods); + return new ConcreteType( + classNode.getName(), + classNode.getSuperTypes(), + fields, + classNode.getStaticConstructor(), + constructor, + methods, + staticMethods); } private static List<TypeName> getArgumentTypes(List<FormalArgumentNode> arguments) { @@ -124,6 +128,7 @@ public class ConcreteType { private final TypeName name; private final Set<TypeName> superTypes; private final Map<String, FieldValue> fields; + private final List<StatementNode> staticConstructor; private final MethodValue constructor; private final Map<MethodSignature, MethodValue> methods; private final Map<MethodSignature, StaticMethodValue> staticMethods; @@ -132,13 +137,14 @@ public class ConcreteType { TypeName name, Set<TypeName> superTypes, Map<String, FieldValue> fields, - MethodValue constructor, + 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; @@ -155,7 +161,11 @@ public class ConcreteType { public Optional<FieldValue> getField(String fieldName) { return Optional.ofNullable(fields.get(fieldName)); } - + + public List<StatementNode> getStaticConstructor() { + return staticConstructor; + } + 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))); 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 3c3d932..8179394 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/InstanceReceiverValue.java @@ -17,4 +17,14 @@ public class InstanceReceiverValue implements ReceiverValue { ConcreteType type = value.getType(); return type.callMethod(environment, value, signature, arguments); } + + @Override + public InterpreterValue getField(String fieldName) { + return value.getField(fieldName); + } + + @Override + public void setField(String fieldName, InterpreterValue value) { + this.value.setField(fieldName, value); + } } diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java new file mode 100644 index 0000000..fc082a5 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterFields.java @@ -0,0 +1,36 @@ +package org.zwobble.couscous.interpreter.values; + +import org.zwobble.couscous.interpreter.InterpreterTypes; +import org.zwobble.couscous.interpreter.errors.NoSuchField; +import org.zwobble.couscous.interpreter.errors.UnboundField; + +import java.util.HashMap; +import java.util.Map; + +public class InterpreterFields { + // TODO: distinguish static and non-static fields + + private final ConcreteType type; + private final Map<String, InterpreterValue> fields; + + public InterpreterFields(ConcreteType type) { + this.type = type; + this.fields = new HashMap<>(); + } + + public InterpreterValue getField(String fieldName) { + type.getField(fieldName).orElseThrow(() -> new NoSuchField(fieldName)); + if (fields.containsKey(fieldName)) { + return fields.get(fieldName); + } else { + throw new UnboundField(fieldName); + } + } + + public void setField(String fieldName, InterpreterValue value) { + FieldValue field = type.getField(fieldName) + .orElseThrow(() -> new NoSuchField(fieldName)); + InterpreterTypes.checkIsInstance(field.getType(), value); + fields.put(fieldName, 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 566ff80..e46ae45 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,16 @@ package org.zwobble.couscous.interpreter.values; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import org.zwobble.couscous.interpreter.InterpreterTypes; -import org.zwobble.couscous.interpreter.errors.NoSuchField; -import org.zwobble.couscous.interpreter.errors.UnboundField; import org.zwobble.couscous.values.PrimitiveValue; +import java.util.Optional; + public class ObjectInterpreterValue implements InterpreterValue { private final ConcreteType type; - private final Map<String, InterpreterValue> fields; + private final InterpreterFields fields; public ObjectInterpreterValue(ConcreteType type) { this.type = type; - this.fields = new HashMap<>(); + this.fields = new InterpreterFields(type); } @Override @@ -29,19 +25,11 @@ public class ObjectInterpreterValue implements InterpreterValue { @Override public InterpreterValue getField(String fieldName) { - type.getField(fieldName).orElseThrow(() -> new NoSuchField(fieldName)); - if (fields.containsKey(fieldName)) { - return fields.get(fieldName); - } else { - throw new UnboundField(fieldName); - } + return fields.getField(fieldName); } @Override public void setField(String fieldName, InterpreterValue value) { - FieldValue field = type.getField(fieldName) - .orElseThrow(() -> new NoSuchField(fieldName)); - InterpreterTypes.checkIsInstance(field.getType(), value); - fields.put(fieldName, value); + fields.setField(fieldName, value); } }
\ No newline at end of file diff --git a/src/main/java/org/zwobble/couscous/interpreter/values/ReceiverValue.java b/src/main/java/org/zwobble/couscous/interpreter/values/ReceiverValue.java index 5b24f95..5d6d804 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/ReceiverValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/ReceiverValue.java @@ -7,4 +7,6 @@ import java.util.List; public interface ReceiverValue { InterpreterValue callMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments); + InterpreterValue getField(String fieldName); + void setField(String fieldName, InterpreterValue value); } 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 f7ce1f6..9844e33 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/StaticReceiverValue.java @@ -2,18 +2,39 @@ 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 java.util.List; public class StaticReceiverValue implements ReceiverValue { private final ConcreteType type; + private final InterpreterFields fields; public StaticReceiverValue(ConcreteType type) { this.type = type; + this.fields = new InterpreterFields(type); } @Override public InterpreterValue callMethod(Environment environment, MethodSignature signature, List<InterpreterValue> arguments) { return type.callStaticMethod(environment, signature, arguments); } + + @Override + public InterpreterValue getField(String fieldName) { + return fields.getField(fieldName); + } + + @Override + public void setField(String fieldName, InterpreterValue value) { + fields.setField(fieldName, value); + } + + public void callStaticConstructor(Environment environment) { + Executor.exec(environment, type.getStaticConstructor()); + } + + public InterpreterValue callConstructor(Environment environment, List<InterpreterValue> arguments) { + return type.callConstructor(environment, arguments); + } } |
