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