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> 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> 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 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