1 /*
  2  * Copyright (c) 2024, 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.CodeReflection;
 25 
 26 
 27 /*
 28  * @test
 29  * @summary Smoke test for code reflection with patterns.
 30  * @modules jdk.incubator.code
 31  * @enablePreview
 32  * @build PatternsTest
 33  * @build CodeReflectionTester
 34  * @run main CodeReflectionTester PatternsTest
 35  */
 36 
 37 public class PatternsTest {
 38 
 39     @CodeReflection
 40     @IR("""
 41             func @"test1" (%0 : PatternsTest, %1 : java.lang.Object)void -> {
 42                 %2 : Var<java.lang.Object> = var %1 @"o";
 43                 %3 : java.lang.Object = var.load %2;
 44                 %4 : java.lang.String = constant @null;
 45                 %5 : Var<java.lang.String> = var %4 @"s";
 46                 %6 : boolean = pattern.match %3
 47                     ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
 48                         %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
 49                         yield %7;
 50                     }
 51                     ^match(%8 : java.lang.String)void -> {
 52                         var.store %5 %8;
 53                         yield;
 54                     };
 55                 %9 : Var<boolean> = var %6 @"x";
 56                 return;
 57             };
 58             """)
 59     void test1(Object o) {
 60         boolean x = o instanceof String s;
 61     }
 62 
 63     @CodeReflection
 64     @IR("""
 65             func @"test2" (%0 : PatternsTest, %1 : java.lang.Object)java.lang.String -> {
 66                 %2 : Var<java.lang.Object> = var %1 @"o";
 67                 %3 : java.lang.String = constant @null;
 68                 %4 : Var<java.lang.String> = var %3 @"s";
 69                 java.if
 70                     ()boolean -> {
 71                         %5 : java.lang.Object = var.load %2;
 72                         %6 : boolean = pattern.match %5
 73                             ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
 74                                 %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
 75                                 yield %7;
 76                             }
 77                             ^match(%8 : java.lang.String)void -> {
 78                                 var.store %4 %8;
 79                                 yield;
 80                             };
 81                         yield %6;
 82                     }
 83                     ^then()void -> {
 84                         %9 : java.lang.String = var.load %4;
 85                         return %9;
 86                     }
 87                     ^else()void -> {
 88                         %10 : java.lang.String = constant @"";
 89                         return %10;
 90                     };
 91                 unreachable;
 92             };
 93             """)
 94     String test2(Object o) {
 95         if (o instanceof String s) {
 96             return s;
 97         } else {
 98             return "";
 99         }
100     }
101 
102     @CodeReflection
103     @IR("""
104             func @"test3" (%0 : PatternsTest, %1 : java.lang.Object)java.lang.String -> {
105                 %2 : Var<java.lang.Object> = var %1 @"o";
106                 %3 : java.lang.String = constant @null;
107                 %4 : Var<java.lang.String> = var %3 @"s";
108                 java.if
109                     ()boolean -> {
110                         %5 : java.lang.Object = var.load %2;
111                         %6 : boolean = pattern.match %5
112                             ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
113                                 %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
114                                 yield %7;
115                             }
116                             ^match(%8 : java.lang.String)void -> {
117                                 var.store %4 %8;
118                                 yield;
119                             };
120                         %9 : boolean = not %6;
121                         yield %9;
122                     }
123                     ^then()void -> {
124                         %10 : java.lang.String = constant @"";
125                         return %10;
126                     }
127                     ^else()void -> {
128                         yield;
129                     };
130                 %11 : java.lang.String = var.load %4;
131                 return %11;
132             };
133             """)
134     String test3(Object o) {
135         if (!(o instanceof String s)) {
136             return "";
137         }
138         return s;
139     }
140 
141     interface Point {
142     }
143 
144     record ConcretePoint(int x, int y) implements Point {
145     }
146 
147     enum Color {RED, GREEN, BLUE}
148 
149     record ColoredPoint(ConcretePoint p, Color c) implements Point {
150     }
151 
152     record Rectangle(Point upperLeft, Point lowerRight) {
153     }
154 
155 
156     @CodeReflection
157     @IR("""
158             func @"test4" (%0 : PatternsTest, %1 : PatternsTest$Rectangle)void -> {
159                 %2 : Var<PatternsTest$Rectangle> = var %1 @"r";
160                 %3 : PatternsTest$ConcretePoint = constant @null;
161                 %4 : Var<PatternsTest$ConcretePoint> = var %3 @"p";
162                 %5 : PatternsTest$Color = constant @null;
163                 %6 : Var<PatternsTest$Color> = var %5 @"c";
164                 %7 : PatternsTest$ColoredPoint = constant @null;
165                 %8 : Var<PatternsTest$ColoredPoint> = var %7 @"lr";
166                 java.if
167                     ()boolean -> {
168                         %9 : PatternsTest$Rectangle = var.load %2;
169                         %10 : boolean = pattern.match %9
170                             ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> -> {
171                                 %11 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<PatternsTest$ConcretePoint> = pattern.type @"p";
172                                 %12 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<PatternsTest$Color> = pattern.type @"c";
173                                 %13 : jdk.incubator.code.op.ExtendedOp$Pattern$Record<PatternsTest$ColoredPoint> = pattern.record %11 %12 @"(PatternsTest$ConcretePoint p, PatternsTest$Color c)PatternsTest$ColoredPoint";
174                                 %14 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<PatternsTest$ColoredPoint> = pattern.type @"lr";
175                                 %15 : jdk.incubator.code.op.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> = pattern.record %13 %14 @"(PatternsTest$Point upperLeft, PatternsTest$Point lowerRight)PatternsTest$Rectangle";
176                                 yield %15;
177                             }
178                             ^match(%16 : PatternsTest$ConcretePoint, %17 : PatternsTest$Color, %18 : PatternsTest$ColoredPoint)void -> {
179                                 var.store %4 %16;
180                                 var.store %6 %17;
181                                 var.store %8 %18;
182                                 yield;
183                             };
184                         yield %10;
185                     }
186                     ^then()void -> {
187                         %19 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
188                         %20 : PatternsTest$ConcretePoint = var.load %4;
189                         invoke %19 %20 @"java.io.PrintStream::println(java.lang.Object)void";
190                         %21 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
191                         %22 : PatternsTest$Color = var.load %6;
192                         invoke %21 %22 @"java.io.PrintStream::println(java.lang.Object)void";
193                         %23 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
194                         %24 : PatternsTest$ColoredPoint = var.load %8;
195                         invoke %23 %24 @"java.io.PrintStream::println(java.lang.Object)void";
196                         yield;
197                     }
198                     ^else()void -> {
199                         %25 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
200                         %26 : java.lang.String = constant @"NO MATCH";
201                         invoke %25 %26 @"java.io.PrintStream::println(java.lang.String)void";
202                         yield;
203                     };
204                 return;
205             };
206             """)
207     void test4(Rectangle r) {
208         if (r instanceof Rectangle(
209                 ColoredPoint(ConcretePoint p, Color c),
210                 ColoredPoint lr)){
211             System.out.println(p);
212             System.out.println(c);
213             System.out.println(lr);
214         }
215         else {
216             System.out.println("NO MATCH");
217         }
218     }
219 
220 
221     @CodeReflection
222     @IR("""
223             func @"test5" (%0 : PatternsTest, %1 : java.lang.Object)void -> {
224                 %2 : Var<java.lang.Object> = var %1 @"o";
225                 %3 : java.lang.String = constant @null;
226                 %4 : Var<java.lang.String> = var %3 @"s";
227                 java.while
228                     ^cond()boolean -> {
229                         %5 : java.lang.Object = var.load %2;
230                         %6 : boolean = pattern.match %5
231                             ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
232                                 %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
233                                 yield %7;
234                             }
235                             ^match(%8 : java.lang.String)void -> {
236                                 var.store %4 %8;
237                                 yield;
238                             };
239                         yield %6;
240                     }
241                     ^body()void -> {
242                         %9 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
243                         %10 : java.lang.String = var.load %4;
244                         invoke %9 %10 @"java.io.PrintStream::println(java.lang.String)void";
245                         java.continue;
246                     };
247                 return;
248             };
249             """)
250     void test5(Object o) {
251         while (o instanceof String s) {
252             System.out.println(s);
253         }
254     }
255 
256     @CodeReflection
257     @IR("""
258             func @"test6" (%0 : PatternsTest, %1 : java.lang.Object)void -> {
259                 %2 : Var<java.lang.Object> = var %1 @"o";
260                 %3 : java.lang.String = constant @null;
261                 %4 : Var<java.lang.String> = var %3 @"s";
262                 java.do.while
263                     ^body()void -> {
264                         java.continue;
265                     }
266                     ^cond()boolean -> {
267                         %5 : java.lang.Object = var.load %2;
268                         %6 : boolean = pattern.match %5
269                             ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
270                                 %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type @"s";
271                                 yield %7;
272                             }
273                             ^match(%8 : java.lang.String)void -> {
274                                 var.store %4 %8;
275                                 yield;
276                             };
277                         %9 : boolean = not %6;
278                         yield %9;
279                     };
280                 %10 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
281                 %11 : java.lang.String = var.load %4;
282                 invoke %10 %11 @"java.io.PrintStream::println(java.lang.String)void";
283                 return;
284             };
285             """)
286     void test6(Object o) {
287         do {
288         } while (!(o instanceof String s));
289         System.out.println(s);
290     }
291 
292 
293     @CodeReflection
294     @IR("""
295             func @"test7" (%0 : PatternsTest, %1 : java.lang.Object)void -> {
296                 %2 : Var<java.lang.Object> = var %1 @"o";
297                 %3 : java.lang.Number = constant @null;
298                 %4 : Var<java.lang.Number> = var %3 @"n";
299                 java.for
300                     ^init()Var<int> -> {
301                         %5 : int = constant @"0";
302                         %6 : Var<int> = var %5 @"i";
303                         yield %6;
304                     }
305                     ^cond(%7 : Var<int>)boolean -> {
306                         %8 : boolean = java.cand
307                             ()boolean -> {
308                                 %9 : int = var.load %7;
309                                 %10 : int = constant @"10";
310                                 %11 : boolean = lt %9 %10;
311                                 yield %11;
312                             }
313                             ()boolean -> {
314                                 %12 : java.lang.Object = var.load %2;
315                                 %13 : boolean = pattern.match %12
316                                     ^pattern()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> -> {
317                                         %14 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.Number> = pattern.type @"n";
318                                         yield %14;
319                                     }
320                                     ^match(%15 : java.lang.Number)void -> {
321                                         var.store %4 %15;
322                                         yield;
323                                     };
324                                 yield %13;
325                             };
326                         yield %8;
327                     }
328                     ^update(%16 : Var<int>)void -> {
329                         %17 : int = var.load %16;
330                         %18 : java.lang.Number = var.load %4;
331                         %19 : int = invoke %18 @"java.lang.Number::intValue()int";
332                         %20 : int = add %17 %19;
333                         var.store %16 %20;
334                         yield;
335                     }
336                     ^body(%21 : Var<int>)void -> {
337                         %22 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
338                         %23 : java.lang.Number = var.load %4;
339                         invoke %22 %23 @"java.io.PrintStream::println(java.lang.Object)void";
340                         java.continue;
341                     };
342                 return;
343             };
344             """)
345     void test7(Object o) {
346         for (int i = 0;
347              i < 10 && o instanceof Number n; i += n.intValue()) {
348             System.out.println(n);
349         }
350     }
351 
352     @IR("""
353             func @"test8" (%0 : PatternsTest, %1 : java.lang.Object)boolean -> {
354                    %2 : Var<java.lang.Object> = var %1 @"o";
355                    %3 : java.lang.Object = var.load %2;
356                    %4 : java.lang.String = constant @null;
357                    %5 : Var<java.lang.String> = var %4;
358                    %6 : boolean = pattern.match %3
359                        ()jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> -> {
360                            %7 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<java.lang.String> = pattern.type;
361                            yield %7;
362                        }
363                        (%8 : java.lang.String)void -> {
364                            var.store %5 %8;
365                            yield;
366                        };
367                    return %6;
368             };
369             """)
370     @CodeReflection
371     boolean test8(Object o) {
372         return o instanceof String _;
373     }
374 
375     @IR("""
376             func @"test9" (%0 : PatternsTest, %1 : java.lang.Object)boolean -> {
377                 %2 : Var<java.lang.Object> = var %1 @"o";
378                 %3 : java.lang.Object = var.load %2;
379                 %4 : PatternsTest$ConcretePoint = constant @null;
380                 %5 : Var<PatternsTest$ConcretePoint> = var %4 @"cp";
381                 %6 : boolean = pattern.match %3
382                     ()jdk.incubator.code.op.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> -> {
383                         %7 : jdk.incubator.code.op.ExtendedOp$Pattern$MatchAll = pattern.match.all;
384                         %8 : jdk.incubator.code.op.ExtendedOp$Pattern$Type<PatternsTest$ConcretePoint> = pattern.type @"cp";
385                         %9 : jdk.incubator.code.op.ExtendedOp$Pattern$Record<PatternsTest$Rectangle> = pattern.record %7 %8 @"(PatternsTest$Point upperLeft, PatternsTest$Point lowerRight)PatternsTest$Rectangle";
386                         yield %9;
387                     }
388                     (%10 : PatternsTest$ConcretePoint)void -> {
389                         var.store %5 %10;
390                         yield;
391                     };
392                 return %6;
393             };
394             """)
395     @CodeReflection
396     boolean test9(Object o) {
397         return o instanceof Rectangle(_, ConcretePoint cp);
398     }
399 }