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  * @summary Smoke test for code reflection with quoted lambdas.
 27  * @modules jdk.incubator.code
 28  * @build QuotedTest
 29  * @build CodeReflectionTester
 30  * @run main CodeReflectionTester QuotedTest
 31  */
 32 
 33 import jdk.incubator.code.Quoted;
 34 import jdk.incubator.code.CodeReflection;
 35 
 36 public class QuotedTest {
 37     @IR("""
 38             func @"f" ()void -> {
 39                  %0 : func<void> = closure ()void -> {
 40                     return;
 41                 };
 42                 return;
 43             };
 44             """)
 45     static final Quoted QUOTED_NO_PARAM_VOID = () -> {
 46     };
 47 
 48     @IR("""
 49             func @"f" ()void -> {
 50                 %0 : func<int> = closure ()int -> {
 51                     %2 : int = constant @"1";
 52                     return %2;
 53                 };
 54                 return;
 55             };
 56             """)
 57     static final Quoted QUOTED_NO_PARAM_CONST = () -> 1;
 58 
 59     @IR("""
 60             func @"f" ()void -> {
 61                 %0 : func<int, int> = closure (%2 : int)int -> {
 62                     %3 : Var<int> = var %2 @"x";
 63                     %4 : int = var.load %3;
 64                     return %4;
 65                 };
 66                 return;
 67             };
 68             """)
 69     static final Quoted QUOTED_ID = (int x) -> x;
 70 
 71     @IR("""
 72             func @"f" ()void -> {
 73                 %0 : func<int, int, int> = closure (%2 : int, %3 : int)int -> {
 74                     %4 : Var<int> = var %2 @"x";
 75                     %5 : Var<int> = var %3 @"y";
 76                     %6 : int = var.load %4;
 77                     %7 : int = var.load %5;
 78                     %8 : int = add %6 %7;
 79                     return %8;
 80                 };
 81                 return;
 82             };
 83             """)
 84     static final Quoted QUOTED_PLUS = (int x, int y) -> x + y;
 85 
 86     @IR("""
 87             func @"f" ()void -> {
 88                 %0 : func<java.lang.Object> = closure ()java.lang.Object -> {
 89                     %2 : java.lang.AssertionError = new @"func<java.lang.AssertionError>";
 90                     throw %2;
 91                 };
 92                 return;
 93             };
 94             """)
 95     static final Quoted QUOTED_THROW_NO_PARAM = () -> {
 96         throw new AssertionError();
 97     };
 98 
 99     // can we write out the root op then extract the closure ?
100 
101     @IR("""
102             func @"f" (%1: Var<int>)void -> {
103                 %0 : func<int, int> = closure (%4 : int)int -> {
104                     %5 : Var<int> = var %4 @"y";
105                     %6 : int = var.load %1;
106                     %7 : int = var.load %5;
107                     %8 : int = add %6 %7;
108                     return %8;
109                 };
110                 return;
111             };
112             """)
113     static final Quoted QUOTED_CAPTURE_PARAM = new Object() {
114         Quoted captureContext(int x) {
115             return (int y) -> x + y;
116         }
117     }.captureContext(42);
118 
119     static class Context {
120         int x, y;
121 
122         Quoted capture() {
123             return (int z) -> x + y + z;
124         }
125     }
126 
127     @IR("""
128             func @"f" (%0 : QuotedTest$Context)void -> {
129                 %1 : func<int, int> = closure (%3 : int)int -> {
130                     %4 : Var<int> = var %3 @"z";
131                     %5 : int = field.load %0 @"QuotedTest$Context::x()int";
132                     %6 : int = field.load %0 @"QuotedTest$Context::y()int";
133                     %7 : int = add %5 %6;
134                     %8 : int = var.load %4;
135                     %9 : int = add %7 %8;
136                     return %9;
137                 };
138                 return;
139             };
140             """)
141     static final Quoted QUOTED_CAPTURE_FIELD = new Context().capture();
142 
143     @CodeReflection
144     @IR("""
145             func @"captureParam" (%0 : int)void -> {
146                 %1 : Var<int> = var %0 @"x";
147                 %2 : jdk.incubator.code.Quoted = quoted ()void -> {
148                     %3 : func<int, int> = closure (%4 : int)int -> {
149                         %5 : Var<int> = var %4 @"y";
150                         %6 : int = var.load %1;
151                         %7 : int = var.load %5;
152                         %8 : int = add %6 %7;
153                         return %8;
154                     };
155                     yield %3;
156                 };
157                 %9 : Var<jdk.incubator.code.Quoted> = var %2 @"op";
158                 return;
159             };
160             """)
161     static void captureParam(int x) {
162         Quoted op = (int y) -> x + y;
163     }
164 
165     int x, y;
166 
167     @CodeReflection
168     @IR("""
169             func @"captureField" (%0 : QuotedTest)void -> {
170                 %1 : jdk.incubator.code.Quoted = quoted ()void -> {
171                     %2 : func<int, int> = closure (%3 : int)int -> {
172                         %4 : Var<int> = var %3 @"z";
173                         %5 : int = field.load %0 @"QuotedTest::x()int";
174                         %6 : int = field.load %0 @"QuotedTest::y()int";
175                         %7 : int = add %5 %6;
176                         %8 : int = var.load %4;
177                         %9 : int = add %7 %8;
178                         return %9;
179                     };
180                     yield %2;
181                 };
182                 %10 : Var<jdk.incubator.code.Quoted> = var %1 @"op";
183                 return;
184             };
185             """)
186     void captureField() {
187         Quoted op = (int z) -> x + y + z;
188     }
189 }