1 package jdk.incubator.code.dialect.java.impl;
  2 
  3 import jdk.incubator.code.CodeType;
  4 import jdk.incubator.code.dialect.core.FunctionType;
  5 import jdk.incubator.code.dialect.java.FieldRef;
  6 import jdk.incubator.code.dialect.java.JavaOp.InvokeOp.InvokeKind;
  7 import jdk.incubator.code.dialect.java.JavaType;
  8 import jdk.incubator.code.dialect.java.MethodRef;
  9 
 10 import java.lang.constant.Constable;
 11 import java.lang.invoke.MethodHandle;
 12 import java.lang.invoke.MethodHandles;
 13 import java.lang.invoke.MethodHandles.Lookup;
 14 import java.lang.invoke.MethodType;
 15 import java.lang.invoke.TypeDescriptor;
 16 import java.lang.invoke.VarHandle;
 17 import java.util.function.Supplier;
 18 
 19 public class ResolutionHelper {
 20     interface HandleResolver<X extends Constable, T extends TypeDescriptor> {
 21         X resolve(Lookup lookup, Class<?> refc, String name, T type) throws ReflectiveOperationException;
 22 
 23         HandleResolver<MethodHandle, MethodType> FIND_STATIC = MethodHandles.Lookup::findStatic;
 24         HandleResolver<MethodHandle, MethodType> FIND_VIRTUAL = MethodHandles.Lookup::findVirtual;
 25         HandleResolver<MethodHandle, MethodType> FIND_SPECIAL = (l, refc, name, type) -> l.findSpecial(refc, name, type, l.lookupClass());
 26         HandleResolver<MethodHandle, MethodType> FIND_CONSTRUCTOR = (l, refc, name, type) -> l.findConstructor(refc, type);
 27         HandleResolver<MethodHandle, Class<?>> FIND_STATIC_GETTER = MethodHandles.Lookup::findStaticGetter;
 28         HandleResolver<MethodHandle, Class<?>> FIND_GETTER = MethodHandles.Lookup::findGetter;
 29         HandleResolver<VarHandle, Class<?>> FIND_STATIC_VARHANDLE = MethodHandles.Lookup::findStaticVarHandle;
 30         HandleResolver<VarHandle, Class<?>> FIND_VARHANDLE = MethodHandles.Lookup::findVarHandle;
 31     }
 32 
 33     sealed interface Result<H extends Constable> {
 34         H handle() throws ReflectiveOperationException;
 35 
 36         default Result<H> orElse(Supplier<Result<H>> resultSupplier) {
 37             if (this instanceof Success<?>) return this;
 38             else return resultSupplier.get();
 39         }
 40     }
 41     record Success<H extends Constable>(H handle) implements Result<H> { }
 42     record Failure<H extends Constable>(ReflectiveOperationException error) implements Result<H> {
 43         @Override
 44         public H handle() throws ReflectiveOperationException {
 45             throw error;
 46         }
 47     }
 48 
 49     static <Z extends Constable, T extends TypeDescriptor> Result<Z> resolveHandle(HandleResolver<Z, T> resolver, MethodHandles.Lookup l, Class<?> refc, String name, T type) {
 50         try {
 51             Z res = resolver.resolve(l, refc, name, type);
 52             return new Success<>(res);
 53         } catch (ReflectiveOperationException ex) {
 54             return new Failure<>(ex);
 55         }
 56     }
 57 
 58     // public API
 59 
 60     public static Class<?> resolveClass(MethodHandles.Lookup l, CodeType t) throws ReflectiveOperationException {
 61         if (t instanceof JavaType jt) {
 62             return (Class<?>)jt.erasure().resolve(l);
 63         } else {
 64             throw new UnsupportedOperationException();
 65         }
 66     }
 67 
 68     public static MethodType resolveMethodType(MethodHandles.Lookup l, FunctionType ft) throws ReflectiveOperationException {
 69         return MethodRef.toNominalDescriptor(ft)
 70                 .resolveConstantDesc(l);
 71     }
 72 
 73     public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef, InvokeKind kind) throws ReflectiveOperationException {
 74         Class<?> refC = resolveClass(l, methodRef.refType());
 75         MethodType mt = resolveMethodType(l, methodRef.signature());
 76         HandleResolver<MethodHandle, MethodType> resolver = switch (kind) {
 77             case INSTANCE -> HandleResolver.FIND_VIRTUAL;
 78             case STATIC -> HandleResolver.FIND_STATIC;
 79             case SUPER -> HandleResolver.FIND_SPECIAL;
 80         };
 81         return resolveHandle(resolver, l, refC, methodRef.name(), mt).handle();
 82     }
 83 
 84     public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef) throws ReflectiveOperationException {
 85         Class<?> refC = resolveClass(l, methodRef.refType());
 86         MethodType mt = resolveMethodType(l, methodRef.signature());
 87         return resolveHandle(HandleResolver.FIND_STATIC, l, refC, methodRef.name(), mt)
 88                 .orElse(() -> resolveHandle(HandleResolver.FIND_VIRTUAL, l, refC, methodRef.name(), mt))
 89                 .handle();
 90     }
 91 
 92     public static MethodHandle resolveFieldGetter(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
 93         Class<?> refC = resolveClass(l, fieldRef.refType());
 94         Class<?> ft = resolveClass(l, fieldRef.type());
 95         return resolveHandle(HandleResolver.FIND_STATIC_GETTER, l, refC, fieldRef.name(), ft)
 96                 .orElse(() -> resolveHandle(HandleResolver.FIND_GETTER, l, refC, fieldRef.name(), ft))
 97                 .handle();
 98     }
 99 
100     public static VarHandle resolveFieldHandle(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
101         Class<?> refC = resolveClass(l, fieldRef.refType());
102         Class<?> ft = resolveClass(l, fieldRef.type());
103         return resolveHandle(HandleResolver.FIND_STATIC_VARHANDLE, l, refC, fieldRef.name(), ft)
104                 .orElse(() -> resolveHandle(HandleResolver.FIND_VARHANDLE, l, refC, fieldRef.name(), ft))
105                 .handle();
106     }
107 
108     public static MethodHandle resolveConstructor(MethodHandles.Lookup l, Class<?> refc, MethodType type) throws ReflectiveOperationException {
109         return resolveHandle(HandleResolver.FIND_CONSTRUCTOR, l, refc, null, type).handle();
110     }
111 }