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 : Var<java.type:"java.lang.String"> = var %5 @"s";
 75                 return;
 76             };
 77             """)
 78     void test2() {
 79         Supplier<String> c = () -> {
 80             return "Hello World";
 81         };
 82         String s = c.get();
 83     }
 84 
 85     @Reflect
 86     @IR("""
 87             func @"test3" (%0 : java.type:"LambdaTest")java.type:"void" -> {
 88                 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
 89                     %2 : java.type:"java.lang.String" = constant @"Hello World";
 90                     return %2;
 91                 };
 92                 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
 93                 return;
 94             };
 95             """)
 96     void test3() {
 97         Supplier<String> c = () -> "Hello World";
 98     }
 99 
100     String s_f;
101 
102     @Reflect
103     @IR("""
104             func @"test4" (%0 : java.type:"LambdaTest")java.type:"void" -> {
105                 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
106                     %2 : java.type:"java.lang.String" = field.load %0 @java.ref:"LambdaTest::s_f:java.lang.String";
107                     return %2;
108                 };
109                 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
110                 return;
111             };
112             """)
113     void test4() {
114         Supplier<String> c = () -> {
115             return s_f;
116         };
117     }
118 
119     @Reflect
120     @IR("""
121             func @"test5" (%0 : java.type:"LambdaTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
122                 %3 : Var<java.type:"int"> = var %1 @"i";
123                 %4 : Var<java.type:"int"> = var %2 @"j";
124                 %5 : java.type:"int" = constant @3;
125                 %6 : Var<java.type:"int"> = var %5 @"k";
126                 %7 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
127                     %8 : java.type:"int" = constant @4;
128                     %9 : Var<java.type:"int"> = var %8 @"l";
129                     %10 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
130                         %11 : java.type:"int" = var.load %4;
131                         %12 : java.type:"int" = var.load %6;
132                         %13 : java.type:"int" = add %11 %12;
133                         %14 : java.type:"int" = var.load %9;
134                         %15 : java.type:"int" = add %13 %14;
135                         %16 : Var<java.type:"int"> = var %15 @"r";
136                         %17 : java.type:"int" = var.load %16;
137                         %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
138                         return %18;
139                     };
140                     %19 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %10 @"sInner";
141                     %20 : java.type:"int" = var.load %3;
142                     %21 : java.type:"java.util.function.Supplier<java.lang.Integer>" = var.load %19;
143                     %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
144                     %23 : java.type:"int" = invoke %22 @java.ref:"java.lang.Integer::intValue():int";
145                     %24 : java.type:"int" = add %20 %23;
146                     %25 : Var<java.type:"int"> = var %24 @"r";
147                     %26 : java.type:"int" = var.load %25;
148                     %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
149                     return %27;
150                 };
151                 %28 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %7 @"sOuter";
152                 return;
153             };
154             """)
155     void test5(int i, int j) {
156         int k = 3;
157         Supplier<Integer> sOuter = () -> {
158             int l = 4;
159             Supplier<Integer> sInner = () -> {
160                 int r = j + k + l;
161                 return r;
162             };
163 
164             int r = i + sInner.get();
165             return r;
166         };
167     }
168 
169     int f;
170 
171     @Reflect
172     @IR("""
173             func @"test6" (%0 : java.type:"LambdaTest")java.type:"void" -> {
174                 %1 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
175                     %2 : java.type:"int" = field.load %0 @java.ref:"LambdaTest::f:int";
176                     %3 : java.type:"java.lang.Integer" = invoke %2 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
177                     return %3;
178                 };
179                 %4 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %1 @"s";
180                 return;
181             };
182             """)
183     void test6() {
184         Supplier<Integer> s = () -> f;
185     }
186 
187     @Reflect
188     @IR("""
189             func @"test7" (%0 : java.type:"LambdaTest")java.type:"java.util.function.Predicate<java.lang.Object>" -> {
190                   %3 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%4 : java.type:"java.lang.Object")java.type:"boolean" -> {
191                       %5 : Var<java.type:"java.lang.Object"> = var %4 @"v";
192                       %1 : java.type:"java.lang.String" = constant @null;
193                       %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
194                       %6 : java.type:"boolean" = java.cand
195                           ()java.type:"boolean" -> {
196                               %7 : java.type:"java.lang.Object" = var.load %5;
197                               %8 : java.type:"boolean" = pattern.match %7
198                                   ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
199                                       %9 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
200                                       yield %9;
201                                   }
202                                   (%10 : java.type:"java.lang.String")java.type:"void" -> {
203                                       var.store %2 %10;
204                                       yield;
205                                   };
206                               yield %8;
207                           }
208                           ()java.type:"boolean" -> {
209                               %11 : java.type:"java.lang.String" = var.load %2;
210                               %12 : java.type:"boolean" = invoke %11 @java.ref:"java.lang.String::isEmpty():boolean";
211                               %13 : java.type:"boolean" = not %12;
212                               yield %13;
213                           };
214                       return %6;
215                   };
216                   return %3;
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                   %3 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%4 : java.type:"java.lang.Object")java.type:"boolean" -> {
227                       %5 : Var<java.type:"java.lang.Object"> = var %4 @"v";
228                       %1 : java.type:"java.lang.String" = constant @null;
229                       %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
230                       %6 : java.type:"boolean" = java.cand
231                           ()java.type:"boolean" -> {
232                               %7 : java.type:"java.lang.Object" = var.load %5;
233                               %8 : java.type:"boolean" = pattern.match %7
234                                   ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
235                                       %9 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
236                                       yield %9;
237                                   }
238                                   (%10 : java.type:"java.lang.String")java.type:"void" -> {
239                                       var.store %2 %10;
240                                       yield;
241                                   };
242                               yield %8;
243                           }
244                           ()java.type:"boolean" -> {
245                               %11 : java.type:"java.lang.String" = var.load %2;
246                               %12 : java.type:"boolean" = invoke %11 @java.ref:"java.lang.String::isEmpty():boolean";
247                               %13 : java.type:"boolean" = not %12;
248                               yield %13;
249                           };
250                       return %6;
251                   };
252                   return;
253               };
254             """)
255     static Predicate<Object> test8 = v -> v instanceof String s && !s.isEmpty();
256 }