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