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 * @modules jdk.incubator.code 27 * @run junit TestClosureOps 28 */ 29 30 import jdk.incubator.code.Block; 31 import jdk.incubator.code.Op; 32 import jdk.incubator.code.Quoted; 33 import jdk.incubator.code.dialect.core.CoreOp; 34 import jdk.incubator.code.dialect.java.JavaOp; 35 import jdk.incubator.code.dialect.java.JavaType; 36 import jdk.incubator.code.dialect.java.MethodRef; 37 import jdk.incubator.code.interpreter.Interpreter; 38 import org.junit.jupiter.api.Assertions; 39 import org.junit.jupiter.api.Test; 40 41 import java.lang.invoke.MethodHandles; 42 import java.util.ArrayList; 43 import java.util.List; 44 45 import static jdk.incubator.code.dialect.core.CoreOp.*; 46 import static jdk.incubator.code.dialect.core.CoreType.functionType; 47 import static jdk.incubator.code.dialect.java.JavaOp.add; 48 import static jdk.incubator.code.dialect.java.JavaType.INT; 49 import static jdk.incubator.code.dialect.java.JavaType.type; 50 51 public class TestClosureOps { 52 53 static class Builder { 54 static final MethodRef ACCEPT_METHOD = MethodRef.method(type(TestClosureOps.Builder.class), "accept", 55 INT, CoreOp.QuotedOp.QUOTED_TYPE); 56 57 static int accept(Quoted c) { 58 Assertions.assertEquals(c.capturedValues().size(), 1); 59 Assertions.assertEquals(c.capturedValues().values().iterator().next(), 1); 60 61 List<Object> arguments = new ArrayList<>(); 62 arguments.add(42); 63 arguments.addAll(c.capturedValues().values()); 64 int r = (int) Interpreter.invoke(MethodHandles.lookup(), (Op & Op.Invokable) c.op(), 65 arguments); 66 return r; 67 } 68 } 69 70 @Test 71 public void testQuotedWithCapture() { 72 // functional type = (int)int 73 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 74 .body(block -> { 75 Block.Parameter i = block.parameters().get(0); 76 77 // functional type = (int)int 78 // op descriptor = ()Quoted<ClosureOp> 79 CoreOp.QuotedOp qop = quoted(block.parentBody(), qblock -> { 80 return closure(qblock.parentBody(), functionType(INT, INT)) 81 .body(cblock -> { 82 Block.Parameter ci = cblock.parameters().get(0); 83 84 cblock.op(return_( 85 // capture i from function's body 86 cblock.op(add(i, ci)) 87 )); 88 }); 89 }); 90 Op.Result cquoted = block.op(qop); 91 92 Op.Result or = block.op(JavaOp.invoke(TestClosureOps.Builder.ACCEPT_METHOD, cquoted)); 93 block.op(return_(or)); 94 }); 95 96 System.out.println(f.toText()); 97 98 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 99 Assertions.assertEquals(43, ir); 100 } 101 102 @Test 103 public void testWithCapture() { 104 // functional type = (int)int 105 CoreOp.FuncOp f = func("f", functionType(INT, INT)) 106 .body(block -> { 107 Block.Parameter i = block.parameters().get(0); 108 109 // functional type = (int)int 110 // captures i 111 CoreOp.ClosureOp closure = CoreOp.closure(block.parentBody(), 112 functionType(INT, INT)) 113 .body(cblock -> { 114 Block.Parameter ci = cblock.parameters().get(0); 115 116 cblock.op(return_( 117 cblock.op(add(i, ci)))); 118 }); 119 Op.Result c = block.op(closure); 120 121 Op.Result fortyTwo = block.op(constant(INT, 42)); 122 Op.Result or = block.op(closureCall(c, fortyTwo)); 123 block.op(return_(or)); 124 }); 125 126 System.out.println(f.toText()); 127 128 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1); 129 Assertions.assertEquals(43, ir); 130 } 131 132 @Test 133 public void testQuotableModel() { 134 Quoted quoted = () -> {}; 135 Op qop = quoted.op(); 136 Op top = qop.ancestorOp().ancestorOp(); 137 Assertions.assertTrue(top instanceof CoreOp.FuncOp); 138 139 CoreOp.FuncOp fop = (CoreOp.FuncOp) top; 140 Assertions.assertEquals(fop.invokableType().returnType(), JavaType.type(Quoted.class)); 141 } 142 }