Преглед на файлове

reflective method to interface

Ranides Atterwim преди 9 години
родител
ревизия
b4f2029b5b

+ 91 - 0
assira.drafts/src/main/java/net/ranides/assira/lambda/LRunner.java

@@ -0,0 +1,91 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira.drafts
+ */
+package net.ranides.assira.lambda;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Type;
+import java.util.List;
+import net.ranides.assira.reflection.IAttribute;
+import static net.ranides.assira.reflection.IAttribute.BRIDGE;
+import static net.ranides.assira.reflection.IAttribute.DECLARED;
+import static net.ranides.assira.reflection.IAttribute.SYNTHETIC;
+import net.ranides.assira.reflection.IClass;
+import net.ranides.assira.reflection.IMethod;
+import net.ranides.assira.reflection.IMethods;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class LRunner {
+    
+    private static Class<?> ttype(IClass<?> ic) {
+        Type t = ic.reflective();
+        return t instanceof Class ? (Class)t : Object.class;
+    }
+    
+    public static void main(String[] args) throws LambdaConversionException, Throwable {
+        IClass<Hello> ic = IClass.typeinfo(Hello.class);
+        
+        
+        MethodHandle mh = ic.method("sum").handle();
+
+        IClass<IFunction> icf = IClass.typeinfo(IFunction.class);
+        
+        IMethod mf = icf.methods().require(DECLARED).discard(SYNTHETIC).discard(BRIDGE).first();
+        System.out.println("f = " + mf);
+        
+        Class<?> rf = ttype(mf.returns());
+        Class<?>[] rfparams = mf.arguments().types().stream().map(t -> ttype(t)).array(Class[]::new);
+        MethodType fmt = MethodType.methodType(rf, rfparams);
+        System.out.println("R = " + fmt);
+        
+        CallSite cs = LambdaMetafactory.metafactory(
+                MethodHandles.lookup(),
+                "apply",
+                MethodType.methodType(IFunction.class),
+//                MethodType.methodType(int.class, Object.class, int.class, int.class), /*mh.type(),*/
+                fmt,
+                mh,
+                mh.type() 
+        );
+        
+        IFunction lambda=(IFunction)cs.getTarget().invokeExact();
+        
+        System.out.println("d = " + lambda.apply(new Hello(400), 3, 0));
+    }
+    
+    
+    public static interface IFunction<T> {
+        
+        int apply(T that, int a, int b);
+        
+    }
+    
+    public static class Hello {
+        
+        private final int seed;
+
+        public Hello(int seed) {
+            this.seed = seed;
+        }
+        
+        public int sum(int a, int b) {
+            return seed+a+b;
+        }
+        
+        public int mul(int a, int b) {
+            return seed+a*b;
+        }
+        
+    };
+}

+ 35 - 0
assira.drafts/src/main/java/net/ranides/assira/lambda/TestMethodPerf.java

@@ -0,0 +1,35 @@
+package net.ranides.assira.lambda;
+
+import java.lang.invoke.LambdaMetafactory;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.util.function.IntBinaryOperator;
+
+public class TestMethodPerf {
+
+    public static void main(String... args) throws Throwable {
+        // hold result to prevent too much optimizations
+        final int[] dummy = new int[4];
+
+        Method reflected = TestMethodPerf.class
+                .getDeclaredMethod("myMethod", int.class, int.class);
+        final MethodHandles.Lookup lookup = MethodHandles.lookup();
+        MethodHandle mh = lookup.unreflect(reflected);
+        IntBinaryOperator lambda = (IntBinaryOperator) LambdaMetafactory.metafactory(
+                lookup, "applyAsInt", MethodType.methodType(IntBinaryOperator.class),
+                mh.type(), mh, mh.type()).getTarget().invokeExact();
+
+        testLambda(dummy[1], lambda);
+
+    }
+
+    private static int testLambda(int v, IntBinaryOperator accessor) {
+        return accessor.applyAsInt(1000, v);
+    }
+
+    private static int myMethod(int a, int b) {
+        return a < b ? a : b;
+    }
+}