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 defaultResultHandle = init == null || init.type().returnType() == void.class ?
4480 zero(void.class) :
4481 identity(init.type().returnType());
4482 MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;
4483 MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);
4484 MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4485 MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred),
4486 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
|
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 Class<?> resultType;
4480 MethodHandle actualInit;
4481 if (init == null) {
4482 resultType = body == null ? void.class : body.type().returnType();
4483 actualInit = empty(methodType(resultType));
4484 } else {
4485 resultType = init.type().returnType();
4486 actualInit = init;
4487 }
4488 MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType);
4489 MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;
4490 MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);
4491 MethodHandle actualEnd = end == null ? constant(int.class, 0) : end;
4492 MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4493 MethodHandle[] loopLimit = {actualEnd, null,
4494 MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4495 MethodHandle[] bodyClause = {actualInit,
4496 filterArgument(dropArguments(actualBody, 1, int.class), 0,
4497 MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4498 return loop(indexVar, loopLimit, bodyClause);
4499 }
4500
4501 /**
4502 * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4503 * The iterator will be produced by the evaluation of the {@code iterator} handle.
4504 * This handle must have {@link java.util.Iterator} as its return type.
4505 * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4506 * and will be applied to a leading argument of the loop handle.
4507 * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4508 * The result of the loop execution is the final value of the additional local state
4509 * obtained by running {@code init}.
4510 * <p>
4511 * This is a convenience wrapper for the
4512 * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4513 * handle follow directly from those described for the latter.
4514 * <p>
4515 * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4516 * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the
|