aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-07-14 19:06:56 +0100
committerMichael Williamson <mike@zwobble.org>2016-07-14 19:06:56 +0100
commitdc601f2d7cdec8cc9c366f70be59fc0666f132cb (patch)
tree7ea47dcb37b2fd3720924065d71b334d2dc40219
parent8cf867da4d0a0d54ab038a3de2adc8bf9cc6de1c (diff)
Make it easier to construct visitors that close over locals
-rw-r--r--src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java14
-rw-r--r--src/main/java/org/zwobble/couscous/interpreter/Evaluator.java36
-rw-r--r--src/main/java/org/zwobble/couscous/util/ExtraSets.java4
3 files changed, 35 insertions, 19 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java b/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java
index a64b7bc..aed1253 100644
--- a/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java
+++ b/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java
@@ -19,6 +19,7 @@ import net.bytebuddy.matcher.ElementMatchers;
import org.zwobble.couscous.ast.Node;
import org.zwobble.couscous.ast.NodeTypes;
import org.zwobble.couscous.util.ExtraIterables;
+import org.zwobble.couscous.util.ExtraSets;
import org.zwobble.couscous.util.asm.Implementations;
import org.zwobble.couscous.util.asm.StackManipulationSwitch;
import org.zwobble.couscous.util.asm.TypeDescriptions;
@@ -26,10 +27,13 @@ import org.zwobble.couscous.util.asm.TypeDescriptions;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import static java.util.Arrays.asList;
+import static org.zwobble.couscous.util.ExtraIterables.lazyMap;
import static org.zwobble.couscous.util.ExtraLists.eagerFilter;
import static org.zwobble.couscous.util.ExtraLists.eagerMap;
@@ -84,6 +88,16 @@ public class DynamicNodeVisitor<T> {
return new DynamicNodeVisitor<>(builder);
}
+ public static <T> BiConsumer<Node, T> visitor(Class<T> clazz) {
+ Set<String> methodNames = ExtraSets.copyOf(lazyMap(asList(clazz.getDeclaredMethods()), Method::getName));
+ if (methodNames.size() != 1) {
+ throw new UnsupportedOperationException("Multiple method names");
+ }
+ String methodName = methodNames.iterator().next();
+ Function<T, Consumer> classSupplier = buildClassSupplier(clazz, Consumer.class, methodName, MethodReturn.VOID);
+ return (node, visitor) -> classSupplier.apply(visitor).accept(node);
+ }
+
public static <T, F> Function<T, F> buildClassSupplier(Class<T> clazz, Class<F> function, String methodName, MethodReturn methodReturn) {
Class<? extends F> visitorClass = buildClass(clazz, function, methodName, methodReturn);
diff --git a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
index afcea8b..75eeb76 100644
--- a/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
+++ b/src/main/java/org/zwobble/couscous/interpreter/Evaluator.java
@@ -12,6 +12,7 @@ import org.zwobble.couscous.types.Type;
import org.zwobble.couscous.types.Types;
import java.util.List;
+import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import static org.zwobble.couscous.types.Types.erasure;
@@ -66,29 +67,26 @@ public class Evaluator implements ExpressionNodeMapper<InterpreterValue> {
@Override
public InterpreterValue visit(AssignmentNode assignment) {
InterpreterValue value = eval(assignment.getValue());
- assignVisitor.instantiate(new Assign(value)).accept(assignment.getTarget());
+ AssignableExpressionVisitor.visit.accept(assignment.getTarget(), new AssignableExpressionVisitor() {
+ @Override
+ public void visit(FieldAccessNode fieldAccess) {
+ ReceiverValue left = evalReceiver(fieldAccess.getLeft());
+ left.setField(fieldAccess.getFieldName(), value);
+ }
+
+ @Override
+ public void visit(VariableReferenceNode reference) {
+ environment.put(reference.getReferentId(), value);
+ }
+ });
return value;
}
- private static final DynamicNodeVisitor<Assign> assignVisitor = DynamicNodeVisitor.build(
- Assign.class, "visit"
- );
+ public interface AssignableExpressionVisitor {
+ BiConsumer<Node, AssignableExpressionVisitor> visit = DynamicNodeVisitor.visitor(AssignableExpressionVisitor.class);
- public class Assign {
- private final InterpreterValue value;
-
- private Assign(InterpreterValue value) {
- this.value = value;
- }
-
- public void visit(FieldAccessNode fieldAccess) {
- ReceiverValue left = evalReceiver(fieldAccess.getLeft());
- left.setField(fieldAccess.getFieldName(), value);
- }
-
- public void visit(VariableReferenceNode reference) {
- environment.put(reference.getReferentId(), value);
- }
+ void visit(VariableReferenceNode node);
+ void visit(FieldAccessNode node);
}
@Override
diff --git a/src/main/java/org/zwobble/couscous/util/ExtraSets.java b/src/main/java/org/zwobble/couscous/util/ExtraSets.java
index 6e807c6..f1df962 100644
--- a/src/main/java/org/zwobble/couscous/util/ExtraSets.java
+++ b/src/main/java/org/zwobble/couscous/util/ExtraSets.java
@@ -18,4 +18,8 @@ public class ExtraSets {
public static <T> Set<T> set(T... values) {
return ImmutableSet.copyOf(values);
}
+
+ public static <T> Set<T> copyOf(Iterable<T> iterable) {
+ return ImmutableSet.copyOf(iterable);
+ }
}