217 assertEquals(23, loop.invoke(23));
218 }
219
220 @Test
221 public static void testWhileLoopNoIteration() throws Throwable {
222 // a while loop that never executes its body because the predicate evaluates to false immediately
223 MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
224 assertEquals(While.MT_string, loop.type());
225 assertEquals("a", loop.invoke());
226 }
227
228 @Test
229 public static void testDoWhileLoop() throws Throwable {
230 // int i = 0; do { ++i; } while (i < limit); return i; => limit
231 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
232 assertEquals(While.MT_while, loop.type());
233 assertEquals(23, loop.invoke(23));
234 }
235
236 @Test
237 public static void testWhileZip() throws Throwable {
238 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
239 assertEquals(While.MT_zip, loop.type());
240 List<String> a = Arrays.asList("a", "b", "c", "d");
241 List<String> b = Arrays.asList("e", "f", "g", "h");
242 List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
243 assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
244 }
245
246 @Test
247 public static void testCountedLoop() throws Throwable {
248 // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
249 MethodHandle fit13 = MethodHandles.constant(int.class, 13);
250 MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
251 assertEquals(Counted.MT_counted, loop.type());
252 assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
253 }
254
255 @Test
256 public static void testCountedArrayLoop() throws Throwable {
257 // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
258 MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
259 MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
260 assertEquals(Counted.MT_arrayCounted, loop.type());
261 int[] a = new int[]{0};
262 loop.invoke(a);
263 assertEquals(13, a[0]);
264 }
265
266 @Test
551 }
552
553 static String stepString(String s) {
554 return s + "a";
555 }
556
557 static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
558 return new ArrayList<>();
559 }
560
561 static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
562 return a.hasNext() && b.hasNext();
563 }
564
565 static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
566 zip.add(a.next());
567 zip.add(b.next());
568 return zip;
569 }
570
571 static final Class<While> WHILE = While.class;
572
573 static final MethodType MT_zero = methodType(int.class, int.class);
574 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
575 static final MethodType MT_fn = methodType(int.class, int.class, int.class);
576 static final MethodType MT_initString = methodType(String.class);
577 static final MethodType MT_predString = methodType(boolean.class, String.class);
578 static final MethodType MT_stepString = methodType(String.class, String.class);
579 static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
580 static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
581 static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
582
583 static final MethodHandle MH_zero;
584 static final MethodHandle MH_pred;
585 static final MethodHandle MH_step;
586 static final MethodHandle MH_initString;
587 static final MethodHandle MH_predString;
588 static final MethodHandle MH_stepString;
589 static final MethodHandle MH_zipInitZip;
590 static final MethodHandle MH_zipPred;
591 static final MethodHandle MH_zipStep;
592
593 static final MethodType MT_while = methodType(int.class, int.class);
594 static final MethodType MT_string = methodType(String.class);
595 static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
596
597 static {
598 try {
599 MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
600 MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
601 MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
602 MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
603 MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
604 MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
605 MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
606 MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
607 MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
608 } catch (Exception e) {
609 throw new ExceptionInInitializerError(e);
610 }
611 }
612
613 }
614
615 static class Counted {
616
617 static String start(String arg) {
618 return arg;
619 }
620
621 static String step(int counter, String v, String arg) {
622 return "na " + v;
623 }
624
625 static void stepUpdateArray(int counter, int[] a) {
626 ++a[0];
627 }
|
217 assertEquals(23, loop.invoke(23));
218 }
219
220 @Test
221 public static void testWhileLoopNoIteration() throws Throwable {
222 // a while loop that never executes its body because the predicate evaluates to false immediately
223 MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
224 assertEquals(While.MT_string, loop.type());
225 assertEquals("a", loop.invoke());
226 }
227
228 @Test
229 public static void testDoWhileLoop() throws Throwable {
230 // int i = 0; do { ++i; } while (i < limit); return i; => limit
231 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
232 assertEquals(While.MT_while, loop.type());
233 assertEquals(23, loop.invoke(23));
234 }
235
236 @Test
237 public static void testDoWhileNullInit() throws Throwable {
238 While w = new While();
239 MethodHandle loop = MethodHandles.doWhileLoop(null, While.MH_voidBody.bindTo(w), While.MH_voidPred.bindTo(w));
240 assertEquals(While.MT_void, loop.type());
241 loop.invoke(5);
242 }
243
244 @Test
245 public static void testWhileZip() throws Throwable {
246 MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
247 assertEquals(While.MT_zip, loop.type());
248 List<String> a = Arrays.asList("a", "b", "c", "d");
249 List<String> b = Arrays.asList("e", "f", "g", "h");
250 List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
251 assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
252 }
253
254 @Test
255 public static void testWhileNullInit() throws Throwable {
256 While w = new While();
257 MethodHandle loop = MethodHandles.whileLoop(null, While.MH_voidPred.bindTo(w), While.MH_voidBody.bindTo(w));
258 assertEquals(While.MT_void, loop.type());
259 loop.invoke(5);
260 }
261
262 @Test
263 public static void testCountedLoop() throws Throwable {
264 // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
265 MethodHandle fit13 = MethodHandles.constant(int.class, 13);
266 MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
267 assertEquals(Counted.MT_counted, loop.type());
268 assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
269 }
270
271 @Test
272 public static void testCountedArrayLoop() throws Throwable {
273 // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
274 MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
275 MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
276 assertEquals(Counted.MT_arrayCounted, loop.type());
277 int[] a = new int[]{0};
278 loop.invoke(a);
279 assertEquals(13, a[0]);
280 }
281
282 @Test
567 }
568
569 static String stepString(String s) {
570 return s + "a";
571 }
572
573 static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
574 return new ArrayList<>();
575 }
576
577 static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
578 return a.hasNext() && b.hasNext();
579 }
580
581 static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
582 zip.add(a.next());
583 zip.add(b.next());
584 return zip;
585 }
586
587 private int i = 0;
588
589 void voidBody(int k) {
590 ++i;
591 }
592
593 boolean voidPred(int k) {
594 return i < k;
595 }
596
597 static final Class<While> WHILE = While.class;
598
599 static final MethodType MT_zero = methodType(int.class, int.class);
600 static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
601 static final MethodType MT_fn = methodType(int.class, int.class, int.class);
602 static final MethodType MT_initString = methodType(String.class);
603 static final MethodType MT_predString = methodType(boolean.class, String.class);
604 static final MethodType MT_stepString = methodType(String.class, String.class);
605 static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
606 static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
607 static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
608 static final MethodType MT_voidBody = methodType(void.class, int.class);
609 static final MethodType MT_voidPred = methodType(boolean.class, int.class);
610
611 static final MethodHandle MH_zero;
612 static final MethodHandle MH_pred;
613 static final MethodHandle MH_step;
614 static final MethodHandle MH_initString;
615 static final MethodHandle MH_predString;
616 static final MethodHandle MH_stepString;
617 static final MethodHandle MH_zipInitZip;
618 static final MethodHandle MH_zipPred;
619 static final MethodHandle MH_zipStep;
620 static final MethodHandle MH_voidBody;
621 static final MethodHandle MH_voidPred;
622
623 static final MethodType MT_while = methodType(int.class, int.class);
624 static final MethodType MT_string = methodType(String.class);
625 static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
626 static final MethodType MT_void = methodType(void.class, int.class);
627
628 static {
629 try {
630 MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
631 MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
632 MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
633 MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
634 MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
635 MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
636 MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
637 MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
638 MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
639 MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody);
640 MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred);
641 } catch (Exception e) {
642 throw new ExceptionInInitializerError(e);
643 }
644 }
645
646 }
647
648 static class Counted {
649
650 static String start(String arg) {
651 return arg;
652 }
653
654 static String step(int counter, String v, String arg) {
655 return "na " + v;
656 }
657
658 static void stepUpdateArray(int counter, int[] a) {
659 ++a[0];
660 }
|