diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-01-01 15:33:57 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-01-01 15:33:57 +0000 |
| commit | fd0769bde1ffad49ca74a404f18aae5d7226c558 (patch) | |
| tree | 64f055dd31d309dddfe4d7c11803d4c6dab1e161 /src/main/java/org/zwobble/couscous/interpreter | |
| parent | 17384f8b7bb6151be3f033ba7e339d9edb59be55 (diff) | |
Get interpreter compiler tests working
Diffstat (limited to 'src/main/java/org/zwobble/couscous/interpreter')
5 files changed, 68 insertions, 16 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java index bb76280..1e644c8 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java +++ b/src/main/java/org/zwobble/couscous/interpreter/InterpreterTypes.java @@ -1,17 +1,25 @@ package org.zwobble.couscous.interpreter; import org.zwobble.couscous.ast.TypeName; +import org.zwobble.couscous.interpreter.values.ConcreteType; import org.zwobble.couscous.interpreter.values.InterpreterValue; import org.zwobble.couscous.values.ObjectValues; public class InterpreterTypes { public static void checkIsInstance(TypeName type, InterpreterValue value) { - checkIsSubType(type, value.getType().getName()); + checkIsSubType(type, value.getType()); } - private static void checkIsSubType(TypeName superType, TypeName subType) { - if (!superType.equals(subType) && !superType.equals(ObjectValues.OBJECT)) { - throw new UnexpectedValueType(superType, subType); + private static void checkIsSubType(TypeName superTypeName, ConcreteType subType) { + if (!isSubType(superTypeName, subType)) { + throw new UnexpectedValueType(superTypeName, subType.getName()); } } + + private static boolean isSubType(TypeName superTypeName, ConcreteType subType) { + return + superTypeName.equals(subType.getName()) || + superTypeName.equals(ObjectValues.OBJECT) || + subType.getSuperTypes().contains(superTypeName); + } } 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 458eca7..3ffa244 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/BoxedIntegerInterpreterValue.java @@ -1,16 +1,32 @@ package org.zwobble.couscous.interpreter.values; +import org.zwobble.couscous.ast.Operator; +import org.zwobble.couscous.values.IntegerValue; +import org.zwobble.couscous.values.ObjectValues; import org.zwobble.couscous.values.StringValue; import static java.util.Arrays.asList; public class BoxedIntegerInterpreterValue { public static final ConcreteType TYPE = ConcreteType.classBuilder("java.lang.Integer") + .field("value", IntegerValue.REF) + .staticMethod("parseInt", asList(StringValue.REF), (environment, arguments) -> { StringInterpreterValue value = (StringInterpreterValue)arguments.get(0); return new IntegerInterpreterValue(Integer.parseInt(value.getValue())); }) - + + .method(Operator.EQUALS.getMethodName(), asList(ObjectValues.OBJECT), + (environment, arguments) -> { + InterpreterValue right = arguments.getPositionalArguments().get(0); + if (right.getType().getName().equals(ObjectValues.BOXED_INT)) { + IntegerInterpreterValue leftValue = (IntegerInterpreterValue)arguments.getReceiver().getField("value"); + IntegerInterpreterValue rightValue = (IntegerInterpreterValue)right.getField("value"); + return new BooleanInterpreterValue(leftValue.getValue() == rightValue.getValue()); + } else { + return new BooleanInterpreterValue(false); + } + }) .build(); } 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 8d2c2d5..c053739 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/ConcreteType.java @@ -1,8 +1,6 @@ package org.zwobble.couscous.interpreter.values; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.BiFunction; import java.util.stream.Collectors; import org.zwobble.couscous.ast.ClassNode; @@ -34,6 +32,7 @@ public class ConcreteType { } public static class Builder<T> { + private final ImmutableMap.Builder<String, FieldValue> fields = ImmutableMap.builder(); private final ImmutableMap.Builder<String, MethodValue> methods = ImmutableMap.builder(); private final ImmutableMap.Builder<String, StaticMethodValue> staticMethods = ImmutableMap.builder(); private final Class<T> interpreterValueType; @@ -43,7 +42,12 @@ public class ConcreteType { this.interpreterValueType = interpreterValueType; this.name = name; } - + + public Builder<T> field(String name, TypeName type) { + fields.put(name, new FieldValue(name, type)); + return this; + } + public Builder<T> method(String name, List<TypeName> argumentsTypes, BiFunction<Environment, MethodCallArguments<T>, InterpreterValue> method) { methods.put(name, new MethodValue(argumentsTypes, (environment, arguments) -> { return Casts.tryCast(interpreterValueType, arguments.getReceiver()).map(typedReceiver -> method.apply(environment, MethodCallArguments.of(typedReceiver, arguments.getPositionalArguments()))).orElseThrow(() -> new RuntimeException("receiver is of wrong type")); @@ -57,7 +61,13 @@ public class ConcreteType { } public ConcreteType build() { - return new ConcreteType(name, ImmutableMap.of(), new MethodValue(ImmutableList.of(), (environment, arguments) -> InterpreterValues.UNIT), methods.build(), staticMethods.build()); + return new ConcreteType( + name, + Collections.emptySet(), + fields.build(), + new MethodValue(ImmutableList.of(), (environment, arguments) -> InterpreterValues.UNIT), + methods.build(), + staticMethods.build()); } } @@ -76,20 +86,28 @@ public class ConcreteType { return Executor.callMethod(environment, method, Optional.empty(), arguments); }); })); - return new ConcreteType(classNode.getName(), fields, constructor, methods, staticMethods); + return new ConcreteType(classNode.getName(), classNode.getSuperTypes(), fields, 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, FieldValue> fields; private final MethodValue constructor; private final Map<String, MethodValue> methods; private final Map<String, StaticMethodValue> staticMethods; - private ConcreteType(TypeName name, Map<String, FieldValue> fields, MethodValue constructor, Map<String, MethodValue> methods, Map<String, StaticMethodValue> staticMethods) { + private ConcreteType( + TypeName name, + Set<TypeName> superTypes, + Map<String, FieldValue> fields, + MethodValue constructor, + Map<String, MethodValue> methods, + Map<String, StaticMethodValue> staticMethods) { this.name = name; + this.superTypes = superTypes; this.fields = fields; this.constructor = constructor; this.methods = methods; @@ -99,7 +117,11 @@ public class ConcreteType { public TypeName getName() { return name; } - + + public Set<TypeName> getSuperTypes() { + return superTypes; + } + public Optional<FieldValue> getField(String fieldName) { return Optional.ofNullable(fields.get(fieldName)); } 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 da28bc5..3bcb41a 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/IntegerInterpreterValue.java @@ -97,6 +97,12 @@ public final class IntegerInterpreterValue implements InterpreterValue { public int getValue() { return this.value; } + + public InterpreterValue box() { + ObjectInterpreterValue box = new ObjectInterpreterValue(BoxedIntegerInterpreterValue.TYPE); + box.setField("value", this); + return box; + } @java.lang.Override public boolean equals(final java.lang.Object o) { 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 ef4c37b..4d3f33a 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java +++ b/src/main/java/org/zwobble/couscous/interpreter/values/InternalCouscousInterpreterValue.java @@ -19,10 +19,10 @@ public class InternalCouscousInterpreterValue { ((environment, arguments) -> arguments.get(0))) .staticMethod("boxInt", asList(IntegerValue.REF), - ((environment, arguments) -> arguments.get(0))) + ((environment, arguments) -> ((IntegerInterpreterValue)arguments.get(0)).box())) - .staticMethod("unboxInt", asList(IntegerValue.REF), - ((environment, arguments) -> arguments.get(0))) + .staticMethod("unboxInt", asList(ObjectValues.BOXED_INT), + ((environment, arguments) -> arguments.get(0).getField("value"))) .build(); } |
