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 testng TestParse
 28  */
 29 
 30 import jdk.incubator.code.dialect.java.JavaOp;
 31 import org.testng.Assert;
 32 import org.testng.annotations.Test;
 33 
 34 import jdk.incubator.code.Block;
 35 import jdk.incubator.code.dialect.core.CoreOp;
 36 import jdk.incubator.code.Op;
 37 import jdk.incubator.code.dialect.java.MethodRef;
 38 import jdk.incubator.code.extern.OpParser;
 39 import java.util.List;
 40 import java.util.function.IntUnaryOperator;
 41 
 42 import static jdk.incubator.code.dialect.core.CoreOp.return_;
 43 import static jdk.incubator.code.dialect.java.JavaOp.add;
 44 import static jdk.incubator.code.dialect.core.CoreOp.constant;
 45 import static jdk.incubator.code.dialect.core.CoreOp.func;
 46 import static jdk.incubator.code.dialect.java.JavaOp.lambda;
 47 import static jdk.incubator.code.dialect.core.CoreType.functionType;
 48 import static jdk.incubator.code.dialect.java.JavaType.INT;
 49 import static jdk.incubator.code.dialect.java.JavaType.type;
 50 
 51 public class TestParse {
 52 
 53     static final MethodRef INT_UNARY_OPERATOR_METHOD = MethodRef.method(
 54             IntUnaryOperator.class, "applyAsInt",
 55             int.class, int.class);
 56 
 57     @Test
 58     public void testParseLambdaOp() {
 59         // functional type = (int)int
 60         CoreOp.FuncOp f = func("f", functionType(INT, INT))
 61                 .body(block -> {
 62                     Block.Parameter i = block.parameters().get(0);
 63 
 64                     // functional type = (int)int
 65                     // op type = ()IntUnaryOperator
 66                     //   captures i
 67                     JavaOp.LambdaOp lambda = lambda(block.parentBody(),
 68                             functionType(INT, INT), type(IntUnaryOperator.class))
 69                             .body(lbody -> {
 70                                 Block.Builder lblock = lbody.entryBlock();
 71                                 Block.Parameter li = lblock.parameters().get(0);
 72 
 73                                 lblock.op(return_(
 74                                         lblock.op(add(i, li))));
 75                             });
 76 
 77                     Op.Result fi = block.op(lambda);
 78                     Op.Result fortyTwo = block.op(constant(INT, 42));
 79                     Op.Result or = block.op(JavaOp.invoke(INT_UNARY_OPERATOR_METHOD, fi, fortyTwo));
 80                     block.op(return_(or));
 81                 });
 82 
 83         List<Op> ops = OpParser.fromString(JavaOp.JAVA_DIALECT_FACTORY, f.toText());
 84         assertTextEquals(f, ops.get(0));
 85     }
 86 
 87 
 88     static final String NAMED_BODY = """
 89             func @"test" ^body1(%0 : java.type:"int", %1 : java.type:"int")java.type:"int" -> {
 90                 %2 : java.type:"int" = constant @5;
 91                 %3 : java.type:"int" = constant @2;
 92                 branch ^b1(%2, %3);
 93 
 94               ^b1(%0 : java.type:"int", %1 : java.type:"int"):
 95                 return %0;
 96             };
 97             """;
 98     @Test
 99     void testParseNamedBody() {
100         Op opE = OpParser.fromString(JavaOp.JAVA_DIALECT_FACTORY, NAMED_BODY).get(0);
101         Op opA = OpParser.fromString(JavaOp.JAVA_DIALECT_FACTORY, opE.toText()).get(0);
102         assertTextEquals(opA, opE);
103     }
104 
105 
106     static final String ESCAPED_STRING = """
107             func @"test" ()java.type:"java.lang.String" -> {
108                 %0 : java.type:"java.lang.String" = constant @"\\b \\f \\n \\r \\t \\' \\" \\\\";
109                 return %0;
110             };
111             """;
112     @Test
113     void testEscapedString() {
114         Op opE = OpParser.fromString(JavaOp.JAVA_DIALECT_FACTORY, ESCAPED_STRING).get(0);
115         Op opA = OpParser.fromString(JavaOp.JAVA_DIALECT_FACTORY, opE.toText()).get(0);
116         assertTextEquals(opA, opE);
117 
118         CoreOp.ConstantOp cop = (CoreOp.ConstantOp) opE.bodies().get(0).entryBlock().firstOp();
119         String v = (String) cop.value();
120         Assert.assertEquals(v, "\b \f \n \r \t \' \" \\");
121     }
122 
123     static void assertTextEquals(Op a, Op b) {
124         Assert.assertEquals(a.toText(), b.toText());
125     }
126 }