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 /*
 25  * @test
 26  * @run testng TestPatterns
 27  * @enablePreview
 28  */
 29 
 30 import org.testng.Assert;
 31 import org.testng.annotations.Test;
 32 
 33 import java.lang.reflect.code.OpTransformer;
 34 import java.lang.reflect.code.op.CoreOp;
 35 import java.lang.reflect.code.Op;
 36 import java.lang.reflect.code.interpreter.Interpreter;
 37 import java.lang.invoke.MethodHandles;
 38 import java.lang.reflect.Method;
 39 import java.lang.runtime.CodeReflection;
 40 import java.util.Optional;
 41 import java.util.stream.Stream;
 42 
 43 public class TestPatterns {
 44 
 45     interface Point {
 46     }
 47 
 48     record ConcretePoint(int x, int y) implements Point {
 49     }
 50 
 51     enum Color {RED, GREEN, BLUE}
 52 
 53     record ColoredPoint(ConcretePoint p, Color c) implements Point {
 54     }
 55 
 56     record Rectangle(Point upperLeft, Point lowerRight) {
 57     }
 58 
 59 
 60     @CodeReflection
 61     public static String recordPatterns(Object r) {
 62         if (r instanceof Rectangle(
 63                 ColoredPoint(ConcretePoint p, Color c),
 64                 ColoredPoint lr)) {
 65             return p.toString();
 66         } else {
 67             return "";
 68         }
 69     }
 70 
 71     @Test
 72     public void testRecordPatterns() {
 73         CoreOp.FuncOp f = getFuncOp("recordPatterns");
 74 
 75         f.writeTo(System.out);
 76 
 77         CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER);
 78 
 79         lf.writeTo(System.out);
 80 
 81         {
 82             Rectangle r = new Rectangle(
 83                     new ColoredPoint(new ConcretePoint(1, 2), Color.RED),
 84                     new ColoredPoint(new ConcretePoint(3, 4), Color.BLUE));
 85             Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, r), recordPatterns(r));
 86         }
 87 
 88         {
 89             Rectangle r = new Rectangle(
 90                     new ColoredPoint(new ConcretePoint(1, 2), Color.RED),
 91                     new ConcretePoint(3, 4));
 92             Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, r), recordPatterns(r));
 93         }
 94 
 95         {
 96             Rectangle r = new Rectangle(
 97                     new ConcretePoint(1, 2),
 98                     new ConcretePoint(3, 4));
 99             Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, r), recordPatterns(r));
100         }
101 
102         {
103             String r = "";;
104             Assert.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf, r), recordPatterns(r));
105         }
106     }
107 
108 
109     static CoreOp.FuncOp getFuncOp(String name) {
110         Optional<Method> om = Stream.of(TestPatterns.class.getDeclaredMethods())
111                 .filter(m -> m.getName().equals(name))
112                 .findFirst();
113 
114         Method m = om.get();
115         return m.getCodeModel().get();
116     }
117 
118 }