Changeset 768b3b4f
- Timestamp:
- May 13, 2019, 2:01:20 PM (4 years ago)
- Branches:
- arm-eh, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 712348a, 9b81fed3
- Parents:
- b78129a (diff), 336d0b3 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 1 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/vtable.md
rb78129a r768b3b4f 8 8 9 9 The basic concept of a virtual table (vtable) is the same here as in most 10 other languages . They will mostly contain function pointers although they11 should be able to store anything that goes into a trait.12 13 I also include notes on a sample implementation, which primar ly exists to show14 there is a re sonable implementation. The code samples for that are in a slight15 ps udo-code to help avoid name mangling and keeps some CFA features while they16 would actually be writ en in C.10 other languages that use them. They will mostly contain function pointers 11 although they should be able to store anything that goes into a trait. 12 13 I also include notes on a sample implementation, which primarily exists to show 14 there is a reasonable implementation. The code samples for that are in a slight 15 pseudo-code to help avoid name mangling and keeps some CFA features while they 16 would actually be written in C. 17 17 18 18 Trait Instances … … 20 20 21 21 Currently traits are completely abstract. Data types might implement a trait 22 but traits are not themselves data types. This will change that and allow 23 instances of traits to be created from instances of data types that implement 24 the trait. 22 but traits are not themselves data types. Which is to say you cannot have an 23 instance of a trait. This proposal will change that and allow instances of 24 traits to be created from instances of data types that implement the trait. 25 26 For example: 25 27 26 28 trait combiner(otype T) { 27 28 29 void combine(T&, int); 30 }; 29 31 30 32 struct summation { 31 32 33 34 35 36 33 int sum; 34 }; 35 36 void ?{}( struct summation & this ) { 37 this.sum = 0; 38 } 37 39 38 40 void combine( struct summation & this, int num ) { 39 40 41 42 43 41 this.sum = this.sum + num; 42 } 43 44 trait combiner obj = struct summation{}; 45 combine(obj, 5); 44 46 45 47 As with `struct` (and `union` and `enum`), `trait` might be optional when … … 49 51 For traits to be used this way they should meet two requirements. First they 50 52 should only have a single polymorphic type and each assertion should use that 51 type once as a parameter. Extentions may later loosen these requirements. 52 53 If a trait object is used it should generate a series of implicate functions 54 each of which implements one of the functions required by the trait. So for 55 combiner there is an implicate: 56 57 void combine(trait combiner & this, int); 58 59 This function is the one actually called at the end 53 type once as a parameter. Extensions may later loosen these requirements. 54 55 Also note this applies to the final expanded list of assertions. Consider: 56 57 trait foo(otype T, otype U) { 58 ... functions that use T once ... 59 } 60 61 trait bar(otype S | foo(S, char)) { 62 ... functions that use S once ... 63 } 64 65 In this example `bar` may be used as a type but `foo` may not. 66 67 When a trait is used as a type it creates a generic object which combines 68 the base structure (an instance of `summation` in this case) and the vtable, 69 which is currently created and provided by a hidden mechanism. 70 71 The generic object type for each trait also implements that trait. This is 72 actually the only means by which it can be used. The type of these functions 73 look something like this: 74 75 void combine(trait combiner & this, int num); 60 76 61 77 The main use case for trait objects is that they can be stored. They can be 62 passed into functions, but using the trait directly is pref red in this case.78 passed into functions, but using the trait directly is preferred in this case. 63 79 64 80 trait drawable(otype T) { … … 78 94 } 79 95 80 Currently these traits are limited to 1 trait parameter and functions should 81 have exactly 1 parameter. We cannot abstract away pairs of types and still 82 pass them into normal functions, which take them seperately. 83 84 The second is required the because we need to get the vtable from somewhere. 85 If there are 0 trait objects than no vtable is avalible, if we have more than 86 1 than the vtables give conflicting answers on what underlying function to 87 call. And even then the underlying type assumes a concrete type. 88 89 This loop can sort of be broken by using the trait object directly in the 90 signature. This has well defined meaning, but might not be useful. 96 The trait types can also be used in the types of assertions on traits as well. 97 In this usage they passed as the underlying object and vtable pair as they 98 are stored. The trait types can also be used in that trait's definition, which 99 means you can pass two instances of a trait to a single function. However the 100 look-up of the one that is not used to look up any functions, until another 101 function that uses that object in the generic/look-up location is called. 91 102 92 103 trait example(otype T) { 93 104 bool test(T & this, trait example & that); 94 105 } 106 107 ### Explanation Of Restrictions 108 109 The two restrictions on traits that can be used as trait objects are: 110 111 1. Only one generic parameter may be defined in the trait's header. 112 2. Each function assertion must have one parameter with the type of the 113 generic parameter. They may or may not return a value of that type. 114 115 Elsewhere in this proposal I suggest ways to broaden these requirements. 116 A simple example would be if a trait meets requirement 1 but not 2, then 117 the assertions that do not satisfy the exactly one parameter requirement can 118 be ignored. 119 120 However I would like to talk about why these two rules are in place in the 121 first place and the problems that any exceptions to these rules must avoid. 122 123 The problems appear when the dispatcher function which operates on the 124 generic object. 125 126 trait combiner(otype T, otype U) { 127 void combine(T&, U); 128 } 129 130 This one is so strange I don't have proper syntax for it but let us say that 131 the concrete dispatcher would be typed as 132 `void combine(combiner(T) &, combiner(U));`. Does the function that combine 133 the two underlying types exist to dispatch too? 134 135 Maybe not. If `combiner(T)` works with ints and `combiner(U)` is a char then 136 they could not be. It would have to enforce that all pairs of any types 137 that are wrapped in this way. Which would pretty much destroy any chance of 138 separate compilation. 139 140 Even then it would be more expensive as the wrappers would have to carry ids 141 that you use to look up on an <number of types>+1 dimensional table. 142 143 The second restriction has a similar issue but makes a bit more sense to 144 write out. 145 146 trait Series(otype T) { 147 ... size, iterators, getters ... 148 T join(T const &, T const &); 149 } 150 151 With the dispatcher typed as: 152 153 Series join(Series const &, Series const &); 154 155 Because these instances are generic and hide the underlying implementation we 156 do not know what that implementation is. Unfortunately this also means the 157 implementation for the two parameters might not be the same. Once we have 158 two different types involved this devolves into the first case. 159 160 We could check at run-time that the have the same underlying type, but this 161 would likely time and space overhead and there is no clear recovery path. 95 162 96 163 #### Sample Implementation … … 116 183 117 184 There may have to be special cases for things like copy construction, that 118 might require a more sig ificant wrapper. On the other hand moving could be185 might require a more significant wrapper. On the other hand moving could be 119 186 implemented by moving the pointers without any need to refer to the base 120 187 object. 121 188 122 ### Extention: Multiple Trait Parameters 123 Currently, this gives traits two independent uses. They use the same syntax, 124 except for limits boxable traits have, and yet don't really mix. The most 125 natural way to do this is to allow trait instances to pick one parameter 126 that they are generic over, the others they choose types to implement. 127 128 The two ways to do the selection, the first is do it at the trait definition. 129 Each trait picks out a single parameter which it can box (here the `virtual` 130 qualifier). When you create an instance of a trait object you provide 131 arguments like for a generic structure, but skip over the marked parameter. 132 133 trait combiner(virtual otype T, otype Combined) { 134 void combine(T &, Combined &); 135 } 136 137 trait combiner(int) int_combiner; 138 139 The second is to do it at the instaniation point. A placeholder (here the 140 keyword `virtual`) is used to explicately skip over the parameter that will be 141 abstracted away, with the same rules as above if it was the marked parameter. 142 143 trait combiner(otype T, otype Combined) { 144 void combine(T &, Combined &); 145 }; 146 147 trait combiner(virtual, int) int_combiner; 148 149 Using both (first to set the default, second as a local override) would also 150 work, although might be exessively complicated. 151 152 This is useful in cases where you want to use a generic type, but leave part 153 of it open and store partially generic result. As a simple example 154 155 trait folder(otype T, otype In, otype Out) { 156 void fold(T & this, In); 157 Out fold_result(T & this); 158 } 159 160 Which allows you to fold values without putting them in a container. If they 161 are already in a container this is exessive, but if they are generated over 162 time this gives you a simple interface. This could for instance be used in 163 a profile, where T changes for each profiling statistic and you can plug in 164 multiple profilers for any run by adding them to an array. 189 ### Extension: Multiple Trait Parameters 190 The base proposal in effect creates another use for the trait syntax that is 191 related to the ones currently in the language but is also separate from them. 192 The current uses generic functions and generic types, this new use could be 193 described as generic objects. 194 195 A generic object is of a concrete type and has concrete functions that work on 196 it. It is generic in that it is a wrapper for an unknown type. Traits serve 197 a similar role here as in generic functions as they limit what the function 198 can be generic over. 199 200 This combines the use allowing to have a generic type that is a generic 201 object. All but one of the trait's parameters is given a concrete type, 202 conceptually currying the trait to create a trait with on generic parameter 203 that fits the original restrictions. The resulting concrete generic object 204 type is different with each set of provided parameters and their values. 205 206 Then it just becomes a question of where this is done. Again both examples use 207 a basic syntax to show the idea. 208 209 trait iterator(virtual otype T, otype Item) { 210 bool has_next(T const &); 211 Item get_next(T const *); 212 } 213 214 iterator(int) int_it = begin(container_of_ints); 215 216 The first option is to do it at the definition of the trait. One parameter 217 is selected (here with the `virtual` keyword, but other rules like "the first" 218 could also be used) and when an instance of the trait is created all the 219 other parameters must be provided. 220 221 trait iterator(otype T, otype Item) { 222 bool has_next(T const &); 223 Item get_next(T const *); 224 } 225 226 iterator(virtual, int) int_it = begin(container_of_ints); 227 228 The second option is to skip a parameter as part of the type instance 229 definition. One parameter is explicitly skipped (again with the `virtual` 230 keyword) and the others have concrete types. The skipped one is the one we 231 are generic on. 232 233 Incidentally in both examples `container_of_ints` may itself be a generic 234 object and `begin` returns a generic iterator with unknown implementation. 235 236 These options are not exclusive. Defining a default on the trait allows for 237 an object to be created as in the first example. However, whether the 238 default is provided or not, the second syntax can be used to pick a 239 parameter on instantiation. 165 240 166 241 Hierarchy 167 242 --------- 168 243 169 Virtual tables by them selves are not quite enough to implement the planned 170 hierarchy system. An addition of type ids, implemented as pointers which 171 point to your parent's type id, is required to actually create the shape of 172 the hierarchy. However vtables would allow behaviour to be carried with the 173 tree. 174 175 The hierarchy would be a tree of types, of traits and structs. Currently we do 176 not support structural extension, so traits form the internal nodes and 177 structures the leaf nodes. 178 179 The syntax is undecided but it will include a clause like `virtual (PARENT)` 180 on trait and struct definitions. It marks out all types in a hierarchy. 181 PARENT may be omitted, if it is this type is the root of a hierarchy. Otherwise 182 it is the name of the type that is this type's parent in the hierarchy. 183 184 Traits define a trait instance type that implements all assertions in this 185 trait and its parents up until the root of the hierarchy. Each trait then 186 defines a vtable type. Structures will also have a vtable type but it should 187 be the same as their parent's. 188 189 Trait objects within the tree can be statically cast to a parent type. Casts 190 from a parent type to a child type are conditional, they check to make sure 191 the underlying instance is an instance of the child type, or an instance of 192 one of its children. The type then is recoverable at run-time. 193 194 As with regular trait objects, calling a function on a trait object will cause 195 a look-up on the the virtual table. The casting rules make sure anything that 196 can be cast to a trait type will have all the function implementations for 197 that trait. 198 199 Converting from a concrete type (structures at the edge of the hierarchy) to 200 an abstract type works the same as with normal trait objects, the underlying 201 object is packaged with a virtual table pointer. Converting back to an abstract 202 type requires confirming the underlying type matches, but then simply extracts 203 the pointer to it. 204 205 Exception Example: 244 We would also like to implement hierarchical relations between types. 245 246 AstNode 247 |-ParseNode 248 | |-Declaration 249 | | |-DeclarationWithType 250 | | |-StructureDeclaration 251 | |-Statement 252 | | |-CompoundStatement 253 | |-Expression 254 |-Type 255 256 Virtual tables by themselves are not quite enough to implement this system. 257 A vtable is just a list of functions and there is no way to check at run-time 258 what these functions, we carry that knowledge with the table. 259 260 This proposal adds type ids to check for position in the hierarchy and an 261 explicate syntax for establishing a hierarchical relation between traits and 262 their implementing types. The ids should uniquely identify each type and 263 allow retrieval of the type's parent if one exists. By recursion this allows 264 the ancestor relation between any two hierarchical types can be checked. 265 266 The hierarchy is created with traits as the internal nodes and structures 267 as the leaf nodes. The structures may be used normally and the traits can 268 be used to create generic objects as in the first section (the same 269 restrictions apply). However these type objects store their type id which can 270 be recovered to figure out which type they are or at least check to see if 271 they fall into a given sub-tree at run-time. 272 273 Here is an example of part of a hierarchy. The `virtual(PARENT)` syntax is 274 just an example. But when used it give the name of the parent type or if 275 empty it shows that this type is the root of its hierarchy. 206 276 (Also I'm not sure where I got these casing rules.) 207 208 trait exception(otype T) virtual() {209 char const * what(T & this);210 }211 212 trait io_error(otype T) virtual(exception) {213 FILE * which_file(T & this);214 }215 216 struct eof_error(otype T) virtual(io_error) {217 FILE * file;218 }219 220 char const * what(eof_error &) {221 return "Tried to read from an empty file.";222 }223 224 FILE * which_file(eof_error & this) {225 return eof_error.file;226 }227 228 Ast Example:229 277 230 278 trait ast_node(otype T) virtual() { … … 267 315 } 268 316 317 ### Extension: Structural Inheritance 318 An extension would be allow structures to be used as internal nodes on the 319 inheritance tree. Its child types would have to implement the same fields. 320 321 The weaker restriction would be to convert the fields into field assertions 322 (Not implemented yet: `U T.x` means there is a field of type you on the type 323 T. Offset unknown and passed in/stored with function pointers.) 324 A concrete child would have to declare the same set of fields with the same 325 types. This is of a more functional style. 326 327 The stronger restriction is that the fields of the parent are a prefix of the 328 child's fields. Possibly automatically inserted. This the imperative view and 329 may also have less overhead. 330 331 ### Extension: Unions and Enumerations 332 Currently there is no reason unions and enumerations, in the cases they 333 do implement the trait, could not be in the hierarchy as leaf nodes. 334 335 It does not work with structural induction, but that could just be a compile 336 time check that all ancestors are traits or do not add field assertions. 337 269 338 #### Sample Implementation 270 339 The type id may be as little as: … … 275 344 276 345 Some linker magic would have to be used to ensure exactly one copy of each 277 structure for each type exists in memory. There seem to be spec tial once346 structure for each type exists in memory. There seem to be special once 278 347 sections that support this and it should be easier than generating unique 279 348 ids across compilation units. … … 300 369 301 370 ### Virtual Casts 302 To convert from a pointer to a type higher on the hierarchy to one lower on 303 the hierarchy a check is used to make sure that the underlying type is also 304 of that lower type. 305 306 The proposed syntax for this is: 371 The generic objects may be cast up and down the hierarchy. 372 373 Casting to an ancestor type always succeeds. From one generic type to another 374 is just a reinterpretation and could be implicate. Wrapping and unwrapping 375 a concrete type will probably use the same syntax as in the first section. 376 377 Casting from an ancestor to a descendent requires a check. The underlying 378 type may or may not belong to the sub-tree headed by that descendent. For this 379 we introduce a new cast operator, which returns the pointer unchanged if the 380 check succeeds and null otherwise. 307 381 308 382 trait SubType * new_value = (virtual trait SubType *)super_type; 309 383 310 It will return the same pointer if it does point to the subtype and null if 311 it does not, doing the check and conversion in one operation. 312 313 ### Inline vtables 384 For the following example I am using the as of yet finished exception system. 385 386 trait exception(otype T) virtual() { 387 char const * what(T & this); 388 } 389 390 trait io_error(otype T) virtual(exception) { 391 FILE * which_file(T & this); 392 } 393 394 struct eof_error(otype T) virtual(io_error) { 395 FILE * file; 396 } 397 398 char const * what(eof_error &) { 399 return "Tried to read from an empty file."; 400 } 401 402 FILE * which_file(eof_error & this) { 403 return eof_error.file; 404 } 405 406 bool handleIoError(exception * exc) { 407 io_error * error = (virtual io_error *)exc; 408 if (NULL == error) { 409 return false; 410 } 411 ... 412 return true; 413 } 414 415 ### Extension: Implicate Virtual Cast Target 416 This is a small extension, even in the example above `io_error *` is repeated 417 in the cast and the variable being assigned to. Using return type inference 418 would allow the second type to be skipped in cases it is clear what type is 419 being checked against. 420 421 The line then becomes: 422 423 io_error * error = (virtual)exc; 424 425 ### Extension: Inline vtables 314 426 Since the structures here are usually made to be turned into trait objects 315 it might be worth it to have fields on them to store the virtual table427 it might be worth it to have fields in them to store the virtual table 316 428 pointer. This would have to be declared on the trait as an assertion (example: 317 429 `vtable;` or `T.vtable;`), but if it is the trait object could be a single … … 320 432 There are also three options for where the pointer to the vtable. It could be 321 433 anywhere, a fixed location for each trait or always at the front. For the per- 322 trait solution an exten tion to specify what it is (example `vtable[0];`) which434 trait solution an extension to specify what it is (example `vtable[0];`) which 323 435 could also be used to combine it with others. So these options can be combined 324 436 to allow access to all three options. … … 344 456 the type declaration, including the functions that satisfy the trait, are 345 457 all defined. Currently there are many points where this can happen, not all 346 of them will have the same definitions and no way to select one over the 347 other. 458 of them have the same definitions and no way to select one over the other. 348 459 349 460 Some syntax would have to be added to specify the resolution point. To ensure … … 395 506 396 507 These could also be placed inside functions. In which case both the name and 397 the default keyword might be optional. If the name is om mited in an assignment398 the closest vtable is cho osen (returning to the global default rule if no399 appropr ate local vtable is in scope).508 the default keyword might be optional. If the name is omitted in an assignment 509 the closest vtable is chosen (returning to the global default rule if no 510 appropriate local vtable is in scope). 400 511 401 512 ### Site Based Resolution: -
src/AST/Attribute.hpp
rb78129a r768b3b4f 47 47 }; 48 48 49 50 51 //================================================================================================= 52 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 53 /// remove only if there is a better solution 54 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 55 /// forward declarations 56 inline void increment( const class Attribute * node, Node::ref_type ref ) { node->increment( ref ); } 57 inline void decrement( const class Attribute * node, Node::ref_type ref ) { node->decrement( ref ); } 49 58 } 50 59 -
src/AST/Bitfield.hpp
rb78129a r768b3b4f 22 22 /// does not allow it. Requires type to have `unsigned val` field 23 23 /// @param BFType Name of containing type 24 #define MakeBitfield( BFType ) \ 25 constexpr BFType() : val( 0 ) {} \ 26 constexpr BFType( unsigned int v ) : val( v ) {} \ 27 bool operator[]( unsigned int i ) const { return val & (1 << i); } \ 28 bool any() const { return val != 0; } \ 29 void reset() { val = 0; } \ 30 int ffs() { return ::ffs( val ) - 1; } \ 31 BFType operator&=( BFType other ) { \ 32 val &= other.val; return *this; \ 33 } \ 34 BFType operator&( BFType other ) const { \ 35 BFType q = other; \ 36 q &= *this; \ 37 return q; \ 38 } \ 39 BFType operator|=( BFType other ) { \ 40 val |= other.val; return *this; \ 41 } \ 42 BFType operator|( BFType other ) const { \ 43 BFType q = other; \ 44 q |= *this; \ 45 return q; \ 46 } \ 47 BFType operator-=( BFType other ) { \ 48 val &= ~other.val; return *this; \ 24 template<typename T> 25 struct bitfield : public T { 26 static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size"); 27 using T::val; 28 using val_t = decltype(val); 29 30 constexpr bitfield() : T( 0 ) {} 31 constexpr bitfield( val_t v ) : T( v ) {} 32 33 bool operator[]( val_t i ) const { return val & (1 << i); } 34 bool any() const { return val != 0; } 35 void reset() { val = 0; } 36 int ffs() { return ::ffs( val ) - 1; } 37 38 bitfield operator&=( bitfield other ) { 39 val &= other.val; return *this; 49 40 } 41 bitfield operator&( bitfield other ) const { 42 bitfield q = other; 43 q &= *this; 44 return q; 45 } 46 bitfield operator|=( bitfield other ) { 47 val |= other.val; return *this; 48 } 49 bitfield operator|( bitfield other ) const { 50 bitfield q = other; 51 q |= *this; 52 return q; 53 } 54 bitfield operator-=( bitfield other ) { 55 val &= ~other.val; return *this; 56 } 57 }; 50 58 51 59 /// Adds default printing operator to a bitfield type. 52 60 /// Include in definition to add print function, requires other bitfield operators. 53 61 /// @param N Number of bits in bitfield 54 #define MakeBitfieldPrint( N ) \ 55 static const char* Names[]; \ 56 void print( std::ostream & os ) const { \ 57 if ( (*this).any() ) { \ 58 for ( unsigned int i = 0; i < N; i += 1 ) { \ 59 if ( (*this)[i] ) { \ 60 os << Names[i] << ' '; \ 61 } \ 62 } \ 63 } \ 62 #define MakeBitfieldPrint( N ) \ 63 static const char* Names[]; \ 64 \ 65 void print( std::ostream & os ) const { \ 66 if ( (*this).any() ) { \ 67 for ( unsigned int i = 0; i < N; i += 1 ) { \ 68 if ( (*this)[i] ) { \ 69 os << Names[i] << ' '; \ 70 } \ 71 } \ 72 } \ 64 73 } 65 74 -
src/AST/Decl.hpp
rb78129a r768b3b4f 122 122 std::vector<ptr<DeclWithType>> assertions; 123 123 124 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 124 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 125 125 Type* b, Linkage::Spec spec = Linkage::Cforall ) 126 126 : Decl( loc, name, storage, spec ), base( b ), parameters(), assertions() {} … … 149 149 Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {} 150 150 Data( Kind k, bool c ) : kind( k ), isComplete( c ) {} 151 Data( const Data& d1, const Data& d2 ) 151 Data( const Data& d1, const Data& d2 ) 152 152 : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {} 153 153 … … 158 158 }; 159 159 160 TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b, 160 TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b, 161 161 Kind k, bool s, Type* i = nullptr ) 162 162 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {} … … 174 174 class TypedefDecl final : public NamedTypeDecl { 175 175 public: 176 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 176 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 177 177 Type* b, Linkage::Spec spec = Linkage::Cforall ) 178 178 : NamedTypeDecl( loc, name, storage, b, spec ) {} … … 275 275 }; 276 276 277 278 //================================================================================================= 279 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 280 /// remove only if there is a better solution 281 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 282 /// forward declarations 283 inline void increment( const class Decl * node, Node::ref_type ref ) { node->increment(ref); } 284 inline void decrement( const class Decl * node, Node::ref_type ref ) { node->decrement(ref); } 285 inline void increment( const class DeclWithType * node, Node::ref_type ref ) { node->increment(ref); } 286 inline void decrement( const class DeclWithType * node, Node::ref_type ref ) { node->decrement(ref); } 287 inline void increment( const class ObjectDecl * node, Node::ref_type ref ) { node->increment(ref); } 288 inline void decrement( const class ObjectDecl * node, Node::ref_type ref ) { node->decrement(ref); } 289 inline void increment( const class FunctionDecl * node, Node::ref_type ref ) { node->increment(ref); } 290 inline void decrement( const class FunctionDecl * node, Node::ref_type ref ) { node->decrement(ref); } 291 inline void increment( const class AggregateDecl * node, Node::ref_type ref ) { node->increment(ref); } 292 inline void decrement( const class AggregateDecl * node, Node::ref_type ref ) { node->decrement(ref); } 293 inline void increment( const class StructDecl * node, Node::ref_type ref ) { node->increment(ref); } 294 inline void decrement( const class StructDecl * node, Node::ref_type ref ) { node->decrement(ref); } 295 inline void increment( const class UnionDecl * node, Node::ref_type ref ) { node->increment(ref); } 296 inline void decrement( const class UnionDecl * node, Node::ref_type ref ) { node->decrement(ref); } 297 inline void increment( const class EnumDecl * node, Node::ref_type ref ) { node->increment(ref); } 298 inline void decrement( const class EnumDecl * node, Node::ref_type ref ) { node->decrement(ref); } 299 inline void increment( const class TraitDecl * node, Node::ref_type ref ) { node->increment(ref); } 300 inline void decrement( const class TraitDecl * node, Node::ref_type ref ) { node->decrement(ref); } 301 inline void increment( const class NamedTypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 302 inline void decrement( const class NamedTypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 303 inline void increment( const class TypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 304 inline void decrement( const class TypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 305 inline void increment( const class FtypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 306 inline void decrement( const class FtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 307 inline void increment( const class DtypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 308 inline void decrement( const class DtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 309 inline void increment( const class TypedefDecl * node, Node::ref_type ref ) { node->increment(ref); } 310 inline void decrement( const class TypedefDecl * node, Node::ref_type ref ) { node->decrement(ref); } 311 inline void increment( const class AsmDecl * node, Node::ref_type ref ) { node->increment(ref); } 312 inline void decrement( const class AsmDecl * node, Node::ref_type ref ) { node->decrement(ref); } 313 inline void increment( const class StaticAssertDecl * node, Node::ref_type ref ) { node->increment(ref); } 314 inline void decrement( const class StaticAssertDecl * node, Node::ref_type ref ) { node->decrement(ref); } 315 277 316 } 278 317 -
src/AST/FunctionSpec.hpp
rb78129a r768b3b4f 31 31 32 32 /// Bitflag type for storage classes 33 union Specs { 34 unsigned int val; 35 struct { 36 bool is_inline : 1; 37 bool is_noreturn : 1; 38 bool is_fortran : 1; 33 struct spec_flags { 34 union { 35 unsigned int val; 36 struct { 37 bool is_inline : 1; 38 bool is_noreturn : 1; 39 bool is_fortran : 1; 40 }; 41 42 // MakeBitfieldPrint( NumSpecs ) 39 43 }; 40 44 41 MakeBitfield( Specs ) 42 MakeBitfieldPrint( NumSpecs ) 45 constexpr spec_flags( unsigned int val ) : val(val) {} 43 46 }; 44 47 48 using Specs = bitfield<spec_flags>; 45 49 } 46 50 } -
src/AST/Fwd.hpp
rb78129a r768b3b4f 16 16 #pragma once 17 17 18 #include "AST/Node.hpp" 19 18 20 namespace ast { 19 21 20 class Node;21 22 class ParseNode; 22 23 … … 137 138 class TypeSubstitution; 138 139 140 //================================================================================================= 141 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 142 /// remove only if there is a better solution 143 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 144 /// forward declarations 145 inline void decrement( const class Node * node, Node::ref_type ref ) { node->decrement(ref); } 146 inline void increment( const class Node * node, Node::ref_type ref ) { node->increment(ref); } 147 inline void increment( const class ParseNode *, Node::ref_type ); 148 inline void decrement( const class ParseNode *, Node::ref_type ); 149 inline void increment( const class Decl *, Node::ref_type ); 150 inline void decrement( const class Decl *, Node::ref_type ); 151 inline void increment( const class DeclWithType *, Node::ref_type ); 152 inline void decrement( const class DeclWithType *, Node::ref_type ); 153 inline void increment( const class ObjectDecl *, Node::ref_type ); 154 inline void decrement( const class ObjectDecl *, Node::ref_type ); 155 inline void increment( const class FunctionDecl *, Node::ref_type ); 156 inline void decrement( const class FunctionDecl *, Node::ref_type ); 157 inline void increment( const class AggregateDecl *, Node::ref_type ); 158 inline void decrement( const class AggregateDecl *, Node::ref_type ); 159 inline void increment( const class StructDecl *, Node::ref_type ); 160 inline void decrement( const class StructDecl *, Node::ref_type ); 161 inline void increment( const class UnionDecl *, Node::ref_type ); 162 inline void decrement( const class UnionDecl *, Node::ref_type ); 163 inline void increment( const class EnumDecl *, Node::ref_type ); 164 inline void decrement( const class EnumDecl *, Node::ref_type ); 165 inline void increment( const class TraitDecl *, Node::ref_type ); 166 inline void decrement( const class TraitDecl *, Node::ref_type ); 167 inline void increment( const class NamedTypeDecl *, Node::ref_type ); 168 inline void decrement( const class NamedTypeDecl *, Node::ref_type ); 169 inline void increment( const class TypeDecl *, Node::ref_type ); 170 inline void decrement( const class TypeDecl *, Node::ref_type ); 171 inline void increment( const class FtypeDecl *, Node::ref_type ); 172 inline void decrement( const class FtypeDecl *, Node::ref_type ); 173 inline void increment( const class DtypeDecl *, Node::ref_type ); 174 inline void decrement( const class DtypeDecl *, Node::ref_type ); 175 inline void increment( const class TypedefDecl *, Node::ref_type ); 176 inline void decrement( const class TypedefDecl *, Node::ref_type ); 177 inline void increment( const class AsmDecl *, Node::ref_type ); 178 inline void decrement( const class AsmDecl *, Node::ref_type ); 179 inline void increment( const class StaticAssertDecl *, Node::ref_type ); 180 inline void decrement( const class StaticAssertDecl *, Node::ref_type ); 181 inline void increment( const class Stmt *, Node::ref_type ); 182 inline void decrement( const class Stmt *, Node::ref_type ); 183 inline void increment( const class CompoundStmt *, Node::ref_type ); 184 inline void decrement( const class CompoundStmt *, Node::ref_type ); 185 inline void increment( const class ExprStmt *, Node::ref_type ); 186 inline void decrement( const class ExprStmt *, Node::ref_type ); 187 inline void increment( const class AsmStmt *, Node::ref_type ); 188 inline void decrement( const class AsmStmt *, Node::ref_type ); 189 inline void increment( const class DirectiveStmt *, Node::ref_type ); 190 inline void decrement( const class DirectiveStmt *, Node::ref_type ); 191 inline void increment( const class IfStmt *, Node::ref_type ); 192 inline void decrement( const class IfStmt *, Node::ref_type ); 193 inline void increment( const class WhileStmt *, Node::ref_type ); 194 inline void decrement( const class WhileStmt *, Node::ref_type ); 195 inline void increment( const class ForStmt *, Node::ref_type ); 196 inline void decrement( const class ForStmt *, Node::ref_type ); 197 inline void increment( const class SwitchStmt *, Node::ref_type ); 198 inline void decrement( const class SwitchStmt *, Node::ref_type ); 199 inline void increment( const class CaseStmt *, Node::ref_type ); 200 inline void decrement( const class CaseStmt *, Node::ref_type ); 201 inline void increment( const class BranchStmt *, Node::ref_type ); 202 inline void decrement( const class BranchStmt *, Node::ref_type ); 203 inline void increment( const class ReturnStmt *, Node::ref_type ); 204 inline void decrement( const class ReturnStmt *, Node::ref_type ); 205 inline void increment( const class ThrowStmt *, Node::ref_type ); 206 inline void decrement( const class ThrowStmt *, Node::ref_type ); 207 inline void increment( const class TryStmt *, Node::ref_type ); 208 inline void decrement( const class TryStmt *, Node::ref_type ); 209 inline void increment( const class CatchStmt *, Node::ref_type ); 210 inline void decrement( const class CatchStmt *, Node::ref_type ); 211 inline void increment( const class FinallyStmt *, Node::ref_type ); 212 inline void decrement( const class FinallyStmt *, Node::ref_type ); 213 inline void increment( const class WaitForStmt *, Node::ref_type ); 214 inline void decrement( const class WaitForStmt *, Node::ref_type ); 215 inline void increment( const class WithStmt *, Node::ref_type ); 216 inline void decrement( const class WithStmt *, Node::ref_type ); 217 inline void increment( const class DeclStmt *, Node::ref_type ); 218 inline void decrement( const class DeclStmt *, Node::ref_type ); 219 inline void increment( const class NullStmt *, Node::ref_type ); 220 inline void decrement( const class NullStmt *, Node::ref_type ); 221 inline void increment( const class ImplicitCtorDtorStmt *, Node::ref_type ); 222 inline void decrement( const class ImplicitCtorDtorStmt *, Node::ref_type ); 223 inline void increment( const class Expr *, Node::ref_type ); 224 inline void decrement( const class Expr *, Node::ref_type ); 225 inline void increment( const class ApplicationExpr *, Node::ref_type ); 226 inline void decrement( const class ApplicationExpr *, Node::ref_type ); 227 inline void increment( const class UntypedExpr *, Node::ref_type ); 228 inline void decrement( const class UntypedExpr *, Node::ref_type ); 229 inline void increment( const class NameExpr *, Node::ref_type ); 230 inline void decrement( const class NameExpr *, Node::ref_type ); 231 inline void increment( const class AddressExpr *, Node::ref_type ); 232 inline void decrement( const class AddressExpr *, Node::ref_type ); 233 inline void increment( const class LabelAddressExpr *, Node::ref_type ); 234 inline void decrement( const class LabelAddressExpr *, Node::ref_type ); 235 inline void increment( const class CastExpr *, Node::ref_type ); 236 inline void decrement( const class CastExpr *, Node::ref_type ); 237 inline void increment( const class KeywordCastExpr *, Node::ref_type ); 238 inline void decrement( const class KeywordCastExpr *, Node::ref_type ); 239 inline void increment( const class VirtualCastExpr *, Node::ref_type ); 240 inline void decrement( const class VirtualCastExpr *, Node::ref_type ); 241 inline void increment( const class MemberExpr *, Node::ref_type ); 242 inline void decrement( const class MemberExpr *, Node::ref_type ); 243 inline void increment( const class UntypedMemberExpr *, Node::ref_type ); 244 inline void decrement( const class UntypedMemberExpr *, Node::ref_type ); 245 inline void increment( const class VariableExpr *, Node::ref_type ); 246 inline void decrement( const class VariableExpr *, Node::ref_type ); 247 inline void increment( const class ConstantExpr *, Node::ref_type ); 248 inline void decrement( const class ConstantExpr *, Node::ref_type ); 249 inline void increment( const class SizeofExpr *, Node::ref_type ); 250 inline void decrement( const class SizeofExpr *, Node::ref_type ); 251 inline void increment( const class AlignofExpr *, Node::ref_type ); 252 inline void decrement( const class AlignofExpr *, Node::ref_type ); 253 inline void increment( const class UntypedOffsetofExpr *, Node::ref_type ); 254 inline void decrement( const class UntypedOffsetofExpr *, Node::ref_type ); 255 inline void increment( const class OffsetofExpr *, Node::ref_type ); 256 inline void decrement( const class OffsetofExpr *, Node::ref_type ); 257 inline void increment( const class OffsetPackExpr *, Node::ref_type ); 258 inline void decrement( const class OffsetPackExpr *, Node::ref_type ); 259 inline void increment( const class AttrExpr *, Node::ref_type ); 260 inline void decrement( const class AttrExpr *, Node::ref_type ); 261 inline void increment( const class LogicalExpr *, Node::ref_type ); 262 inline void decrement( const class LogicalExpr *, Node::ref_type ); 263 inline void increment( const class ConditionalExpr *, Node::ref_type ); 264 inline void decrement( const class ConditionalExpr *, Node::ref_type ); 265 inline void increment( const class CommaExpr *, Node::ref_type ); 266 inline void decrement( const class CommaExpr *, Node::ref_type ); 267 inline void increment( const class TypeExpr *, Node::ref_type ); 268 inline void decrement( const class TypeExpr *, Node::ref_type ); 269 inline void increment( const class AsmExpr *, Node::ref_type ); 270 inline void decrement( const class AsmExpr *, Node::ref_type ); 271 inline void increment( const class ImplicitCopyCtorExpr *, Node::ref_type ); 272 inline void decrement( const class ImplicitCopyCtorExpr *, Node::ref_type ); 273 inline void increment( const class ConstructorExpr *, Node::ref_type ); 274 inline void decrement( const class ConstructorExpr *, Node::ref_type ); 275 inline void increment( const class CompoundLiteralExpr *, Node::ref_type ); 276 inline void decrement( const class CompoundLiteralExpr *, Node::ref_type ); 277 inline void increment( const class UntypedValofExpr *, Node::ref_type ); 278 inline void decrement( const class UntypedValofExpr *, Node::ref_type ); 279 inline void increment( const class RangeExpr *, Node::ref_type ); 280 inline void decrement( const class RangeExpr *, Node::ref_type ); 281 inline void increment( const class UntypedTupleExpr *, Node::ref_type ); 282 inline void decrement( const class UntypedTupleExpr *, Node::ref_type ); 283 inline void increment( const class TupleExpr *, Node::ref_type ); 284 inline void decrement( const class TupleExpr *, Node::ref_type ); 285 inline void increment( const class TupleIndexExpr *, Node::ref_type ); 286 inline void decrement( const class TupleIndexExpr *, Node::ref_type ); 287 inline void increment( const class TupleAssignExpr *, Node::ref_type ); 288 inline void decrement( const class TupleAssignExpr *, Node::ref_type ); 289 inline void increment( const class StmtExpr *, Node::ref_type ); 290 inline void decrement( const class StmtExpr *, Node::ref_type ); 291 inline void increment( const class UniqueExpr *, Node::ref_type ); 292 inline void decrement( const class UniqueExpr *, Node::ref_type ); 293 inline void increment( const class UntypedInitExpr *, Node::ref_type ); 294 inline void decrement( const class UntypedInitExpr *, Node::ref_type ); 295 inline void increment( const class InitExpr *, Node::ref_type ); 296 inline void decrement( const class InitExpr *, Node::ref_type ); 297 inline void increment( const class DeletedExpr *, Node::ref_type ); 298 inline void decrement( const class DeletedExpr *, Node::ref_type ); 299 inline void increment( const class DefaultArgExpr *, Node::ref_type ); 300 inline void decrement( const class DefaultArgExpr *, Node::ref_type ); 301 inline void increment( const class GenericExpr *, Node::ref_type ); 302 inline void decrement( const class GenericExpr *, Node::ref_type ); 303 inline void increment( const class Type *, Node::ref_type ); 304 inline void decrement( const class Type *, Node::ref_type ); 305 inline void increment( const class VoidType *, Node::ref_type ); 306 inline void decrement( const class VoidType *, Node::ref_type ); 307 inline void increment( const class BasicType *, Node::ref_type ); 308 inline void decrement( const class BasicType *, Node::ref_type ); 309 inline void increment( const class PointerType *, Node::ref_type ); 310 inline void decrement( const class PointerType *, Node::ref_type ); 311 inline void increment( const class ArrayType *, Node::ref_type ); 312 inline void decrement( const class ArrayType *, Node::ref_type ); 313 inline void increment( const class ReferenceType *, Node::ref_type ); 314 inline void decrement( const class ReferenceType *, Node::ref_type ); 315 inline void increment( const class QualifiedType *, Node::ref_type ); 316 inline void decrement( const class QualifiedType *, Node::ref_type ); 317 inline void increment( const class FunctionType *, Node::ref_type ); 318 inline void decrement( const class FunctionType *, Node::ref_type ); 319 inline void increment( const class ReferenceToType *, Node::ref_type ); 320 inline void decrement( const class ReferenceToType *, Node::ref_type ); 321 inline void increment( const class StructInstType *, Node::ref_type ); 322 inline void decrement( const class StructInstType *, Node::ref_type ); 323 inline void increment( const class UnionInstType *, Node::ref_type ); 324 inline void decrement( const class UnionInstType *, Node::ref_type ); 325 inline void increment( const class EnumInstType *, Node::ref_type ); 326 inline void decrement( const class EnumInstType *, Node::ref_type ); 327 inline void increment( const class TraitInstType *, Node::ref_type ); 328 inline void decrement( const class TraitInstType *, Node::ref_type ); 329 inline void increment( const class TypeInstType *, Node::ref_type ); 330 inline void decrement( const class TypeInstType *, Node::ref_type ); 331 inline void increment( const class TupleType *, Node::ref_type ); 332 inline void decrement( const class TupleType *, Node::ref_type ); 333 inline void increment( const class TypeofType *, Node::ref_type ); 334 inline void decrement( const class TypeofType *, Node::ref_type ); 335 inline void increment( const class AttrType *, Node::ref_type ); 336 inline void decrement( const class AttrType *, Node::ref_type ); 337 inline void increment( const class VarArgsType *, Node::ref_type ); 338 inline void decrement( const class VarArgsType *, Node::ref_type ); 339 inline void increment( const class ZeroType *, Node::ref_type ); 340 inline void decrement( const class ZeroType *, Node::ref_type ); 341 inline void increment( const class OneType *, Node::ref_type ); 342 inline void decrement( const class OneType *, Node::ref_type ); 343 inline void increment( const class GlobalScopeType *, Node::ref_type ); 344 inline void decrement( const class GlobalScopeType *, Node::ref_type ); 345 inline void increment( const class Designation *, Node::ref_type ); 346 inline void decrement( const class Designation *, Node::ref_type ); 347 inline void increment( const class Init *, Node::ref_type ); 348 inline void decrement( const class Init *, Node::ref_type ); 349 inline void increment( const class SingleInit *, Node::ref_type ); 350 inline void decrement( const class SingleInit *, Node::ref_type ); 351 inline void increment( const class ListInit *, Node::ref_type ); 352 inline void decrement( const class ListInit *, Node::ref_type ); 353 inline void increment( const class ConstructorInit *, Node::ref_type ); 354 inline void decrement( const class ConstructorInit *, Node::ref_type ); 355 inline void increment( const class Constant *, Node::ref_type ); 356 inline void decrement( const class Constant *, Node::ref_type ); 357 inline void increment( const class Label *, Node::ref_type ); 358 inline void decrement( const class Label *, Node::ref_type ); 359 inline void increment( const class Attribute *, Node::ref_type ); 360 inline void decrement( const class Attribute *, Node::ref_type ); 361 inline void increment( const class TypeSubstitution *, Node::ref_type ); 362 inline void decrement( const class TypeSubstitution *, Node::ref_type ); 363 139 364 typedef unsigned int UniqueId; 140 365 -
src/AST/Init.hpp
rb78129a r768b3b4f 28 28 class Stmt; 29 29 30 /// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an 30 /// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an 31 31 /// object being initialized 32 32 class Designation final : public ParseNode { … … 34 34 std::vector<ptr<Expr>> designators; 35 35 36 Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} ) 36 Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} ) 37 37 : ParseNode( loc ), designators( std::move(ds) ) {} 38 38 … … 60 60 ptr<Expr> value; 61 61 62 SingleInit( const CodeLocation& loc, Expr* val, bool mc = false ) 62 SingleInit( const CodeLocation& loc, Expr* val, bool mc = false ) 63 63 : Init( loc, mc ), value( val ) {} 64 64 … … 77 77 std::vector<ptr<Designation>> designations; 78 78 79 ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 79 ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 80 80 std::vector<ptr<Designation>>&& ds = {}, bool mc = false ); 81 81 82 82 using iterator = std::vector<ptr<Init>>::iterator; 83 83 using const_iterator = std::vector<ptr<Init>>::const_iterator; … … 93 93 94 94 /// Either a constructor expression or a C-style initializer. 95 /// Should not be necessary to create manually; instead set `maybeConstructed` true on `SingleInit` 95 /// Should not be necessary to create manually; instead set `maybeConstructed` true on `SingleInit` 96 96 /// or `ListInit` if the object should be constructed. 97 97 class ConstructorInit final : public Init { … … 99 99 ptr<Stmt> ctor; 100 100 ptr<Stmt> dtor; 101 /// C-style initializer made up of SingleInit/ListInit nodes to use as a fallback if an 101 /// C-style initializer made up of SingleInit/ListInit nodes to use as a fallback if an 102 102 /// appropriate constructor definition is not found by the resolver. 103 103 ptr<Init> init; … … 111 111 }; 112 112 113 114 //================================================================================================= 115 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 116 /// remove only if there is a better solution 117 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 118 /// forward declarations 119 inline void increment( const class Init * node, Node::ref_type ref ) { node->increment( ref ); } 120 inline void decrement( const class Init * node, Node::ref_type ref ) { node->decrement( ref ); } 121 inline void increment( const class SingleInit * node, Node::ref_type ref ) { node->increment( ref ); } 122 inline void decrement( const class SingleInit * node, Node::ref_type ref ) { node->decrement( ref ); } 123 inline void increment( const class ListInit * node, Node::ref_type ref ) { node->increment( ref ); } 124 inline void decrement( const class ListInit * node, Node::ref_type ref ) { node->decrement( ref ); } 125 inline void increment( const class ConstructorInit * node, Node::ref_type ref ) { node->increment( ref ); } 126 inline void decrement( const class ConstructorInit * node, Node::ref_type ref ) { node->decrement( ref ); } 113 127 } 114 128 -
src/AST/Label.hpp
rb78129a r768b3b4f 25 25 namespace ast { 26 26 27 27 class Attribute; 28 28 29 30 31 32 33 34 29 /// Named labels for statements 30 class Label { 31 public: 32 CodeLocation location; 33 std::string name; 34 std::vector< ptr<Attribute> > attributes; 35 35 36 37 38 36 Label( CodeLocation loc, const std::string& name = "", 37 const std::vector<ptr<Attribute>>& attrs = std::vector<ptr<Attribute>>{} ) 38 : location( loc ), name( name ), attributes( attrs ) {} 39 39 40 41 42 40 operator std::string () const { return name; } 41 bool empty() { return name.empty(); } 42 }; 43 43 44 45 46 44 inline bool operator== ( const Label& l1, const Label& l2 ) { return l1.name == l2.name; } 45 inline bool operator!= ( const Label& l1, const Label& l2 ) { return !(l1 == l2); } 46 inline bool operator< ( const Label& l1, const Label& l2 ) { return l1.name < l2.name; } 47 47 48 inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; } 48 inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; } 49 50 51 //================================================================================================= 52 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 53 /// remove only if there is a better solution 54 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 55 /// forward declarations 56 inline void increment( const class Label * node, Node::ref_type ref ) { node->increment( ref ); } 57 inline void decrement( const class Label * node, Node::ref_type ref ) { node->decrement( ref ); } 49 58 50 59 } -
src/AST/LinkageSpec.hpp
rb78129a r768b3b4f 35 35 36 36 /// Bitflag type for storage classes 37 union Spec { 38 unsigned int val; 39 struct { 40 bool is_mangled : 1; 41 bool is_generatable : 1; 42 bool is_overrideable : 1; 43 bool is_builtin : 1; 44 bool is_gcc_builtin : 1; 37 struct spec_flags { 38 union { 39 unsigned int val; 40 struct { 41 bool is_mangled : 1; 42 bool is_generatable : 1; 43 bool is_overrideable : 1; 44 bool is_builtin : 1; 45 bool is_gcc_builtin : 1; 46 }; 45 47 }; 46 48 47 MakeBitfield( Spec )49 constexpr spec_flags( unsigned int val ) : val(val) {} 48 50 }; 51 52 using Spec = bitfield<spec_flags>; 49 53 50 54 /// If `cmd` = "C" returns `spec` with `is_mangled = false`. -
src/AST/ParseNode.hpp
rb78129a r768b3b4f 22 22 namespace ast { 23 23 24 25 26 27 24 /// AST node with an included source location 25 class ParseNode : public Node { 26 public: 27 CodeLocation location; 28 28 29 30 31 29 // Default constructor is deliberately omitted, all ParseNodes must have a location. 30 // Escape hatch if needed is to explicitly pass a default-constructed location, but 31 // this should be used sparingly. 32 32 33 33 ParseNode( const CodeLocation& loc ) : Node(), location(loc) {} 34 34 35 36 35 ParseNode( const ParseNode& o ) = default; 36 }; 37 37 38 39 //================================================================================================= 40 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 41 /// remove only if there is a better solution 42 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 43 /// forward declarations 44 inline void increment( const class ParseNode * node, Node::ref_type ref ) { node->increment( ref ); } 45 inline void decrement( const class ParseNode * node, Node::ref_type ref ) { node->decrement( ref ); } 38 46 } 39 47 -
src/AST/Pass.hpp
rb78129a r768b3b4f 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // Pass.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 // IWYU pragma: private, include " Common/PassVisitor.h"17 // IWYU pragma: private, include "AST/Pass.hpp" 3 18 4 19 #include <functional> … … 6 21 #include <stack> 7 22 8 #include "Fwd.hpp" 9 #include "Node.hpp" 23 #include "AST/Fwd.hpp" 24 #include "AST/Node.hpp" 25 #include "AST/Decl.hpp" 26 #include "AST/Visitor.hpp" 27 28 #include "SymTab/Indexer.h" 10 29 11 30 // Private prelude header, needed for some of the magic tricks this class pulls off 12 #include " Pass.proto.hpp"31 #include "AST/Pass.proto.hpp" 13 32 14 33 namespace ast { … … 20 39 // 21 40 // Several additional features are available through inheritance 22 // | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression 41 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 42 // current expression 23 43 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 24 44 // statement by adding new statements into stmtsToAddBefore or 25 45 // stmtsToAddAfter respectively. 46 // | WithDeclsToAdd - provides the ability to insert declarations before or after the current 47 // declarations by adding new DeclStmt into declsToAddBefore or 48 // declsToAddAfter respectively. 26 49 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 27 50 // to false in pre{visit,visit} to skip visiting children … … 30 53 // automatically be restored to its previous value after the corresponding 31 54 // postvisit/postmutate teminates. 55 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 56 // | WithIndexer - provides indexer functionality (i.e. up-to-date symbol table) 32 57 //------------------------------------------------------------------------------------------------- 33 58 template< typename pass_t > 34 59 class Pass final : public ast::Visitor { 35 60 public: 61 /// Forward any arguments to the pass constructor 62 /// Propagate 'this' if necessary 36 63 template< typename... Args > 37 64 Pass( Args &&... args) 38 : m_pass( std::forward<Args>( args )... )65 : pass( std::forward<Args>( args )... ) 39 66 { 40 67 // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor 41 68 typedef Pass<pass_t> this_t; 42 this_t * const * visitor = __pass::visitor( m_pass, 0);69 this_t * const * visitor = __pass::visitor(pass, 0); 43 70 if(visitor) { 44 71 *const_cast<this_t **>( visitor ) = this; … … 48 75 virtual ~Pass() = default; 49 76 50 pass_t m_pass; 51 77 /// Storage for the actual pass 78 pass_t pass; 79 80 /// Visit function declarations 52 81 virtual DeclWithType * visit( const ObjectDecl * ) override final; 53 82 virtual DeclWithType * visit( const FunctionDecl * ) override final; … … 145 174 virtual TypeSubstitution * visit( const TypeSubstitution * ) override final; 146 175 176 friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor ); 147 177 private: 148 178 149 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children( m_pass, 0); return ptr ? *ptr : true; }179 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; } 150 180 151 181 private: 182 /// Logic to call the accept and mutate the parent if needed, delegates call to accept 152 183 template<typename parent_t, typename child_t> 153 184 void maybe_accept(parent_t * & , typename parent_t::child_t *); 154 185 155 ast::Statement * call_accept( const ast::Statement* );156 ast::Expression * call_accept( const ast::Expression* );186 Stmt * call_accept( const Stmt * ); 187 Expr * call_accept( const Expr * ); 157 188 158 189 template< template <class> class container_t > 159 container_t< ast::ptr<ast::Statement> > call_accept( const container_t< ast::ptr<ast::Statement> > & );190 container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & ); 160 191 161 192 template< template <class> class container_t, typename node_t > 162 container_t< ast::ptr<node_t> > call_accept( const container_t< ast::ptr<node_t> > & container );193 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 163 194 164 195 private: 165 struct indexer_guard { 196 /// Internal RAII guard for indexer features 197 struct guard_indexer { 198 guard_indexer( Pass<pass_t> & pass ): pass( pass ) { __pass::indexer::enter(pass, 0); } 199 ~guard_indexer() { __pass::indexer::leave(pass, 0); } 166 200 Pass<pass_t> & pass; 167 168 indexer_guard( Pass<pass_t> & pass ) : pass( pass ) { __pass::indexer::enter(pass, 0); }169 ~indexer_guard() { __pass::indexer::leave(pass, 0); }170 201 }; 171 202 172 indexer_guard make_indexer_guard() { return { *this }; }173 174 private: 175 struct scope_guard {203 /// Internal RAII guard for scope features 204 struct guard_scope { 205 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); } 206 ~guard_scope() { __pass::scope::leave(pass, 0); } 176 207 Pass<pass_t> & pass; 177 178 scope_guard( Pass<pass_t> & pass ) : pass( pass ) { __pass::scope::enter(pass, 0); }179 ~scope_guard() { __pass::scope::leave(pass, 0); }180 208 }; 181 182 scope_guard make_scope_guard() { return { *this }; } 183 }; 184 185 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 186 // Guard value : RAII type to restore a value when the Pass finishes visiting this node 187 template<typename pass_t, typename T> 188 void GuardValue( pass_t * pass, T& val ) { 189 pass->at_cleanup( [ val ]( void * newVal ) { 190 * static_cast< T * >( newVal ) = val; 191 }, static_cast< void * >( & val ) ); 192 } 193 194 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 209 }; 210 211 template<typename pass_t> 212 void acceptAll( std::list< ptr<Decl> >, Pass<pass_t>& visitor ); 213 214 //------------------------------------------------------------------------------------------------- 195 215 // PASS ACCESSORIES 196 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 197 198 // Keep track of the type substitution 199 struct WithConstTypeSubstitution { 200 const ast::TypeSubstitution * env = nullptr; 201 }; 216 //------------------------------------------------------------------------------------------------- 202 217 203 218 template<typename T> 204 219 using std_list = std::list<T>; 205 220 206 // Used if visitor requires added statements before or after the current node. 207 // The Pass template handles what *before* and *after* means automatically 221 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression 222 struct WithConstTypeSubstitution { 223 const TypeSubstitution * env = nullptr; 224 }; 225 226 /// Used if visitor requires added statements before or after the current node. 227 /// The Pass template handles what *before* and *after* means automatically 208 228 template< template<class> class container_t = std_list > 209 229 struct WithStmtsToAdd { 210 container_t< ast::ptr< ast::Statement> > stmtsToAddBefore;211 container_t< ast::ptr< ast::Statement> > stmtsToAddAfter;212 }; 213 214 // Used if visitor requires added declarations before or after the current node.215 // The Pass template handles what *before* and *after* means automatically230 container_t< ptr<Stmt> > stmtsToAddBefore; 231 container_t< ptr<Stmt> > stmtsToAddAfter; 232 }; 233 234 /// Used if visitor requires added declarations before or after the current node. 235 /// The Pass template handles what *before* and *after* means automatically 216 236 template< template<class> class container_t = std_list > 217 237 struct WithDeclsToAdd { 218 ~WithDeclsToAdd() { 219 assert( declsToAddBefore.empty() ); 220 } 221 222 container_t< ast::ptr< ast::Declaration > > declsToAddBefore; 223 container_t< ast::ptr< ast::Declaration > > declsToAddAfter; 224 }; 225 226 // Use if visitation should stop at certain levels 227 // set visit_children false of all child nodes should be ignored 238 container_t< ptr<Decl> > declsToAddBefore; 239 container_t< ptr<Decl> > declsToAddAfter; 240 }; 241 242 /// Use if visitation should stop at certain levels 243 /// set visit_children false of all child nodes should be ignored 228 244 struct WithShortCircuiting { 229 245 __pass::bool_ref visit_children; 230 246 }; 231 247 232 // class WithGuards { 233 // protected: 234 // WithGuards() = default; 235 // ~WithGuards() = default; 236 237 // public: 238 // at_cleanup_t at_cleanup; 239 240 // template< typename T > 241 // void GuardValue( T& val ) { 242 // at_cleanup( [ val ]( void * newVal ) { 243 // * static_cast< T * >( newVal ) = val; 244 // }, static_cast< void * >( & val ) ); 245 // } 246 247 // template< typename T > 248 // void GuardScope( T& val ) { 249 // val.beginScope(); 250 // at_cleanup( []( void * val ) { 251 // static_cast< T * >( val )->endScope(); 252 // }, static_cast< void * >( & val ) ); 253 // } 254 255 // template< typename Func > 256 // void GuardAction( Func func ) { 257 // at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr ); 258 // } 259 // }; 260 261 // template<typename pass_type> 262 // class WithVisitorRef { 263 // protected: 264 // WithVisitorRef() {} 265 // ~WithVisitorRef() {} 266 267 // public: 268 // PassVisitor<pass_type> * const visitor = nullptr; 269 // }; 270 248 /// Used to restore values/functions/etc. when the Pass finishes visiting this node 249 class WithGuards { 250 __pass::at_cleanup_t at_cleanup; 251 252 public: 253 /// When this node is finished being visited, restore the value of a variable 254 template< typename T > 255 void GuardValue( T& val ) { 256 at_cleanup( [ val ]( void * newVal ) { 257 * static_cast< T * >( newVal ) = val; 258 }, static_cast< void * >( & val ) ); 259 } 260 261 /// On the object, all beginScope now and endScope when the current node is finished being visited 262 template< typename T > 263 void GuardScope( T& val ) { 264 val.beginScope(); 265 at_cleanup( []( void * val ) { 266 static_cast< T * >( val )->endScope(); 267 }, static_cast< void * >( & val ) ); 268 } 269 270 /// When this node is finished being visited, call a function 271 template< typename Func > 272 void GuardAction( Func func ) { 273 at_cleanup( [func](void *) { func(); }, nullptr ); 274 } 275 }; 276 277 /// Used to get a pointer to the pass with its wrapped type 278 template<typename pass_t> 279 struct WithVisitorRef { 280 Pass<pass_t> * const visitor = nullptr; 281 }; 282 283 /// Use when the templated visitor should update the indexer 271 284 struct WithIndexer { 272 285 SymTab::Indexer indexer; -
src/AST/Pass.impl.hpp
rb78129a r768b3b4f 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // Pass.impl.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 // IWYU pragma: private, include " Pass.hpp"17 // IWYU pragma: private, include "AST/Pass.hpp" 3 18 4 19 #define VISIT_START( node ) \ 20 using namespace ast; \ 5 21 /* back-up the visit children */ \ 6 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children( m_pass, 0) ); \22 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \ 7 23 /* setup the scope for passes that want to run code at exit */ \ 8 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup ( m_pass, 0) ); \24 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (pass, 0) ); \ 9 25 /* call the implementation of the previsit of this pass */ \ 10 __pass::previsit( m_pass, node, 0 );26 __pass::previsit( pass, node, 0 ); 11 27 12 28 #define VISIT( code ) \ … … 98 114 99 115 template< typename pass_t > 100 ast::Expr ession * Pass< pass_t >::call_accept( const ast::Expression* expr ) {116 ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) { 101 117 __pedantic_pass_assert( __visit_children() ); 102 118 __pedantic_pass_assert( expr ); 103 119 104 const ast::TypeSubstitution ** env_ptr = __pass::env( m_pass, 0);120 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0); 105 121 if ( env_ptr && expr->env ) { 106 122 *env_ptr = expr->env; … … 111 127 112 128 template< typename pass_t > 113 ast::Statement * Pass< pass_t >::call_accept( const ast::Statement * stmt ) {129 Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) { 114 130 __pedantic_pass_assert( __visit_children() ); 115 131 __pedantic_pass_assert( stmt ); 116 117 // add a few useful symbols to the scope118 using __pass::empty;119 using decls_t = typename std::remove_pointer< decltype(__decls_before()) >::type;120 using stmts_t = typename std::remove_pointer< decltype(__stmts_before()) >::type;121 122 // get the stmts/decls that will need to be spliced in123 auto stmts_before = __pass::stmtsToAddBefore( m_pass, 0);124 auto stmts_after = __pass::stmtsToAddAfter ( m_pass, 0);125 auto decls_before = __pass::declsToAddBefore( m_pass, 0);126 auto decls_after = __pass::declsToAddAfter ( m_pass, 0);127 128 // These may be modified by subnode but most be restored once we exit this statemnet.129 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( m_pass, 0); );130 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );131 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after );132 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before );133 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after );134 135 // Now is the time to actually visit the node136 ast::Statement * nstmt = stmt->accept( *this );137 138 // If the pass doesn't want to add anything then we are done139 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {140 return nstmt;141 }142 143 // Make sure that it is either adding statements or declartions but not both144 // this is because otherwise the order would be awkward to predict145 assert(( empty( stmts_before ) && empty( stmts_after ))146 || ( empty( decls_before ) && empty( decls_after )) );147 148 // Create a new Compound Statement to hold the new decls/stmts149 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );150 151 // Take all the declarations that go before152 __pass::take_all( std::back_inserter( compound->kids ), decls_before );153 __pass::take_all( std::back_inserter( compound->kids ), stmts_before );154 155 // Insert the original declaration156 compound->kids.push_back( nstmt );157 158 // Insert all the declarations that go before159 __pass::take_all( std::back_inserter( compound->kids ), decls_after );160 __pass::take_all( std::back_inserter( compound->kids ), stmts_after );161 162 return compound;163 }164 165 template< typename pass_t >166 template< template <class> class container_t >167 container_t< ast::ptr<ast::Statement> > Pass< pass_t >::call_accept( const container_t< ast::ptr<ast::Statement> > & statements ) {168 __pedantic_pass_assert( __visit_children() );169 if( statements.empty() ) return {};170 171 // We are going to aggregate errors for all these statements172 SemanticErrorException errors;173 132 174 133 // add a few useful symbols to the scope … … 182 141 183 142 // These may be modified by subnode but most be restored once we exit this statemnet. 143 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0); ); 184 144 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before ); 185 145 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after ); … … 187 147 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after ); 188 148 149 // Now is the time to actually visit the node 150 ast::Statement * nstmt = stmt->accept( *this ); 151 152 // If the pass doesn't want to add anything then we are done 153 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 154 return nstmt; 155 } 156 157 // Make sure that it is either adding statements or declartions but not both 158 // this is because otherwise the order would be awkward to predict 159 assert(( empty( stmts_before ) && empty( stmts_after )) 160 || ( empty( decls_before ) && empty( decls_after )) ); 161 162 // Create a new Compound Statement to hold the new decls/stmts 163 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location ); 164 165 // Take all the declarations that go before 166 __pass::take_all( std::back_inserter( compound->kids ), decls_before ); 167 __pass::take_all( std::back_inserter( compound->kids ), stmts_before ); 168 169 // Insert the original declaration 170 compound->kids.push_back( nstmt ); 171 172 // Insert all the declarations that go before 173 __pass::take_all( std::back_inserter( compound->kids ), decls_after ); 174 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 175 176 return compound; 177 } 178 179 template< typename pass_t > 180 template< template <class> class container_t > 181 container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 182 __pedantic_pass_assert( __visit_children() ); 183 if( statements.empty() ) return {}; 184 185 // We are going to aggregate errors for all these statements 186 SemanticErrorException errors; 187 188 // add a few useful symbols to the scope 189 using __pass::empty; 190 191 // get the stmts/decls that will need to be spliced in 192 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 193 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 194 auto decls_before = __pass::declsToAddBefore( pass, 0); 195 auto decls_after = __pass::declsToAddAfter ( pass, 0); 196 197 // These may be modified by subnode but most be restored once we exit this statemnet. 198 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before ); 199 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after ); 200 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before ); 201 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after ); 202 189 203 // update pass statitistics 190 204 pass_visitor_stats.depth++; … … 193 207 194 208 bool mutated = false; 195 container_t< ast::ptr< ast::Statement >> new_kids;196 for( const ast::Statement * stmt : statements ) {209 container_t< ptr<Stmt> > new_kids; 210 for( const Stmt * stmt : statements ) { 197 211 try { 198 212 __pedantic_pass_assert( stmt ); … … 269 283 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 270 284 285 template< typename pass_t > 286 inline void ast::acceptAll( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) { 287 // We are going to aggregate errors for all these statements 288 SemanticErrorException errors; 289 290 // add a few useful symbols to the scope 291 using __pass::empty; 292 293 // get the stmts/decls that will need to be spliced in 294 auto decls_before = __pass::declsToAddBefore( pass, 0); 295 auto decls_after = __pass::declsToAddAfter ( pass, 0); 296 297 // update pass statitistics 298 pass_visitor_stats.depth++; 299 pass_visitor_stats.max->push(pass_visitor_stats.depth); 300 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 301 302 for ( std::list< ast::ptr<ast::Decl> >::iterator i = decls.begin(); ; ++i ) { 303 // splice in new declarations after previous decl 304 if ( !empty( decls_after ) ) { decls.splice( i, *decls_after ); } 305 306 if ( i == decls.end() ) break; 307 308 try { 309 // run visitor on declaration 310 ast::ptr<ast::Decl> & node = *i; 311 assert( node ); 312 node = node->accept( visitor ); 313 } 314 catch( SemanticErrorException &e ) { 315 errors.append( e ); 316 } 317 318 // splice in new declarations before current decl 319 if ( !empty( decls_before ) ) { decls.splice( i, *decls_before ); } 320 } 321 pass_visitor_stats.depth--; 322 if ( !errors.isEmpty() ) { throw errors; } 323 } 324 271 325 // A NOTE ON THE ORDER OF TRAVERSAL 272 326 // … … 289 343 // ObjectDecl 290 344 template< typename pass_t > 291 ast::Decl arationWithType * Pass< pass_t >::mutate(ast::ObjectDecl * node ) {345 ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) { 292 346 VISIT_START( node ); 293 347 294 348 VISIT( 295 349 { 296 auto guard = make_indexer_guard();297 maybe_accept( node, ast::ObjectDecl::type );298 } 299 maybe_accept( node, ast::ObjectDecl::init );300 maybe_accept( node, ast::ObjectDecl::bitfieldWidth );301 maybe_accept( node, ast::ObjectDecl::attributes );350 indexer_guard guard { *this }; 351 maybe_accept( node, ObjectDecl::type ); 352 } 353 maybe_accept( node, ObjectDecl::init ); 354 maybe_accept( node, ObjectDecl::bitfieldWidth ); 355 maybe_accept( node, ObjectDecl::attributes ); 302 356 ) 303 357 304 __pass::indexer::AddId( m_pass, 0, node );305 306 VISIT_END( Decl arationWithType, node );358 __pass::indexer::AddId( pass, 0, node ); 359 360 VISIT_END( DeclWithType, node ); 307 361 } 308 362 … … 310 364 // Attribute 311 365 template< typename pass_type > 312 ast::Attribute * ast::Pass< pass_type >::visit( ast::ptr<ast::Attribute> &node ) {366 ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node ) { 313 367 VISIT_START(node); 314 368 … … 323 377 // TypeSubstitution 324 378 template< typename pass_type > 325 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {379 TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) { 326 380 MUTATE_START( node ); 327 381 -
src/AST/Pass.proto.hpp
rb78129a r768b3b4f 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // Pass.impl.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 17 // IWYU pragma: private, include "Pass.hpp" 3 18 4 19 namespace ast { 5 template<typename pass_type> 6 class Pass; 7 8 namespace __pass { 9 typedef std::function<void( void * )> cleanup_func_t; 10 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 11 12 13 // boolean reference that may be null 14 // either refers to a boolean value or is null and returns true 15 class bool_ref { 16 public: 17 bool_ref() = default; 18 ~bool_ref() = default; 19 20 operator bool() { return m_ref ? *m_ref : true; } 21 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 22 23 private: 24 25 friend class visit_children_guard; 26 27 bool * set( bool * val ) { 28 bool * prev = m_ref; 29 m_ref = val; 30 return prev; 20 template<typename pass_type> 21 class Pass; 22 23 namespace __pass { 24 typedef std::function<void( void * )> cleanup_func_t; 25 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 26 27 28 // boolean reference that may be null 29 // either refers to a boolean value or is null and returns true 30 class bool_ref { 31 public: 32 bool_ref() = default; 33 ~bool_ref() = default; 34 35 operator bool() { return m_ref ? *m_ref : true; } 36 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 37 38 private: 39 40 friend class visit_children_guard; 41 42 bool * set( bool * val ) { 43 bool * prev = m_ref; 44 m_ref = val; 45 return prev; 46 } 47 48 bool * m_ref = nullptr; 49 }; 50 51 // Implementation of the guard value 52 // Created inside the visit scope 53 class guard_value { 54 public: 55 /// Push onto the cleanup 56 guard_value( at_cleanup_t * at_cleanup ) { 57 if( at_cleanup ) { 58 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 59 push( std::move( func ), val ); 60 }; 31 61 } 32 33 bool * m_ref = nullptr; 62 } 63 64 ~guard_value() { 65 while( !cleanups.empty() ) { 66 auto& cleanup = cleanups.top(); 67 cleanup.func( cleanup.val ); 68 cleanups.pop(); 69 } 70 } 71 72 void push( cleanup_func_t && func, void* val ) { 73 cleanups.emplace( std::move(func), val ); 74 } 75 76 private: 77 struct cleanup_t { 78 cleanup_func_t func; 79 void * val; 80 81 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 34 82 }; 35 83 36 // Implementation of the guard value 37 // Created inside the visit scope 38 class guard_value { 39 public: 40 guard_value( at_cleanup_t * at_cleanup ) { 41 if( at_cleanup ) { 42 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 43 push( std::move( func ), val ); 44 }; 45 } 84 std::stack< cleanup_t > cleanups; 85 }; 86 87 // Guard structure implementation for whether or not children should be visited 88 class visit_children_guard { 89 public: 90 91 visit_children_guard( bool_ref * ref ) 92 : m_val ( true ) 93 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 94 , m_ref ( ref ) 95 {} 96 97 ~visit_children_guard() { 98 if( m_ref ) { 99 m_ref->set( m_prev ); 46 100 } 47 48 ~guard_value() { 49 while( !cleanups.empty() ) { 50 auto& cleanup = cleanups.top(); 51 cleanup.func( cleanup.val ); 52 cleanups.pop(); 53 } 54 } 55 56 void push( cleanup_func_t && func, void* val ) { 57 cleanups.emplace( std::move(func), val ); 58 } 59 60 private: 61 struct cleanup_t { 62 cleanup_func_t func; 63 void * val; 64 65 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 66 }; 67 68 std::stack< cleanup_t > cleanups; 69 }; 70 71 // Guard structure implementation for whether or not children should be visited 72 class visit_children_guard { 73 public: 74 75 visit_children_guard( bool_ref * ref ) 76 : m_val ( true ) 77 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 78 , m_ref ( ref ) 79 {} 80 81 ~visit_children_guard() { 82 if( m_ref ) { 83 m_ref->set( m_prev ); 84 } 85 } 86 87 operator bool() { return m_val; } 88 89 private: 90 bool m_val; 91 bool * m_prev; 92 bool_ref * m_ref; 93 }; 94 95 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 96 // Deep magic (a.k.a template meta programming) to make the templated visitor work 97 // Basically the goal is to make 2 previsit 98 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 99 // 'pass.previsit( node )' that compiles will be used for that node for that type 100 // This requires that this option only compile for passes that actually define an appropriate visit. 101 // SFINAE will make sure the compilation errors in this function don't halt the build. 102 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 103 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 104 // This is needed only to eliminate the need for passes to specify any kind of handlers. 105 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 106 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 107 // the first implementation takes priority in regards to overloading. 108 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 109 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 110 template<typename pass_t, typename node_t> 111 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) { 112 node = pass.previsit( node ); 113 assert(node); 114 } 115 116 template<typename pass_t, typename node_t> 117 static inline auto previsit( pass_t &, const node_t *, long ) {} 118 119 // PostVisit : never mutates the passed pointer but may return a different node 120 template<typename pass_t, typename node_t> 121 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) { 122 return pass.postvisit( node ); 123 } 124 125 template<typename pass_t, typename node_t> 126 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; } 127 128 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 129 // Deep magic (a.k.a template meta programming) continued 130 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 131 // from in order to get extra functionallity for example 132 // class ErrorChecker : WithShortCircuiting { ... }; 133 // Pass<ErrorChecker> checker; 134 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 135 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 136 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 137 // For several accessories, the feature is enabled by detecting that a specific field is present 138 // Use a macro the encapsulate the logic of detecting a particular field 139 // The type is not strictly enforced but does match the accessory 140 #define FIELD_PTR( name, default_type ) \ 141 template< typename pass_t > \ 142 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \ 101 } 102 103 operator bool() { return m_val; } 104 105 private: 106 bool m_val; 107 bool * m_prev; 108 bool_ref * m_ref; 109 }; 110 111 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 112 // Deep magic (a.k.a template meta programming) to make the templated visitor work 113 // Basically the goal is to make 2 previsit 114 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 115 // 'pass.previsit( node )' that compiles will be used for that node for that type 116 // This requires that this option only compile for passes that actually define an appropriate visit. 117 // SFINAE will make sure the compilation errors in this function don't halt the build. 118 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 119 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 120 // This is needed only to eliminate the need for passes to specify any kind of handlers. 121 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 122 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 123 // the first implementation takes priority in regards to overloading. 124 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 125 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 126 template<typename pass_t, typename node_t> 127 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) { 128 node = pass.previsit( node ); 129 assert(node); 130 } 131 132 template<typename pass_t, typename node_t> 133 static inline auto previsit( pass_t &, const node_t *, long ) {} 134 135 // PostVisit : never mutates the passed pointer but may return a different node 136 template<typename pass_t, typename node_t> 137 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) { 138 return pass.postvisit( node ); 139 } 140 141 template<typename pass_t, typename node_t> 142 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; } 143 144 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 145 // Deep magic (a.k.a template meta programming) continued 146 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 147 // from in order to get extra functionallity for example 148 // class ErrorChecker : WithShortCircuiting { ... }; 149 // Pass<ErrorChecker> checker; 150 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 151 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 152 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 153 // For several accessories, the feature is enabled by detecting that a specific field is present 154 // Use a macro the encapsulate the logic of detecting a particular field 155 // The type is not strictly enforced but does match the accessory 156 #define FIELD_PTR( name, default_type ) \ 157 template< typename pass_t > \ 158 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \ 159 \ 160 template< typename pass_t > \ 161 static inline default_type * name( pass_t &, long ) { return nullptr; } 162 163 // List of fields and their expected types 164 FIELD_PTR( env, const ast::TypeSubstitution ) 165 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 166 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 167 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 168 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 169 FIELD_PTR( visit_children, __pass::bool_ref ) 170 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 171 FIELD_PTR( visitor, ast::Pass<pass_t> * const ) 172 173 // Remove the macro to make sure we don't clash 174 #undef FIELD_PTR 175 176 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 177 // All passes which have such functions are assumed desire this behaviour 178 // detect it using the same strategy 179 namespace scope { 180 template<typename pass_t> 181 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) { 182 pass.beginScope(); 183 } 184 185 template<typename pass_t> 186 static inline void enter( pass_t &, long ) {} 187 188 template<typename pass_t> 189 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) { 190 pass.endScope(); 191 } 192 193 template<typename pass_t> 194 static inline void leave( pass_t &, long ) {} 195 }; 196 197 // Finally certain pass desire an up to date indexer automatically 198 // detect the presence of a member name indexer and call all the members appropriately 199 namespace indexer { 200 // Some simple scoping rules 201 template<typename pass_t> 202 static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) { 203 pass.indexer.enterScope(); 204 } 205 206 template<typename pass_t> 207 static inline auto enter( pass_t &, long ) {} 208 209 template<typename pass_t> 210 static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) { 211 pass.indexer.leaveScope(); 212 } 213 214 template<typename pass_t> 215 static inline auto leave( pass_t &, long ) {} 216 217 // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments 218 // Create macro to condense these common patterns 219 #define INDEXER_FUNC1( func, type ) \ 220 template<typename pass_t> \ 221 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\ 222 pass.indexer.func( arg ); \ 223 } \ 143 224 \ 144 template< typename pass_t > \ 145 static inline default_type * name( pass_t &, long ) { return nullptr; } 146 147 // List of fields and their expected types 148 FIELD_PTR( env, const ast::TypeSubstitution ) 149 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 150 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 151 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 152 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 153 FIELD_PTR( visit_children, __pass::bool_ref ) 154 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 155 FIELD_PTR( visitor, ast::Pass<pass_t> * const ) 156 157 // Remove the macro to make sure we don't clash 158 #undef FIELD_PTR 159 160 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 161 // All passes which have such functions are assumed desire this behaviour 162 // detect it using the same strategy 163 namespace scope { 164 template<typename pass_t> 165 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) { 166 pass.beginScope(); 167 } 168 169 template<typename pass_t> 170 static inline void enter( pass_t &, long ) {} 171 172 template<typename pass_t> 173 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) { 174 pass.endScope(); 175 } 176 177 template<typename pass_t> 178 static inline void leave( pass_t &, long ) {} 179 }; 180 181 // Finally certain pass desire an up to date indexer automatically 182 // detect the presence of a member name indexer and call all the members appropriately 183 namespace indexer { 184 // Some simple scoping rules 185 template<typename pass_t> 186 static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) { 187 pass.indexer.enterScope(); 188 } 189 190 template<typename pass_t> 191 static inline auto enter( pass_t &, long ) {} 192 193 template<typename pass_t> 194 static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) { 195 pass.indexer.leaveScope(); 196 } 197 198 template<typename pass_t> 199 static inline auto leave( pass_t &, long ) {} 200 201 // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments 202 // Create macro to condense these common patterns 203 #define INDEXER_FUNC1( func, type ) \ 204 template<typename pass_t> \ 205 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\ 206 pass.indexer.func( arg ); \ 207 } \ 225 template<typename pass_t> \ 226 static inline void func( pass_t &, long, type ) {} 227 228 #define INDEXER_FUNC2( func, type1, type2 ) \ 229 template<typename pass_t> \ 230 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\ 231 pass.indexer.func( arg1, arg2 ); \ 232 } \ 208 233 \ 209 template<typename pass_t> \ 210 static inline void func( pass_t &, long, type ) {} 211 212 #define INDEXER_FUNC2( func, type1, type2 ) \ 213 template<typename pass_t> \ 214 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\ 215 pass.indexer.func( arg1, arg2 ); \ 216 } \ 217 \ 218 template<typename pass_t> \ 219 static inline void func( pass_t &, long, type1, type2 ) {} 220 221 INDEXER_FUNC1( addId , DeclarationWithType * ); 222 INDEXER_FUNC1( addType , NamedTypeDecl * ); 223 INDEXER_FUNC1( addStruct , StructDecl * ); 224 INDEXER_FUNC1( addEnum , EnumDecl * ); 225 INDEXER_FUNC1( addUnion , UnionDecl * ); 226 INDEXER_FUNC1( addTrait , TraitDecl * ); 227 INDEXER_FUNC2( addWith , std::list< Expression * > &, BaseSyntaxNode * ); 228 229 // A few extra functions have more complicated behaviour, they are hand written 230 template<typename pass_t> 231 static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) { 232 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 233 fwd->parameters = decl->parameters; 234 pass.indexer.addStruct( fwd ); 235 } 236 237 template<typename pass_t> 238 static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {} 239 240 template<typename pass_t> 241 static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) { 242 UnionDecl * fwd = new UnionDecl( decl->name ); 243 fwd->parameters = decl->parameters; 244 pass.indexer.addUnion( fwd ); 245 } 246 247 template<typename pass_t> 248 static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {} 249 250 template<typename pass_t> 251 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) { 252 if ( ! pass.indexer.lookupStruct( str ) ) { 253 pass.indexer.addStruct( str ); 254 } 255 } 256 257 template<typename pass_t> 258 static inline void addStruct( pass_t &, long, const std::string & ) {} 259 260 template<typename pass_t> 261 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) { 262 if ( ! pass.indexer.lookupUnion( str ) ) { 263 pass.indexer.addUnion( str ); 264 } 265 } 266 267 template<typename pass_t> 268 static inline void addUnion( pass_t &, long, const std::string & ) {} 269 270 #undef INDEXER_FUNC1 271 #undef INDEXER_FUNC2 272 }; 234 template<typename pass_t> \ 235 static inline void func( pass_t &, long, type1, type2 ) {} 236 237 INDEXER_FUNC1( addId , DeclWithType * ); 238 INDEXER_FUNC1( addType , NamedTypeDecl * ); 239 INDEXER_FUNC1( addStruct , StructDecl * ); 240 INDEXER_FUNC1( addEnum , EnumDecl * ); 241 INDEXER_FUNC1( addUnion , UnionDecl * ); 242 INDEXER_FUNC1( addTrait , TraitDecl * ); 243 INDEXER_FUNC2( addWith , std::list< Expression * > &, Node * ); 244 245 // A few extra functions have more complicated behaviour, they are hand written 246 // template<typename pass_t> 247 // static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) { 248 // ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 249 // fwd->parameters = decl->parameters; 250 // pass.indexer.addStruct( fwd ); 251 // } 252 253 // template<typename pass_t> 254 // static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {} 255 256 // template<typename pass_t> 257 // static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) { 258 // UnionDecl * fwd = new UnionDecl( decl->name ); 259 // fwd->parameters = decl->parameters; 260 // pass.indexer.addUnion( fwd ); 261 // } 262 263 // template<typename pass_t> 264 // static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {} 265 266 // template<typename pass_t> 267 // static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) { 268 // if ( ! pass.indexer.lookupStruct( str ) ) { 269 // pass.indexer.addStruct( str ); 270 // } 271 // } 272 273 // template<typename pass_t> 274 // static inline void addStruct( pass_t &, long, const std::string & ) {} 275 276 // template<typename pass_t> 277 // static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) { 278 // if ( ! pass.indexer.lookupUnion( str ) ) { 279 // pass.indexer.addUnion( str ); 280 // } 281 // } 282 283 // template<typename pass_t> 284 // static inline void addUnion( pass_t &, long, const std::string & ) {} 285 286 #undef INDEXER_FUNC1 287 #undef INDEXER_FUNC2 273 288 }; 274 289 }; 290 }; -
src/AST/Stmt.hpp
rb78129a r768b3b4f 89 89 90 90 91 //================================================================================================= 92 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 93 /// remove only if there is a better solution 94 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 95 /// forward declarations 96 inline void increment( const class Stmt * node, Node::ref_type ref ) { node->increment( ref ); } 97 inline void decrement( const class Stmt * node, Node::ref_type ref ) { node->decrement( ref ); } 98 inline void increment( const class CompoundStmt * node, Node::ref_type ref ) { node->increment( ref ); } 99 inline void decrement( const class CompoundStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 100 inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); } 101 inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 102 inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); } 103 inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 104 inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); } 105 inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 106 inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); } 107 inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 108 inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); } 109 inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 110 inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); } 111 inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 112 inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 113 inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 114 inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); } 115 inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 116 inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 117 inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 118 inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); } 119 inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 120 inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); } 121 inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 122 inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); } 123 inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 124 inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 125 inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 126 inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); } 127 inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 128 inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); } 129 inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 130 inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); } 131 inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 132 inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); } 133 inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 134 inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); } 135 inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 136 inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); } 137 inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 138 91 139 } 92 140 -
src/AST/StorageClasses.hpp
rb78129a r768b3b4f 33 33 34 34 /// Bitflag type for storage classes 35 union Classes { 36 unsigned int val; 37 struct { 38 bool is_extern : 1; 39 bool is_static : 1; 40 bool is_auto : 1; 41 bool is_register : 1; 42 bool is_threadlocal : 1; 35 struct class_flags { 36 union { 37 unsigned int val; 38 struct { 39 bool is_extern : 1; 40 bool is_static : 1; 41 bool is_auto : 1; 42 bool is_register : 1; 43 bool is_threadlocal : 1; 44 }; 45 46 // MakeBitfieldPrint( NumClasses ) 43 47 }; 44 48 45 MakeBitfield( Classes ) 46 MakeBitfieldPrint( NumClasses ) 49 constexpr class_flags( unsigned int val ) : val(val) {} 47 50 }; 48 51 52 using Classes = bitfield<class_flags>; 49 53 } 50 54 } -
src/AST/Type.hpp
rb78129a r768b3b4f 24 24 }; 25 25 26 27 28 //================================================================================================= 29 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 30 /// remove only if there is a better solution 31 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 32 /// forward declarations 33 inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); } 34 inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); } 35 inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); } 36 inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); } 37 inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); } 38 inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); } 39 inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); } 40 inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); } 41 inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); } 42 inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); } 43 inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); } 44 inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); } 45 inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); } 46 inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); } 47 inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); } 48 inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); } 49 inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); } 50 inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); } 51 inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); } 52 inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 53 inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); } 54 inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 55 inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); } 56 inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 57 inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); } 58 inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 59 inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); } 60 inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 61 inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); } 62 inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); } 63 inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); } 64 inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); } 65 inline void increment( const class AttrType * node, Node::ref_type ref ) { node->increment( ref ); } 66 inline void decrement( const class AttrType * node, Node::ref_type ref ) { node->decrement( ref ); } 67 inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); } 68 inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); } 69 inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); } 70 inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); } 71 inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); } 72 inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); } 73 inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); } 74 inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); } 75 26 76 } 27 77 -
src/AST/porting.md
rb78129a r768b3b4f 96 96 97 97 `Expr` 98 * Merged `inferParams`/`resnSlots` into union, as suggested by comment 98 * Merged `inferParams`/`resnSlots` into union, as suggested by comment in old version 99 * does imply get_/set_ API, and some care about moving backward 99 100 100 101 `Label` -
src/Common/PassVisitor.impl.h
rb78129a r768b3b4f 168 168 template< typename Container, typename pass_type > 169 169 inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) { 170 170 171 if ( ! mutator.get_visit_children() ) return; 171 172 SemanticErrorException errors; … … 217 218 try { 218 219 func( *i ); 220 assert( *i ); 219 221 assert(( empty( beforeStmts ) && empty( afterStmts )) 220 222 || ( empty( beforeDecls ) && empty( afterDecls )) ); -
src/Common/PassVisitor.proto.h
rb78129a r768b3b4f 222 222 INDEXER_FUNC2( addWith , std::list< Expression * > &, BaseSyntaxNode * ); 223 223 224 #undef INDEXER_FUNC1 225 #undef INDEXER_FUNC2 224 226 225 227 template<typename pass_type> -
src/SynTree/Declaration.h
rb78129a r768b3b4f 71 71 static Declaration *declFromId( UniqueId id ); 72 72 73 private: 73 UniqueId uniqueId; 74 74 Type::StorageClasses storageClasses; 75 UniqueId uniqueId; 75 private: 76 76 }; 77 77 … … 213 213 TypeDecl::Kind kind; 214 214 bool isComplete; 215 215 216 216 Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {} 217 217 Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {} 218 218 Data( Kind kind, bool isComplete ) : kind( kind ), isComplete( isComplete ) {} 219 Data( const Data& d1, const Data& d2 ) 219 Data( const Data& d1, const Data& d2 ) 220 220 : kind( d1.kind ), isComplete ( d1.isComplete || d2.isComplete ) {} 221 221
Note: See TracChangeset
for help on using the changeset viewer.