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.Predicate;
 27 import java.util.function.Supplier;
 28 
 29 /*
 30  * @test
 31  * @summary Smoke test for code reflection with lambda expressions.
 32  * @modules jdk.incubator.code
 33  * @build LambdaTest
 34  * @build CodeReflectionTester
 35  * @run main CodeReflectionTester LambdaTest
 36  */
 37 
 38 public class LambdaTest {
 39 
 40     @Reflect
 41     @IR("""
 42             func @"test1" (%0 : java.type:"LambdaTest")java.type:"void" -> {
 43                 %1 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isReflectable=true (%2 : java.type:"java.lang.String")java.type:"void" -> {
 44                     %3 : Var<java.type:"java.lang.String"> = var %2 @"s";
 45                     %4 : java.type:"java.io.PrintStream" = field.load @java.ref:"java.lang.System::out:java.io.PrintStream";
 46                     %5 : java.type:"java.lang.String" = var.load %3;
 47                     invoke %4 %5 @java.ref:"java.io.PrintStream::println(java.lang.String):void";
 48                     return;
 49                 };
 50                 %6 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %1 @"c";
 51                 %7 : java.type:"java.util.function.Consumer<java.lang.String>" = var.load %6;
 52                 %8 : java.type:"java.lang.String" = constant @"Hello World";
 53                 invoke %7 %8 @java.ref:"java.util.function.Consumer::accept(java.lang.Object):void";
 54                 return;
 55             };
 56             """)
 57     void test1() {
 58         Consumer<String> c = s -> {
 59             System.out.println(s);
 60         };
 61         c.accept("Hello World");
 62     }
 63 
 64     @Reflect
 65     @IR("""
 66             func @"test2" (%0 : java.type:"LambdaTest")java.type:"void" -> {
 67                 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
 68                     %2 : java.type:"java.lang.String" = constant @"Hello World";
 69                     return %2;
 70                 };
 71                 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
 72                 %4 : java.type:"java.util.function.Supplier<java.lang.String>" = var.load %3;
 73                 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
 74                 %6 : java.type:"java.lang.String" = cast %5 @java.type:"java.lang.String";
 75                 %7 : Var<java.type:"java.lang.String"> = var %6 @"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:"java.lang.Integer" = cast %22 @java.type:"java.lang.Integer";
146                     %24 : java.type:"int" = invoke %23 @java.ref:"java.lang.Integer::intValue():int";
147                     %25 : java.type:"int" = add %20 %24;
148                     %26 : Var<java.type:"int"> = var %25 @"r";
149                     %27 : java.type:"int" = var.load %26;
150                     %28 : java.type:"java.lang.Integer" = invoke %27 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
151                     return %28;
152                 };
153                 %29 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %7 @"sOuter";
154                 return;
155             };
156             """)
157     void test5(int i, int j) {
158         int k = 3;
159         Supplier<Integer> sOuter = () -> {
160             int l = 4;
161             Supplier<Integer> sInner = () -> {
162                 int r = j + k + l;
163                 return r;
164             };
165 
166             int r = i + sInner.get();
167             return r;
168         };
169     }
170 
171     int f;
172 
173     @Reflect
174     @IR("""
175             func @"test6" (%0 : java.type:"LambdaTest")java.type:"void" -> {
176                 %1 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
177                     %2 : java.type:"int" = field.load %0 @java.ref:"LambdaTest::f:int";
178                     %3 : java.type:"java.lang.Integer" = invoke %2 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
179                     return %3;
180                 };
181                 %4 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %1 @"s";
182                 return;
183             };
184             """)
185     void test6() {
186         Supplier<Integer> s = () -> f;
187     }
188 
189     @Reflect
190     @IR("""
191             func @"test7" (%0 : java.type:"LambdaTest")java.type:"java.util.function.Predicate<java.lang.Object>" -> {
192                   %3 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%4 : java.type:"java.lang.Object")java.type:"boolean" -> {
193                       %5 : Var<java.type:"java.lang.Object"> = var %4 @"v";
194                       %1 : java.type:"java.lang.String" = constant @null;
195                       %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
196                       %6 : java.type:"boolean" = java.cand
197                           ()java.type:"boolean" -> {
198                               %7 : java.type:"java.lang.Object" = var.load %5;
199                               %8 : java.type:"boolean" = pattern.match %7
200                                   ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
201                                       %9 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
202                                       yield %9;
203                                   }
204                                   (%10 : java.type:"java.lang.String")java.type:"void" -> {
205                                       var.store %2 %10;
206                                       yield;
207                                   };
208                               yield %8;
209                           }
210                           ()java.type:"boolean" -> {
211                               %11 : java.type:"java.lang.String" = var.load %2;
212                               %12 : java.type:"boolean" = invoke %11 @java.ref:"java.lang.String::isEmpty():boolean";
213                               %13 : java.type:"boolean" = not %12;
214                               yield %13;
215                           };
216                       return %6;
217                   };
218                   return %3;
219               };
220             """)
221     Predicate<Object> test7() {
222         return v -> v instanceof String s && !s.isEmpty();
223     }
224 
225     @Reflect
226     @IR("""
227             func @"f" ()java.type:"void" -> {
228                   %3 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%4 : java.type:"java.lang.Object")java.type:"boolean" -> {
229                       %5 : Var<java.type:"java.lang.Object"> = var %4 @"v";
230                       %1 : java.type:"java.lang.String" = constant @null;
231                       %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
232                       %6 : java.type:"boolean" = java.cand
233                           ()java.type:"boolean" -> {
234                               %7 : java.type:"java.lang.Object" = var.load %5;
235                               %8 : java.type:"boolean" = pattern.match %7
236                                   ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
237                                       %9 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
238                                       yield %9;
239                                   }
240                                   (%10 : java.type:"java.lang.String")java.type:"void" -> {
241                                       var.store %2 %10;
242                                       yield;
243                                   };
244                               yield %8;
245                           }
246                           ()java.type:"boolean" -> {
247                               %11 : java.type:"java.lang.String" = var.load %2;
248                               %12 : java.type:"boolean" = invoke %11 @java.ref:"java.lang.String::isEmpty():boolean";
249                               %13 : java.type:"boolean" = not %12;
250                               yield %13;
251                           };
252                       return %6;
253                   };
254                   return;
255               };
256             """)
257     static Predicate<Object> test8 = v -> v instanceof String s && !s.isEmpty();
258 }