1 /*
2 * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 import jdk.incubator.code.Reflect;
25 import java.util.function.Consumer;
26 import java.util.function.IntSupplier;
27 import java.util.function.Predicate;
28 import java.util.function.Supplier;
29
30 /*
31 * @test
32 * @summary Smoke test for code reflection with lambda expressions.
33 * @modules jdk.incubator.code
34 * @build LambdaTest
35 * @build CodeReflectionTester
36 * @run main CodeReflectionTester LambdaTest
37 */
38
39 public class LambdaTest {
40
41 @Reflect
42 @IR("""
43 func @"test1" (%0 : java.type:"LambdaTest")java.type:"void" -> {
44 %1 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isReflectable=true (%2 : java.type:"java.lang.String")java.type:"void" -> {
45 %3 : Var<java.type:"java.lang.String"> = var %2 @"s";
46 %4 : java.type:"java.io.PrintStream" = field.load @java.ref:"java.lang.System::out:java.io.PrintStream";
47 %5 : java.type:"java.lang.String" = var.load %3;
48 invoke %4 %5 @java.ref:"java.io.PrintStream::println(java.lang.String):void";
49 return;
50 };
51 %6 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %1 @"c";
52 %7 : java.type:"java.util.function.Consumer<java.lang.String>" = var.load %6;
53 %8 : java.type:"java.lang.String" = constant @"Hello World";
54 invoke %7 %8 @java.ref:"java.util.function.Consumer::accept(java.lang.Object):void";
55 return;
56 };
57 """)
58 void test1() {
59 Consumer<String> c = s -> {
60 System.out.println(s);
61 };
62 c.accept("Hello World");
63 }
64
65 @Reflect
66 @IR("""
67 func @"test2" (%0 : java.type:"LambdaTest")java.type:"void" -> {
68 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
69 %2 : java.type:"java.lang.String" = constant @"Hello World";
70 return %2;
71 };
72 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
73 %4 : java.type:"java.util.function.Supplier<java.lang.String>" = var.load %3;
74 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
75 %6 : Var<java.type:"java.lang.String"> = var %5 @"s";
76 return;
77 };
78 """)
79 void test2() {
80 Supplier<String> c = () -> {
81 return "Hello World";
82 };
83 String s = c.get();
84 }
85
86 @Reflect
87 @IR("""
88 func @"test3" (%0 : java.type:"LambdaTest")java.type:"void" -> {
89 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
90 %2 : java.type:"java.lang.String" = constant @"Hello World";
91 return %2;
92 };
93 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
94 return;
95 };
96 """)
97 void test3() {
98 Supplier<String> c = () -> "Hello World";
99 }
100
101 String s_f;
102
103 @Reflect
104 @IR("""
105 func @"test4" (%0 : java.type:"LambdaTest")java.type:"void" -> {
106 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
107 %2 : java.type:"java.lang.String" = field.load %0 @java.ref:"LambdaTest::s_f:java.lang.String";
108 return %2;
109 };
110 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
111 return;
112 };
113 """)
114 void test4() {
115 Supplier<String> c = () -> {
116 return s_f;
117 };
118 }
119
120 @Reflect
121 @IR("""
122 func @"test5" (%0 : java.type:"LambdaTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
123 %3 : Var<java.type:"int"> = var %1 @"i";
124 %4 : Var<java.type:"int"> = var %2 @"j";
125 %5 : java.type:"int" = constant @3;
126 %6 : Var<java.type:"int"> = var %5 @"k";
127 %7 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
128 %8 : java.type:"int" = constant @4;
129 %9 : Var<java.type:"int"> = var %8 @"l";
130 %10 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
131 %11 : java.type:"int" = var.load %4;
132 %12 : java.type:"int" = var.load %6;
133 %13 : java.type:"int" = add %11 %12;
134 %14 : java.type:"int" = var.load %9;
135 %15 : java.type:"int" = add %13 %14;
136 %16 : Var<java.type:"int"> = var %15 @"r";
137 %17 : java.type:"int" = var.load %16;
138 %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
139 return %18;
140 };
141 %19 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %10 @"sInner";
142 %20 : java.type:"int" = var.load %3;
143 %21 : java.type:"java.util.function.Supplier<java.lang.Integer>" = var.load %19;
144 %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
145 %23 : java.type:"int" = invoke %22 @java.ref:"java.lang.Integer::intValue():int";
146 %24 : java.type:"int" = add %20 %23;
147 %25 : Var<java.type:"int"> = var %24 @"r";
148 %26 : java.type:"int" = var.load %25;
149 %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
150 return %27;
151 };
152 %28 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %7 @"sOuter";
153 return;
154 };
155 """)
156 void test5(int i, int j) {
157 int k = 3;
158 Supplier<Integer> sOuter = () -> {
159 int l = 4;
160 Supplier<Integer> sInner = () -> {
161 int r = j + k + l;
162 return r;
163 };
164
165 int r = i + sInner.get();
166 return r;
167 };
168 }
169
170 int f;
171
172 @Reflect
173 @IR("""
174 func @"test6" (%0 : java.type:"LambdaTest")java.type:"void" -> {
175 %1 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
176 %2 : java.type:"int" = field.load %0 @java.ref:"LambdaTest::f:int";
177 %3 : java.type:"java.lang.Integer" = invoke %2 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
178 return %3;
179 };
180 %4 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %1 @"s";
181 return;
182 };
183 """)
184 void test6() {
185 Supplier<Integer> s = () -> f;
186 }
187
188 @Reflect
189 @IR("""
190 func @"test7" (%0 : java.type:"LambdaTest")java.type:"java.util.function.Predicate<java.lang.Object>" -> {
191 %1 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%2 : java.type:"java.lang.Object")java.type:"boolean" -> {
192 %3 : Var<java.type:"java.lang.Object"> = var %2 @"v";
193 %4 : Var<java.type:"java.lang.String"> = var @"s";
194 %5 : java.type:"boolean" = java.cand
195 ()java.type:"boolean" -> {
196 %6 : java.type:"java.lang.Object" = var.load %3;
197 %7 : java.type:"boolean" = pattern.match %6
198 ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
199 %8 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
200 yield %8;
201 }
202 (%9 : java.type:"java.lang.String")java.type:"void" -> {
203 var.store %4 %9;
204 yield;
205 };
206 yield %7;
207 }
208 ()java.type:"boolean" -> {
209 %10 : java.type:"java.lang.String" = var.load %4;
210 %11 : java.type:"boolean" = invoke %10 @java.ref:"java.lang.String::isEmpty():boolean";
211 %12 : java.type:"boolean" = not %11;
212 yield %12;
213 };
214 return %5;
215 };
216 return %1;
217 };
218 """)
219 Predicate<Object> test7() {
220 return v -> v instanceof String s && !s.isEmpty();
221 }
222
223 @Reflect
224 @IR("""
225 func @"f" ()java.type:"void" -> {
226 %0 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%1 : java.type:"java.lang.Object")java.type:"boolean" -> {
227 %2 : Var<java.type:"java.lang.Object"> = var %1 @"v";
228 %3 : Var<java.type:"java.lang.String"> = var @"s";
229 %4 : java.type:"boolean" = java.cand
230 ()java.type:"boolean" -> {
231 %5 : java.type:"java.lang.Object" = var.load %2;
232 %6 : java.type:"boolean" = pattern.match %5
233 ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
234 %7 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
235 yield %7;
236 }
237 (%8 : java.type:"java.lang.String")java.type:"void" -> {
238 var.store %3 %8;
239 yield;
240 };
241 yield %6;
242 }
243 ()java.type:"boolean" -> {
244 %9 : java.type:"java.lang.String" = var.load %3;
245 %10 : java.type:"boolean" = invoke %9 @java.ref:"java.lang.String::isEmpty():boolean";
246 %11 : java.type:"boolean" = not %10;
247 yield %11;
248 };
249 return %4;
250 };
251 return;
252 };
253 """)
254 static Predicate<Object> test8 = v -> v instanceof String s && !s.isEmpty();
255
256 @Reflect
257 @IR("""
258 func @"constantCapture" ()java.type:"java.util.function.IntSupplier" -> {
259 %0 : java.type:"int" = constant @1;
260 %1 : java.type:"int" = constant @2;
261 %2 : java.type:"int" = add %0 %1;
262 %3 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
263 return %2;
264 };
265 return %3;
266 };
267 """)
268 static IntSupplier constantCapture() {
269 final int i = 1 + 2;
270 return () -> i;
271 }
272
273 @Reflect
274 @IR("""
275 func @"constantAndRuntimeCapture" (%0 : java.type:"int")java.type:"java.util.function.IntSupplier" -> {
276 %1 : Var<java.type:"int"> = var %0 @"arg";
277 %2 : java.type:"int" = constant @1;
278 %3 : java.type:"int" = constant @2;
279 %4 : java.type:"int" = add %2 %3;
280 %5 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
281 %6 : java.type:"int" = var.load %1;
282 %7 : java.type:"int" = add %4 %6;
283 return %7;
284 };
285 return %5;
286 };
287 """)
288 static IntSupplier constantAndRuntimeCapture(int arg) {
289 final int i = 1 + 2;
290 return () -> i + arg;
291 }
292
293 @Reflect
294 @IR("""
295 func @"nestedCaptures" ()java.type:"java.util.function.Supplier<java.util.function.IntSupplier>" -> {
296 %0 : java.type:"int" = constant @1;
297 %1 : java.type:"int" = constant @2;
298 %2 : java.type:"int" = add %0 %1;
299 %3 : java.type:"java.util.function.Supplier<java.util.function.IntSupplier>" = lambda @lambda.isReflectable=true ()java.type:"java.util.function.IntSupplier" -> {
300 %4 : java.type:"int" = constant @4;
301 %5 : java.type:"int" = mul %2 %4;
302 %6 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
303 %7 : java.type:"int" = add %2 %5;
304 %8 : java.type:"int" = add %7 %2;
305 %9 : java.type:"int" = add %8 %5;
306 return %9;
307 };
308 return %6;
309 };
310 return %3;
311 };
312 """)
313 static Supplier<IntSupplier> nestedCaptures() {
314 final int methodConstant = 1 + 2;
315 return () -> {
316 final int outerConstant = methodConstant * 4;
317 return () -> {
318 final int innerConstant = methodConstant + outerConstant;
319 return innerConstant + methodConstant + outerConstant;
320 };
321 };
322 }
323 }