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