2628 * It is an error if there are elements of {@code filters}
2629 * (null or not)
2630 * which do not correspond to argument positions in the target.
2631 * <p><b>Example:</b>
2632 * <blockquote><pre>{@code
2633 import static java.lang.invoke.MethodHandles.*;
2634 import static java.lang.invoke.MethodType.*;
2635 ...
2636 MethodHandle cat = lookup().findVirtual(String.class,
2637 "concat", methodType(String.class, String.class));
2638 MethodHandle upcase = lookup().findVirtual(String.class,
2639 "toUpperCase", methodType(String.class));
2640 assertEquals("xy", (String) cat.invokeExact("x", "y"));
2641 MethodHandle f0 = filterArguments(cat, 0, upcase);
2642 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
2643 MethodHandle f1 = filterArguments(cat, 1, upcase);
2644 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
2645 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
2646 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
2647 * }</pre></blockquote>
2648 * <p> Here is pseudocode for the resulting adapter:
2649 * <blockquote><pre>{@code
2650 * V target(P... p, A[i]... a[i], B... b);
2651 * A[i] filter[i](V[i]);
2652 * T adapter(P... p, V[i]... v[i], B... b) {
2653 * return target(p..., f[i](v[i])..., b...);
2654 * }
2655 * }</pre></blockquote>
2656 * <p>
2657 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2658 * variable-arity method handle}, even if the original target method handle was.
2659 *
2660 * @param target the method handle to invoke after arguments are filtered
2661 * @param pos the position of the first argument to filter
2662 * @param filters method handles to call initially on filtered arguments
2663 * @return method handle which incorporates the specified argument filtering logic
2664 * @throws NullPointerException if the target is null
2665 * or if the {@code filters} array is null
2666 * @throws IllegalArgumentException if a non-null element of {@code filters}
2667 * does not match a corresponding argument type of target as described above,
2668 * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
2669 * or if the resulting method handle's type would have
2670 * <a href="MethodHandle.html#maxarity">too many parameters</a>
2671 */
2672 public static
2673 MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
2745
2746 MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
2747 assertEquals("[strange]", (String) ts1.invokeExact("strange"));
2748
2749 MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
2750 assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
2751
2752 MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
2753 MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
2754 assertEquals("[top, [up, down], strange]",
2755 (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
2756
2757 MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
2758 assertEquals("[top, [up, down], [strange]]",
2759 (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
2760
2761 MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
2762 assertEquals("[top, [[up, down, strange], charm], bottom]",
2763 (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
2764 * }</pre></blockquote>
2765 * <p> Here is pseudocode for the resulting adapter:
2766 * <blockquote><pre>{@code
2767 * T target(A...,V,C...);
2768 * V filter(B...);
2769 * T adapter(A... a,B... b,C... c) {
2770 * V v = filter(b...);
2771 * return target(a...,v,c...);
2772 * }
2773 * // and if the filter has no arguments:
2774 * T target2(A...,V,C...);
2775 * V filter2();
2776 * T adapter2(A... a,C... c) {
2777 * V v = filter2();
2778 * return target2(a...,v,c...);
2779 * }
2780 * // and if the filter has a void return:
2781 * T target3(A...,C...);
2782 * void filter3(B...);
2783 * void adapter3(A... a,B... b,C... c) {
2784 * filter3(b...);
2785 * return target3(a...,c...);
2786 * }
2787 * }</pre></blockquote>
2788 * <p>
2789 * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
2790 * one which first "folds" the affected arguments, and then drops them, in separate
2791 * steps as follows:
2792 * <blockquote><pre>{@code
2793 * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
2794 * mh = MethodHandles.foldArguments(mh, coll); //step 1
2795 * }</pre></blockquote>
2796 * If the target method handle consumes no arguments besides than the result
2797 * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
2798 * is equivalent to {@code filterReturnValue(coll, mh)}.
2799 * If the filter method handle {@code coll} consumes one argument and produces
2800 * a non-void result, then {@code collectArguments(mh, N, coll)}
2801 * is equivalent to {@code filterArguments(mh, N, coll)}.
2802 * Other equivalences are possible but would require argument permutation.
2803 * <p>
2859 * If the target returns void, the filter must accept no arguments.
2860 * <p>
2861 * The return type of the filter
2862 * replaces the return type of the target
2863 * in the resulting adapted method handle.
2864 * The argument type of the filter (if any) must be identical to the
2865 * return type of the target.
2866 * <p><b>Example:</b>
2867 * <blockquote><pre>{@code
2868 import static java.lang.invoke.MethodHandles.*;
2869 import static java.lang.invoke.MethodType.*;
2870 ...
2871 MethodHandle cat = lookup().findVirtual(String.class,
2872 "concat", methodType(String.class, String.class));
2873 MethodHandle length = lookup().findVirtual(String.class,
2874 "length", methodType(int.class));
2875 System.out.println((String) cat.invokeExact("x", "y")); // xy
2876 MethodHandle f0 = filterReturnValue(cat, length);
2877 System.out.println((int) f0.invokeExact("x", "y")); // 2
2878 * }</pre></blockquote>
2879 * <p> Here is pseudocode for the resulting adapter:
2880 * <blockquote><pre>{@code
2881 * V target(A...);
2882 * T filter(V);
2883 * T adapter(A... a) {
2884 * V v = target(a...);
2885 * return filter(v);
2886 * }
2887 * // and if the target has a void return:
2888 * void target2(A...);
2889 * T filter2();
2890 * T adapter2(A... a) {
2891 * target2(a...);
2892 * return filter2();
2893 * }
2894 * // and if the filter has a void return:
2895 * V target3(A...);
2896 * void filter3(V);
2897 * void adapter3(A... a) {
2898 * V v = target3(a...);
2899 * filter3(v);
2900 * }
2901 * }</pre></blockquote>
2902 * <p>
2903 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2904 * variable-arity method handle}, even if the original target method handle was.
2905 * @param target the method handle to invoke before filtering the return value
2906 * @param filter method handle to call on the return value
2907 * @return method handle which incorporates the specified return value filtering logic
2908 * @throws NullPointerException if either argument is null
2909 * @throws IllegalArgumentException if the argument list of {@code filter}
2910 * does not match the return type of target as described above
2911 */
2912 public static
2913 MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
2914 MethodType targetType = target.type();
2915 MethodType filterType = filter.type();
2916 filterReturnValueChecks(targetType, filterType);
2917 BoundMethodHandle result = target.rebind();
2918 BasicType rtype = BasicType.basicType(filterType.returnType());
2919 LambdaForm lform = result.editor().filterReturnForm(rtype, false);
2962 * that either the combiner or the target does not wish to receive.
2963 * If some of the incoming arguments are destined only for the combiner,
2964 * consider using {@link MethodHandle#asCollector asCollector} instead, since those
2965 * arguments will not need to be live on the stack on entry to the
2966 * target.)
2967 * <p><b>Example:</b>
2968 * <blockquote><pre>{@code
2969 import static java.lang.invoke.MethodHandles.*;
2970 import static java.lang.invoke.MethodType.*;
2971 ...
2972 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
2973 "println", methodType(void.class, String.class))
2974 .bindTo(System.out);
2975 MethodHandle cat = lookup().findVirtual(String.class,
2976 "concat", methodType(String.class, String.class));
2977 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
2978 MethodHandle catTrace = foldArguments(cat, trace);
2979 // also prints "boo":
2980 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
2981 * }</pre></blockquote>
2982 * <p> Here is pseudocode for the resulting adapter:
2983 * <blockquote><pre>{@code
2984 * // there are N arguments in A...
2985 * T target(V, A[N]..., B...);
2986 * V combiner(A...);
2987 * T adapter(A... a, B... b) {
2988 * V v = combiner(a...);
2989 * return target(v, a..., b...);
2990 * }
2991 * // and if the combiner has a void return:
2992 * T target2(A[N]..., B...);
2993 * void combiner2(A...);
2994 * T adapter2(A... a, B... b) {
2995 * combiner2(a...);
2996 * return target2(a..., b...);
2997 * }
2998 * }</pre></blockquote>
2999 * <p>
3000 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3001 * variable-arity method handle}, even if the original target method handle was.
3002 * @param target the method handle to invoke after arguments are combined
3023 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3024 if (ok && !(combinerType.parameterList()
3025 .equals(targetType.parameterList().subList(afterInsertPos,
3026 afterInsertPos + foldArgs))))
3027 ok = false;
3028 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3029 ok = false;
3030 if (!ok)
3031 throw misMatchedTypes("target and combiner types", targetType, combinerType);
3032 return rtype;
3033 }
3034
3035 /**
3036 * Makes a method handle which adapts a target method handle,
3037 * by guarding it with a test, a boolean-valued method handle.
3038 * If the guard fails, a fallback handle is called instead.
3039 * All three method handles must have the same corresponding
3040 * argument and return types, except that the return type
3041 * of the test must be boolean, and the test is allowed
3042 * to have fewer arguments than the other two method handles.
3043 * <p> Here is pseudocode for the resulting adapter:
3044 * <blockquote><pre>{@code
3045 * boolean test(A...);
3046 * T target(A...,B...);
3047 * T fallback(A...,B...);
3048 * T adapter(A... a,B... b) {
3049 * if (test(a...))
3050 * return target(a..., b...);
3051 * else
3052 * return fallback(a..., b...);
3053 * }
3054 * }</pre></blockquote>
3055 * Note that the test arguments ({@code a...} in the pseudocode) cannot
3056 * be modified by execution of the test, and so are passed unchanged
3057 * from the caller to the target or fallback as appropriate.
3058 * @param test method handle used for test, must return boolean
3059 * @param target method handle to call if test passes
3060 * @param fallback method handle to call if test fails
3061 * @return method handle which incorporates the specified if/then/else logic
3062 * @throws NullPointerException if any argument is null
3063 * @throws IllegalArgumentException if {@code test} does not return boolean,
3085 gtype = test.type();
3086 }
3087 return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
3088 }
3089
3090 static <T> RuntimeException misMatchedTypes(String what, T t1, T t2) {
3091 return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
3092 }
3093
3094 /**
3095 * Makes a method handle which adapts a target method handle,
3096 * by running it inside an exception handler.
3097 * If the target returns normally, the adapter returns that value.
3098 * If an exception matching the specified type is thrown, the fallback
3099 * handle is called instead on the exception, plus the original arguments.
3100 * <p>
3101 * The target and handler must have the same corresponding
3102 * argument and return types, except that handler may omit trailing arguments
3103 * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
3104 * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
3105 * <p> Here is pseudocode for the resulting adapter:
3106 * <blockquote><pre>{@code
3107 * T target(A..., B...);
3108 * T handler(ExType, A...);
3109 * T adapter(A... a, B... b) {
3110 * try {
3111 * return target(a..., b...);
3112 * } catch (ExType ex) {
3113 * return handler(ex, a...);
3114 * }
3115 * }
3116 * }</pre></blockquote>
3117 * Note that the saved arguments ({@code a...} in the pseudocode) cannot
3118 * be modified by execution of the target, and so are passed unchanged
3119 * from the caller to the handler, if the handler is invoked.
3120 * <p>
3121 * The target and handler must return the same type, even if the handler
3122 * always throws. (This might happen, for instance, because the handler
3123 * is simulating a {@code finally} clause).
3124 * To create such a throwing handler, compose the handler creation logic
3125 * with {@link #throwException throwException},
3934 * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
3935 * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
3936 * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
3937 * 0.
3938 * <p>
3939 * @apiNote Example:
3940 * <blockquote><pre>{@code
3941 import static java.lang.invoke.MethodHandles.*;
3942 import static java.lang.invoke.MethodType.*;
3943 ...
3944 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
3945 "println", methodType(void.class, String.class))
3946 .bindTo(System.out);
3947 MethodHandle cat = lookup().findVirtual(String.class,
3948 "concat", methodType(String.class, String.class));
3949 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3950 MethodHandle catTrace = foldArguments(cat, 1, trace);
3951 // also prints "jum":
3952 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3953 * }</pre></blockquote>
3954 * <p> Here is pseudocode for the resulting adapter:
3955 * <blockquote><pre>{@code
3956 * // there are N arguments in A...
3957 * T target(Z..., V, A[N]..., B...);
3958 * V combiner(A...);
3959 * T adapter(Z... z, A... a, B... b) {
3960 * V v = combiner(a...);
3961 * return target(z..., v, a..., b...);
3962 * }
3963 * // and if the combiner has a void return:
3964 * T target2(Z..., A[N]..., B...);
3965 * void combiner2(A...);
3966 * T adapter2(Z... z, A... a, B... b) {
3967 * combiner2(a...);
3968 * return target2(z..., a..., b...);
3969 * }
3970 * }</pre></blockquote>
3971 * <p>
3972 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3973 * variable-arity method handle}, even if the original target method handle was.
3974 *
|
2628 * It is an error if there are elements of {@code filters}
2629 * (null or not)
2630 * which do not correspond to argument positions in the target.
2631 * <p><b>Example:</b>
2632 * <blockquote><pre>{@code
2633 import static java.lang.invoke.MethodHandles.*;
2634 import static java.lang.invoke.MethodType.*;
2635 ...
2636 MethodHandle cat = lookup().findVirtual(String.class,
2637 "concat", methodType(String.class, String.class));
2638 MethodHandle upcase = lookup().findVirtual(String.class,
2639 "toUpperCase", methodType(String.class));
2640 assertEquals("xy", (String) cat.invokeExact("x", "y"));
2641 MethodHandle f0 = filterArguments(cat, 0, upcase);
2642 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
2643 MethodHandle f1 = filterArguments(cat, 1, upcase);
2644 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
2645 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
2646 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
2647 * }</pre></blockquote>
2648 * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
2649 * denotes the return type of both the {@code target} and resulting adapter.
2650 * {@code P}/{@code p} and {@code B}/{@code b} represent the types / values
2651 * of the parameters / arguments that precede / follow the filter position
2652 * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types /
2653 * values of the filtered parameters / arguments; they also represent the
2654 * return types of the {@code filter[i]} handles. The latter accept arguments
2655 * {@code v[i]} of type {@code V[i]}, which also appear in the signature of
2656 * the resulting adapter.
2657 * <blockquote><pre>{@code
2658 * T target(P... p, A[i]... a[i], B... b);
2659 * A[i] filter[i](V[i]);
2660 * T adapter(P... p, V[i]... v[i], B... b) {
2661 * return target(p..., filter[i](v[i])..., b...);
2662 * }
2663 * }</pre></blockquote>
2664 * <p>
2665 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2666 * variable-arity method handle}, even if the original target method handle was.
2667 *
2668 * @param target the method handle to invoke after arguments are filtered
2669 * @param pos the position of the first argument to filter
2670 * @param filters method handles to call initially on filtered arguments
2671 * @return method handle which incorporates the specified argument filtering logic
2672 * @throws NullPointerException if the target is null
2673 * or if the {@code filters} array is null
2674 * @throws IllegalArgumentException if a non-null element of {@code filters}
2675 * does not match a corresponding argument type of target as described above,
2676 * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
2677 * or if the resulting method handle's type would have
2678 * <a href="MethodHandle.html#maxarity">too many parameters</a>
2679 */
2680 public static
2681 MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
2753
2754 MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
2755 assertEquals("[strange]", (String) ts1.invokeExact("strange"));
2756
2757 MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
2758 assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
2759
2760 MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
2761 MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
2762 assertEquals("[top, [up, down], strange]",
2763 (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
2764
2765 MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
2766 assertEquals("[top, [up, down], [strange]]",
2767 (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
2768
2769 MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
2770 assertEquals("[top, [[up, down, strange], charm], bottom]",
2771 (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
2772 * }</pre></blockquote>
2773 * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
2774 * represents the return type of the {@code target} and resulting adapter.
2775 * {@code V}/{@code v} stand for the return type and value of the
2776 * {@code filter}, which are also found in the signature and arguments of
2777 * the {@code target}, respectively, unless {@code V} is {@code void}.
2778 * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types
2779 * and values preceding and following the collection position, {@code pos},
2780 * in the {@code target}'s signature. They also turn up in the resulting
2781 * adapter's signature and arguments, where they surround
2782 * {@code B}/{@code b}, which represent the parameter types and arguments
2783 * to the {@code filter} (if any).
2784 * <blockquote><pre>{@code
2785 * T target(A...,V,C...);
2786 * V filter(B...);
2787 * T adapter(A... a,B... b,C... c) {
2788 * V v = filter(b...);
2789 * return target(a...,v,c...);
2790 * }
2791 * // and if the filter has no arguments:
2792 * T target2(A...,V,C...);
2793 * V filter2();
2794 * T adapter2(A... a,C... c) {
2795 * V v = filter2();
2796 * return target2(a...,v,c...);
2797 * }
2798 * // and if the filter has a void return:
2799 * T target3(A...,C...);
2800 * void filter3(B...);
2801 * T adapter3(A... a,B... b,C... c) {
2802 * filter3(b...);
2803 * return target3(a...,c...);
2804 * }
2805 * }</pre></blockquote>
2806 * <p>
2807 * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
2808 * one which first "folds" the affected arguments, and then drops them, in separate
2809 * steps as follows:
2810 * <blockquote><pre>{@code
2811 * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
2812 * mh = MethodHandles.foldArguments(mh, coll); //step 1
2813 * }</pre></blockquote>
2814 * If the target method handle consumes no arguments besides than the result
2815 * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
2816 * is equivalent to {@code filterReturnValue(coll, mh)}.
2817 * If the filter method handle {@code coll} consumes one argument and produces
2818 * a non-void result, then {@code collectArguments(mh, N, coll)}
2819 * is equivalent to {@code filterArguments(mh, N, coll)}.
2820 * Other equivalences are possible but would require argument permutation.
2821 * <p>
2877 * If the target returns void, the filter must accept no arguments.
2878 * <p>
2879 * The return type of the filter
2880 * replaces the return type of the target
2881 * in the resulting adapted method handle.
2882 * The argument type of the filter (if any) must be identical to the
2883 * return type of the target.
2884 * <p><b>Example:</b>
2885 * <blockquote><pre>{@code
2886 import static java.lang.invoke.MethodHandles.*;
2887 import static java.lang.invoke.MethodType.*;
2888 ...
2889 MethodHandle cat = lookup().findVirtual(String.class,
2890 "concat", methodType(String.class, String.class));
2891 MethodHandle length = lookup().findVirtual(String.class,
2892 "length", methodType(int.class));
2893 System.out.println((String) cat.invokeExact("x", "y")); // xy
2894 MethodHandle f0 = filterReturnValue(cat, length);
2895 System.out.println((int) f0.invokeExact("x", "y")); // 2
2896 * }</pre></blockquote>
2897 * <p>Here is pseudocode for the resulting adapter. In the code,
2898 * {@code T}/{@code t} represent the result type and value of the
2899 * {@code target}; {@code V}, the result type of the {@code filter}; and
2900 * {@code A}/{@code a}, the types / values of the parameters / arguments
2901 * of the {@code target} as well as the resulting adapter.
2902 * <blockquote><pre>{@code
2903 * T target(A...);
2904 * V filter(T);
2905 * V adapter(A... a) {
2906 * T t = target(a...);
2907 * return filter(t);
2908 * }
2909 * // and if the target has a void return:
2910 * void target2(A...);
2911 * V filter2();
2912 * V adapter2(A... a) {
2913 * target2(a...);
2914 * return filter2();
2915 * }
2916 * // and if the filter has a void return:
2917 * T target3(A...);
2918 * void filter3(V);
2919 * void adapter3(A... a) {
2920 * T t = target3(a...);
2921 * filter3(t);
2922 * }
2923 * }</pre></blockquote>
2924 * <p>
2925 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2926 * variable-arity method handle}, even if the original target method handle was.
2927 * @param target the method handle to invoke before filtering the return value
2928 * @param filter method handle to call on the return value
2929 * @return method handle which incorporates the specified return value filtering logic
2930 * @throws NullPointerException if either argument is null
2931 * @throws IllegalArgumentException if the argument list of {@code filter}
2932 * does not match the return type of target as described above
2933 */
2934 public static
2935 MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
2936 MethodType targetType = target.type();
2937 MethodType filterType = filter.type();
2938 filterReturnValueChecks(targetType, filterType);
2939 BoundMethodHandle result = target.rebind();
2940 BasicType rtype = BasicType.basicType(filterType.returnType());
2941 LambdaForm lform = result.editor().filterReturnForm(rtype, false);
2984 * that either the combiner or the target does not wish to receive.
2985 * If some of the incoming arguments are destined only for the combiner,
2986 * consider using {@link MethodHandle#asCollector asCollector} instead, since those
2987 * arguments will not need to be live on the stack on entry to the
2988 * target.)
2989 * <p><b>Example:</b>
2990 * <blockquote><pre>{@code
2991 import static java.lang.invoke.MethodHandles.*;
2992 import static java.lang.invoke.MethodType.*;
2993 ...
2994 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
2995 "println", methodType(void.class, String.class))
2996 .bindTo(System.out);
2997 MethodHandle cat = lookup().findVirtual(String.class,
2998 "concat", methodType(String.class, String.class));
2999 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3000 MethodHandle catTrace = foldArguments(cat, trace);
3001 // also prints "boo":
3002 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3003 * }</pre></blockquote>
3004 * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3005 * represents the result type of the {@code target} and resulting adapter.
3006 * {@code V}/{@code v} represent the type / value of the parameter / argument
3007 * of {@code target} that precedes the folding position; {@code V} also is
3008 * the result type of the {@code combiner}. {@code A}/{@code a} denote the
3009 * types / values of the {@code N} parameters / arguments at the folding
3010 * position. {@code B}/{@code b} represent the types / values of the
3011 * {@code target} parameters / arguments that follow the folded parameters /
3012 * arguments.
3013 * <blockquote><pre>{@code
3014 * // there are N arguments in A...
3015 * T target(V, A[N]..., B...);
3016 * V combiner(A...);
3017 * T adapter(A... a, B... b) {
3018 * V v = combiner(a...);
3019 * return target(v, a..., b...);
3020 * }
3021 * // and if the combiner has a void return:
3022 * T target2(A[N]..., B...);
3023 * void combiner2(A...);
3024 * T adapter2(A... a, B... b) {
3025 * combiner2(a...);
3026 * return target2(a..., b...);
3027 * }
3028 * }</pre></blockquote>
3029 * <p>
3030 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3031 * variable-arity method handle}, even if the original target method handle was.
3032 * @param target the method handle to invoke after arguments are combined
3053 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3054 if (ok && !(combinerType.parameterList()
3055 .equals(targetType.parameterList().subList(afterInsertPos,
3056 afterInsertPos + foldArgs))))
3057 ok = false;
3058 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3059 ok = false;
3060 if (!ok)
3061 throw misMatchedTypes("target and combiner types", targetType, combinerType);
3062 return rtype;
3063 }
3064
3065 /**
3066 * Makes a method handle which adapts a target method handle,
3067 * by guarding it with a test, a boolean-valued method handle.
3068 * If the guard fails, a fallback handle is called instead.
3069 * All three method handles must have the same corresponding
3070 * argument and return types, except that the return type
3071 * of the test must be boolean, and the test is allowed
3072 * to have fewer arguments than the other two method handles.
3073 * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3074 * represents the uniform result type of the three involved handles;
3075 * {@code A}/{@code a}, the types / values of the {@code target}
3076 * parameters / arguments that are consumed by the {@code test}; and
3077 * {@code B}/{@code b}, those types / values of the {@code target}
3078 * parameters / arguments that are not consumed by the {@code test}.
3079 * <blockquote><pre>{@code
3080 * boolean test(A...);
3081 * T target(A...,B...);
3082 * T fallback(A...,B...);
3083 * T adapter(A... a,B... b) {
3084 * if (test(a...))
3085 * return target(a..., b...);
3086 * else
3087 * return fallback(a..., b...);
3088 * }
3089 * }</pre></blockquote>
3090 * Note that the test arguments ({@code a...} in the pseudocode) cannot
3091 * be modified by execution of the test, and so are passed unchanged
3092 * from the caller to the target or fallback as appropriate.
3093 * @param test method handle used for test, must return boolean
3094 * @param target method handle to call if test passes
3095 * @param fallback method handle to call if test fails
3096 * @return method handle which incorporates the specified if/then/else logic
3097 * @throws NullPointerException if any argument is null
3098 * @throws IllegalArgumentException if {@code test} does not return boolean,
3120 gtype = test.type();
3121 }
3122 return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
3123 }
3124
3125 static <T> RuntimeException misMatchedTypes(String what, T t1, T t2) {
3126 return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
3127 }
3128
3129 /**
3130 * Makes a method handle which adapts a target method handle,
3131 * by running it inside an exception handler.
3132 * If the target returns normally, the adapter returns that value.
3133 * If an exception matching the specified type is thrown, the fallback
3134 * handle is called instead on the exception, plus the original arguments.
3135 * <p>
3136 * The target and handler must have the same corresponding
3137 * argument and return types, except that handler may omit trailing arguments
3138 * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
3139 * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
3140 * <p>
3141 * Here is pseudocode for the resulting adapter. In the code, {@code T}
3142 * represents the return type of the {@code target} and {@code handler},
3143 * and correspondingly that of the resulting adapter; {@code A}/{@code a},
3144 * the types and values of arguments to the resulting handle consumed by
3145 * {@code handler}; and {@code B}/{@code b}, those of arguments to the
3146 * resulting handle discarded by {@code handler}.
3147 * <blockquote><pre>{@code
3148 * T target(A..., B...);
3149 * T handler(ExType, A...);
3150 * T adapter(A... a, B... b) {
3151 * try {
3152 * return target(a..., b...);
3153 * } catch (ExType ex) {
3154 * return handler(ex, a...);
3155 * }
3156 * }
3157 * }</pre></blockquote>
3158 * Note that the saved arguments ({@code a...} in the pseudocode) cannot
3159 * be modified by execution of the target, and so are passed unchanged
3160 * from the caller to the handler, if the handler is invoked.
3161 * <p>
3162 * The target and handler must return the same type, even if the handler
3163 * always throws. (This might happen, for instance, because the handler
3164 * is simulating a {@code finally} clause).
3165 * To create such a throwing handler, compose the handler creation logic
3166 * with {@link #throwException throwException},
3975 * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
3976 * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
3977 * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
3978 * 0.
3979 * <p>
3980 * @apiNote Example:
3981 * <blockquote><pre>{@code
3982 import static java.lang.invoke.MethodHandles.*;
3983 import static java.lang.invoke.MethodType.*;
3984 ...
3985 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
3986 "println", methodType(void.class, String.class))
3987 .bindTo(System.out);
3988 MethodHandle cat = lookup().findVirtual(String.class,
3989 "concat", methodType(String.class, String.class));
3990 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3991 MethodHandle catTrace = foldArguments(cat, 1, trace);
3992 // also prints "jum":
3993 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3994 * }</pre></blockquote>
3995 * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3996 * represents the result type of the {@code target} and resulting adapter.
3997 * {@code V}/{@code v} represent the type / value of the parameter / argument
3998 * of {@code target} that precedes the folding position; {@code V} also is
3999 * the result type of the {@code combiner}. {@code A}/{@code a} denote the
4000 * types / values of the {@code N} parameters / arguments at the folding
4001 * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
4002 * / values of the {@code target} parameters / arguments that precede and
4003 * follow the folded parameters / arguments starting at {@code pos},
4004 * respectively.
4005 * <blockquote><pre>{@code
4006 * // there are N arguments in A...
4007 * T target(Z..., V, A[N]..., B...);
4008 * V combiner(A...);
4009 * T adapter(Z... z, A... a, B... b) {
4010 * V v = combiner(a...);
4011 * return target(z..., v, a..., b...);
4012 * }
4013 * // and if the combiner has a void return:
4014 * T target2(Z..., A[N]..., B...);
4015 * void combiner2(A...);
4016 * T adapter2(Z... z, A... a, B... b) {
4017 * combiner2(a...);
4018 * return target2(z..., a..., b...);
4019 * }
4020 * }</pre></blockquote>
4021 * <p>
4022 * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
4023 * variable-arity method handle}, even if the original target method handle was.
4024 *
|