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