Inferno
0.2
|
00001 #ifndef CPPTREE_HPP 00002 #define CPPTREE_HPP 00003 00004 #include "clang/Basic/SourceLocation.h" 00005 #include "clang/Basic/TokenKinds.h" 00006 #include "llvm/ADT/APSInt.h" 00007 #include "llvm/ADT/APFloat.h" 00008 #include <string> 00009 #include <deque> 00010 #include "node/node.hpp" 00011 #include "clang/Parse/DeclSpec.h" 00012 #include "tree/type_db.hpp" 00013 00014 /// CPPTree namespace contains node definitions that represent elements of the C++ language 00015 namespace CPPTree { 00016 00017 //////////////////////////// Underlying Node Types //////////////////////////// 00018 00019 /// Property is the base class for property nodes. 00020 /** Each kind of property has an 00021 intermediate which can represent any value of the property. Enum-like and 00022 bool-like are implemented by choosing one of a choice of empty nodes derived 00023 from the intermediate. Other properties that cannot be represented this way 00024 have a Specific<Foo> node that actually contains the datatype (eg int, string 00025 etc). The intermediates should be the target of SharedPtrs and may be used in 00026 search patterns. The actual tree nodes for a program should always be the leaf 00027 node type. */ 00028 struct Property : virtual Node { NODE_FUNCTIONS }; 00029 00030 /// Variable initialiser or function body 00031 /** This intermediate is used for an initial value for for a variable/object in 00032 which case it will be an Expression, or for the implementation of a Callable 00033 in which case it will be a Compound. For an uninitialised variable/object 00034 or a function declaration, it will be Uninitialised. */ 00035 struct Initialiser : virtual Node { NODE_FUNCTIONS }; 00036 00037 /// an uninitialised Instance. 00038 struct Uninitialised : Initialiser { NODE_FUNCTIONS_FINAL }; 00039 00040 /// Represents a statement as found inside a function body. 00041 /** Basically anything 00042 that ends with a ; inside a function body, as well as labels (which we consider as 00043 statements in their own right). */ 00044 struct Statement : virtual Node { NODE_FUNCTIONS }; 00045 00046 /// An expression that computes a result value. 00047 /** Can be used anywhere a statement can, per C syntax rules. */ 00048 struct Expression : virtual Statement, 00049 Initialiser { NODE_FUNCTIONS }; 00050 00051 /// Any abstract data type 00052 /** Any abstract data type including fundamentals, structs, function prototypes 00053 and user-named types. */ 00054 struct Type : virtual Node { NODE_FUNCTIONS }; 00055 00056 /// A declaration specifies the creation of a UserType or an Instance. 00057 /** Declaration can appear where statements can and also inside structs etc 00058 and at top level. */ 00059 struct Declaration : virtual Node { NODE_FUNCTIONS }; 00060 00061 /// A scope is any space in a program where declarations may appear. Declarations 00062 /** in the collection are associated with the scope node but unordered. Scopes 00063 are used for name resolution during parse. */ 00064 struct Scope : virtual Node 00065 { 00066 NODE_FUNCTIONS 00067 Collection<Declaration> members; /// The declarations in this scope 00068 }; 00069 00070 /// The top level of a program 00071 /** The top level of a program is considered a collection of declarations. 00072 main() would typically be a function instance somewhere in this collection. */ 00073 struct Program : Scope { NODE_FUNCTIONS_FINAL }; 00074 00075 /// Indicates that the node cannot be combinationalised 00076 struct Uncombable : virtual Node { NODE_FUNCTIONS }; 00077 00078 //////////////////////////// Literals /////////////////////////////// 00079 00080 /// A property that can also be used as a literal in a program 00081 /** There are also used as properties, so that we do not need to 00082 duplicate literals and properties. */ 00083 struct Literal : Expression, 00084 Property 00085 { 00086 NODE_FUNCTIONS 00087 }; 00088 00089 /// Intermediate property node that represents a string of any value. 00090 struct String : Literal { NODE_FUNCTIONS }; 00091 00092 /// A string with a specific value 00093 /** Value must be filled in. 00094 TODO could be a problem with memory management here or nearby. See 00095 comment in test harness in search_replace.cpp. */ 00096 struct SpecificString : String 00097 { 00098 NODE_FUNCTIONS_FINAL 00099 SpecificString() {} ///< default constructor, for making architypes 00100 SpecificString( string s ) : 00101 value(s) /// Construct with a given STL string 00102 { 00103 } 00104 virtual bool IsLocalMatch( const Matcher *candidate ) const /// Overloaded comparison for search&replace 00105 { 00106 ASSERT( candidate ); 00107 const SpecificString *c = dynamic_cast<const SpecificString *>(candidate); 00108 return c && c->value == value; 00109 } 00110 virtual operator string() const /// Produce a string for debug 00111 { 00112 // Since this is a string literal, output it quoted 00113 return "\"" + value + "\""; 00114 } 00115 private: 00116 string value; ///< The string itself 00117 }; 00118 00119 /// Intermediate property node that represents a number of any value 00120 /** (anything you 00121 can do +, - etc on). */ 00122 struct Number : Literal { NODE_FUNCTIONS }; 00123 00124 #define INTEGER_DEFAULT_WIDTH 32 00125 00126 /// Intermediate property node that represents an integer of any value and signedness. 00127 struct Integer : Number { NODE_FUNCTIONS }; 00128 00129 /// Property node for a specific integer value. 00130 /** We use LLVM's class for this, 00131 so that we can deal with any size of number (so this can be used for 00132 large bit vectors). The LLVM object also stores the signedness. The 00133 value must always be filled in. */ 00134 struct SpecificInteger : Integer, llvm::APSInt 00135 { 00136 NODE_FUNCTIONS_FINAL 00137 SpecificInteger() {} ///< default constructor, for making architypes 00138 SpecificInteger( llvm::APSInt i ) : llvm::APSInt(i) {} ///< Construct with an LLVM-style integer 00139 SpecificInteger( int i ) : llvm::APSInt(INTEGER_DEFAULT_WIDTH) { *(llvm::APSInt *)this = i; } ///< Construct with an ordinary int 00140 virtual bool IsLocalMatch( const Matcher *candidate ) const /// Overloaded comparison for search&replace 00141 { 00142 ASSERT( candidate ); 00143 const SpecificInteger *c = dynamic_cast<const SpecificInteger *>(candidate); 00144 return c && *(llvm::APSInt *)c == *(llvm::APSInt *)this; 00145 } 00146 virtual operator string() const /// Produce a string for debug 00147 { 00148 return string(toString(10)) + // decimal 00149 (isUnsigned() ? "U" : "") + 00150 (getBitWidth()>TypeDb::integral_bits[clang::DeclSpec::TSW_unspecified] ? "L" : "") + 00151 (getBitWidth()>TypeDb::integral_bits[clang::DeclSpec::TSW_long] ? "L" : ""); 00152 // note, assuming longlong bigger than long, so second L appends first to get LL 00153 } 00154 }; 00155 00156 /// Intermediate property node that represents a floating point number of any value. 00157 struct Float : Number { NODE_FUNCTIONS }; 00158 00159 /// Property node for a specific floating point value. 00160 /** We use LLVM's class for this, 00161 so that we can deal with any representation convention. The value must 00162 always be filled in. To determine the type, use llvm::getSemantics() */ 00163 struct SpecificFloat : Float, llvm::APFloat 00164 { 00165 NODE_FUNCTIONS_FINAL 00166 SpecificFloat() : llvm::APFloat(0.0) {} ///< default constructor, for making architypes 00167 SpecificFloat( llvm::APFloat v ) : llvm::APFloat(v) {}; ///< Construct with an LLVM-style float 00168 virtual bool IsLocalMatch( const Matcher *candidate ) const /// Overloaded comparison for search&replace 00169 { 00170 ASSERT( candidate ); 00171 const SpecificFloat *c = dynamic_cast<const SpecificFloat *>(candidate); 00172 return c && bitwiseIsEqual( *c ); 00173 } 00174 virtual operator string() const /// Produce a string for debug 00175 { 00176 char hs[256]; 00177 // generate hex float since it can be exact 00178 convertToHexString( hs, 0, false, llvm::APFloat::rmTowardNegative); // note rounding mode ignored when hex_digits==0 00179 return string(hs) + 00180 (&getSemantics()==TypeDb::float_semantics ? "F" : "") + 00181 (&getSemantics()==TypeDb::long_double_semantics ? "L" : ""); 00182 } 00183 }; 00184 00185 /// Intermediate property node that represents either boolean value. 00186 /** Note: Bool here is considered a noun, and in general Property/Literal 00187 intermediates are named using nouns. C.f. the Type node Boolean */ 00188 struct Bool : Literal { NODE_FUNCTIONS }; 00189 00190 /// Property node for boolean value true 00191 struct True : Bool 00192 { 00193 NODE_FUNCTIONS_FINAL 00194 virtual operator string() const { return "true"; } ///< Produce a string for debug 00195 }; 00196 00197 /// Property node for boolean value false 00198 struct False : Bool 00199 { 00200 NODE_FUNCTIONS_FINAL 00201 virtual operator string() const { return "false"; } ///< Produce a string for debug 00202 }; 00203 00204 //////////////////////////// Declarations ///////////////////// 00205 00206 /// Property node for any identifier 00207 /** An Identifier is a name given to a user-defined entity within 00208 the program (variable/object/function, user-defined type or 00209 label). In the inferno tree, these are fully scope resolved 00210 and are maintained as unique nodes so that the declaration 00211 and all usages all point to the same node, this preserving 00212 00213 identity via topology. We store a string, but it isn't strictly 00214 needed and there's no need to uniquify it (it's really just 00215 a hint for users examining the output). */ 00216 struct Identifier : virtual Property { NODE_FUNCTIONS }; 00217 00218 /// Property for a specific identifier, linked to by a particular Declaration 00219 /** This is for unquoted strings, as opposed to String. Strictly, 00220 Inferno doesn't need to keep this data, but it helps 00221 to make renders and graphs clearer. Inferno will uniquify 00222 the name when rendering code. */ 00223 struct SpecificIdentifier : virtual Property 00224 { 00225 NODE_FUNCTIONS 00226 SpecificIdentifier() {} ///< default constructor, for making architypes 00227 SpecificIdentifier( string s ) : name(s) {} ///< construct with a given name 00228 virtual shared_ptr<Cloner> Duplicate( shared_ptr<Cloner> p ) /// Overloaded duplication function for search&replace 00229 { 00230 return p; // duplicating specific identifiers just gets the same id, since they are unique. 00231 // This means x.Duplicate() matches x, wheras x.Clone() does not 00232 } 00233 virtual bool IsLocalMatch( const Matcher *candidate ) const /// Overloaded comparison for search&replace 00234 { 00235 ASSERT( candidate ); 00236 return candidate == this; 00237 } 00238 virtual string GetName() const /// This is relied upon to just return the identifier name for rendering 00239 { 00240 return name; 00241 } 00242 private: 00243 string name; 00244 }; 00245 00246 /// Identifier for any Instance (variable or object or function) 00247 struct InstanceIdentifier : Identifier, 00248 Expression { NODE_FUNCTIONS }; 00249 00250 /// Identifier for a specific Instance, linked to by a particular Declaration 00251 struct SpecificInstanceIdentifier : InstanceIdentifier, 00252 SpecificIdentifier 00253 { 00254 SpecificInstanceIdentifier() {} ///< Default constructor 00255 SpecificInstanceIdentifier( string s ) : SpecificIdentifier(s) {} ///< make identifier with the given name 00256 NODE_FUNCTIONS_FINAL 00257 }; 00258 00259 00260 /// Identifier for any user defined type. 00261 struct TypeIdentifier : Identifier, 00262 Type { NODE_FUNCTIONS }; 00263 00264 /// Identifier for a specific user defined type, linked to by a particular Declaration. 00265 struct SpecificTypeIdentifier : TypeIdentifier, 00266 SpecificIdentifier 00267 { 00268 SpecificTypeIdentifier() {} ///< Default constructor 00269 SpecificTypeIdentifier( string s ) : SpecificIdentifier(s) {} ///< make identifier with the given name 00270 NODE_FUNCTIONS_FINAL 00271 }; 00272 00273 // General note about identifiers: in a valid program tree, there should 00274 // be *one* Declaration node that points to the identifier and serves to 00275 // declare it. There should be 0 or more "users" that point to the 00276 // identifier. 00277 00278 /// Property for a member function that may or may not be virtual. 00279 struct Virtuality : Property { NODE_FUNCTIONS }; 00280 00281 /// Property for a virtual member funciton 00282 struct Virtual : Virtuality 00283 { 00284 NODE_FUNCTIONS_FINAL 00285 // TODO pure when supported by clang 00286 }; 00287 /// Property for a non-virtual member funciton 00288 struct NonVirtual : Virtuality { NODE_FUNCTIONS_FINAL }; 00289 00290 /// Property for any access spec 00291 /** Property for C++ access specifiers public, protected and private. AccessSpec 00292 represents any access spec, the subsequent empty nodes specify particular 00293 access specs. Inferno uses access specs for all Instance. Declaration 00294 in Record are as specified, Function parameters and external Declaration 00295 are Public, all others Private. It is anticipated that the access spec will 00296 control generated high-level interfaces. Note that we only specify access 00297 for physical things like instances. Abstract stuff like TypeDef are always 00298 considered Public. */ 00299 struct AccessSpec : Property { NODE_FUNCTIONS }; 00300 00301 /// Property for public access 00302 struct Public : AccessSpec { NODE_FUNCTIONS_FINAL }; 00303 00304 /// Property for private access 00305 struct Private : AccessSpec { NODE_FUNCTIONS_FINAL }; 00306 00307 /// Property for protected access 00308 struct Protected : AccessSpec { NODE_FUNCTIONS_FINAL }; 00309 00310 /// Property that indicates whether some Instance is constant. 00311 struct Constancy : Property { NODE_FUNCTIONS }; 00312 00313 /// Property indicating the Instance is constant 00314 struct Const : Constancy { NODE_FUNCTIONS_FINAL }; 00315 00316 /// Property indicating the Instance is not constant 00317 struct NonConst : Constancy { NODE_FUNCTIONS_FINAL }; 00318 // TODO add mutable when supported by clang 00319 00320 /// Declaration of a variable, object or function 00321 /** Instance represents a variable/object or a function. In case of function, type is a 00322 type under Callable and initialiser is a Statement (or Uninitialised for a function 00323 declaration). For a variable/object, type is basically anything else, and if there is 00324 an initialiser, it is an Expression. We allow init here for various reasons including 00325 - it can be hard to know where to put stand-alone init for statics 00326 - C++ constructors tie init to declaration 00327 - Fits in with single-static-assignment style 00328 The instance node can go into a Declaration Collection or a Statement Sequence. 00329 The latter case is used where initialisaiton/construction demands ordering. It points 00330 to an InstanceIdentifier, and all usages of the instance actually point to the 00331 InstanceIdentifier. */ 00332 struct Instance : Declaration, 00333 Statement 00334 { 00335 NODE_FUNCTIONS 00336 TreePtr<InstanceIdentifier> identifier; ///< acts as a handle for the instance, and holds its name only as a hint 00337 TreePtr<Type> type; ///< the Type of the instance, can be data or Callable type 00338 TreePtr<Initialiser> initialiser; ///< init value for data, body for Callable type 00339 }; 00340 00341 /// A variable or function with one instance across the entire program. 00342 /** This includes extern and 00343 static scope for globals, as well as static locals. If a Static variable is Const, then it may be 00344 regarded as a compile-time constant. A static constant function may be regarded as idempotent. */ 00345 struct Static : Instance 00346 { 00347 NODE_FUNCTIONS_FINAL 00348 TreePtr<Constancy> constancy; ///< is the instance constant (ie compile time value)? 00349 }; 00350 00351 /// A non-static member Instance (function or variable) 00352 /** A variable or function with one instance for each object of the containing class, ie 00353 non-static members. Functions have a "this" pointer. Note that access and constancy 00354 are intended to control the generation of read/write lines for modules. This usage of 00355 Constancy differs from that in Static, so we do not try to introduce a common intermediate. 00356 Note that static members are Static, not Field */ 00357 struct Field : Instance 00358 { 00359 NODE_FUNCTIONS_FINAL 00360 TreePtr<Virtuality> virt; ///< Is the field virtual? 00361 TreePtr<AccessSpec> access; ///< Is it accessible outside the current Scope? 00362 TreePtr<Constancy> constancy; ///< Is the field constant (ie only written by constructor) 00363 }; 00364 00365 /// Any variable local to a Compound-statement. Cannot be a function. 00366 struct LocalVariable : Instance 00367 { 00368 NODE_FUNCTIONS 00369 }; 00370 00371 /// A local variable with automatic allocation 00372 /** A variable with one instance for each *invocation* of a function, ie 00373 non-static locals. Safe across recursion. Note that static locals 00374 are Static, not Automatic. */ 00375 struct Automatic : LocalVariable 00376 { 00377 NODE_FUNCTIONS_FINAL 00378 }; 00379 00380 /// A local temp variable not preserved across function calls 00381 /** A local variable with unspecified storage which may be used within a function but is not preserved 00382 across recursion or between calls (such a variable could safely be implemented as any of 00383 Static, Field or Automatic since it supports only those guarantees common to all). */ 00384 struct Temporary : LocalVariable 00385 { 00386 NODE_FUNCTIONS_FINAL 00387 }; 00388 00389 /// Node for a base class within a class declaration, specifies another class from which to inherit 00390 struct Base : Declaration 00391 { 00392 NODE_FUNCTIONS_FINAL 00393 TreePtr<AccessSpec> access; ///< Can inherited members be accessed? 00394 TreePtr<TypeIdentifier> record; ///< what do we inherit? must refer to InheritanceRecord 00395 }; 00396 00397 /// Identifier for a label that can be any label. 00398 /** LabelIdentifier is an Expression as well as an Identifier so that 00399 it may be assigned to variables and used in ?: expressions as 00400 supported in the gcc variable-label extenstion. Inferno tree 00401 does not require any representation of && or * - Labels 00402 and expressions may be mixed directly. */ 00403 struct LabelIdentifier : Identifier, 00404 Expression { NODE_FUNCTIONS }; 00405 00406 /// Identifier for a specific label that has been declared somewhere. 00407 struct SpecificLabelIdentifier : LabelIdentifier, 00408 SpecificIdentifier 00409 { 00410 SpecificLabelIdentifier() {} ///< Default constructor 00411 SpecificLabelIdentifier( string s ) : SpecificIdentifier(s) {} ///< construct with initial name 00412 NODE_FUNCTIONS_FINAL 00413 }; 00414 00415 /// Declaration of a label for switch, goto etc. 00416 /** This node represents a label such as mylabel: 00417 It serves to declare the label; the identifier should be 00418 used for references. */ 00419 struct Label : Declaration, //TODO commonize with Case and Default 00420 Statement, 00421 Uncombable 00422 { 00423 NODE_FUNCTIONS_FINAL 00424 TreePtr<LabelIdentifier> identifier; ///< a handle for the label to be referenced elewhere 00425 }; 00426 00427 //////////////////////////// Anonymous Types //////////////////////////// 00428 00429 /// Anything that can be called 00430 /** Types under Callable refer to a function's interface as seen by 00431 caller and as used in eg function pointers (which is simply Pointer to 00432 the function type). To actually have a function, with a body, you need 00433 an Instance with type filled in to something derived from Callable. */ 00434 struct Callable : Type 00435 { 00436 NODE_FUNCTIONS 00437 }; 00438 00439 /// Anything that can be called and has parameters 00440 /** Parameters are generated as a sequence of automatic variable/object 00441 declarations (ie Instances) inside the Scope we derive from. */ 00442 struct CallableParams : Callable, 00443 Scope // For the parameters 00444 { 00445 NODE_FUNCTIONS 00446 }; 00447 00448 /// Anything that can be called and has parameters and return value 00449 struct CallableParamsReturn : CallableParams 00450 { 00451 NODE_FUNCTIONS 00452 TreePtr<Type> return_type; ///< The return type 00453 }; 00454 00455 /// Subroutine like in Basic, no params or return. 00456 /** Note: Subroutine has *explicitly* no params or return, this may be relied upon 00457 in transformations that use Subroutine as a wildcard */ 00458 struct Subroutine : Callable 00459 { 00460 NODE_FUNCTIONS 00461 }; 00462 00463 /// A procedure like in pascal etc, params but no return value. 00464 /** Note: Procedure has *explicitly* no return, this may be relied upon 00465 in transformations that use Subroutine as a wildcard */ 00466 struct Procedure : CallableParams 00467 { 00468 NODE_FUNCTIONS 00469 }; 00470 00471 /// A function like in C, Pascal; params and a single return value of the specified type. 00472 struct Function : CallableParamsReturn 00473 { 00474 NODE_FUNCTIONS_FINAL 00475 }; 00476 00477 /// A C++ constructor. The init list is just zero or more calls to constructors in the body 00478 struct Constructor : Procedure { NODE_FUNCTIONS_FINAL }; 00479 00480 /// A C++ destructor 00481 struct Destructor : Subroutine { NODE_FUNCTIONS_FINAL }; 00482 00483 /// This is the type of an array that contains the specified number of elements of the specified type. 00484 struct Array : Type 00485 { 00486 NODE_FUNCTIONS_FINAL 00487 TreePtr<Type> element; ///< the element type 00488 TreePtr<Initialiser> size; ///< evaluates to the size or Uninitialised if not given eg [] 00489 }; 00490 00491 /// Intermediate for indirect access to some type as specified 00492 struct Indirection : Type 00493 { 00494 NODE_FUNCTIONS 00495 TreePtr<Type> destination; ///< reaching an object of this type, indirectly 00496 }; 00497 00498 /// A C/C++ pointer 00499 struct Pointer : Indirection { NODE_FUNCTIONS_FINAL }; 00500 00501 /// A C++ reference 00502 struct Reference : Indirection { NODE_FUNCTIONS_FINAL }; 00503 00504 /// The pseudo-type void, disallowed in some circumstances as per C. 00505 struct Void : Type { NODE_FUNCTIONS_FINAL }; 00506 00507 /// Boolean type. 00508 /** We support bool separately from 1-bit ints, at least for now. 00509 (note that (bool)2==true but (int:1)2==0) 00510 Note: Boolean here is considered an adjective, and in general Type 00511 nodes are named using adjectives. C.f. the Property/Literal intermediate Bool */ 00512 struct Boolean : Type { NODE_FUNCTIONS_FINAL }; 00513 00514 /// Intermediate for any type that represents a number that you can eg add and subtract. 00515 struct Numeric : Type { NODE_FUNCTIONS }; 00516 00517 /// Type represents an integral (singed or unsigned) type. 00518 /** The total number of bits (including sign when signed, and 00519 fractional if fixed-point) is given */ 00520 struct Integral : Numeric 00521 { 00522 NODE_FUNCTIONS 00523 TreePtr<Integer> width; ///< Number of bits, not bytes 00524 }; 00525 00526 /// Type of a signed integer number (2's complement). 00527 struct Signed : Integral { NODE_FUNCTIONS_FINAL }; 00528 00529 /// Type of an unsigned integer number. 00530 struct Unsigned : Integral { NODE_FUNCTIONS_FINAL }; 00531 00532 /// Property for the details of any floating point behaviour 00533 /** implying representation size and implementation. */ 00534 struct FloatSemantics : Property { NODE_FUNCTIONS }; 00535 00536 /// Property for the details of a specific floating point behaviour 00537 struct SpecificFloatSemantics : FloatSemantics 00538 { 00539 NODE_FUNCTIONS_FINAL 00540 SpecificFloatSemantics() {} ///< default constructor, for making architypes 00541 SpecificFloatSemantics( const llvm::fltSemantics *s ) : /// Construct from LLVM's class 00542 value(s) 00543 { 00544 } 00545 virtual bool IsLocalMatch( const Matcher *candidate ) const /// Overloaded comparison for search&replace 00546 { 00547 ASSERT( candidate ); 00548 const SpecificFloatSemantics *c = dynamic_cast<const SpecificFloatSemantics *>(candidate); 00549 return c && c->value == value; 00550 } 00551 virtual operator string() const /// get a debug string 00552 { 00553 return SSPrintf("fltSemantics@%p", value ); 00554 } 00555 operator const llvm::fltSemantics &() const /// convert back to LLVM's class 00556 { 00557 return *value; 00558 } 00559 const llvm::fltSemantics *value; 00560 }; 00561 00562 /// Type of a floating point number. 00563 struct Floating : Numeric 00564 { 00565 NODE_FUNCTIONS_FINAL 00566 TreePtr<FloatSemantics> semantics; ///< These are the semantics of the representation 00567 }; 00568 00569 /// Type of a variable that can hold a label. Similar to the GCC extension 00570 /// for labels-in-variables but we use this type not void * (which is 00571 /// inconvenient for stataic analysis). To declare a conventional label 00572 /// at a particular position, use Label. 00573 struct Labeley : Type 00574 { 00575 NODE_FUNCTIONS_FINAL 00576 }; 00577 00578 //////////////////////////// User-defined Types //////////////////////////// 00579 00580 /// Intermediate declaration of a user defined type of any kind (struct, typedef etc). 00581 /* The user type node is a declaration and goes into a declaration scope. It points 00582 to a TypeIdentifier, and all usages of the type actually point to the 00583 TypeIdentifier. */ 00584 struct UserType : Declaration 00585 { 00586 NODE_FUNCTIONS 00587 TreePtr<TypeIdentifier> identifier; ///< The handle to the type that has been declared 00588 }; 00589 00590 /// Represents a typedef. 00591 /** Typedef is to the specified type. We do not expand these at parse, but try to retain 00592 them for as long as possible */ 00593 struct Typedef : UserType 00594 { 00595 NODE_FUNCTIONS_FINAL 00596 TreePtr<Type> type; ///< emulate this type 00597 }; 00598 00599 /// Intermediate for declaration of a struct, class, union or enum. 00600 /** The set of member Declaration (which will be Field 00601 or Static) is in the Scope. They can be variables/objects in all 00602 cases and additionally Callable instances in Struct/Class. */ 00603 struct Record : UserType, 00604 Scope // Member declarations go in here 00605 { 00606 NODE_FUNCTIONS 00607 }; 00608 00609 /// A union, as per Record. 00610 struct Union : Record { NODE_FUNCTIONS_FINAL }; 00611 00612 /// An Enum, as per record. 00613 /** We regard enumerations as static const variables, initialised as per 00614 the given value. Values are always explicit. */ 00615 struct Enum : Record { NODE_FUNCTIONS_FINAL }; 00616 00617 /// A record that can inherit from other records and be inherited from. 00618 /** We add in a list of base class declarations. */ 00619 struct InheritanceRecord : Record 00620 { 00621 NODE_FUNCTIONS 00622 Collection<Base> bases; ///< contains the InheritanceRecords from which we inherit 00623 // TODO just chuck them into Record::members? 00624 }; 00625 00626 /// Struct as per InheritanceRecord 00627 struct Struct : InheritanceRecord { NODE_FUNCTIONS_FINAL }; 00628 00629 /// Class as per InheritanceRecord 00630 struct Class : InheritanceRecord { NODE_FUNCTIONS_FINAL }; 00631 00632 //////////////////////////// Expressions //////////////////////////// 00633 00634 /// An operator 00635 //TODO maybe fix the number of operands for binop and unop categories. 00636 struct Operator : Expression 00637 { 00638 NODE_FUNCTIONS 00639 }; 00640 00641 /// An operator with operands whose order is defined 00642 struct NonCommutativeOperator : Operator 00643 { 00644 NODE_FUNCTIONS 00645 Sequence<Expression> operands; ///< the operands are here, order preserved 00646 }; 00647 00648 /// An operator with operands whose order does not matter 00649 struct CommutativeOperator : Operator 00650 { 00651 NODE_FUNCTIONS 00652 Collection<Expression> operands; ///< the operands are here, order not preserved 00653 }; 00654 00655 // Intermediate categories of operators. We categorise based on 00656 // topology, and commutative is considered topologically 00657 // distinct from non-commutative. 00658 00659 /// An operator with a single operand 00660 struct Unop : NonCommutativeOperator { NODE_FUNCTIONS }; 00661 00662 /// An operator with two operands 00663 struct Binop : NonCommutativeOperator { NODE_FUNCTIONS }; 00664 00665 /// An operator with three operands 00666 struct Ternop : NonCommutativeOperator { NODE_FUNCTIONS }; 00667 00668 /// An operator with two interchangable operands 00669 struct CommutativeBinop : CommutativeOperator { NODE_FUNCTIONS }; 00670 00671 /// An operator with two operands, that writes its result back to the first operand 00672 struct AssignmentOperator : NonCommutativeOperator { NODE_FUNCTIONS }; 00673 00674 // Use an include file to generate nodes for all the actual operators based on 00675 // contents of operator_db.inc 00676 #define PREFIX(TOK, TEXT, NODE, BASE, CAT) struct NODE : BASE { NODE_FUNCTIONS_FINAL }; 00677 #define POSTFIX(TOK, TEXT, NODE, BASE, CAT) struct NODE : BASE { NODE_FUNCTIONS_FINAL }; 00678 #define INFIX(TOK, TEXT, NODE, BASE, CAT) struct NODE : BASE { NODE_FUNCTIONS_FINAL }; 00679 #define OTHER(TOK, TEXT, NODE, BASE, CAT) struct NODE : BASE { NODE_FUNCTIONS_FINAL }; 00680 #include "operator_db.inc" 00681 00682 /// Property indicating whether a New/Delete is global 00683 /** New/Delete is global if it has :: in 00684 front of it. This differentiates when placement args are given as follows: 00685 Global: must be one placement arg, it is address to construct at 00686 NonGlobal: all placement args go to a corresponding operator new which returns address to construct at 00687 TODO bring these in line with Call etc */ 00688 struct Globality : Property { NODE_FUNCTIONS }; 00689 00690 /// Property indicating ::new/::delete was used 00691 struct Global : Globality { NODE_FUNCTIONS_FINAL }; 00692 00693 /// Property indicating just new/delete, no :: was used 00694 struct NonGlobal : Globality { NODE_FUNCTIONS_FINAL }; 00695 00696 /// Property indicating whether a delete should delete an array. 00697 /** Apologies for the tenuous grammar. */ 00698 struct DeleteArrayness : Property { NODE_FUNCTIONS }; 00699 00700 /// Property indicating delete[] was used 00701 struct DeleteArray : DeleteArrayness { NODE_FUNCTIONS_FINAL }; 00702 00703 /// Property indicating delete, no [] 00704 struct DeleteNonArray : DeleteArrayness { NODE_FUNCTIONS_FINAL }; 00705 00706 /// Node for the C++ new operator 00707 /** gives all the syntactical elements required for allocation and initialisation */ 00708 struct New : Operator 00709 { 00710 NODE_FUNCTIONS_FINAL 00711 TreePtr<Type> type; ///< Type of object to be constructed 00712 Sequence<Expression> placement_arguments; ///< arguments for placement usage 00713 Sequence<Expression> constructor_arguments; ///< arguments to the constructor 00714 TreePtr<Globality> global; ///< whether placement is global 00715 }; 00716 00717 /// Node for C++ delete operator 00718 struct Delete : Operator // TODO Statement surely? (clang forces it to be an Expression) 00719 { 00720 NODE_FUNCTIONS_FINAL 00721 TreePtr<Expression> pointer; ///< pointer to object to delete 00722 TreePtr<DeleteArrayness> array; ///< whether array delete 00723 TreePtr<Globality> global; ///< whether global placement 00724 }; 00725 00726 /// Node for accessing an element in a record as in base.member 00727 /** Note that the parser breaks down a->b into (*a).b which may 00728 be detected using a search pattern if desired. */ 00729 struct Lookup : Operator 00730 { 00731 NODE_FUNCTIONS_FINAL 00732 TreePtr<Expression> base; ///< the Record we look in 00733 TreePtr<InstanceIdentifier> member; ///< the member to find 00734 }; 00735 00736 /// Node for a c-style cast. 00737 // TODO C++ casts are not in here yet and C casts will be harmonised into whatever scheme I use for that. 00738 struct Cast : Operator 00739 { 00740 NODE_FUNCTIONS_FINAL 00741 TreePtr<Expression> operand; ///< the expression to cast 00742 TreePtr<Type> type; ///< the desired new type 00743 }; 00744 00745 /// Associates an Expression with an InstanceIdentifier. 00746 /** Basically a key-value pair of identifier and value. Use in Maps. */ 00747 struct MapOperand : virtual Node 00748 { 00749 NODE_FUNCTIONS_FINAL 00750 TreePtr<InstanceIdentifier> identifier; ///< the handle for this particualar operand 00751 TreePtr<Expression> value; ///< the Expression for this operand 00752 }; 00753 00754 /// An operator with operands whose order is established by mapping 00755 /** Maps a multiplicity of Instances to Expressions via their InstanceIdentifiers.*/ 00756 struct MapOperator : Operator 00757 { 00758 NODE_FUNCTIONS 00759 Collection<MapOperand> operands; ///< Operands whose relationship is established via identifiers 00760 }; 00761 00762 /// A function call to specified function passing in specified arguments 00763 /* Function is an expression to allow eg function pointer dereference. Normal 00764 calls have callee -> some InstanceIdentifier for a Callable Instance. 00765 Arguments passed via MapOperator - mapped to the parameters in the callee 00766 type (if it's a CallableParams). */ 00767 struct Call : MapOperator, Uncombable 00768 { 00769 NODE_FUNCTIONS_FINAL 00770 TreePtr<Expression> callee; ///< evaluates to the Callable Instance we must call 00771 }; 00772 00773 /// Initialiser for a record 00774 /** Uses a map to associate elements with corresponding record 00775 members. We also give the record type explicitly since the map is 00776 not enough information. */ 00777 struct MakeRecord : MapOperator 00778 { 00779 NODE_FUNCTIONS_FINAL 00780 TreePtr<TypeIdentifier> type; ///< handle of the type of the record we are making 00781 }; 00782 00783 /// Operator that operates on data types as parameters. 00784 /** Where either is allowed we use the type one, since it's more concise. */ 00785 struct TypeOperator : Operator 00786 { 00787 NODE_FUNCTIONS 00788 TreePtr<Type> operand; ///< This Type is an input operand 00789 }; 00790 00791 /// sizeof() a type 00792 struct SizeOf : TypeOperator { NODE_FUNCTIONS_FINAL }; 00793 00794 /// alignof() a type 00795 struct AlignOf : TypeOperator { NODE_FUNCTIONS_FINAL }; 00796 00797 //////////////////////////// Statements //////////////////////////// 00798 00799 /// A sequence of statements in a scope that shall execute in sequence 00800 /** Note that local declarations 00801 can go in the members of the Scope or in the statements (since Declaration 00802 derives from Statement). There is a sequence point between each statement. */ 00803 struct SequentialScope : Scope, 00804 virtual Statement 00805 { 00806 NODE_FUNCTIONS 00807 Sequence<Statement> statements; ///< Can contain local declarations and code 00808 }; 00809 00810 /// Declarations and Statements inside {} or begin/end. 00811 struct Compound : SequentialScope, ///< Local declarations go in here (preferably) 00812 Initialiser ///< Can "initialise" a function (with the body) 00813 { 00814 NODE_FUNCTIONS_FINAL 00815 }; 00816 00817 /// GCC extension for compound statements that return a value 00818 /** The returned value is that returned by the last statement if it 00819 is an expresison. Otherwise evaluates to void */ 00820 struct CompoundExpression : Expression, ///< Evaluates to whatever the last statement evaluates to 00821 SequentialScope ///< Local declarations go in here (preferably) 00822 { 00823 NODE_FUNCTIONS_FINAL 00824 }; 00825 00826 /// The return statement of a function 00827 /** return_value is an Expression giving the return value or 00828 Uninitialised if none is present. */ 00829 struct Return : Statement 00830 { 00831 NODE_FUNCTIONS_FINAL 00832 TreePtr<Initialiser> return_value; ///< return value or Uninitialised 00833 }; 00834 00835 /// A goto statement 00836 /** inferno tree supports goto-a-variable because 00837 it is expected to be useful during sequential lowering (state-out). 00838 Therefore we do not directly require LabelIdentifier, but the Expression 00839 must evaluate to one. No * or && needed. */ 00840 struct Goto : Statement, Uncombable 00841 { 00842 NODE_FUNCTIONS_FINAL 00843 // Dest is an expression for goto-a-variable support. 00844 // Ordinary gotos will have Label here. 00845 TreePtr<Expression> destination; ///< where to go to, expresison allowed 00846 }; 00847 00848 /// If statement 00849 struct If : Statement 00850 { 00851 NODE_FUNCTIONS_FINAL 00852 TreePtr<Expression> condition; ///< condition to test 00853 TreePtr<Statement> body; ///< executes when true 00854 TreePtr<Statement> else_body; ///< executes when false, can be Nop if no else clause 00855 }; 00856 00857 /// Designate a statement that may be broken out of 00858 /** A "break" statement jumps out of the innermost one of these 00859 and then execution commences immediately after this statement. 00860 We must specify a body here; the break statement will be 00861 within the body */ 00862 struct Breakable : Statement 00863 { 00864 NODE_FUNCTIONS 00865 TreePtr<Statement> body; ///< a break in here jumps to the end of here 00866 }; 00867 00868 /// Any loop. 00869 /** A "continue" statement jumps out of the innermost one of 00870 these and goes to the bottom of the body. So this is effectively 00871 "Continuable". Our body is inherited from Breakable. */ 00872 struct Loop : Breakable { NODE_FUNCTIONS }; 00873 00874 /// While loop 00875 struct While : Loop, Uncombable 00876 { 00877 NODE_FUNCTIONS_FINAL 00878 TreePtr<Expression> condition; ///< Tested before each iteration; false terminates immediately 00879 }; 00880 00881 /// Do loop (first iteration always runs) 00882 struct Do : Loop, Uncombable // a do..while() construct 00883 { 00884 NODE_FUNCTIONS_FINAL 00885 TreePtr<Expression> condition; ///< Tested after each iteration; false terminates immediately 00886 }; 00887 00888 /// C-style for loop. 00889 struct For : Loop 00890 { 00891 NODE_FUNCTIONS_FINAL 00892 TreePtr<Statement> initialisation; // Initialiser; use Nop if absent 00893 TreePtr<Expression> condition; // Condition; use True if absent 00894 TreePtr<Statement> increment; // Increment; use Nop if absent 00895 }; 00896 00897 /// Switch statement. 00898 /** Body (From Breakable) is just a statement scope - case labels 00899 and breaks are dropped into the sequence at the corresponding 00900 positions. This caters for fall-throughs etc. Really just a 00901 Compound with a goto-a-variable at the top and some mapping. */ 00902 struct Switch : Breakable 00903 { 00904 NODE_FUNCTIONS_FINAL 00905 TreePtr<Expression> condition; ///< Evaluates to a value whose case we'll jump to 00906 }; 00907 00908 /// Intermediate for labels in a switch statement. 00909 struct SwitchTarget : Statement { NODE_FUNCTIONS }; 00910 00911 /// Case label, supporting range extension in case useful for optimisation 00912 struct RangeCase : SwitchTarget 00913 { 00914 NODE_FUNCTIONS_FINAL 00915 // support gcc extension of case x..y: 00916 TreePtr<Expression> value_lo; ///< start of range, inclusive 00917 TreePtr<Expression> value_hi; ///< end of range, inclusive 00918 }; 00919 00920 /// Case label 00921 struct Case : SwitchTarget 00922 { 00923 NODE_FUNCTIONS_FINAL 00924 TreePtr<Expression> value; ///< Switch jumps here when condition is this value 00925 }; 00926 00927 /// Default label in a switch statement 00928 struct Default : SwitchTarget { NODE_FUNCTIONS_FINAL }; 00929 00930 /// Continue (to innermost Loop) 00931 struct Continue : Statement, Uncombable { NODE_FUNCTIONS_FINAL }; 00932 00933 /// Break (from innermost Breakable) 00934 struct Break : Statement { NODE_FUNCTIONS_FINAL }; 00935 00936 /// Do nothing; these get optimised out where possible 00937 struct Nop : Statement { NODE_FUNCTIONS_FINAL }; 00938 00939 }; // end namespace 00940 00941 #endif 00942