""" Java java.lang.invoke standard library APIs implemented in Python. java.lang.invoke package - MethodHandle, MethodType, MethodHandles, CallSite, VarHandle, etc. """ from __future__ import annotations from .._core import Stub from ..java.lang import RuntimeException, Exception as _JavaException import typing as _typing import types as _py_types import inspect as _inspect import functools as _functools __all__ = [ "MethodHandle", "MethodType", "MethodHandles", "MethodHandles_Lookup", "CallSite", "ConstantCallSite", "MutableCallSite", "VolatileCallSite", "SwitchPoint", "VarHandle", "VarHandle_AccessMode", "MethodHandleInfo", "MethodHandleProxies", "SerializedLambda", "LambdaMetafactory", "StringConcatFactory", "REF_GET_FIELD", "REF_GET_STATIC", "REF_PUT_FIELD", "REF_PUT_STATIC", "REF_INVOKE_VIRTUAL", "REF_INVOKE_STATIC", "REF_INVOKE_SPECIAL", "REF_NEW_INVOKE_SPECIAL", "REF_INVOKE_INTERFACE", "LT_GLOBAL", "LT_NEW", ] # ============================================================ # Reference Constants # ============================================================ REF_GET_FIELD = 1 REF_GET_STATIC = 2 REF_PUT_FIELD = 3 REF_PUT_STATIC = 4 REF_INVOKE_VIRTUAL = 5 REF_INVOKE_STATIC = 6 REF_INVOKE_SPECIAL = 7 REF_NEW_INVOKE_SPECIAL = 8 REF_INVOKE_INTERFACE = 9 LT_GLOBAL = "global" LT_NEW = "new" # ============================================================ # MethodType # ============================================================ class MethodType(Stub): """java.lang.invoke.MethodType""" def __init__(self, return_type, param_types=None): super().__init__() self._return_type = return_type self._param_types = list(param_types or []) def returnType(self): return self._return_type def parameterCount(self): return len(self._param_types) def parameterType(self, index): return self._param_types[index] def parameterList(self): return list(self._param_types) def parameterArray(self): return list(self._param_types) def appendParameterTypes(self, *types): return MethodType(self._return_type, self._param_types + list(types)) def changeReturnType(self, return_type): return MethodType(return_type, self._param_types) def changeParameterType(self, index, param_type): new_params = list(self._param_types) new_params[index] = param_type return MethodType(self._return_type, new_params) def dropParameterTypes(self, start, end): new_params = self._param_types[:start] + self._param_types[end:] return MethodType(self._return_type, new_params) def insertParameterTypes(self, index, *types): new_params = self._param_types[:index] + list(types) + self._param_types[index:] return MethodType(self._return_type, new_params) def genericMethodType(self, object_count, final_array=False): return MethodType(object, [object] * object_count) @staticmethod def methodType(return_type, *param_types): return MethodType(return_type, list(param_types)) @staticmethod def genericMethodType(object_count, final_array=False): return MethodType(object, [object] * object_count) def toString(self): params = ", ".join(str(t) for t in self._param_types) return f"({params}) -> {self._return_type}" def equals(self, other): if not isinstance(other, MethodType): return False return (self._return_type == other._return_type and self._param_types == other._param_types) def hashCode(self): return hash((self._return_type, tuple(self._param_types))) def wrap(self): return self def unwrap(self): return self # ============================================================ # MethodHandle # ============================================================ class MethodHandle(Stub): """java.lang.invoke.MethodHandle""" def __init__(self, method_type=None, target=None): super().__init__() self._type = method_type or MethodType(object, []) self._target = target def type(self): return self._type def invoke(self, *args): if self._target is None: return None return self._target(*args) def invokeExact(self, *args): return self.invoke(*args) def invokeWithArguments(self, *args): return self.invoke(*args) def asType(self, new_type): return self._target def asCollector(self, array_type, array_length): return self def asSpreader(self, array_type, array_length): return self def bindTo(self, argument): bound_target = None if self._target is not None: bound_target = _functools.partial(self._target, argument) return MethodHandle(self._type.dropParameterTypes(0, 1), bound_target) def toString(self): return f"MethodHandle{self._type}" # ============================================================ # MethodHandles / Lookup # ============================================================ class MethodHandles_Lookup(Stub): """java.lang.invoke.MethodHandles.Lookup""" def __init__(self, lookup_class=None): super().__init__() self._lookup_class = lookup_class def lookupClass(self): return self._lookup_class def findStatic(self, refc, name, type_): return MethodHandle(type_) def findVirtual(self, refc, name, type_): return MethodHandle(type_) def findConstructor(self, refc, type_): return MethodHandle(type_) def findSpecial(self, refc, name, type_, special_caller): return MethodHandle(type_) def findGetter(self, refc, name, type_): return MethodHandle(type_) def findSetter(self, refc, name, type_): return MethodHandle(type_) def findStaticGetter(self, refc, name, type_): return MethodHandle(type_) def findStaticSetter(self, refc, name, type_): return MethodHandle(type_) def bind(self, receiver, name, type_): return MethodHandle(type_) def unreflect(self, method): return MethodHandle(MethodType(object, [])) def unreflectConstructor(self, constructor): return MethodHandle(MethodType(object, [])) def unreflectGetter(self, field): return MethodHandle(MethodType(object, [])) def unreflectSetter(self, field): return MethodHandle(MethodType(object, [])) def dropLookupMode(self, mode_to_drop): return MethodHandles_Lookup(self._lookup_class) def toString(self): return f"Lookup[{self._lookup_class}]" PACKAGE = 8 PRIVATE = 4 PROTECTED = 2 PUBLIC = 1 class MethodHandles(Stub): """java.lang.invoke.MethodHandles""" @staticmethod def lookup(): return MethodHandles_Lookup() @staticmethod def publicLookup(): return MethodHandles_Lookup(object) @staticmethod def arrayElementGetter(array_class): return MethodHandle(MethodType(object, [array_class, int])) @staticmethod def arrayElementSetter(array_class): return MethodHandle(MethodType(None, [array_class, int, object])) @staticmethod def identity(type_): return MethodHandle(MethodType(type_, [type_])) @staticmethod def constant(type_, value): return MethodHandle(MethodType(type_, [])) @staticmethod def zero(type_): return MethodHandle(MethodType(type_, [])) @staticmethod def filterReturnValue(target, filter_): return target @staticmethod def filterArguments(target, pos, *filters): return target @staticmethod def collectArguments(target, pos, filter_): return target @staticmethod def foldArguments(target, combiner): return target @staticmethod def guardWithTest(test, target, fallback): class Guarded(MethodHandle): def invoke(self, *args): if test.invoke(*args): return target.invoke(*args) return fallback.invoke(*args) return Guarded(MethodType(object, [])) @staticmethod def throwException(return_type, ex_type): return MethodHandle(MethodType(return_type, [ex_type])) @staticmethod def spreadInvoker(type_, leading_arg_count): return MethodHandle(type_) @staticmethod def explicitCastArguments(target, new_type): return target @staticmethod def permuteArguments(target, new_type, *reorder): return target @staticmethod def catchException(target, ex_type, handler): return target @staticmethod def tryFinally(target, cleanup): return target @staticmethod def loop(loop_handles): return MethodHandle(MethodType(object, [])) # ============================================================ # CallSite / ConstantCallSite / MutableCallSite / VolatileCallSite # ============================================================ class CallSite(Stub): """java.lang.invoke.CallSite""" def __init__(self, target=None): super().__init__() self._target = target def type(self): if self._target: return self._target.type() return MethodType(object, []) def target(self): return self._target def setTarget(self, new_target): self._target = new_target def dynamicInvoker(self): return self._target class ConstantCallSite(CallSite): """java.lang.invoke.ConstantCallSite""" def __init__(self, target): super().__init__(target) def setTarget(self, new_target): raise UnsupportedOperationException("ConstantCallSite target is immutable") class MutableCallSite(CallSite): """java.lang.invoke.MutableCallSite""" def __init__(self, target_or_type): if isinstance(target_or_type, MethodType): super().__init__(MethodHandle(target_or_type)) else: super().__init__(target_or_type) def syncAll(self, sites): pass def setTarget(self, new_target): if hasattr(self, '_target'): self._target = new_target class VolatileCallSite(MutableCallSite): """java.lang.invoke.VolatileCallSite""" def __init__(self, target_or_type): super().__init__(target_or_type) def setTarget(self, new_target): super().setTarget(new_target) def target(self): return self._target # ============================================================ # SwitchPoint # ============================================================ class SwitchPoint(Stub): """java.lang.invoke.SwitchPoint""" def __init__(self): super().__init__() self._has_been_invalidated = False def hasBeenInvalidated(self): return self._has_been_invalidated def invalidateAll(self): self._has_been_invalidated = True @staticmethod def guardWithTest(switch_point, target, fallback): class GuardedSwitch(MethodHandle): def invoke(self, *args): if switch_point.hasBeenInvalidated(): return fallback.invoke(*args) return target.invoke(*args) return GuardedSwitch(MethodType(object, [])) # ============================================================ # VarHandle # ============================================================ class VarHandle_AccessMode(Stub): """java.lang.invoke.VarHandle.AccessMode""" def __init__(self, name): super().__init__() self._name = name def name(self): return self._name def toString(self): return self._name # Access mode constants GET = None SET = None GET_VOLATILE = None SET_VOLATILE = None GET_ACQUIRE = None SET_RELEASE = None GET_OPAQUE = None SET_OPAQUE = None COMPARE_AND_SET = None COMPARE_AND_EXCHANGE = None COMPARE_AND_EXCHANGE_ACQUIRE = None COMPARE_AND_EXCHANGE_RELEASE = None WEAK_COMPARE_AND_SET = None WEAK_COMPARE_AND_SET_ACQUIRE = None WEAK_COMPARE_AND_SET_RELEASE = None GET_AND_SET = None GET_AND_SET_ACQUIRE = None GET_AND_SET_RELEASE = None GET_AND_ADD = None GET_AND_ADD_ACQUIRE = None GET_AND_ADD_RELEASE = None GET_AND_BITWISE_OR = None GET_AND_BITWISE_OR_ACQUIRE = None GET_AND_BITWISE_OR_RELEASE = None GET_AND_BITWISE_AND = None GET_AND_BITWISE_AND_ACQUIRE = None GET_AND_BITWISE_AND_RELEASE = None GET_AND_BITWISE_XOR = None GET_AND_BITWISE_XOR_ACQUIRE = None GET_AND_BITWISE_XOR_RELEASE = None GET = None class VarHandle(Stub): """java.lang.invoke.VarHandle""" def __init__(self, var_type=None, coordinate_types=None): super().__init__() self._var_type = var_type or object self._coordinate_types = list(coordinate_types or []) self._access_modes = {} def get(self, *coordinates): return None def set(self, *coordinates_and_value): pass def getVolatile(self, *coordinates): return self.get(*coordinates) def setVolatile(self, *coordinates_and_value): self.set(*coordinates_and_value) def getAcquire(self, *coordinates): return self.get(*coordinates) def setRelease(self, *coordinates_and_value): self.set(*coordinates_and_value) def getOpaque(self, *coordinates): return self.get(*coordinates) def setOpaque(self, *coordinates_and_value): self.set(*coordinates_and_value) def compareAndSet(self, *args): return True def compareAndExchange(self, *args): return args[-2] def compareAndExchangeAcquire(self, *args): return self.compareAndExchange(*args) def compareAndExchangeRelease(self, *args): return self.compareAndExchange(*args) def weakCompareAndSet(self, *args): return True def weakCompareAndSetAcquire(self, *args): return True def weakCompareAndSetRelease(self, *args): return True def getAndSet(self, *coordinates_and_value): return None def getAndSetAcquire(self, *coordinates_and_value): return self.getAndSet(*coordinates_and_value) def getAndSetRelease(self, *coordinates_and_value): return self.getAndSet(*coordinates_and_value) def getAndAdd(self, *coordinates_and_value): return 0 def getAndAddAcquire(self, *coordinates_and_value): return self.getAndAdd(*coordinates_and_value) def getAndAddRelease(self, *coordinates_and_value): return self.getAndAdd(*coordinates_and_value) def getAndBitwiseOr(self, *coordinates_and_value): return 0 def getAndBitwiseAnd(self, *coordinates_and_value): return 0 def getAndBitwiseXor(self, *coordinates_and_value): return 0 def varType(self): return self._var_type def coordinateTypes(self): return self._coordinate_types def toMethodHandle(self, access_mode): return MethodHandle(MethodType(self._var_type, self._coordinate_types)) def getAccessModes(self): return list(self._access_modes.values()) def isAccessModeSupported(self, access_mode): return True AccessMode = VarHandle_AccessMode def toString(self): return f"VarHandle[{self._var_type}]" # ============================================================ # Initialize VarHandle_AccessMode constants # ============================================================ VarHandle_AccessMode.GET = VarHandle_AccessMode("GET") VarHandle_AccessMode.SET = VarHandle_AccessMode("SET") VarHandle_AccessMode.GET_VOLATILE = VarHandle_AccessMode("GET_VOLATILE") VarHandle_AccessMode.SET_VOLATILE = VarHandle_AccessMode("SET_VOLATILE") VarHandle_AccessMode.GET_ACQUIRE = VarHandle_AccessMode("GET_ACQUIRE") VarHandle_AccessMode.SET_RELEASE = VarHandle_AccessMode("SET_RELEASE") VarHandle_AccessMode.GET_OPAQUE = VarHandle_AccessMode("GET_OPAQUE") VarHandle_AccessMode.SET_OPAQUE = VarHandle_AccessMode("SET_OPAQUE") VarHandle_AccessMode.COMPARE_AND_SET = VarHandle_AccessMode("COMPARE_AND_SET") VarHandle_AccessMode.COMPARE_AND_EXCHANGE = VarHandle_AccessMode("COMPARE_AND_EXCHANGE") VarHandle_AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE = VarHandle_AccessMode("COMPARE_AND_EXCHANGE_ACQUIRE") VarHandle_AccessMode.COMPARE_AND_EXCHANGE_RELEASE = VarHandle_AccessMode("COMPARE_AND_EXCHANGE_RELEASE") VarHandle_AccessMode.WEAK_COMPARE_AND_SET = VarHandle_AccessMode("WEAK_COMPARE_AND_SET") VarHandle_AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE = VarHandle_AccessMode("WEAK_COMPARE_AND_SET_ACQUIRE") VarHandle_AccessMode.WEAK_COMPARE_AND_SET_RELEASE = VarHandle_AccessMode("WEAK_COMPARE_AND_SET_RELEASE") VarHandle_AccessMode.GET_AND_SET = VarHandle_AccessMode("GET_AND_SET") VarHandle_AccessMode.GET_AND_SET_ACQUIRE = VarHandle_AccessMode("GET_AND_SET_ACQUIRE") VarHandle_AccessMode.GET_AND_SET_RELEASE = VarHandle_AccessMode("GET_AND_SET_RELEASE") VarHandle_AccessMode.GET_AND_ADD = VarHandle_AccessMode("GET_AND_ADD") VarHandle_AccessMode.GET_AND_ADD_ACQUIRE = VarHandle_AccessMode("GET_AND_ADD_ACQUIRE") VarHandle_AccessMode.GET_AND_ADD_RELEASE = VarHandle_AccessMode("GET_AND_ADD_RELEASE") VarHandle_AccessMode.GET_AND_BITWISE_OR = VarHandle_AccessMode("GET_AND_BITWISE_OR") VarHandle_AccessMode.GET_AND_BITWISE_OR_ACQUIRE = VarHandle_AccessMode("GET_AND_BITWISE_OR_ACQUIRE") VarHandle_AccessMode.GET_AND_BITWISE_OR_RELEASE = VarHandle_AccessMode("GET_AND_BITWISE_OR_RELEASE") VarHandle_AccessMode.GET_AND_BITWISE_AND = VarHandle_AccessMode("GET_AND_BITWISE_AND") VarHandle_AccessMode.GET_AND_BITWISE_AND_ACQUIRE = VarHandle_AccessMode("GET_AND_BITWISE_AND_ACQUIRE") VarHandle_AccessMode.GET_AND_BITWISE_AND_RELEASE = VarHandle_AccessMode("GET_AND_BITWISE_AND_RELEASE") VarHandle_AccessMode.GET_AND_BITWISE_XOR = VarHandle_AccessMode("GET_AND_BITWISE_XOR") VarHandle_AccessMode.GET_AND_BITWISE_XOR_ACQUIRE = VarHandle_AccessMode("GET_AND_BITWISE_XOR_ACQUIRE") VarHandle_AccessMode.GET_AND_BITWISE_XOR_RELEASE = VarHandle_AccessMode("GET_AND_BITWISE_XOR_RELEASE") # ============================================================ # MethodHandleInfo # ============================================================ class MethodHandleInfo(Stub): """java.lang.invoke.MethodHandleInfo""" def __init__(self, reference_kind=0, declaring_class=None, name="", method_type=None): super().__init__() self._reference_kind = reference_kind self._declaring_class = declaring_class self._name = name self._method_type = method_type or MethodType(object, []) def getReferenceKind(self): return self._reference_kind def getDeclaringClass(self): return self._declaring_class def getName(self): return self._name def getMethodType(self): return self._method_type def isVarArgs(self): return False def reflectAs(self, expected_type, lookup): return None def toString(self): return (f"MethodHandleInfo[{self._name}, kind={self._reference_kind}, " f"class={self._declaring_class}, type={self._method_type}]") # Reference kind constants REF_getField = REF_GET_FIELD REF_getStatic = REF_GET_STATIC REF_putField = REF_PUT_FIELD REF_putStatic = REF_PUT_STATIC REF_invokeVirtual = REF_INVOKE_VIRTUAL REF_invokeStatic = REF_INVOKE_STATIC REF_invokeSpecial = REF_INVOKE_SPECIAL REF_newInvokeSpecial = REF_NEW_INVOKE_SPECIAL REF_invokeInterface = REF_INVOKE_INTERFACE # ============================================================ # MethodHandleProxies # ============================================================ class MethodHandleProxies(Stub): """java.lang.invoke.MethodHandleProxies""" @staticmethod def asInterfaceInstance(iface, target): return target @staticmethod def isWrapperClass(cls): return False @staticmethod def wrapperInstanceTarget(proxy): return None @staticmethod def wrapperInstanceType(proxy): return None # ============================================================ # SerializedLambda # ============================================================ class SerializedLambda(Stub): """java.lang.invoke.SerializedLambda""" def __init__(self): super().__init__() self._capturing_class = "" self._functional_interface_class_name = "" self._functional_interface_method_name = "" self._functional_interface_method_signature = "" self._impl_class = "" self._impl_method_name = "" self._impl_method_signature = "" self._impl_method_kind = 0 self._captured_args = [] self._instantiated_method_type = "" self._captured_arg_count = 0 def getCapturingClass(self): return self._capturing_class def getFunctionalInterfaceClassName(self): return self._functional_interface_class_name def getFunctionalInterfaceMethodName(self): return self._functional_interface_method_name def getFunctionalInterfaceMethodSignature(self): return self._functional_interface_method_signature def getImplClass(self): return self._impl_class def getImplMethodName(self): return self._impl_method_name def getImplMethodSignature(self): return self._impl_method_signature def getImplMethodKind(self): return self._impl_method_kind def getCapturedArgCount(self): return self._captured_arg_count def getCapturedArg(self, i): return self._captured_args[i] if i < len(self._captured_args) else None def getInstantiatedMethodType(self): return self._instantiated_method_type # ============================================================ # LambdaMetafactory # ============================================================ class LambdaMetafactory(Stub): """java.lang.invoke.LambdaMetafactory""" FLAG_SERIALIZABLE = 1 FLAG_MARKERS = 2 FLAG_BRIDGES = 4 @staticmethod def metafactory(caller, invoked_name, invoked_type, sam_method_type, impl_method, instantiated_method_type, *args): return MethodHandle(instantiated_method_type) @staticmethod def altMetafactory(caller, invoked_name, invoked_type, *args): return MethodHandle(MethodType(object, [])) # ============================================================ # StringConcatFactory # ============================================================ class StringConcatFactory(Stub): """java.lang.invoke.StringConcatFactory""" @staticmethod def makeConcatWithConstants(lookup, name, concat_type, recipe, *constants): return MethodHandle(concat_type) @staticmethod def makeConcat(lookup, name, concat_type): class ConcatHandle(MethodHandle): def invoke(self, *args): return "".join(str(a) for a in args) return ConcatHandle(concat_type, lambda *args: "".join(str(a) for a in args)) # ============================================================ # UnsupportedOperationException # ============================================================ class UnsupportedOperationException(RuntimeException): """java.lang.UnsupportedOperationException""" pass # ============================================================ # Alias for MethodHandles.Lookup # ============================================================ MethodHandles_Lookup = MethodHandles_Lookup MethodHandles.Lookup = MethodHandles_Lookup VarHandle.AccessMode = VarHandle_AccessMode