4459 * return loop(indexVar, loopLimit, bodyClause);
4460 * }
4461 * }</pre></blockquote>
4462 *
4463 * @param start a handle to return the start value of the loop counter.
4464 * If it is {@code null}, a constant zero is assumed.
4465 * @param end a non-{@code null} handle to return the end value of the loop counter (the loop will run to {@code end-1}).
4466 * @param init initializer for additional loop state. This determines the loop's result type.
4467 * Passing {@code null} or a {@code void} init function will make the loop's result type
4468 * {@code void}.
4469 * @param body the body of the loop, which must not be {@code null}.
4470 * It must accept an initial {@code int} parameter (for the counter), and then any
4471 * additional loop-local variable plus loop parameters.
4472 *
4473 * @return a method handle representing the loop.
4474 * @throws IllegalArgumentException if any argument has a type inconsistent with the loop structure
4475 *
4476 * @since 9
4477 */
4478 public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
4479 MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ?
4480 zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class);
4481 MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4482 MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4483 MethodHandle[] bodyClause = {init,
4484 filterArgument(dropArguments(body, 1, int.class), 0,
4485 MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4486 return loop(indexVar, loopLimit, bodyClause);
4487 }
4488
4489 /**
4490 * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4491 * The iterator will be produced by the evaluation of the {@code iterator} handle.
4492 * This handle must have {@link java.util.Iterator} as its return type.
4493 * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4494 * and will be applied to a leading argument of the loop handle.
4495 * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4496 * The result of the loop execution is the final value of the additional local state
4497 * obtained by running {@code init}.
4498 * <p>
4499 * This is a convenience wrapper for the
4500 * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4501 * handle follow directly from those described for the latter.
4502 * <p>
4503 * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4504 * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the
|
4459 * return loop(indexVar, loopLimit, bodyClause);
4460 * }
4461 * }</pre></blockquote>
4462 *
4463 * @param start a handle to return the start value of the loop counter.
4464 * If it is {@code null}, a constant zero is assumed.
4465 * @param end a non-{@code null} handle to return the end value of the loop counter (the loop will run to {@code end-1}).
4466 * @param init initializer for additional loop state. This determines the loop's result type.
4467 * Passing {@code null} or a {@code void} init function will make the loop's result type
4468 * {@code void}.
4469 * @param body the body of the loop, which must not be {@code null}.
4470 * It must accept an initial {@code int} parameter (for the counter), and then any
4471 * additional loop-local variable plus loop parameters.
4472 *
4473 * @return a method handle representing the loop.
4474 * @throws IllegalArgumentException if any argument has a type inconsistent with the loop structure
4475 *
4476 * @since 9
4477 */
4478 public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
4479 boolean voidReturn = init == null || init.type().returnType() == void.class;
4480 MethodHandle adaptedBody = body == null ?
4481 dropArguments(voidReturn ? zero(void.class) : identity(init.type().returnType()), 0, int.class) :
4482 body;
4483 MethodHandle returnVar = dropArguments(voidReturn ? zero(void.class) : identity(init.type().returnType()),
4484 0, int.class, int.class);
4485 MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4486 MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4487 MethodHandle[] bodyClause = {init,
4488 filterArgument(dropArguments(adaptedBody, 1, int.class), 0,
4489 MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4490 return loop(indexVar, loopLimit, bodyClause);
4491 }
4492
4493 /**
4494 * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4495 * The iterator will be produced by the evaluation of the {@code iterator} handle.
4496 * This handle must have {@link java.util.Iterator} as its return type.
4497 * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4498 * and will be applied to a leading argument of the loop handle.
4499 * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4500 * The result of the loop execution is the final value of the additional local state
4501 * obtained by running {@code init}.
4502 * <p>
4503 * This is a convenience wrapper for the
4504 * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4505 * handle follow directly from those described for the latter.
4506 * <p>
4507 * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4508 * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the
|