1 /****************************************************************************
2  * Copyright (C) 2012 by Matteo Franchin                                    *
3  *                                                                          *
4  * This file is part of Box.                                                *
5  *                                                                          *
6  *   Box is free software: you can redistribute it and/or modify it         *
7  *   under the terms of the GNU Lesser General Public License as published  *
8  *   by the Free Software Foundation, either version 3 of the License, or   *
9  *   (at your option) any later version.                                    *
10  *                                                                          *
11  *   Box is distributed in the hope that it will be useful,                 *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
14  *   GNU Lesser General Public License for more details.                    *
15  *                                                                          *
16  *   You should have received a copy of the GNU Lesser General Public       *
17  *   License along with Box.  If not, see <http://www.gnu.org/licenses/>.   *
18  ****************************************************************************/
19 
20 /**
21  * @file types.h
22  * @brief Declaration of functionality related to the #BoxType object type.
23  *
24  * This header defines most of the functions needed to create #BoxType objects,
25  * manipulate them and retrieve informations from them.
26  * @b Note that #BoxType and #BoxTypeId are defined inside the header core.h.
27  * These two types are indeed fundamental parts of the Box infrastructure. In
28  * this header we rather expose the functionality to create and inspect types
29  * (#BoxType).
30  */
31 
32 #ifndef _BOX_TYPES_H
33 #  define _BOX_TYPES_H
34 
35 #  include <stdlib.h>
36 
37 #  include <box/core.h>
38 #  include <box/container.h>
39 
40 /* NOTE: BoxType and BoxTypeId are defined in core.h (see comment above). */
41 
42 /**
43  * Type class (whether a type is a structure, a species, etc).
44  */
45 typedef enum {
46   BOXTYPECLASS_NONE,
47   BOXTYPECLASS_STRUCTURE_NODE,
48   BOXTYPECLASS_SPECIES_NODE,
49   BOXTYPECLASS_ENUM_NODE,
50   BOXTYPECLASS_COMB_NODE,
51   BOXTYPECLASS_SUBTYPE_NODE,
52   BOXTYPECLASS_PRIMARY,
53   BOXTYPECLASS_INTRINSIC,
54   BOXTYPECLASS_IDENT,
55   BOXTYPECLASS_RAISED,
56   BOXTYPECLASS_STRUCTURE,
57   BOXTYPECLASS_SPECIES,
58   BOXTYPECLASS_ENUM,
59   BOXTYPECLASS_FUNCTION,
60   BOXTYPECLASS_POINTER,
61   BOXTYPECLASS_ANY
62 } BoxTypeClass;
63 
64 /**
65  * Combination type.
66  */
67 typedef enum {
68   BOXCOMBTYPE_AT,
69   BOXCOMBTYPE_COPY,
70   BOXCOMBTYPE_MOVE
71 } BoxCombType;
72 
73 /**
74  * Initialize a BoxPtr pointer from a single pointer (BoxSPtr).
75  */
76 #define BoxPtr_Init_From_SPtr(obj, sptr) \
77   do {(obj)->block = (char *) (sptr) - sizeof(BoxObjHeader); \
78       (obj)->ptr = (sptr);} while(0)
79 
80 /**
81  * Initialize a BoxPtr pointer from a single pointer (BoxSPtr).
82  */
83 #define BoxPtr_Add_Offset(dst, src, offset)                       \
84   do {(dst)->block = (src)->block;                                \
85       (dst)->ptr = (char *) (src)->ptr + (offset);} while(0)
86 
87 
88 /**
89  * @brief Value which determines the relationship between two types left and
90  *   right. This is what is returned by BoxType_Compare().
91  */
92 typedef enum {
93   BOXTYPECMP_DIFFERENT = 0x0, /**< the two types are different. */
94   BOXTYPECMP_MATCHING  = 0x1, /**< right can be expanded to left. */
95   BOXTYPECMP_EQUAL     = 0x3, /**< right and left are equal. */
96   BOXTYPECMP_SAME      = 0x7  /**< right and left are the same type. */
97 } BoxTypeCmp;
98 
99 /**
100  * @brief Type used to specify which type classes should be resolved in
101  *   BoxType_Resolve().
102  */
103 typedef enum {
104   BOXTYPERESOLVE_IDENT   = 0x01,
105   BOXTYPERESOLVE_SPECIES = 0x02,
106   BOXTYPERESOLVE_RAISED  = 0x04,
107   BOXTYPERESOLVE_POINTER = 0x08,
108   BOXTYPERESOLVE_SUBTYPE = 0x10
109 } BoxTypeResolve;
110 
111 /*****************************************************************************
112  * TYPE CREATION ROUTINES                                                    *
113  *****************************************************************************/
114 
115 /**
116  * @brief Get the type class of a given type. The type class is effectively the
117  *   type of type (the answer to whether the type is a struct, a species, etc.)
118  *
119  * @param t The input type.
120  * @return The type class of t.
121  */
122 BOXEXPORT BoxTypeClass
123 BoxType_Get_Class(BoxType *t);
124 
125 /**
126  * @brief Get the data part of a type. The size and composition of the data
127  *   type of a given type changes depending on the type class.
128  */
129 BOXEXPORT void *
130 BoxType_Get_Data(BoxType *t);
131 
132 /**
133  * @brief Remove a reference to the given type.
134  */
135 #define BoxType_Unlink(t) ((BoxType *) BoxSPtr_Unlink(t))
136 
137 /**
138  * @brief Add a reference to the given type.
139  */
140 #define BoxType_Link(t) ((BoxType *) BoxSPtr_Link(t))
141 
142 /**
143  * @brief Create an instance of a primary type with the given id, size and
144  *   alignment.
145  *
146  * An primary type is one of the builtin core types.
147  * @param id The ID associated to the primary type.
148  * @param size The size of the type (in bytes).
149  * @param alignment The alignment for the type.
150  * @return A new primary type (or BOXTYPE_NONE if errors occurred).
151  */
152 BOXEXPORT BoxType *
153 BoxType_Create_Primary(BoxTypeId id, size_t size, size_t alignment);
154 
155 /**
156  * @brief Create a new intrinsic type with the given name, size and alignment.
157  *
158  * An intrinsic type can be imagined as a descriptor for an atomic
159  * (i.e. indivisible) portion of memory.
160  * @param size The size of the type (in bytes).
161  * @param alignment The alignment for the type.
162  * @return A new intrinsic type (or BOXTYPE_NONE if errors occurred).
163  */
164 BOXEXPORT BoxType *
165 BoxType_Create_Intrinsic(size_t size, size_t alignment);
166 
167 /**
168  * @brief Create a new type identifier from the type 'source'.
169  *
170  * A type identifier is a type which can be referred using a name. It can be
171  * put inside the namespace of a parent type and has itself a namespace which
172  * can contain children types. An identifier type can also have combinations
173  * and subtypes. It is thus a central concept for organising the type hierarchy
174  * in the Box language.
175  * @param source The target type to which this identifier refers to.
176  * @param name The name to use for identifying the type.
177  * @return A new type identifier (or @c NULL in case of errors).
178  */
179 BOXEXPORT BOXOUT BoxType *
180 BoxType_Create_Ident(BOXIN BoxType *source, const char *name);
181 
182 /**
183  * @brief Create a new raised type from the type 'source'.
184  *
185  * The new type will be similar to t, but incompatible: BoxType_Compare() will
186  * not match the two types. As a consequence, the new raised type will not be
187  * matched as a child of types expecting the source type as a child. The raised
188  * type does, however, inherit the combinations of the source type.  Notice
189  * also that an object whose type is raised can be unraised to obtain an object
190  * having the source type.#
191  * @param source The source type.
192  * @return A new raised type.
193  */
194 BOXEXPORT BoxType *
195 BoxType_Create_Raised(BOXIN BoxType *source);
196 
197 /**
198  * @brief Un-raise a raised type.
199  *
200  * For example, if @c r is the raised type of @c t, then
201  * <tt>BoxType_Unraise(r)</tt> returns  t.
202  * @param raised A raised type.
203  * @return The unraised type.
204  */
205 BOXEXPORT BoxType *
206 BoxType_Unraise(BoxType *raised);
207 
208 /**
209  * Create an empty structure. Members can be added with
210  * BoxType_Add_Member_To_Structure().
211  */
212 BOXEXPORT BOXOUT BoxType *
213 BoxType_Create_Structure(void);
214 
215 /**
216  * @brief Add a member to a structure defined with BoxType_Create_Structure().
217  *
218  * Note that this function does not check for members with duplicate name.
219  * @param structure A type created with BoxType_Create_Structure().
220  * @param member The type of the member.
221  * @param member_name The member name.
222  */
223 BOXEXPORT void
224 BoxType_Add_Member_To_Structure(BoxType *structure, BoxType *member,
225                                 const char *member_name);
226 
227 /**
228  */
229 BOXEXPORT BoxType *
230 BoxType_Get_Species_Target(BoxType *node);
231 
232 /**
233  * @brief Get information on a structure member as obtained from
234  *   BoxTypeIter_Get_Next().
235  */
236 BOXEXPORT BoxBool
237 BoxType_Get_Structure_Member(BoxType *node, char **name, size_t *offset,
238                              size_t *size, BoxType **type);
239 
240 /**
241  * @brief Get the type of a structure member obtained from
242  *   BoxTypeIter_Get_Next().
243  *
244  * This is a convenience function to be used as a replacement of
245  * BoxType_Get_Struct_Member() in the case where only the member type is
246  * needed.
247  * @param node The type node as obtained from BoxTypeIter_Get_Next.
248  * @return The type of the member.
249  */
250 BOXEXPORT BoxType *
251 BoxType_Get_Structure_Member_Type(BoxType *node);
252 
253 /**
254  * @brief Find the member of a structure with the given name.
255  *
256  * @param structure The input structure.
257  * @param name The name of the structure member.
258  * @return If the member is found, return the type node of the member (which
259  *   can be used with BoxType_Get_Structure_Member), otherwise return NULL.
260  */
261 BOXEXPORT BoxType *
262 BoxType_Find_Structure_Member(BoxType *structure, const char *name);
263 
264 /**
265  * @brief Get the number of members of the structure.
266  */
267 BOXEXPORT size_t
268 BoxType_Get_Structure_Num_Members(BoxType *t);
269 
270 /**
271  * @brief Create an empty species.
272  *
273  * Members can be added with BoxType_Add_Member_To_Species().
274  */
275 BOXEXPORT BOXOUT BoxType *
276 BoxType_Create_Species(void);
277 
278 /**
279  * @brief Add a member to a species type defined with BoxType_Create_Species().
280  */
281 BOXEXPORT void
282 BoxType_Add_Member_To_Species(BoxType *species, BoxType *member);
283 
284 /**
285  * @brief Get the type of a species member as obtained from
286  *   BoxTypeIter_Get_Next().
287  *
288  * @param node The type node as obtained from BoxTypeIter_Get_Next().
289  * @return The type of the member.
290  */
291 BOXEXPORT BoxType *
292 BoxType_Get_Species_Member_Type(BoxType *node);
293 
294 /**
295  * @brief Create a species of type '(*=>Dest)' (everything is converted to
296  *   'Dest').
297  */
298 BOXEXPORT BoxType *
299 BoxType_Create_Star_Species(BoxType *dest);
300 
301 /** Create an empty enum type. */
302 BOXEXPORT BoxType *
303 BoxType_Create_Enum(void);
304 
305 /** Add a member to an enum type cerated with BoxType_New_Enum. */
306 BOXEXPORT void
307 BoxType_Add_Member_To_Enum(BoxType *member, const char *member_name);
308 
309 /**
310  * @brief Create a new function type taking @p child as an argument and working
311  *   on @p parent.
312  *
313  * @param parent The type of the value returned by the function.
314  * @param child The type of the argument of the function.
315  * @return A new type corresponding to the specified function.
316  */
317 BOXEXPORT BOXOUT BoxType *
318 BoxType_Create_Callable(BoxType *parent, BoxType *child);
319 
320 /**
321  * @brief Get the parent of a callable type.
322  *
323  * @param callable The callable type.
324  * @return Return the callable parent type.
325  * @note If @p callable is @c NULL, then @c NULL is returned.
326  */
327 BOXEXPORT BoxType *
328 BoxType_Get_Callable_Parent(BoxType *callable);
329 
330 /**
331  * @brief Get the child of a callable type.
332  *
333  * @param callable The callable type.
334  * @return Return the callable child type.
335  * @note If @p callable is @c NULL, then @c NULL is returned.
336  */
337 BOXEXPORT BoxType *
338 BoxType_Get_Callable_Child(BoxType *callable);
339 
340 /**
341  * @brief Create a new pointer type to @p source.
342  *
343  * @param target The type of the pointer target.
344  * @return A new pointer type.
345  */
346 BOXEXPORT BoxType *
347 BoxType_Create_Pointer(BoxType *target);
348 
349 /**
350  * @brief Create a new Any type.
351  */
352 BOXEXPORT BoxType *
353 BoxType_Create_Any(void);
354 
355 /**
356  * @brief Resolve the given type.
357  *
358  * Resolution is an operation on types which allow obtaining the original type
359  * one type refers to. For example, resolving a species allows obtaining the
360  * target type of the species and resolving an identifier type allows obtaining
361  * the underlying type.
362  * @param type Type to resolve.
363  * @param resolve What type class should be resolved. This is a sum of one
364  *   or more #BoxTypeResolve masks, one for each class that should be resolved.
365  * @param num Number of resolutions (0 means as many as necessary).
366  * @return The resolved type.
367  */
368 BOXEXPORT BoxType *
369 BoxType_Resolve(BoxType *type, BoxTypeResolve resolve, int num);
370 
371 /*****************************************************************************
372  * TYPE FINE-TUNING ROUTINES                                                 *
373  *****************************************************************************/
374 
375 /**
376  * @brief Add a child type to the namespace of a parent type.
377  *
378  * Note that both the child and the parent must be identifier types.
379  * @param parent The parent type.
380  * @param child The child type.
381  * @see BoxType_Create_Ident
382  */
383 BOXEXPORT void
384 BoxType_Add_Type(BoxType *parent, BOXIN BoxType *child);
385 
386 /**
387  * @brief Add a subtype type for a given type.
388  *
389  * Note that the parent must be an identifier type.
390  * @param parent The parent type.
391  * @param name The name of the subtype.
392  * @param subtype The type of the subtype or NULL to leave the subtype
393  *   untyped. BoxType_Register_Subtype() can be used to provide the type
394  *   later.
395  * @return Return the subtype node. Note that the caller is not give a
396  *   reference to the node. In other words, the caller may need to use
397  *   BoxType_Link() to claim a reference to the subtype.
398  */
399 BOXEXPORT BoxType *
400 BoxType_Create_Subtype(BoxType *parent, const char *name, BoxType *type);
401 
402 /**
403  * @brief Find a subtype of the given type.
404  *
405  * @param parent The type whose subtype we are trying to find.
406  * @param name The name of the subtype.
407  * @return A new subtype node or @c NULL, if the subtype could not be found.
408  */
409 BOXEXPORT BoxType *
410 BoxType_Find_Subtype(BoxType *parent, const char *name);
411 
412 /**
413  * @brief Find the non-inherited subtypes of the given type.
414  *
415  * This function is similar to BoxType_Find_Subtype(), but does not try to
416  * find subtypes inherited by types from which @p parent derives.
417  * @see BoxType_Find_Subtype
418  */
419 BOXEXPORT BoxType *
420 BoxType_Find_Own_Subtype(BoxType *parent, const char *name);
421 
422 /**
423  * @brief Get details about a subtype found with BoxType_Find_Combination().
424  */
425 BOXEXPORT BoxBool
426 BoxType_Get_Subtype_Info(BoxType *subtype, char **name,
427                          BoxType **parent, BoxType **type);
428 
429 /**
430  * @brief Return whether the subtype was registered (it has a definite type).
431  *
432  * @param subtype A subtype.
433  * @return Whether the subtype was registered. A subtype is registered when
434  *   it is given all non @c NULL arguments to BoxType_Create_Subtype() or
435  *   when it is registered with BoxType_Register_Subtype().
436  */
437 BOXEXPORT BoxBool
438 BoxType_Is_Registered_Subtype(BoxType *subtype);
439 
440 /**
441  * @brief Register the type for a given subtype, if not given during creation.
442  *
443  * @param subtype A subtype created with BoxType_Create_Subtype(), giving
444  *   @p NULL for the type.
445  * @param type The type to associate to the subtype.
446  * @return Whether the operation was successful.
447  */
448 BOXEXPORT BoxBool
449 BoxType_Register_Subtype(BoxType *subtype, BoxType *type);
450 
451 /**
452  * @brief Identifier used to determine the state of a Box.
453  */
454 typedef unsigned int BoxBoxState;
455 
456 /** Return a Box state identifier from its string representation. */
457 BoxBoxState BoxType_Get_State(BoxType *t, const char *source);
458 
459 /*****************************************************************************
460  * TYPE ENQUIRY ROUTINES                                                     *
461  *****************************************************************************/
462 
463 /**
464  * @brief Get the size of an allocated object of the given type.
465  */
466 BOXEXPORT size_t
467 BoxType_Get_Size(BoxType *t);
468 
469 /**
470  * @brief Get the size and the aligment of a given input type.
471  *
472  * @param t The input type.
473  * @param size Where to store the size of the type.
474  * @param algn Where to store the alignment of the type.
475  * @return @c BOXTYPE_TRUE if size/alignment were retrieved successfully.
476  */
477 BOXEXPORT BoxBool
478 BoxType_Get_Size_And_Alignment(BoxType *t, size_t *size, size_t *algn);
479 
480 /**
481  * @brief Create the string representation of the provided type.
482  *
483  * @note The returned string has to be freed with Box_Mem_Free().
484  */
485 char *BoxType_Get_Repr(BoxType *t);
486 
487 /**
488  * @brief Compare right to left and return a #BoxTypeCmp value.
489  */
490 BOXEXPORT BoxTypeCmp
491 BoxType_Compare(BoxType *left, BoxType *right);
492 
493 /**
494  * @brief Type iterator. Allows to iter through the types that do have members,
495  *   such as structures, species and enums.
496  *
497  * @see BoxTypeIter_Init
498  */
499 typedef struct BoxTypeIter_struct {
500   BoxType *current_node;
501 } BoxTypeIter;
502 
503 /**
504  * @brief Initialize an iterator for iteration over the members of the given type.
505  *
506  * @param ti Pointer to location of memory to initialize.
507  * @param t Iteration is done over the members of this type.
508  */
509 BOXEXPORT void
510 BoxTypeIter_Init(BoxTypeIter *ti, BoxType *t);
511 
512 /**
513  * @brief Iterate over the next member of the provided iterator.
514  *
515  * @param ti Pointer to an initialized iterator.
516  * @param next This is a pointer where to put the next item in the iteration.
517  * @return @c BOXBOOL_TRUE if a new item was retrieved and written in ``*next``,
518  *   @c BOXBOOL_FALSE otherwise.
519  *
520  * @note The idea is to use this as:
521  * @code
522  *  BoxTypeIter ti;
523  *  BoxType *t;
524  *  for (BoxTypeIter_Init(& ti, parent); BoxTypeIter_Get_Next(& ti, & t);) {
525  *    BoxType_Get_Structure_Member(& t, ...);
526  *    ...
527  *  }
528  * @endcode
529  */
530 BOXEXPORT BoxBool
531 BoxTypeIter_Get_Next(BoxTypeIter *ti, BoxType **next);
532 
533 /**
534  * @brief Finalize an iterator initialized with BoxTypeIter_Init.
535  */
536 #define BoxTypeIter_Finish(iter) \
537   do {(void) (iter);} while(0)
538 
539 /**
540  * @brief Whether an iterator has more items to read with BoxTypeIter_Get_Next().
541  *
542  * @param ti Pointer to an initialized, possibly "used" iterator.
543  * @return @c BOXBOOL_TRUE if the iterator has some items (in other words, if the
544  *   next call to BoxTypeIter_Get_Next is going to return BOXBOOL_TRUE),
545  *   @c BOXBOOL_FALSE otherwise.
546  */
547 BOXEXPORT BoxBool
548 BoxTypeIter_Has_Items(BoxTypeIter *ti);
549 
550 /**
551  * @brief Get the stem type of a type.
552  *
553  * The stem type for a type @p t is the most basic type which can describe what
554  * is contained inside @p t. It is used by the compiler to determine how to
555  * handle the object (which type of register to use, for example).  In
556  * practice, the stem type is obtained by resolving species, identifiers and
557  * raised types (with BoxType_Resolve()).
558  *
559  * @param type The input type.
560  * @return The stem type of type (or @c NULL in case of failure).
561  */
562 BOXEXPORT BoxType *
563 BoxType_Get_Stem(BoxType *type);
564 
565 /**
566  * @brief Get the container type associated with a given type.
567  *
568  * The container type is strictly related to the way the compiler handles types
569  * (e.g. register types).
570  * @param t The input type.
571  * @return The container of @p t.
572  */
573 BOXEXPORT BoxContType
574 BoxType_Get_Cont_Type(BoxType *t);
575 
576 /**
577  * @brief Return whether the type is a void type (contains nothing).
578  *
579  * @param t The input type.
580  * @return Whether @p t is an empty type.
581  */
582 BOXEXPORT BoxBool
583 BoxType_Is_Empty(BoxType *t);
584 
585 /**
586  * @brief Return whether the type is an Any type.
587  *
588  * @param t The input type.
589  * @return Whether @p t is an Any type.
590  */
591 BOXEXPORT BoxBool
592 BoxType_Is_Any(BoxType *t);
593 
594 /**
595  * @brief Return whether the type is a subtype.
596  *
597  * @param t The input type.
598  * @return Whether @p t is a subtype.
599  */
600 #define BoxType_Is_Subtype(t) \
601   (BoxType_Get_Class((t)) == BOXTYPECLASS_SUBTYPE_NODE)
602 
603 /**
604  * @brief Whether the type is a fast type.
605  *
606  * A type is fast when it can be stored entirely inside a register with
607  * appropriate type. Fast types are integers and floating point numbers and
608  * pointers.
609  *
610  * @param t The input type.
611  * @return Whether @p t is a fast type.
612  */
613 BOXEXPORT BoxBool
614 BoxType_Is_Fast(BoxType *t);
615 
616 /**
617  * @brief Get a string representation of the given type.
618  *
619  * @param t The input type.
620  * @return A freshly allocated string containing the representation of @p t.
621  *   The string must be freed by the user with Box_Mem_Free().
622  */
623 BOXEXPORT char *
624 BoxType_Get_Repr(BoxType *t);
625 
626 #endif /* _BOX_TYPES_H */
627