import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class LoopExampleTest1 {

    public static void main(String[] args) throws Throwable {
        new LoopExampleTest1().call();
    }

    private void call() throws Throwable {
        MethodHandle[] counterClause = new MethodHandle[]{
                null,
                MethodHandles.lookup().findVirtual(LoopExampleTest1.class, "inc", MethodType.methodType(int.class, int.class, int.class, int.class)).bindTo(this)
        };
        MethodHandle[] accumulatorClause = new MethodHandle[]{
                MethodHandles.lookup().findStatic(LoopExampleTest1.class, "one", MethodType.methodType(int.class, int.class)),
                MethodHandles.lookup().findVirtual(LoopExampleTest1.class, "mult", MethodType.methodType(int.class, int.class, int.class, int.class)).bindTo(this),
                MethodHandles.lookup().findVirtual(LoopExampleTest1.class, "pred", MethodType.methodType(boolean.class, int.class, int.class, int.class)).bindTo(this),
                MethodHandles.lookup().findVirtual(LoopExampleTest1.class, "fin", MethodType.methodType(int.class, int.class, int.class, int.class)).bindTo(this)
        };
        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);

        Object invoke = loop.invoke(5);

        System.out.println(invoke);
    }

    public static int one(int k) {
        return 1;
    }

    int inc(int i, int acc, int k) {
        return i + 1;
    }

    int mult(int i, int acc, int k) {
        return i * acc;
    }

    boolean pred(int i, int acc, int k) {
        return i < k;
    }

    int fin(int i, int acc, int k) {
        return acc;
    }

}
