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 import java.util.List;
 37 
 38 public class QuotedTest {
 39     @IR("""
 40             func @"f" ()java.type:"void" -> {
 41                 %0 : func<java.type:"void"> = closure ()java.type:"void" -> {
 42                     return;
 43                 };
 44                 return;
 45             };
 46             """)
 47     static final Quoted QUOTED_NO_PARAM_VOID = () -> {
 48     };
 49 
 50     @IR("""
 51             func @"f" ()java.type:"void" -> {
 52                 %0 : func<java.type:"int"> = closure ()java.type:"int" -> {
 53                     %1 : java.type:"int" = constant @1;
 54                     return %1;
 55                 };
 56                 return;
 57             };
 58             """)
 59     static final Quoted QUOTED_NO_PARAM_CONST = () -> 1;
 60 
 61     @IR("""
 62             func @"f" ()java.type:"void" -> {
 63                 %0 : func<java.type:"int", java.type:"int"> = closure (%1 : java.type:"int")java.type:"int" -> {
 64                     %2 : Var<java.type:"int"> = var %1 @"x";
 65                     %3 : java.type:"int" = var.load %2;
 66                     return %3;
 67                 };
 68                 return;
 69             };
 70             """)
 71     static final Quoted QUOTED_ID = (int x) -> x;
 72 
 73     @IR("""
 74             func @"f" ()java.type:"void" -> {
 75                 %0 : func<java.type:"int", java.type:"int", java.type:"int"> = closure (%1 : java.type:"int", %2 : java.type:"int")java.type:"int" -> {
 76                     %3 : Var<java.type:"int"> = var %1 @"x";
 77                     %4 : Var<java.type:"int"> = var %2 @"y";
 78                     %5 : java.type:"int" = var.load %3;
 79                     %6 : java.type:"int" = var.load %4;
 80                     %7 : java.type:"int" = add %5 %6;
 81                     return %7;
 82                 };
 83                 return;
 84             };
 85             """)
 86     static final Quoted QUOTED_PLUS = (int x, int y) -> x + y;
 87 
 88     @IR("""
 89             func @"f" ()java.type:"void" -> {
 90                 %0 : func<java.type:"java.lang.Object"> = closure ()java.type:"java.lang.Object" -> {
 91                     %1 : java.type:"java.lang.AssertionError" = new @java.ref:"java.lang.AssertionError::()";
 92                     throw %1;
 93                 };
 94                 return;
 95             };
 96             """)
 97     static final Quoted QUOTED_THROW_NO_PARAM = () -> {
 98         throw new AssertionError();
 99     };
100 
101     // can we write out the root op then extract the closure ?
102 
103     @IR("""
104             func @"f" (%0 : Var<java.type:"int">)java.type:"void" -> {
105                 %1 : func<java.type:"int", java.type:"int"> = closure (%2 : java.type:"int")java.type:"int" -> {
106                     %3 : Var<java.type:"int"> = var %2 @"y";
107                     %4 : java.type:"int" = var.load %0;
108                     %5 : java.type:"int" = var.load %3;
109                     %6 : java.type:"int" = add %4 %5;
110                     return %6;
111                 };
112                 return;
113             };
114             """)
115     static final Quoted QUOTED_CAPTURE_PARAM = new Object() {
116         Quoted captureContext(int x) {
117             return (int y) -> x + y;
118         }
119     }.captureContext(42);
120 
121     static class Context {
122         int x, y;
123 
124         Quoted capture() {
125             return (int z) -> x + y + z;
126         }
127     }
128 
129     @IR("""
130             func @"f" (%0 : java.type:"QuotedTest$Context")java.type:"void" -> {
131                 %1 : func<java.type:"int", java.type:"int"> = closure (%2 : java.type:"int")java.type:"int" -> {
132                     %3 : Var<java.type:"int"> = var %2 @"z";
133                     %4 : java.type:"int" = field.load %0 @java.ref:"QuotedTest$Context::x:int";
134                     %5 : java.type:"int" = field.load %0 @java.ref:"QuotedTest$Context::y:int";
135                     %6 : java.type:"int" = add %4 %5;
136                     %7 : java.type:"int" = var.load %3;
137                     %8 : java.type:"int" = add %6 %7;
138                     return %8;
139                 };
140                 return;
141             };
142             """)
143     static final Quoted QUOTED_CAPTURE_FIELD = new Context().capture();
144 
145     @CodeReflection
146     @IR("""
147             func @"captureParam" (%0 : java.type:"int")java.type:"void" -> {
148                 %1 : Var<java.type:"int"> = var %0 @"x";
149                 %2 : java.type:"jdk.incubator.code.Quoted" = quoted ()java.type:"void" -> {
150                     %3 : func<java.type:"int", java.type:"int"> = closure (%4 : java.type:"int")java.type:"int" -> {
151                         %5 : Var<java.type:"int"> = var %4 @"y";
152                         %6 : java.type:"int" = var.load %1;
153                         %7 : java.type:"int" = var.load %5;
154                         %8 : java.type:"int" = add %6 %7;
155                         return %8;
156                     };
157                     yield %3;
158                 };
159                 %9 : Var<java.type:"jdk.incubator.code.Quoted"> = var %2 @"op";
160                 return;
161             };
162             """)
163     static void captureParam(int x) {
164         Quoted op = (int y) -> x + y;
165     }
166 
167     int x, y;
168 
169     @CodeReflection
170     @IR("""
171             func @"captureField" (%0 : java.type:"QuotedTest")java.type:"void" -> {
172                 %1 : java.type:"jdk.incubator.code.Quoted" = quoted ()java.type:"void" -> {
173                     %2 : func<java.type:"int", java.type:"int"> = closure (%3 : java.type:"int")java.type:"int" -> {
174                         %4 : Var<java.type:"int"> = var %3 @"z";
175                         %5 : java.type:"int" = field.load %0 @java.ref:"QuotedTest::x:int";
176                         %6 : java.type:"int" = field.load %0 @java.ref:"QuotedTest::y:int";
177                         %7 : java.type:"int" = add %5 %6;
178                         %8 : java.type:"int" = var.load %4;
179                         %9 : java.type:"int" = add %7 %8;
180                         return %9;
181                     };
182                     yield %2;
183                 };
184                 %10 : Var<java.type:"jdk.incubator.code.Quoted"> = var %1 @"op";
185                 return;
186             };
187             """)
188     void captureField() {
189         Quoted op = (int z) -> x + y + z;
190     }
191 
192     @CodeReflection
193     @IR("""
194             func @"upwardNonDenotableReturn" (%0 : java.type:"QuotedTest")java.type:"void" -> {
195                 %1 : java.type:"jdk.incubator.code.Quoted" = quoted ()java.type:"void" -> {
196                     %2 : func<java.type:"java.util.List<? extends java.io.Serializable>", java.type:"boolean", java.type:"java.util.List<java.lang.String>", java.type:"java.util.List<java.lang.Integer>"> = closure (%3 : java.type:"boolean", %4 : java.type:"java.util.List<java.lang.String>", %5 : java.type:"java.util.List<java.lang.Integer>")java.type:"java.util.List<? extends java.io.Serializable>" -> {
197                         %6 : Var<java.type:"boolean"> = var %3 @"cond";
198                         %7 : Var<java.type:"java.util.List<java.lang.String>"> = var %4 @"ls";
199                         %8 : Var<java.type:"java.util.List<java.lang.Integer>"> = var %5 @"li";
200                         %9 : java.type:"java.util.List<? extends java.io.Serializable>" = java.cexpression
201                             ()java.type:"boolean" -> {
202                                 %10 : java.type:"boolean" = var.load %6;
203                                 yield %10;
204                             }
205                             ()java.type:"java.util.List<? extends java.io.Serializable>" -> {
206                                 %11 : java.type:"java.util.List<java.lang.String>" = var.load %7;
207                                 yield %11;
208                             }
209                             ()java.type:"java.util.List<? extends java.io.Serializable>" -> {
210                                 %12 : java.type:"java.util.List<java.lang.Integer>" = var.load %8;
211                                 yield %12;
212                             };
213                         return %9;
214                     };
215                     yield %2;
216                 };
217                 %13 : Var<java.type:"jdk.incubator.code.Quoted"> = var %1 @"op";
218                 return;
219             };
220             """)
221     void upwardNonDenotableReturn() {
222         Quoted op = (boolean cond, List<String> ls, List<Integer> li) -> cond ? ls : li;
223     }
224 }