aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Arguments.java29
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java5
-rw-r--r--src/main/java/org/zwobble/couscous/values/BooleanValue.java9
-rw-r--r--src/main/java/org/zwobble/couscous/values/ConcreteType.java46
-rw-r--r--src/main/java/org/zwobble/couscous/values/IntegerValue.java9
-rw-r--r--src/main/java/org/zwobble/couscous/values/InterpreterValue.java4
-rw-r--r--src/main/java/org/zwobble/couscous/values/StringValue.java27
-rw-r--r--src/main/java/org/zwobble/couscous/values/UnitValue.java9
8 files changed, 106 insertions, 32 deletions
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Arguments.java b/src/main/java/org/zwobble/couscous/interpreter/Arguments.java
new file mode 100644
index 0000000..d08393d
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/interpreter/Arguments.java
@@ -0,0 +1,29 @@
+package org.zwobble.couscous.interpreter;
+
+import java.util.List;
+
+import org.zwobble.couscous.values.InterpreterValue;
+
+import lombok.val;
+
+public class Arguments {
+ private int index = 0;
+ private List<InterpreterValue> values;
+
+ public Arguments(List<InterpreterValue> values) {
+ this.values = values;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends InterpreterValue> T pop(Class<T> valueType) {
+ val value = values.get(index);
+ index++;
+ if (valueType.isInstance(value)) {
+ return (T) value;
+ } else {
+ // TODO: throw a more specific error
+ throw new UnsupportedOperationException();
+ }
+
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index 7aba54b..6a566c9 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -61,12 +61,11 @@ public class Evaluator implements ExpressionNodeVisitor<InterpreterValue> {
@Override
public InterpreterValue visit(MethodCallNode methodCall) {
val receiver = eval(methodCall.getReceiver());
+ val type = receiver.getType();
val arguments = methodCall.getArguments()
.stream()
.map(argument -> eval(argument))
.collect(Collectors.toList());
- val method = receiver.getMethod(methodCall.getMethodName())
- .orElseThrow(() -> new NoSuchMethod(methodCall.getMethodName()));
- return method.call(arguments);
+ return type.callMethod(receiver, methodCall.getMethodName(), arguments);
}
}
diff --git a/src/main/java/org/zwobble/couscous/values/BooleanValue.java b/src/main/java/org/zwobble/couscous/values/BooleanValue.java
index 0bcb256..3f1f2a2 100644
--- a/src/main/java/org/zwobble/couscous/values/BooleanValue.java
+++ b/src/main/java/org/zwobble/couscous/values/BooleanValue.java
@@ -1,13 +1,14 @@
package org.zwobble.couscous.values;
-import java.util.Optional;
-
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Value;
@Value
public class BooleanValue implements InterpreterValue {
+ private static final ConcreteType<BooleanValue> TYPE = ConcreteType.<BooleanValue>builder()
+ .build();
+
@Getter(value = AccessLevel.NONE)
boolean value;
@@ -16,7 +17,7 @@ public class BooleanValue implements InterpreterValue {
}
@Override
- public Optional<MethodValue> getMethod(String methodName) {
- throw new UnsupportedOperationException();
+ public ConcreteType<?> getType() {
+ return TYPE;
}
}
diff --git a/src/main/java/org/zwobble/couscous/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
new file mode 100644
index 0000000..c3ead74
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/values/ConcreteType.java
@@ -0,0 +1,46 @@
+package org.zwobble.couscous.values;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import org.zwobble.couscous.interpreter.Arguments;
+import org.zwobble.couscous.interpreter.NoSuchMethod;
+
+import com.google.common.collect.ImmutableMap;
+
+import lombok.val;
+
+public class ConcreteType<T> {
+ public static class Builder<T> {
+ private final ImmutableMap.Builder<String, BiFunction<T, Arguments, InterpreterValue>> methods =
+ ImmutableMap.builder();
+
+ public Builder<T> method(String name, BiFunction<T, Arguments, InterpreterValue> method) {
+ methods.put(name, method);
+ return this;
+ }
+
+ public ConcreteType<T> build() {
+ return new ConcreteType<T>(methods.build());
+ }
+ }
+
+ private Map<String, BiFunction<T, Arguments, InterpreterValue>> methods;
+
+ public ConcreteType(Map<String, BiFunction<T, Arguments, InterpreterValue>> methods) {
+ this.methods = methods;
+ }
+
+ public static <T> ConcreteType.Builder<T> builder() {
+ return new Builder<>();
+ }
+
+ public InterpreterValue callMethod(InterpreterValue receiver, String methodName, List<InterpreterValue> arguments) {
+ if (!methods.containsKey(methodName)) {
+ throw new NoSuchMethod(methodName);
+ }
+ val method = methods.get(methodName);
+ return method.apply((T)receiver, new Arguments(arguments));
+ }
+}
diff --git a/src/main/java/org/zwobble/couscous/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
index 9b77b69..eb7031d 100644
--- a/src/main/java/org/zwobble/couscous/values/IntegerValue.java
+++ b/src/main/java/org/zwobble/couscous/values/IntegerValue.java
@@ -1,15 +1,16 @@
package org.zwobble.couscous.values;
-import java.util.Optional;
-
import lombok.Value;
@Value
public class IntegerValue implements InterpreterValue {
+ private static final ConcreteType<?> TYPE = ConcreteType.<IntegerValue>builder()
+ .build();
+
int value;
@Override
- public Optional<MethodValue> getMethod(String methodName) {
- throw new UnsupportedOperationException();
+ public ConcreteType<?> getType() {
+ return TYPE;
}
}
diff --git a/src/main/java/org/zwobble/couscous/values/InterpreterValue.java b/src/main/java/org/zwobble/couscous/values/InterpreterValue.java
index 17a3722..f1afa85 100644
--- a/src/main/java/org/zwobble/couscous/values/InterpreterValue.java
+++ b/src/main/java/org/zwobble/couscous/values/InterpreterValue.java
@@ -1,7 +1,5 @@
package org.zwobble.couscous.values;
-import java.util.Optional;
-
public interface InterpreterValue {
- Optional<MethodValue> getMethod(String methodName);
+ ConcreteType<?> getType();
}
diff --git a/src/main/java/org/zwobble/couscous/values/StringValue.java b/src/main/java/org/zwobble/couscous/values/StringValue.java
index 3f4b2b0..da45f02 100644
--- a/src/main/java/org/zwobble/couscous/values/StringValue.java
+++ b/src/main/java/org/zwobble/couscous/values/StringValue.java
@@ -1,26 +1,25 @@
package org.zwobble.couscous.values;
-import java.util.Optional;
-
import lombok.Value;
import lombok.val;
@Value
public class StringValue implements InterpreterValue {
+ private static final ConcreteType<?> TYPE = ConcreteType.<StringValue>builder()
+ .method("length", (receiver, arguments) -> new IntegerValue(receiver.value.length()))
+
+ .method("substring", (receiver, arguments) -> {
+ val startIndex = arguments.pop(IntegerValue.class);
+ val endIndex = arguments.pop(IntegerValue.class);
+ return new StringValue(receiver.value.substring(startIndex.getValue(), endIndex.getValue()));
+ })
+
+ .build();
+
String value;
@Override
- public Optional<MethodValue> getMethod(String methodName) {
- if (methodName == "length") {
- return Optional.of(arguments -> new IntegerValue(value.length()));
- } else if (methodName == "substring") {
- return Optional.of(arguments -> {
- val startIndex = (IntegerValue)arguments.get(0);
- val endIndex = (IntegerValue)arguments.get(1);
- return new StringValue(value.substring(startIndex.getValue(), endIndex.getValue()));
- });
- } else {
- return Optional.empty();
- }
+ public ConcreteType<?> getType() {
+ return TYPE;
}
}
diff --git a/src/main/java/org/zwobble/couscous/values/UnitValue.java b/src/main/java/org/zwobble/couscous/values/UnitValue.java
index 8d75529..5742d8a 100644
--- a/src/main/java/org/zwobble/couscous/values/UnitValue.java
+++ b/src/main/java/org/zwobble/couscous/values/UnitValue.java
@@ -1,18 +1,19 @@
package org.zwobble.couscous.values;
-import java.util.Optional;
-
import lombok.ToString;
@ToString
public class UnitValue implements InterpreterValue {
+ private static final ConcreteType<?> TYPE = ConcreteType.<UnitValue>builder()
+ .build();
+
public static final UnitValue UNIT = new UnitValue();
private UnitValue() {
}
@Override
- public Optional<MethodValue> getMethod(String methodName) {
- throw new UnsupportedOperationException();
+ public ConcreteType<?> getType() {
+ return TYPE;
}
}