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 quotable lambdas.
 27  * @modules jdk.incubator.code
 28  * @build QuotableSubtypeTest
 29  * @build CodeReflectionTester
 30  * @run main CodeReflectionTester QuotableSubtypeTest
 31  */
 32 
 33 import jdk.incubator.code.Quotable;
 34 import jdk.incubator.code.CodeReflection;
 35 import java.util.function.IntBinaryOperator;
 36 import java.util.function.IntFunction;
 37 import java.util.function.IntSupplier;
 38 import java.util.function.IntUnaryOperator;
 39 
 40 public class QuotableSubtypeTest {
 41 
 42     interface QuotableRunnable extends Runnable, Quotable { }
 43 
 44     @IR("""
 45             func @"f" ()void -> {
 46                 %0 : QuotableSubtypeTest$QuotableRunnable = lambda ()void -> {
 47                     return;
 48                 };
 49                 return;
 50             };
 51             """)
 52     static final QuotableRunnable QUOTED_NO_PARAM_VOID = () -> { };
 53 
 54     interface QuotableIntSupplier extends IntSupplier, Quotable { }
 55 
 56     @IR("""
 57            func @"f" ()void -> {
 58                 %0 : QuotableSubtypeTest$QuotableIntSupplier = lambda ()int -> {
 59                     %2 : int = constant @"1";
 60                     return %2;
 61                 };
 62                 return;
 63            };
 64             """)
 65     static final QuotableIntSupplier QUOTED_NO_PARAM_CONST = () -> 1;
 66 
 67     interface QuotableIntUnaryOperator extends IntUnaryOperator, Quotable { }
 68 
 69     @IR("""
 70             func @"f" ()void -> {
 71                 %0 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%2 : int)int -> {
 72                     %3 : Var<int> = var %2 @"x";
 73                     %4 : int = var.load %3;
 74                     return %4;
 75                 };
 76                 return;
 77             };
 78             """)
 79     static final QuotableIntUnaryOperator QUOTED_ID = x -> x;
 80 
 81     interface QuotableIntBinaryOperator extends IntBinaryOperator, Quotable { }
 82 
 83     @IR("""
 84             func @"f" ()void -> {
 85                 %0 : QuotableSubtypeTest$QuotableIntBinaryOperator = lambda (%2 : int, %3 : int)int -> {
 86                     %4 : Var<int> = var %2 @"x";
 87                     %5 : Var<int> = var %3 @"y";
 88                     %6 : int = var.load %4;
 89                     %7 : int = var.load %5;
 90                     %8 : int = add %6 %7;
 91                     return %8;
 92                 };
 93                 return;
 94             };
 95             """)
 96     static final QuotableIntBinaryOperator QUOTED_PLUS = (x, y) -> x + y;
 97     @IR("""
 98             func @"f" ()void -> {
 99                 %0 : QuotableSubtypeTest$QuotableRunnable = lambda ()void -> {
100                     %2 : java.lang.AssertionError = new @"func<java.lang.AssertionError>";
101                     throw %2;
102                 };
103                 return;
104             };
105             """)
106     static final QuotableRunnable QUOTED_THROW_NO_PARAM = () -> { throw new AssertionError(); };
107 
108     @IR("""
109             func @"f" (%1 : Var<int>)void -> {
110                 %0 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%4 : int)int -> {
111                     %5 : Var<int> = var %4 @"y";
112                     %6 : int = var.load %1;
113                     %7 : int = var.load %5;
114                     %8 : int = add %6 %7;
115                     return %8;
116                 };
117                 return;
118             };
119             """)
120     static final QuotableIntUnaryOperator QUOTED_CAPTURE_PARAM = new Object() {
121         QuotableIntUnaryOperator captureContext(int x) {
122             return y -> x + y;
123         }
124     }.captureContext(42);
125 
126     static class Context {
127         int x, y;
128 
129         QuotableIntUnaryOperator capture() {
130             return z -> x + y + z;
131         }
132     }
133 
134     @IR("""
135             func @"f" (%0 : QuotableSubtypeTest$Context)void -> {
136                 %1 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%3 : int)int -> {
137                     %4 : Var<int> = var %3 @"z";
138                     %5 : int = field.load %0 @"QuotableSubtypeTest$Context::x()int";
139                     %6 : int = field.load %0 @"QuotableSubtypeTest$Context::y()int";
140                     %7 : int = add %5 %6;
141                     %8 : int = var.load %4;
142                     %9 : int = add %7 %8;
143                     return %9;
144                 };
145                 return;
146             };
147             """)
148     static final QuotableIntUnaryOperator QUOTED_CAPTURE_FIELD = new Context().capture();
149 
150     @CodeReflection
151     @IR("""
152             func @"captureParam" (%0 : int)void -> {
153                 %1 : Var<int> = var %0 @"x";
154                 %2 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%3 : int)int -> {
155                     %4 : Var<int> = var %3 @"y";
156                     %5 : int = var.load %1;
157                     %6 : int = var.load %4;
158                     %7 : int = add %5 %6;
159                     return %7;
160                 };
161                 %8 : Var<QuotableSubtypeTest$QuotableIntUnaryOperator> = var %2 @"op";
162                 return;
163             };
164             """)
165     static void captureParam(int x) {
166         QuotableIntUnaryOperator op = y -> x + y;
167     }
168 
169     int x, y;
170 
171     @CodeReflection
172     @IR("""
173             func @"captureField" (%0 : QuotableSubtypeTest)void -> {
174                 %1 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%2 : int)int -> {
175                     %3 : Var<int> = var %2 @"z";
176                     %4 : int = field.load %0 @"QuotableSubtypeTest::x()int";
177                     %5 : int = field.load %0 @"QuotableSubtypeTest::y()int";
178                     %6 : int = add %4 %5;
179                     %7 : int = var.load %3;
180                     %8 : int = add %6 %7;
181                     return %8;
182                 };
183                 %9 : Var<QuotableSubtypeTest$QuotableIntUnaryOperator> = var %1 @"op";
184                 return;
185             };
186             """)
187     void captureField() {
188         QuotableIntUnaryOperator op = z -> x + y + z;
189     }
190 
191     static void m() { }
192 
193     @IR("""
194             func @"f" ()void -> {
195                 %0 : QuotableSubtypeTest$QuotableRunnable = lambda ()void -> {
196                     invoke @"QuotableSubtypeTest::m()void";
197                     return;
198                 };
199                 return;
200             };
201             """)
202     static final QuotableRunnable QUOTED_NO_PARAM_VOID_REF = QuotableSubtypeTest::m;
203 
204     static int g(int i) { return i; }
205 
206     @IR("""
207             func @"f" ()void -> {
208                 %0 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%2 : int)int -> {
209                     %3 : Var<int> = var %2 @"x$0";
210                     %4 : int = var.load %3;
211                     %5 : int = invoke %4 @"QuotableSubtypeTest::g(int)int";
212                     return %5;
213                 };
214                 return;
215             };
216             """)
217     static final QuotableIntUnaryOperator QUOTED_INT_PARAM_INT_RET_REF = QuotableSubtypeTest::g;
218 
219     interface QuotableIntFunction<A> extends Quotable, IntFunction<A> { }
220 
221     @IR("""
222             func @"f" ()void -> {
223                 %0 : QuotableSubtypeTest$QuotableIntFunction<int[]> = lambda (%2 : int)int[] -> {
224                     %3 : Var<int> = var %2 @"x$0";
225                     %4 : int = var.load %3;
226                     %5 : int[] = new %4 @"func<int[], int>";
227                     return %5;
228                 };
229                 return;
230             };
231             """)
232     static final QuotableIntFunction<int[]> QUOTED_INT_PARAM_ARR_RET_REF = int[]::new;
233 
234     static class ContextRef {
235         int g(int i) { return i; }
236 
237         QuotableIntUnaryOperator capture() {
238             return this::g;
239         }
240     }
241 
242     @IR("""
243             func @"f" (%0 : QuotableSubtypeTest$ContextRef)void -> {
244                 %1 : QuotableSubtypeTest$QuotableIntUnaryOperator = lambda (%3 : int)int -> {
245                     %4 : Var<int> = var %3 @"x$0";
246                     %5 : int = var.load %4;
247                     %6 : int = invoke %0 %5 @"QuotableSubtypeTest$ContextRef::g(int)int";
248                     return %6;
249                 };
250                 return;
251             };
252             """)
253     static final QuotableIntUnaryOperator QUOTED_CAPTURE_THIS_REF = new ContextRef().capture();
254 }