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 }