1 /*
  2  *  Copyright (c) 2020, 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 
 27 package jdk.incubator.jextract;
 28 
 29 import jdk.incubator.foreign.FunctionDescriptor;
 30 import jdk.incubator.foreign.MemoryLayout;
 31 import jdk.incubator.foreign.ValueLayout;
 32 import jdk.internal.jextract.impl.TypeImpl;
 33 import jdk.internal.jextract.impl.UnsupportedLayouts;
 34 
 35 import java.util.List;
 36 import java.util.Optional;
 37 import java.util.OptionalLong;
 38 import java.util.function.Supplier;
 39 import java.util.stream.Collectors;
 40 import java.util.stream.Stream;
 41 
 42 /**
 43  * Instances of this class are used to model types in the foreign language.
 44  * Instances of this class support the <em>visitor</em> pattern (see {@link Type#accept(Type.Visitor, Object)} and
 45  * {@link Type.Visitor}).
 46  */
 47 public interface Type {
 48 
 49     /**
 50      * Is this type the erroneous type?
 51      * @return true, if this type is the erroneous type.
 52      */
 53     boolean isErroneous();
 54 
 55     /**
 56      * Entry point for visiting type instances.
 57      * @param visitor the type visitor.
 58      * @param data optional data to be passed to the visitor.
 59      * @param <R> the visitor's return type.
 60      * @param <D> the visitor's argument type.
 61      * @return the result of visiting this type through the specified type visitor.
 62      */
 63     <R,D> R accept(Visitor<R, D> visitor, D data);
 64 
 65     /**
 66      * Compares the specified object with this Type for equality.  Returns
 67      * {@code true} if and only if the specified object is also a Type and both
 68      * the Types are <i>equal</i>.
 69      *
 70      * @param o the object to be compared for equality with this Type
 71      * @return {@code true} if the specified object is equal to this Type
 72      */
 73     boolean equals(Object o);
 74 
 75     /**
 76      * Returns the hash code value for this Type.
 77      *
 78      * @return the hash code value for this Type.
 79      */
 80     int hashCode();
 81 
 82     /**
 83      * A primitive type.
 84      */
 85     interface Primitive extends Type {
 86 
 87         /**
 88          * The primitive type kind.
 89          */
 90         enum Kind {
 91             /**
 92              * {@code void} type.
 93              */
 94             Void("void", null),
 95             /**
 96              * {@code Bool} type.
 97              */
 98             Bool("_Bool", ValueLayout.JAVA_BOOLEAN),
 99             /**
100              * {@code char} type.
101              */
102             Char("char", ValueLayout.JAVA_BYTE),
103             /**
104              * {@code char16} type.
105              */
106             Char16("char16", UnsupportedLayouts.CHAR16),
107             /**
108              * {@code short} type.
109              */
110             Short("short", ValueLayout.JAVA_SHORT),
111             /**
112              * {@code int} type.
113              */
114             Int("int", ValueLayout.JAVA_INT),
115             /**
116              * {@code long} type.
117              */
118             Long("long", TypeImpl.IS_WINDOWS ? ValueLayout.JAVA_INT : ValueLayout.JAVA_LONG),
119             /**
120              * {@code long long} type.
121              */
122             LongLong("long long", ValueLayout.JAVA_LONG),
123             /**
124              * {@code int128} type.
125              */
126             Int128("__int128", UnsupportedLayouts.__INT128),
127             /**
128              * {@code float} type.
129              */
130             Float("float", ValueLayout.JAVA_FLOAT),
131             /**
132              * {@code double} type.
133              */
134             Double("double", ValueLayout.JAVA_DOUBLE),
135             /**
136               * {@code long double} type.
137               */
138             LongDouble("long double", UnsupportedLayouts.LONG_DOUBLE),
139             /**
140              * {@code float128} type.
141              */
142             Float128("float128", UnsupportedLayouts._FLOAT128),
143             /**
144              * {@code float16} type.
145              */
146             HalfFloat("__fp16", UnsupportedLayouts.__FP16),
147             /**
148              * {@code wchar} type.
149              */
150             WChar("wchar_t", UnsupportedLayouts.WCHAR_T);
151 
152             private final String typeName;
153             private final MemoryLayout layout;
154 
155             Kind(String typeName, MemoryLayout layout) {
156                 this.typeName = typeName;
157                 this.layout = layout;
158             }
159 
160             public String typeName() {
161                 return typeName;
162             }
163 
164             /**
165              * The primitive type (optional) layout.
166              * @return The primitive type (optional) layout.
167              */
168             public Optional<MemoryLayout> layout() {
169                 return Optional.ofNullable(layout);
170             }
171         }
172 
173         /**
174          * The primitive type kind.
175          * @return The primitive type kind.
176          */
177         Kind kind();
178     }
179 
180     /**
181      * Instances of this class are used to model types which are associated to a declaration in the foreign language
182      * (see {@link Declaration}).
183      */
184     interface Declared extends Type {
185         /**
186          * The declaration to this type refers to.
187          * @return The declaration to this type refers to.
188          */
189         Declaration.Scoped tree();
190     }
191 
192     /**
193      * A function type.
194      */
195     interface Function extends Type {
196         /**
197          * Is this function type a variable-arity?
198          * @return true, if this function type is a variable-arity.
199          */
200         boolean varargs();
201 
202         /**
203          * The function formal parameter types.
204          * @return The function formal parameter types.
205          */
206         List<Type> argumentTypes();
207 
208         /**
209          * The function return type.
210          * @return The function return type.
211          */
212         Type returnType();
213     }
214 
215     /**
216      * An array type. Array types feature an element type and an optional size. As such they can also be used to
217      * model array types.
218      */
219     interface Array extends Type {
220 
221         /**
222          * The array type kind.
223          */
224         enum Kind {
225             /**
226              * Vector kind.
227              */
228             VECTOR,
229             /**
230              * Array kind.
231              */
232             ARRAY,
233             /**
234              * Incomplete array kind.
235              */
236             INCOMPLETE_ARRAY;
237         }
238 
239         /**
240          * The array type kind.
241          * @return The array type kind.
242          */
243         Kind kind();
244 
245         /**
246          * The (optional) array element count.
247          * @return The (optional) array element count.
248          *
249          * @implSpec an element count is present if the array type kind is one of {@link Kind#VECTOR}, {@link Kind#ARRAY}.
250          */
251         OptionalLong elementCount();
252 
253         /**
254          * The array type element type.
255          * @return The array type element type.
256          */
257         Type elementType();
258     }
259 
260     /**
261      * A delegated type is used to model a type which contains an indirection to some other underlying type. For instance,
262      * a delegated type can be used to model foreign pointers, where the indirection is used to model the pointee type.
263      */
264     interface Delegated extends Type {
265 
266         /**
267          * The delegated type kind.
268          */
269         enum Kind {
270             /**
271              * Type-defined type.
272              */
273             TYPEDEF,
274             /**
275              * Pointer type.
276              */
277             POINTER,
278             /**
279              * Signed type.
280              */
281             SIGNED,
282             /**
283              * Unsigned type.
284              */
285             UNSIGNED,
286             /**
287              * Atomic type.
288              */
289             ATOMIC,
290             /**
291              * Volatile type.
292              */
293             VOLATILE,
294             /**
295              * Complex type.
296              */
297             COMPLEX;
298         }
299 
300         /**
301          * The delegated type kind.
302          * @return The delegated type kind.
303          */
304         Kind kind();
305 
306         /**
307          * The delegated type (optional) name.
308          * @return The delegated type (optional) name.
309          *
310          * @implSpec an element count is present if the array type kind is one of {@link Kind#TYPEDEF}.
311          */
312         Optional<String> name();
313 
314         /**
315          * The delegated type underlying type.
316          * @return The delegated type underlying type.
317          */
318         Type type();
319     }
320 
321     /**
322      * Type visitor interface.
323      * @param <R> the visitor's return type.
324      * @param <P> the visitor's parameter type.
325      */
326     interface Visitor<R,P> {
327         /**
328          * Visit a primitive type.
329          * @param t the primitive type.
330          * @param p the visitor parameter.
331          * @return the result of visiting the given primitive type through this visitor object.
332          */
333         default R visitPrimitive(Primitive t, P p) { return visitType(t, p); }
334 
335         /**
336          * Visit a function type.
337          * @param t the function type.
338          * @param p the visitor parameter.
339          * @return the result of visiting the given function type through this visitor object.
340          */
341         default R visitFunction(Function t, P p) { return visitType(t, p); }
342 
343         /**
344          * Visit a declared type.
345          * @param t the declared type.
346          * @param p the visitor parameter.
347          * @return the result of visiting the given declared type through this visitor object.
348          */
349         default R visitDeclared(Declared t, P p) { return visitType(t, p); }
350 
351         /**
352          * Visit a delegated type.
353          * @param t the delegated type.
354          * @param p the visitor parameter.
355          * @return the result of visiting the given delegated type through this visitor object.
356          */
357         default R visitDelegated(Delegated t, P p) { return visitType(t, p); }
358 
359         /**
360          * Visit an array type.
361          * @param t the array type.
362          * @param p the visitor parameter.
363          * @return the result of visiting the given array type through this visitor object.
364          */
365         default R visitArray(Array t, P p) { return visitType(t, p); }
366 
367         /**
368          * Visit a type.
369          * @param t the type.
370          * @param p the visitor parameter.
371          * @return the result of visiting the given type through this visitor object.
372          */
373         default R visitType(Type t, P p) { throw new UnsupportedOperationException(); }
374     }
375 
376     /**
377      * Compute the layout for a given type.
378      * @param t the type.
379      * @return the layout for given type.
380      */
381     static Optional<MemoryLayout> layoutFor(Type t) {
382         return TypeImpl.getLayout(t);
383     }
384 
385     /**
386      * Compute the function descriptor for a given function type.
387      * @param function the function type.
388      * @return the function descriptor for given function type.
389      */
390     static Optional<FunctionDescriptor> descriptorFor(Function function) {
391         return TypeImpl.getDescriptor(function);
392     }
393 
394     /**
395      * Create the {@code void} type.
396      * @return the {@code void} type.
397      */
398     static Type.Primitive void_() {
399         return new TypeImpl.PrimitiveImpl(Type.Primitive.Kind.Void);
400     }
401 
402     /**
403      * Creates a new primitive type given kind.
404      * @param kind the primitive type kind.
405      * @return a new primitive type with given kind.
406      */
407     static Type.Primitive primitive(Type.Primitive.Kind kind) {
408         return new TypeImpl.PrimitiveImpl(kind);
409     }
410 
411     /**
412      * Creates a new qualified type given kind and underlying type.
413      * @param kind the qualified type kind.
414      * @param type the qualified type underlying type.
415      * @return a new qualified type with given name and underlying type.
416      */
417     static Type.Delegated qualified(Type.Delegated.Kind kind, Type type) {
418         return new TypeImpl.QualifiedImpl(kind, type);
419     }
420 
421     /**
422      * Creates a new typedef type given name and underlying type.
423      * @param name the typedef type name.
424      * @param aliased the typeef type underlying type.
425      * @return a new typedef type with given name and underlying type.
426      */
427     static Type.Delegated typedef(String name, Type aliased) {
428         return new TypeImpl.QualifiedImpl(Delegated.Kind.TYPEDEF, name, aliased);
429     }
430 
431     /**
432      * Creates a new pointer type with no associated pointee information.
433      * @return a new pointer type with no associated pointee information.
434      */
435     static Type.Delegated pointer() {
436         return new TypeImpl.PointerImpl(() -> new TypeImpl.PrimitiveImpl(Type.Primitive.Kind.Void));
437     }
438 
439     /**
440      * Creates a new pointer type with given pointee type.
441      * @param pointee the pointee type.
442      * @return a new pointer type with given pointee type.
443      */
444     static Type.Delegated pointer(Type pointee) {
445         return new TypeImpl.PointerImpl(() -> pointee);
446     }
447 
448     /**
449      * Creates a new pointer type with given pointee type.
450      * @param pointee factory to (lazily) build the pointee type.
451      * @return a new pointer type with given pointee type (lazily built from factory).
452      */
453     static Type.Delegated pointer(Supplier<Type> pointee) {
454         return new TypeImpl.PointerImpl(pointee);
455     }
456 
457     /**
458      * Creates a new function type with given parameter types and return type.
459      * @param varargs is this function type variable-arity?
460      * @param returnType the function type return type.
461      * @param arguments the function type formal parameter types.
462      * @return a new function type with given parameter types and return type.
463      */
464     static Type.Function function(boolean varargs, Type returnType, Type... arguments) {
465         return new TypeImpl.FunctionImpl(varargs, Stream.of(arguments).collect(Collectors.toList()), returnType);
466     }
467 
468     /**
469      * Creates a new declared type with given foreign declaration.
470      * @param tree the foreign declaration the type refers to.
471      * @return  a new declared type with given foreign declaration.
472      */
473     static Type.Declared declared(Declaration.Scoped tree) {
474         return new TypeImpl.DeclaredImpl(tree);
475     }
476 
477     /**
478      * Creates a new vector type with given element count and element type.
479      * @param elementCount the vector type element count.
480      * @param elementType the vector type element type.
481      * @return a new vector type with given element count and element type.
482      */
483     static Type.Array vector(long elementCount, Type elementType) {
484         return new TypeImpl.ArrayImpl(Array.Kind.VECTOR, elementCount, elementType);
485     }
486 
487     /**
488      * Creates a new array type with given element count and element type.
489      * @param elementCount the array type element count.
490      * @param elementType the array type element type.
491      * @return a new array type with given element count and element type.
492      */
493     static Type.Array array(long elementCount, Type elementType) {
494         return new TypeImpl.ArrayImpl(Array.Kind.ARRAY, elementCount, elementType);
495     }
496 
497     /**
498      * Creates a new array type with given element type.
499      * @param elementType the array type element type.
500      * @return a new array type with given element type.
501      */
502     static Type.Array array(Type elementType) {
503         return new TypeImpl.ArrayImpl(Array.Kind.INCOMPLETE_ARRAY, elementType);
504     }
505 
506     /**
507      * Creates an erroneous type.
508      * @return an erroneous type.
509      */
510     static Type error() {
511         return TypeImpl.ERROR;
512     }
513 }