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