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.externalizeOpName(),
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 }