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 java.lang.constant.Constable;
 30 import java.util.List;
 31 import java.util.Optional;
 32 import java.util.Set;
 33 import java.util.stream.Collectors;
 34 import java.util.stream.Stream;
 35 import jdk.incubator.foreign.MemoryLayout;
 36 import jdk.internal.jextract.impl.DeclarationImpl;
 37 
 38 /**
 39  * Instances of this class are used to model declaration elements in the foreign language.
 40  * All declarations have a position (see {@link Position}) and a name. Instances of this class
 41  * support the <em>visitor</em> pattern (see {@link Declaration#accept(Visitor, Object)} and
 42  * {@link Visitor}).
 43  */
 44 public interface Declaration {
 45 
 46     /**
 47      * The position associated with this declaration.
 48      * @return The position associated with this declaration.
 49      */
 50     Position pos();
 51 
 52     /**
 53      * The name associated with this declaration.
 54      * @return The name associated with this declaration.
 55      */
 56     String name();
 57 
 58     /**
 59      * Get a declaration with specified attribute.
 60      * Set the values to the specified attribute while other attributes remains unchanged. If the specified attribute
 61      * already exist, the new values are replacing the old ones. By not specifying any value, the attribute will become
 62      * empty as {@link #getAttribute(String) getAttribute(name).isEmpty()} will return true.
 63      * @param name The attribute name
 64      * @param values More attribute values
 65      * @return the Declaration with attributes
 66      */
 67     Declaration withAttribute(String name, Constable... values);
 68 
 69     /**
 70      * Get a declaration without current attributes
 71      * @return the Declatation without any attributes
 72      */
 73     Declaration stripAttributes();
 74 
 75     /**
 76      * The values of the specified attribute.
 77      * @param name The attribute to retrieve
 78      * @return The list of values associate with this attribute
 79      */
 80     Optional<List<Constable>> getAttribute(String name);
 81 
 82     /**
 83      * The attributes associated with this declaration
 84      * @return The attributes associated with this declaration
 85      */
 86     Set<String> attributeNames();
 87 
 88     /**
 89      * Entry point for visiting declaration instances.
 90      * @param visitor the declaration visitor.
 91      * @param data optional data to be passed to the visitor.
 92      * @param <R> the visitor's return type.
 93      * @param <D> the visitor's argument type.
 94      * @return the result of visiting this declaration through the specified declaration visitor.
 95      */
 96     <R,D> R accept(Visitor<R, D> visitor, D data);
 97 
 98     /**
 99      * Compares the specified object with this Declaration for equality.  Returns
100      * {@code true} if and only if the specified object is also a Declaration and both
101      * the declarations are <i>equal</i>.
102      *
103      * @param o the object to be compared for equality with this Declaration
104      * @return {@code true} if the specified object is equal to this Declaration
105      */
106     boolean equals(Object o);
107 
108     /**
109      * Returns the hash code value for this Declaration.
110      *
111      * @return the hash code value for this Declaration.
112      */
113     int hashCode();
114 
115     /**
116      * A function declaration.
117      */
118     interface Function extends Declaration {
119         /**
120          * The parameters associated with this function declaration.
121          * @return The parameters associated with this function declaration.
122          */
123         List<Variable> parameters();
124 
125         /**
126          * The foreign type associated with this function declaration.
127          * @return The foreign type associated with this function declaration.
128          */
129         Type.Function type();
130     }
131 
132     /**
133      * A scoped declaration is a container for one or more nested declarations. This declaration can be used to model
134      * several constructs in the foreign languages, such as (but not limited to) structs, unions and structs (see also
135      * {@link Scoped.Kind}).
136      */
137     interface Scoped extends Declaration {
138 
139         /**
140          * The scoped declaration kind.
141          */
142         enum Kind {
143             /**
144              * Namespace declaration.
145              */
146             NAMESPACE,
147             /**
148              * Class declaration.
149              */
150             CLASS,
151             /**
152              * Enum declaration.
153              */
154             ENUM,
155             /**
156              * Struct declaration.
157              */
158             STRUCT,
159             /**
160              * Union declaration.
161              */
162             UNION,
163             /**
164              * Bitfields declaration.
165              */
166             BITFIELDS,
167             /**
168              * Toplevel declaration.
169              */
170             TOPLEVEL;
171         }
172 
173         /**
174          * The member declarations associated with this scoped declaration.
175          * @return The member declarations associated with this scoped declaration.
176          */
177         List<Declaration> members();
178 
179         /**
180          * The (optional) layout associated with this scoped declaration.
181          * @return The (optional) layout associated with this scoped declaration.
182          *
183          * @implSpec a layout is present if the scoped declaration kind is one of {@link Kind#STRUCT}, {@link Kind#UNION},
184          * {@link Kind#ENUM}, {@link Kind#BITFIELDS}, {@link Kind#CLASS} <em>and</em> if this declaration models an entity in the foreign
185          * language that is associated with a <em>definition</em>.
186          */
187         Optional<MemoryLayout> layout();
188 
189         /**
190          * The scoped declaration kind.
191          * @return The scoped declaration kind.
192          */
193         Kind kind();
194     }
195 
196     /**
197      * A typedef declaration
198      */
199     interface Typedef extends Declaration {
200         /**
201          * The canonical type associated with this typedef declaration.
202          * @return The canonical type associated with this typedef declaration.
203          */
204         Type type();
205     }
206 
207     /**
208      * A variable declaration.
209      */
210     interface Variable extends Declaration {
211         /**
212          * The variable declaration kind.
213          */
214         enum Kind {
215             /**
216              * Global variable declaration.
217              */
218             GLOBAL,
219             /**
220              * Field declaration.
221              */
222             FIELD,
223             /**
224              * Bitfield declaration.
225              */
226             BITFIELD,
227             /**
228              * Function parameter declaration.
229              */
230             PARAMETER;
231         }
232 
233         /**
234          * The type associated with this variable declaration.
235          * @return The type associated with this variable declaration.
236          */
237         Type type();
238 
239         /**
240          * The optional layout associated with this variable declaration.
241          * @return The optional layout associated with this variable declaration.
242          */
243         Optional<MemoryLayout> layout();
244 
245         /**
246          * The kind associated with this variable declaration.
247          * @return The kind associated with this variable declaration.
248          */
249         Kind kind();
250     }
251 
252     /**
253      * A constant value declaration.
254      */
255     interface Constant extends Declaration {
256         /**
257          * The value associated with this constant declaration.
258          * @return The value associated with this constant declaration.
259          */
260         Object value();
261 
262         /**
263          * The type associated with this constant declaration.
264          * @return The type associated with this constant declaration.
265          */
266         Type type();
267     }
268 
269     /**
270      * Declaration visitor interface.
271      * @param <R> the visitor's return type.
272      * @param <P> the visitor's parameter type.
273      */
274     interface Visitor<R,P> {
275         /**
276          * Visit a scoped declaration.
277          * @param d the scoped declaration.
278          * @param p the visitor parameter.
279          * @return the result of visiting the given scoped declaration through this visitor object.
280          */
281         default R visitScoped(Scoped d, P p) { return visitDeclaration(d, p); }
282 
283         /**
284          * Visit a function declaration.
285          * @param d the function declaration.
286          * @param p the visitor parameter.
287          * @return the result of visiting the given function declaration through this visitor object.
288          */
289         default R visitFunction(Function d, P p) { return visitDeclaration(d, p); }
290 
291         /**
292          * Visit a variable declaration.
293          * @param d the variable declaration.
294          * @param p the visitor parameter.
295          * @return the result of visiting the given variable declaration through this visitor object.
296          */
297         default R visitVariable(Variable d, P p) { return visitDeclaration(d, p); }
298 
299         /**
300          * Visit a constant declaration.
301          * @param d the constant declaration.
302          * @param p the visitor parameter.
303          * @return the result of visiting the given constant declaration through this visitor object.
304          */
305         default R visitConstant(Constant d, P p) { return visitDeclaration(d, p); }
306 
307         /**
308          * Visit a typedef declaration.
309          * @param d the typedef declaration.
310          * @param p the visitor parameter.
311          * @return the result of visiting the given typedef declaration through this visitor object.
312          */
313         default R visitTypedef(Typedef d, P p) { return visitDeclaration(d, p); }
314 
315         /**
316          * Visit a declaration.
317          * @param d the declaration.
318          * @param p the visitor parameter.
319          * @return the result of visiting the given declaration through this visitor object.
320          */
321         default R visitDeclaration(Declaration d, P p) { throw new UnsupportedOperationException(); }
322     }
323 
324     /**
325      * Creates a new constant declaration with given name and type.
326      * @param pos the constant declaration position.
327      * @param name the constant declaration name.
328      * @param value the constant declaration value.
329      * @param type the constant declaration type.
330      * @return a new constant declaration with given name and type.
331      */
332     static Declaration.Constant constant(Position pos, String name, Object value, Type type) {
333         return new DeclarationImpl.ConstantImpl(type, value, name, pos);
334     }
335 
336     /**
337      * Creates a new global variable declaration with given name and type.
338      * @param pos the global variable declaration position.
339      * @param name the global variable declaration name.
340      * @param type the global variable declaration type.
341      * @return a new global variable declaration with given name and type.
342      */
343     static Declaration.Variable globalVariable(Position pos, String name, Type type) {
344         return new DeclarationImpl.VariableImpl(type, Declaration.Variable.Kind.GLOBAL, name, pos);
345     }
346 
347     /**
348      * Creates a new field declaration with given name and type.
349      * @param pos the field declaration position.
350      * @param name the field declaration name.
351      * @param type the field declaration type.
352      * @return a new field declaration with given name and type.
353      */
354     static Declaration.Variable field(Position pos, String name, Type type) {
355         return new DeclarationImpl.VariableImpl(type, Declaration.Variable.Kind.FIELD, name, pos);
356     }
357 
358     /**
359      * Creates a new bitfield declaration with given name, type and layout.
360      * @param pos the bitfield declaration position.
361      * @param name the bitfield declaration name.
362      * @param type the bitfield declaration type.
363      * @param layout the bitfield declaration layout.
364      * @return a new bitfield declaration with given name, type and layout.
365      */
366     static Declaration.Variable bitfield(Position pos, String name, Type type, MemoryLayout layout) {
367         return new DeclarationImpl.VariableImpl(type, layout, Declaration.Variable.Kind.BITFIELD, name, pos);
368     }
369 
370     /**
371      * Creates a new parameter declaration with given name and type.
372      * @param pos the parameter declaration position.
373      * @param name the parameter declaration name.
374      * @param type the parameter declaration type.
375      * @return a new parameter declaration with given name and type.
376      */
377     static Declaration.Variable parameter(Position pos, String name, Type type) {
378         return new DeclarationImpl.VariableImpl(type, Declaration.Variable.Kind.PARAMETER, name, pos);
379     }
380 
381     /**
382      * Creates a new toplevel declaration with given member declarations.
383      * @param pos the toplevel declaration position.
384      * @param decls the toplevel declaration member declarations.
385      * @return a new toplevel declaration with given member declarations.
386      */
387     static Declaration.Scoped toplevel(Position pos, Declaration... decls) {
388         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
389         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.TOPLEVEL, declList, "<toplevel>", pos);
390     }
391 
392     /**
393      * Creates a new namespace declaration with given name and member declarations.
394      * @param pos the namespace declaration position.
395      * @param name the namespace declaration name.
396      * @param decls the namespace declaration member declarations.
397      * @return a new namespace declaration with given name and member declarations.
398      */
399     static Declaration.Scoped namespace(Position pos, String name, Declaration... decls) {
400         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
401         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.NAMESPACE, declList, name, pos);
402     }
403 
404     /**
405      * Creates a new bitfields group declaration with given name and layout.
406      * @param pos the bitfields group declaration position.
407      * @param layout the bitfields group declaration layout.
408      * @param bitfields the bitfields group member declarations.
409      * @return a new bitfields group declaration with given name and layout.
410      */
411     static Declaration.Scoped bitfields(Position pos, MemoryLayout layout, Declaration.Variable... bitfields) {
412         List<Declaration> declList = Stream.of(bitfields).collect(Collectors.toList());
413         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.BITFIELDS, layout, declList, "", pos);
414     }
415 
416     /**
417      * Creates a new struct declaration with given name and member declarations.
418      * @param pos the struct declaration position.
419      * @param name the struct declaration name.
420      * @param decls the struct declaration member declarations.
421      * @return a new struct declaration with given name, layout and member declarations.
422      */
423     static Declaration.Scoped struct(Position pos, String name, Declaration... decls) {
424         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
425         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.STRUCT, declList, name, pos);
426     }
427 
428     /**
429      * Creates a new struct declaration with given name, layout and member declarations.
430      * @param pos the struct declaration position.
431      * @param name the struct declaration name.
432      * @param layout the struct declaration layout.
433      * @param decls the struct declaration member declarations.
434      * @return a new struct declaration with given name, layout and member declarations.
435      */
436     static Declaration.Scoped struct(Position pos, String name, MemoryLayout layout, Declaration... decls) {
437         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
438         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.STRUCT, layout, declList, name, pos);
439     }
440 
441     /**
442      * Creates a new union declaration with given name and member declarations.
443      * @param pos the union declaration position.
444      * @param name the union declaration name.
445      * @param decls the union declaration member declarations.
446      * @return a new union declaration with given name and member declarations.
447      */
448     static Declaration.Scoped union(Position pos, String name, Declaration... decls) {
449         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
450         return new DeclarationImpl.ScopedImpl(Scoped.Kind.UNION, declList, name, pos);
451     }
452 
453     /**
454      * Creates a new union declaration with given name, layout and member declarations.
455      * @param pos the union declaration position.
456      * @param name the union declaration name.
457      * @param layout the union declaration layout.
458      * @param decls the union declaration member declarations.
459      * @return a new union declaration with given name, layout and member declarations.
460      */
461     static Declaration.Scoped union(Position pos, String name, MemoryLayout layout, Declaration... decls) {
462         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
463         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.UNION, layout, declList, name, pos);
464     }
465 
466     /**
467      * Creates a new class declaration with given name and member declarations.
468      * @param pos the class declaration position.
469      * @param name the class declaration name.
470      * @param decls the class declaration member declarations.
471      * @return a new class declaration with given name and member declarations.
472      */
473     static Declaration.Scoped class_(Position pos, String name, Declaration... decls) {
474         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
475         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.CLASS, declList, name, pos);
476     }
477 
478     /**
479      * Creates a new class declaration with given name, layout and member declarations.
480      * @param pos the class declaration position.
481      * @param name the class declaration name.
482      * @param layout the class declaration layout.
483      * @param decls the class declaration member declarations.
484      * @return a new class declaration with given name, layout and member declarations.
485      */
486     static Declaration.Scoped class_(Position pos, String name, MemoryLayout layout, Declaration... decls) {
487         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
488         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.CLASS, layout, declList, name, pos);
489     }
490 
491     /**
492      * Creates a new enum declaration with given name and member declarations.
493      * @param pos the enum declaration position.
494      * @param name the enum declaration name.
495      * @param decls the enum declaration member declarations.
496      * @return a new enum declaration with given name, layout and member declarations.
497      */
498     static Declaration.Scoped enum_(Position pos, String name, Declaration... decls) {
499         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
500         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.ENUM, declList, name, pos);
501     }
502 
503     /**
504      * Creates a new enum declaration with given name, layout and member declarations.
505      * @param pos the enum declaration position.
506      * @param name the enum declaration name.
507      * @param layout the enum declaration layout.
508      * @param decls the enum declaration member declarations.
509      * @return a new enum declaration with given name, layout and member declarations.
510      */
511     static Declaration.Scoped enum_(Position pos, String name, MemoryLayout layout, Declaration... decls) {
512         List<Declaration> declList = Stream.of(decls).collect(Collectors.toList());
513         return new DeclarationImpl.ScopedImpl(Declaration.Scoped.Kind.ENUM, layout, declList, name, pos);
514     }
515 
516     /**
517      * Creates a new function declaration with given name, type and parameter declarations.
518      * @param pos the function declaration position.
519      * @param name the function declaration name.
520      * @param type the function declaration type.
521      * @param params the function declaration parameter declarations.
522      * @return a new function declaration with given name, type and parameter declarations.
523      */
524     static Declaration.Function function(Position pos, String name, Type.Function type, Declaration.Variable... params) {
525         List<Variable> paramList = Stream.of(params).collect(Collectors.toList());
526         return new DeclarationImpl.FunctionImpl(type, paramList, name, pos);
527     }
528 
529     /**
530      * Creates a new typedef declaration with given name and declared type.
531      * @param pos the typedef declaration position.
532      * @param name the typedef declaration name.
533      * @param type the typedef type
534      * @return a new type declaration with given name and declared type.
535      */
536     static Declaration.Typedef typedef(Position pos, String name, Type type) {
537         return new DeclarationImpl.TypedefImpl(type, name, pos, null);
538     }
539 }