From 0970f5a5074da34fffaea70f3b42d012edb501c5 Mon Sep 17 00:00:00 2001
From: Michael Williamson
Date: Thu, 14 Jul 2016 22:50:55 +0100
Subject: Simplify dynamic visitor creation
---
.../couscous/ast/visitors/DynamicNodeMapper.java | 33 ++++++++++------------
.../couscous/ast/visitors/DynamicNodeVisitor.java | 33 ++++++++++------------
2 files changed, 30 insertions(+), 36 deletions(-)
(limited to 'src/main/java/org/zwobble/couscous/ast')
diff --git a/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeMapper.java b/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeMapper.java
index 243dde1..0637c44 100644
--- a/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeMapper.java
+++ b/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeMapper.java
@@ -1,29 +1,26 @@
package org.zwobble.couscous.ast.visitors;
-import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import org.zwobble.couscous.ast.Node;
+import java.util.HashMap;
+import java.util.Map;
import java.util.function.Function;
-public class DynamicNodeMapper {
- public static DynamicNodeMapper build(Class clazz, Class returnType, String methodName) {
- return build(clazz, new TypeDescription.ForLoadedType(returnType), methodName);
- }
-
- public static DynamicNodeMapper build(Class clazz, TypeDescription returnType, String methodName) {
- return new DynamicNodeMapper<>(
- DynamicNodeVisitor.buildClassSupplier(clazz, Function.class, methodName, MethodReturn.REFERENCE)
- );
- }
+import static org.zwobble.couscous.util.ExtraMaps.entry;
- private final Function visitor;
-
- public DynamicNodeMapper(Function visitor) {
- this.visitor = visitor;
- }
+public class DynamicNodeMapper {
+ private static final Map, String>, Function, Function>> VISITOR_BUILDERS
+ = new HashMap<>();
- public Function instantiate(T instance) {
- return visitor.apply(instance);
+ // TODO: check return type -- at the very least, check the methods are consistent.
+ public static Function instantiate(T visitor, String methodName) {
+ Map.Entry, String> key = entry(visitor.getClass(), methodName);
+ Function builder = VISITOR_BUILDERS.get(key);
+ if (builder == null) {
+ builder = DynamicNodeVisitor.buildClassSupplier(visitor.getClass(), Function.class, methodName, MethodReturn.REFERENCE);
+ VISITOR_BUILDERS.put(key, builder);
+ }
+ return (Function) builder.apply(visitor);
}
}
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 aed1253..438bcea 100644
--- a/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java
+++ b/src/main/java/org/zwobble/couscous/ast/visitors/DynamicNodeVisitor.java
@@ -25,9 +25,7 @@ import org.zwobble.couscous.util.asm.StackManipulationSwitch;
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.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -36,6 +34,7 @@ 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;
+import static org.zwobble.couscous.util.ExtraMaps.entry;
/**
* Dynamically generate a method to dispatch methods based on node type.
@@ -82,10 +81,18 @@ import static org.zwobble.couscous.util.ExtraLists.eagerMap;
* (which affects which node types later stages are required to handle).
*
*/
-public class DynamicNodeVisitor {
- public static DynamicNodeVisitor build(Class clazz, String methodName) {
- Function builder = buildClassSupplier(clazz, Consumer.class, methodName, MethodReturn.VOID);
- return new DynamicNodeVisitor<>(builder);
+public class DynamicNodeVisitor {
+ private static final Map, String>, Function, Consumer>> VISITOR_BUILDERS
+ = new HashMap<>();
+
+ public static Consumer instantiate(T visitor, String methodName) {
+ Map.Entry, String> key = entry(visitor.getClass(), methodName);
+ Function builder = VISITOR_BUILDERS.get(key);
+ if (builder == null) {
+ builder = buildClassSupplier(visitor.getClass(), Consumer.class, methodName, MethodReturn.VOID);
+ VISITOR_BUILDERS.put(key, builder);
+ }
+ return (Consumer) builder.apply(visitor);
}
public static BiConsumer visitor(Class clazz) {
@@ -98,7 +105,7 @@ public class DynamicNodeVisitor {
return (node, visitor) -> classSupplier.apply(visitor).accept(node);
}
- public static Function buildClassSupplier(Class clazz, Class function, String methodName, MethodReturn methodReturn) {
+ static Function buildClassSupplier(Class clazz, Class function, String methodName, MethodReturn methodReturn) {
Class extends F> visitorClass = buildClass(clazz, function, methodName, methodReturn);
try {
@@ -208,14 +215,4 @@ public class DynamicNodeVisitor {
Node.class.isAssignableFrom(method.getParameterTypes()[0]) &&
!method.getParameterTypes()[0].equals(Node.class);
}
-
- private final Function visitor;
-
- private DynamicNodeVisitor(Function visitor) {
- this.visitor = visitor;
- }
-
- public Consumer instantiate(T instance) {
- return visitor.apply(instance);
- }
}
--
cgit v1.2.3