1 package jdk.incubator.code.extern; 2 3 import jdk.incubator.code.*; 4 5 import java.util.List; 6 import java.util.Map; 7 import java.util.function.Function; 8 9 /** 10 * An operation's externalized state (a record) that can be utilized to construct an instance 11 * of an {@link Op} associated with that state, such as the operation's name. 12 * 13 * @param name the operation name 14 * @param location the source location associated with the operation, may be null 15 * @param operands the list of operands 16 * @param successors the list of successors 17 * @param resultType the operation result type 18 * @param attributes the operation's specific state as a map of attributes 19 * @param bodyDefinitions the list of body builders for building the operation's bodies 20 * @apiNote Deserializers of operations may utilize this record to construct operations, 21 * thereby separating the specifics of deserializing from construction. 22 */ 23 public record ExternalizedOp(String name, 24 Location location, 25 List<Value> operands, 26 List<Block.Reference> successors, 27 TypeElement resultType, 28 Map<String, Object> attributes, 29 List<Body.Builder> bodyDefinitions) { 30 31 /** 32 * The attribute value that represents the external null value. 33 */ 34 public static final Object NULL_ATTRIBUTE_VALUE = new Object(); 35 36 public ExternalizedOp { 37 attributes = Map.copyOf(attributes); 38 } 39 40 /** 41 * Gets an attribute value from the attributes map, converts the value by applying it 42 * to mapping function, and returns the result. 43 * 44 * <p>If the attribute is a default attribute then this method first attempts to 45 * get the attribute whose name is the empty string, otherwise if there is no such 46 * attribute present or the attribute is not a default attribute then this method 47 * attempts to get the attribute with the given name. 48 * 49 * <p>On successfully obtaining the attribute its value is converted by applying the value 50 * to the mapping function. A {@code null} value is represented by the value 51 * {@link ExternalizedOp#NULL_ATTRIBUTE_VALUE}. 52 * 53 * <p>If no attribute is present the {@code null} value is applied to the mapping function. 54 * 55 * @param name the attribute name. 56 * @param isDefault true if the attribute is a default attribute 57 * @param <T> the converted attribute value type 58 * @return the converted attribute value 59 */ 60 public <T> T extractAttributeValue(String name, boolean isDefault, Function<Object, T> mapper) { 61 Object value = null; 62 if (isDefault && attributes.containsKey("")) { 63 value = attributes.get(""); 64 assert value != null; 65 } 66 67 if (value == null && attributes.containsKey(name)) { 68 value = attributes.get(name); 69 assert value != null; 70 } 71 72 return mapper.apply(value); 73 } 74 75 /** 76 * Externalizes an operation's content. 77 * <p> 78 * If the operation is an instanceof {@code ExternalizableOp} then the operation's 79 * specific content is externalized to an attribute map, otherwise the attribute map 80 * is empty. 81 * 82 * @param cc the copy context 83 * @param op the operation 84 * @return the operation's content. 85 */ 86 public static ExternalizedOp externalizeOp(CopyContext cc, Op op) { 87 return new ExternalizedOp( 88 op.opName(), 89 op.location(), 90 cc.getValues(op.operands()), 91 op.successors().stream().map(cc::getSuccessorOrCreate).toList(), 92 op.resultType(), 93 op.externalize(), 94 op.bodies().stream().map(b -> b.copy(cc)).toList() 95 ); 96 } 97 }