1 package jdk.incubator.code.dialect.core;
2
3 import jdk.incubator.code.TypeElement;
4 import jdk.incubator.code.Value;
5 import jdk.incubator.code.extern.ExternalizedTypeElement;
6 import jdk.incubator.code.extern.TypeElementFactory;
7 import jdk.incubator.code.dialect.java.JavaType;
8
9 import java.util.ArrayList;
10 import java.util.List;
11 import java.util.Objects;
12 import java.util.stream.Stream;
13
14 /**
15 * The symbolic description of a core type.
16 */
17 public sealed interface CoreType extends TypeElement
18 permits FunctionType, TupleType, VarType {
19
20 /**
21 * Creates a composed type element factory for core type elements and type elements from the given
22 * type element factory, where the core type elements can refer to type elements from the
23 * given type element factory.
24 *
25 * @param f the type element factory.
26 * @return the composed type element factory.
27 */
28 static TypeElementFactory coreTypeFactory(TypeElementFactory f) {
29 class CodeModelFactory implements TypeElementFactory {
30 final TypeElementFactory thisThenF = this.andThen(f);
31
32 @Override
33 public TypeElement constructType(ExternalizedTypeElement tree) {
34 return switch (tree.identifier()) {
35 case VarType.NAME -> {
36 if (tree.arguments().size() != 1) {
37 throw new IllegalArgumentException();
38 }
39
40 TypeElement v = thisThenF.constructType(tree.arguments().getFirst());
41 if (v == null) {
42 throw new IllegalArgumentException("Bad type: " + tree);
43 }
44 yield varType(v);
45 }
46 case TupleType.NAME -> {
47 if (tree.arguments().isEmpty()) {
48 throw new IllegalArgumentException("Bad type: " + tree);
49 }
50
51 List<TypeElement> cs = new ArrayList<>(tree.arguments().size());
52 for (ExternalizedTypeElement child : tree.arguments()) {
53 TypeElement c = thisThenF.constructType(child);
54 if (c == null) {
55 throw new IllegalArgumentException("Bad type: " + tree);
56 }
57 cs.add(c);
58 }
59 yield tupleType(cs);
60 }
61 case FunctionType.NAME -> {
62 if (tree.arguments().isEmpty()) {
63 throw new IllegalArgumentException("Bad type: " + tree);
64 }
65
66 TypeElement rt = thisThenF.constructType(tree.arguments().getFirst());
67 if (rt == null) {
68 throw new IllegalArgumentException("Bad type: " + tree);
69 }
70 List<TypeElement> pts = new ArrayList<>(tree.arguments().size() - 1);
71 for (ExternalizedTypeElement child : tree.arguments().subList(1, tree.arguments().size())) {
72 TypeElement c = thisThenF.constructType(child);
73 if (c == null) {
74 throw new IllegalArgumentException("Bad type: " + tree);
75 }
76 pts.add(c);
77 }
78 yield functionType(rt, pts);
79 }
80 default -> null;
81 };
82 }
83 }
84 if (f instanceof CodeModelFactory) {
85 throw new IllegalArgumentException();
86 }
87
88 return new CodeModelFactory().thisThenF;
89 }
90
91
92 /**
93 * The function type with no parameters, returning void.
94 */
95 // @@@ Uses JavaType
96 FunctionType FUNCTION_TYPE_VOID = functionType(JavaType.VOID);
97
98 /**
99 * Constructs a function type.
100 *
101 * @param returnType the function type's return type.
102 * @param parameterTypes the function type's parameter types.
103 * @return a function type.
104 */
105 static FunctionType functionType(TypeElement returnType, List<? extends TypeElement> parameterTypes) {
106 Objects.requireNonNull(returnType);
107 Objects.requireNonNull(parameterTypes);
108 return new FunctionType(returnType, parameterTypes);
109 }
110
111 /**
112 * Constructs a function type.
113 *
114 * @param returnType the function type's return type.
115 * @param parameterTypes the function type's parameter types.
116 * @return a function type.
117 */
118 static FunctionType functionType(TypeElement returnType, TypeElement... parameterTypes) {
119 return functionType(returnType, List.of(parameterTypes));
120 }
121
122 /**
123 * Constructs a tuple type.
124 *
125 * @param componentTypes the tuple type's component types.
126 * @return a tuple type.
127 */
128 static TupleType tupleType(TypeElement... componentTypes) {
129 return tupleType(List.of(componentTypes));
130 }
131
132 /**
133 * Constructs a tuple type.
134 *
135 * @param componentTypes the tuple type's component types.
136 * @return a tuple type.
137 */
138 static TupleType tupleType(List<? extends TypeElement> componentTypes) {
139 Objects.requireNonNull(componentTypes);
140 return new TupleType(componentTypes);
141 }
142
143 /**
144 * Constructs a tuple type whose components are the types of
145 * the given values.
146 *
147 * @param values the values.
148 * @return a tuple type.
149 */
150 static TupleType tupleTypeFromValues(Value... values) {
151 return tupleType(Stream.of(values).map(Value::type).toList());
152 }
153
154 /**
155 * Constructs a tuple type whose components are the types of
156 * the given values.
157 *
158 * @param values the values.
159 * @return a tuple type.
160 */
161 static TupleType tupleTypeFromValues(List<? extends Value> values) {
162 return tupleType(values.stream().map(Value::type).toList());
163 }
164
165 /**
166 * Constructs a variable type.
167 *
168 * @param valueType the variable's value type.
169 * @return a variable type.
170 */
171 static VarType varType(TypeElement valueType) {
172 Objects.requireNonNull(valueType);
173 return new VarType(valueType);
174 }
175 }