--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Dec 03 15:34:39 2015 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Dec 03 15:36:20 2015 +0100
@@ -3463,7 +3463,7 @@
* return zip;
* }
* // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods
- * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipPred, MH_zipStep);
+ * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
* List<String> a = Arrays.asList("a", "b", "c", "d");
* List<String> b = Arrays.asList("e", "f", "g", "h");
* List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
@@ -3602,7 +3602,8 @@
* String start(String arg) { return arg; }
* String step(int counter, String v, String arg) { return "na " + v; }
* // assume MH_start and MH_step are handles to the two methods above
- * MethodHandle loop = MethodHandles.countedLoop(13, MH_start, MH_step);
+ * MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+ * MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
* assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
* }</pre></blockquote>
*
@@ -3742,11 +3743,11 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // reverse a list
- * List<String> reverseStep(String e, List<String> r) {
+ * List<String> reverseStep(String e, List<String> r, List<String> l) {
* r.add(0, e);
* return r;
* }
- * List<String> newArrayList() { return new ArrayList<>(); }
+ * List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
* // assume MH_reverseStep, MH_newArrayList are handles to the above methods
* MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
* List<String> list = Arrays.asList("a", "b", "c", "d", "e");
--- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Thu Dec 03 15:34:39 2015 +0100
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Thu Dec 03 15:36:20 2015 +0100
@@ -29,6 +29,7 @@
package test.java.lang.invoke;
+import java.io.StringWriter;
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
@@ -36,7 +37,6 @@
import java.util.*;
import org.testng.*;
-import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
/**
@@ -322,6 +322,13 @@
Assert.assertEquals(exp, act);
}
+ static void assertTrue(boolean b) {
+ if (verbosity > 0) {
+ System.out.println("result: " + b);
+ }
+ Assert.assertTrue(b);
+ }
+
@Test public void testMethodHandlesSummary() throws Throwable {
{{
{} /// JAVADOC
@@ -639,6 +646,165 @@
}}
}
+ static int one(int k) { return 1; }
+ static int inc(int i, int acc, int k) { return i + 1; }
+ static int mult(int i, int acc, int k) { return i * acc; }
+ static boolean pred(int i, int acc, int k) { return i < k; }
+ static int fin(int i, int acc, int k) { return acc; }
+
+ @Test public void testLoop() throws Throwable {
+ MethodHandle MH_inc, MH_one, MH_mult, MH_pred, MH_fin;
+ Class<?> I = int.class;
+ MH_inc = LOOKUP.findStatic(THIS_CLASS, "inc", methodType(I, I, I, I));
+ MH_one = LOOKUP.findStatic(THIS_CLASS, "one", methodType(I, I));
+ MH_mult = LOOKUP.findStatic(THIS_CLASS, "mult", methodType(I, I, I, I));
+ MH_pred = LOOKUP.findStatic(THIS_CLASS, "pred", methodType(boolean.class, I, I, I));
+ MH_fin = LOOKUP.findStatic(THIS_CLASS, "fin", methodType(I, I, I, I));
+ {{
+{} /// JAVADOC
+// iterative implementation of the factorial function as a loop handle
+// null initializer for counter, should initialize to 0
+MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+assertEquals(120, loop.invoke(5));
+{}
+ }}
+ }
+
+ static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
+ static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
+ static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ zip.add(a.next());
+ zip.add(b.next());
+ return zip;
+ }
+
+ @Test public void testWhileLoop() throws Throwable {
+ MethodHandle MH_initZip, MH_zipPred, MH_zipStep;
+ Class<?> IT = Iterator.class;
+ Class<?> L = List.class;
+ MH_initZip = LOOKUP.findStatic(THIS_CLASS, "initZip", methodType(L, IT, IT));
+ MH_zipPred = LOOKUP.findStatic(THIS_CLASS, "zipPred", methodType(boolean.class, L, IT, IT));
+ MH_zipStep = LOOKUP.findStatic(THIS_CLASS, "zipStep", methodType(L, L, IT, IT));
+ {{
+{} /// JAVADOC
+// implement the zip function for lists as a loop handle
+MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
+List<String> a = Arrays.asList("a", "b", "c", "d");
+List<String> b = Arrays.asList("e", "f", "g", "h");
+List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+{}
+ }}
+ }
+
+ static int zero(int limit) { return 0; }
+ static int step(int i, int limit) { return i + 1; }
+ static boolean pred(int i, int limit) { return i < limit; }
+
+ @Test public void testDoWhileLoop() throws Throwable {
+ MethodHandle MH_zero, MH_step, MH_pred;
+ Class<?> I = int.class;
+ MH_zero = LOOKUP.findStatic(THIS_CLASS, "zero", methodType(I, I));
+ MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(I, I, I));
+ MH_pred = LOOKUP.findStatic(THIS_CLASS, "pred", methodType(boolean.class, I, I));
+ {{
+{} /// JAVADOC
+// int i = 0; while (i < limit) { ++i; } return i; => limit
+MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
+assertEquals(23, loop.invoke(23));
+{}
+ }}
+ }
+
+ static String start(String arg) { return arg; }
+ static String step(int counter, String v, String arg) { return "na " + v; }
+
+ @Test public void testCountedLoop() throws Throwable {
+ MethodHandle MH_start, MH_step;
+ Class<?> S = String.class;
+ MH_start = LOOKUP.findStatic(THIS_CLASS, "start", methodType(S, S));
+ MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(S, int.class, S, S));
+ {{
+{} /// JAVADOC
+// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
+// => a variation on a well known theme
+MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
+assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+{}
+ }}
+ }
+
+ static List<String> reverseStep(String e, List<String> r, List<String> l) {
+ r.add(0, e);
+ return r;
+ }
+ static List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
+
+ @Test public void testIteratedLoop() throws Throwable {
+ MethodHandle MH_newArrayList, MH_reverseStep;
+ Class<?> L = List.class;
+ MH_newArrayList = LOOKUP.findStatic(THIS_CLASS, "newArrayList", methodType(L, L));
+ MH_reverseStep = LOOKUP.findStatic(THIS_CLASS, "reverseStep", methodType(L, String.class, L, L));
+ {{
+{} /// JAVADOC
+// reverse a list
+MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
+List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+assertEquals(reversedList, (List<String>) loop.invoke(list));
+{}
+ }}
+ }
+
+ @Test public void testFoldArguments3() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+ "println", methodType(void.class, String.class))
+ .bindTo(System.out);
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+MethodHandle catTrace = foldArguments(cat, 1, trace);
+// also prints "jum":
+assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+{}
+ }}
+ }
+
+ @Test public void testAsCollector2() throws Throwable {
+ {{
+{} /// JAVADOC
+StringWriter swr = new StringWriter();
+MethodHandle swWrite = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).bindTo(swr);
+MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+assertEquals("BC", swr.toString());
+swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+assertEquals("BCPQRS", swr.toString());
+swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+assertEquals("BCPQRSZ", swr.toString());
+{}
+ }}
+ }
+
+ @Test public void testAsSpreader2() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+Object[] ints = new Object[]{3, 9, 7, 7};
+Comparator<Integer> cmp = (a, b) -> a - b;
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+{}
+ }}
+ }
+
/* ---- TEMPLATE ----
@Test public void testFoo() throws Throwable {
{{