diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-10-06 16:24:37 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-10-06 16:24:37 +0100 |
| commit | e6f463257720bee91a1b4954d97684dbb3398cbf (patch) | |
| tree | c8d1f04dfe8928d33361108aefee7e7572dae1c7 /src/main/java/org/zwobble/couscous/interpreter/values | |
| parent | 9685c8fb7fa14d5b75d828f8443dd948715ac4af (diff) | |
Add support for constructors and fields
Diffstat (limited to 'src/main/java/org/zwobble/couscous/interpreter/values')
7 files changed, 93 insertions, 15 deletions
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 b98eb20..06e8bee 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,7 @@ package org.zwobble.couscous.interpreter.values; import java.util.Optional; +import org.zwobble.couscous.interpreter.NoSuchField; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.PrimitiveValues; @@ -30,4 +31,9 @@ public class BooleanInterpreterValue implements InterpreterValue { public Optional<PrimitiveValue> toPrimitiveValue() { return Optional.of(PrimitiveValues.value(value)); } + + @Override + public InterpreterValue getField(String fieldName) { + throw new NoSuchField(fieldName); + } } 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 70ba96a..bd63d7f 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java @@ -2,10 +2,12 @@ package org.zwobble.couscous.interpreter.values; import java.util.List; import java.util.Map; +import java.util.Optional; 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.TypeName; import org.zwobble.couscous.interpreter.PositionalArguments; import org.zwobble.couscous.interpreter.Environment; @@ -15,6 +17,7 @@ import org.zwobble.couscous.interpreter.UnexpectedValueType; import org.zwobble.couscous.interpreter.WrongNumberOfArguments; 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; @@ -57,22 +60,38 @@ public class ConcreteType { } public ConcreteType build() { - return new ConcreteType(name, methods.build(), staticMethods.build()); + return new ConcreteType( + name, + new MethodValue( + ImmutableList.of(), + (environment, arguments) -> InterpreterValues.UNIT), + methods.build(), + staticMethods.build()); } } public static ConcreteType fromNode(ClassNode classNode) { + val constructor = new MethodValue( + getArgumentTypes(classNode.getConstructor().getArguments()), + (environment, arguments) -> Executor.callMethod( + environment, + classNode.getConstructor(), + Optional.of(arguments.getReceiver()), + arguments.getPositionalArguments())); + val methods = classNode.getMethods().stream() .filter(method -> !method.isStatic()) .collect(toMap( method -> method.getName(), method -> { - List<TypeName> argumentTypes = method.getArguments() - .stream() - .map(arg -> arg.getType()) - .collect(Collectors.toList()); + val argumentTypes = getArgumentTypes(method.getArguments()); + return new MethodValue(argumentTypes, (environment, arguments) -> { - return Executor.callMethod(environment, method, arguments.getPositionalArguments()); + return Executor.callMethod( + environment, + method, + Optional.of(arguments.getReceiver()), + arguments.getPositionalArguments()); }); })); @@ -82,29 +101,42 @@ public class ConcreteType { .collect(toMap( method -> method.getName(), method -> { - List<TypeName> argumentTypes = method.getArguments() - .stream() - .map(arg -> arg.getType()) - .collect(Collectors.toList()); + val argumentTypes = getArgumentTypes(method.getArguments()); + return new StaticMethodValue(argumentTypes, (environment, arguments) -> { - return Executor.callMethod(environment, method, arguments); + return Executor.callMethod( + environment, + method, + Optional.empty(), + arguments); }); })); return new ConcreteType( classNode.getName(), + constructor, methods, staticMethods); } + + private static List<TypeName> getArgumentTypes(List<FormalArgumentNode> arguments) { + return arguments + .stream() + .map(arg -> arg.getType()) + .collect(Collectors.toList()); + } - private TypeName name; - private Map<String, MethodValue> methods; - private Map<String, StaticMethodValue> staticMethods; + private final TypeName name; + private final MethodValue constructor; + private final Map<String, MethodValue> methods; + private final Map<String, StaticMethodValue> staticMethods; public ConcreteType( TypeName name, + MethodValue constructor, Map<String, MethodValue> methods, Map<String, StaticMethodValue> staticMethods) { this.name = name; + this.constructor = constructor; this.methods = methods; this.staticMethods = staticMethods; } @@ -136,7 +168,11 @@ public class ConcreteType { public InterpreterValue callConstructor( Environment environment, List<InterpreterValue> arguments) { - return new ObjectInterpreterValue(this); + val object = new ObjectInterpreterValue(this); + constructor.apply( + environment, + MethodCallArguments.of(object, new PositionalArguments(arguments))); + return object; } private static <T extends Callable> T findMethod(Map<String, T> methods, String methodName, List<InterpreterValue> 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 92ba306..1effe6a 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java @@ -2,6 +2,7 @@ package org.zwobble.couscous.interpreter.values; import java.util.Optional; +import org.zwobble.couscous.interpreter.NoSuchField; import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.PrimitiveValues; @@ -34,4 +35,9 @@ public class IntegerInterpreterValue implements InterpreterValue { public Optional<PrimitiveValue> toPrimitiveValue() { return Optional.of(PrimitiveValues.value(value)); } + + @Override + public InterpreterValue getField(String fieldName) { + throw 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 6c3c2ec..78d27d2 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/InterpreterValue.java @@ -7,4 +7,5 @@ import org.zwobble.couscous.values.PrimitiveValue; public interface InterpreterValue { ConcreteType getType(); Optional<PrimitiveValue> toPrimitiveValue(); + InterpreterValue getField(String fieldName); } 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 4383353..acb6ef7 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/ObjectInterpreterValue.java @@ -1,14 +1,18 @@ package org.zwobble.couscous.interpreter.values; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import org.zwobble.couscous.values.PrimitiveValue; public class ObjectInterpreterValue implements InterpreterValue { private final ConcreteType type; + private final Map<String, InterpreterValue> fields; public ObjectInterpreterValue(ConcreteType type) { this.type = type; + this.fields = new HashMap<>(); } @Override @@ -20,4 +24,17 @@ public class ObjectInterpreterValue implements InterpreterValue { public Optional<PrimitiveValue> toPrimitiveValue() { return Optional.empty(); } + + @Override + public InterpreterValue getField(String fieldName) { + if (fields.containsKey(fieldName)) { + return fields.get(fieldName); + } else { + throw new UnsupportedOperationException(); + } + } + + public void setField(String fieldName, InterpreterValue value) { + fields.put(fieldName, value); + } } 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 aa3432a..a4dde19 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,7 @@ package org.zwobble.couscous.interpreter.values; import java.util.Optional; +import org.zwobble.couscous.interpreter.NoSuchField; import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.PrimitiveValues; @@ -39,4 +40,9 @@ public class StringInterpreterValue implements InterpreterValue { public Optional<PrimitiveValue> toPrimitiveValue() { return Optional.of(PrimitiveValues.value(value)); } + + @Override + public InterpreterValue getField(String fieldName) { + throw new NoSuchField(fieldName); + } } 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 253932f..e221fee 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/UnitInterpreterValue.java @@ -2,6 +2,7 @@ package org.zwobble.couscous.interpreter.values; import java.util.Optional; +import org.zwobble.couscous.interpreter.NoSuchField; import org.zwobble.couscous.values.PrimitiveValue; import org.zwobble.couscous.values.PrimitiveValues; @@ -26,4 +27,9 @@ public class UnitInterpreterValue implements InterpreterValue { public Optional<PrimitiveValue> toPrimitiveValue() { return Optional.of(PrimitiveValues.UNIT); } + + @Override + public InterpreterValue getField(String fieldName) { + throw new NoSuchField(fieldName); + } } |
