/** * Create a new SmartHandle from the given Signature and MethodHandle. * * @param signature the signature for the new smart handle * @param handle the method handle for the new smart handle * @return a new SmartHandle */ public static SmartHandle from(Signature signature, MethodHandle handle) { return new SmartHandle(signature, handle); }
/** * Terminate this binder by invoking the given target handle. * * @param target the handle to invoke * @return a new SmartHandle with this binder's starting signature, bound * through to the given handle */ public SmartHandle invoke(MethodHandle target) { return new SmartHandle(start, binder.invoke(target)); }
/** * Produce a SmartHandle from this binder that invokes a leading * MethodHandle argument with the remaining arguments. * * @return a SmartHandle that invokes its leading MethodHandle argument */ public SmartHandle invoker() { return new SmartHandle(start, binder.invoker()); }
/** * Use this SmartHandle as a test to guard target and fallback handles. * * @param target the "true" path for this handle's test * @param fallback the "false" path for this handle's test * @return a new SmartHandle that performs the test and branch */ public SmartHandle guard(SmartHandle target, SmartHandle fallback) { return new SmartHandle(target.signature, MethodHandles.guardWithTest(handle, target.handle, fallback.handle)); }
/** * Terminate this binder by returning its sole remaining argument. The * signature must take only one argument whose type matches the return * type. * * Invoking the resulting handle will (eventually) return the argument * passed in at this point. * * @return a new SmartHandle with this binder's starting signature that * simply returns its sole received argument */ public SmartHandle identity() { return new SmartHandle(start, binder.identity()); }
/** * Terminate this binder by setting an array element based on the current * signature. The signature should have the array as its first argument, * an integer index as its second, and an appropriately-typed value as its * third. It should have a void return value. * * Invoking the resulting handle will (eventually) perform the array * assignment. * * @return a new SmartHandle with this binder's starting signature, bound * to an array assignment operation */ public SmartHandle arrayGet() { return new SmartHandle(start, binder.arrayGet()); }
/** * Create a new SmartHandle that casts arguments from the given signature to * the current signature's type with the new argument names. This casting * is equivalent to MethodHandle#asType. * * @param incoming the target MethodType from which arguments will be converted * @return a new SmartHandle that accepts the given argument types */ public SmartHandle cast(Signature incoming) { return new SmartHandle(incoming, MethodHandles.explicitCastArguments(handle, incoming.type())); }
/** * Terminate this binder by invoking the given target handle. The signature * of this binder is not compared to the signature of the given * SmartHandle. * * @param target the handle to invoke * @return a new SmartHandle with this binder's starting signature, bound * through to the given handle */ public SmartHandle invoke(SmartHandle target) { return new SmartHandle(start, binder.invoke(target.handle())); }
/** * Create a new SmartHandle that converts arguments from the given signature to * the current signature's type with the new argument names. This conversion * is equivalent to MethodHandle#asType. * * @param incoming the target MethodType from which arguments will be converted * @return a new SmartHandle that accepts the given argument types */ public SmartHandle convert(Signature incoming) { return new SmartHandle(incoming, handle.asType(incoming.type())); }
/** * Drop an argument from the handle at the given index, returning a new * SmartHandle. * * @param index index before which the dropped argument goes * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle drop(int index, String newName, Class<?> type) { return new SmartHandle(signature.insertArg(index, newName, type), MethodHandles.dropArguments(handle, index, type)); }
/** * Bind the first argument of this SmartHandle to the given object, * returning a new adapted handle. * * @param obj the object to which to bind this handle's first argument * @return a new SmartHandle with the first argument dropped in favor of obj */ public SmartHandle bindTo(Object obj) { return new SmartHandle(signature.dropFirst(), handle.bindTo(obj)); }
/** * Apply an argument into the handle at the given index, returning a new * SmartHandle. The new handle will use the given value for the argument at * the given index, accepting one fewer argument as a result. In other words, * fix that argument (partial application) into the given handle. * * @param index the index of the argument in the new SmartHandle's Signature * @param arg the argument value * @return a new SmartHandle that already has applied the given argument */ public SmartHandle apply(int index, Object arg) { return new SmartHandle(signature.dropArg(index), MethodHandles.insertArguments(handle, index, arg)); }
/** * Replace the return value with the given value, performing no other * processing of the original value. * * @param type the type for the new return value * @param value the new value to return * @return a new SmartHandle that returns the given value */ public SmartHandle returnValue(Class<?> type, Object value) { return new SmartHandle(signature.changeReturn(type), MethodHandles.filterReturnValue(handle, MethodHandles.constant(type, value))); }
/** * Apply an argument into the handle at the given name, returning a new * SmartHandle. The new handle will use the given value for the argument at * the given index, accepting one fewer argument as a result. In other words, * fix that argument (partial application) into the given handle. * * @param name the name of the argument in the new SmartHandle's Signature * @param arg the argument value * @return a new SmartHandle that already has applied the given argument */ public SmartHandle apply(String name, Object arg) { return new SmartHandle(signature.dropArg(name), MethodHandles.insertArguments(handle, signature.argOffset(name), arg)); }
/** * Drop an argument name and type from the handle at the given index, returning a new * SmartHandle. * * @param beforeName name before which the dropped argument goes * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle drop(String beforeName, String newName, Class<?> type) { return new SmartHandle(signature.insertArg(beforeName, newName, type), MethodHandles.dropArguments(handle, signature.argOffset(beforeName), type)); }
/** * Drop an argument from the handle at the end, returning a new * SmartHandle. * * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle dropLast(String newName, Class<?> type) { return new SmartHandle(signature.appendArg(newName, type), MethodHandles.dropArguments(handle, signature.argOffset(newName), type)); }
/** * Apply an argument into the handle at the end, returning a new * SmartHandle. The new handle will use the given value for the last * argument, accepting one fewer argument as a result. In other words, * fix that argument (partial application) into the given handle. * * @param arg the argument value * @return a new SmartHandle that already has applied the given argument */ public SmartHandle applyLast(Object arg) { return new SmartHandle(signature.dropLast(), MethodHandles.insertArguments(handle, signature.type().parameterCount(), arg)); }
/** * Create a new SmartHandle that casts arguments from the given type to * the current signature's type, using the same argument names. This casting * is equivalent to MethodHandles#explicitCastArguments. * * @param incoming the target MethodType from which arguments will be converted * @return a new SmartHandle that accepts the given argument types */ public SmartHandle cast(MethodType incoming) { return new SmartHandle(new Signature(incoming, signature.argNames()), MethodHandles.explicitCastArguments(handle, incoming)); }
/** * Create a new SmartHandle that converts arguments from the given type to * the current signature's type, using the same argument names. This conversion * is equivalent to MethodHandle#asType. * * @param incoming the target MethodType from which arguments will be converted * @return a new SmartHandle that accepts the given argument types */ public SmartHandle convert(MethodType incoming) { return new SmartHandle(new Signature(incoming, signature.argNames()), handle.asType(incoming)); }
/** * Produce a new SmartHandle by permuting this Signature's arguments to the * Signature of a target SmartHandle. The new SmartHandle's signature will * match this one, permuting those arguments and invoking the target handle. * * @param target the SmartHandle to use as a permutation target * @return a new SmartHandle that permutes this Signature's args into a call * to the target SmartHandle. * @see Signature#permuteWith(java.lang.invoke.MethodHandle, java.lang.String[]) */ public SmartHandle permuteWith(SmartHandle target) { String[] argNames = target.signature().argNames(); return new SmartHandle(this, permuteWith(target.handle(), argNames)); }