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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.code; 27 28 import java.util.Objects; 29 import java.util.function.BiFunction; 30 31 /** 32 * An operation transformer. 33 */ 34 @FunctionalInterface 35 public interface OpTransformer extends BiFunction<Block.Builder, Op, Block.Builder> { 36 /** 37 * A copying transformer that applies the operation to the block builder, and returning the block builder. 38 */ 39 OpTransformer COPYING_TRANSFORMER = (block, op) -> { 40 block.op(op); 41 return block; 42 }; 43 44 /** 45 * A transformer that performs no action on the block builder. 46 */ 47 OpTransformer NOOP_TRANSFORMER = (block, op) -> block; 48 49 /** 50 * A transformer that drops location information from operations. 51 */ 52 OpTransformer DROP_LOCATION_TRANSFORMER = (block, op) -> { 53 Op.Result r = block.op(op); 54 r.op().setLocation(Location.NO_LOCATION); 55 return block; 56 }; 57 58 /** 59 * A transformer that lowers operations that are {@link Op.Lowerable lowerable}, 60 * and copies other operations. 61 */ 62 OpTransformer LOWERING_TRANSFORMER = (block, op) -> { 63 if (op instanceof Op.Lowerable lop) { 64 return lop.lower(block); 65 } else { 66 block.op(op); 67 return block; 68 } 69 }; 70 71 /** 72 * Transforms a given operation to zero or more other operations appended to the 73 * given block builder. Returns a block builder to be used for appending further operations, such 74 * as subsequent operations from the same block as the given operation. 75 * 76 * @param block the block builder. 77 * @param op the operation to transform. 78 * @return the block builder to append to for subsequent operations to transform that have same parent block. 79 */ 80 Block.Builder apply(Block.Builder block, Op op); 81 82 /** 83 * Transforms a given block to zero or more operations appended to the given block builder. 84 * 85 * @implSpec 86 * The default implementation iterates through each operation of the block to transform 87 * and {@link #apply(Block.Builder, Op) applies} a block builder and the operation to this 88 * transformer. 89 * On first iteration the block builder that is applied is block builder passed as an argument 90 * to this method. 91 * On second and subsequent iterations the block builder that is applied is the resulting 92 * block builder of the prior iteration. 93 * 94 * @param block the block builder 95 * @param b the block to transform 96 * @throws NullPointerException if a resulting block builder is null 97 */ 98 default void apply(Block.Builder block, Block b) { 99 for (Op op : b.ops()) { 100 block = apply(block, op); 101 // @@@ See andThen composition 102 Objects.requireNonNull(block); 103 } 104 } 105 106 default OpTransformer compose(OpTransformer before) { 107 return before.andThen(this); 108 } 109 110 default OpTransformer andThen(OpTransformer after) { 111 if (after == NOOP_TRANSFORMER) { 112 return this; 113 } else if (this == NOOP_TRANSFORMER) { 114 return after; 115 } else { 116 return (bb, o) -> { 117 Block.Builder nbb = apply(bb, o); 118 if (nbb != null) { 119 return after.apply(nbb, o); 120 } else { 121 // @@@ This does not currently occur 122 return null; 123 } 124 }; 125 } 126 } 127 }