Changeset e67a82d for src/AST/Expr.hpp
- Timestamp:
- Aug 20, 2020, 11:48:15 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- d685cb0
- Parents:
- 67ca73e (diff), 013b028 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.hpp
r67ca73e re67a82d 31 31 32 32 // Must be included in *all* AST classes; should be #undef'd at the end of the file 33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 33 #define MUTATE_FRIEND \ 34 template<typename node_t> friend node_t * mutate(const node_t * node); \ 35 template<typename node_t> friend node_t * shallowCopy(const node_t * node); 36 34 37 35 38 class ConverterOldToNew; … … 42 45 struct ParamEntry { 43 46 UniqueId decl; 44 ptr<Decl> declptr;47 readonly<Decl> declptr; 45 48 ptr<Type> actualType; 46 49 ptr<Type> formalType; … … 62 65 class Expr : public ParseNode { 63 66 public: 64 /// Saves space (~16 bytes) by combining ResnSlots and InferredParams 67 /* 68 * NOTE: the union approach is incorrect until the case of 69 * partial resolution in InferMatcher is eliminated. 70 * it is reverted to allow unresolved and resolved parameters 71 * to coexist in an expression node. 72 */ 65 73 struct InferUnion { 74 // mode is now unused 66 75 enum { Empty, Slots, Params } mode; 67 union data_t { 68 char def; 69 ResnSlots resnSlots; 70 InferredParams inferParams; 71 72 data_t() : def('\0') {} 73 ~data_t() {} 76 struct data_t { 77 // char def; 78 ResnSlots * resnSlots; 79 InferredParams * inferParams; 80 81 data_t(): resnSlots(nullptr), inferParams(nullptr) {} 82 data_t(const data_t &other) = delete; 83 ~data_t() { 84 delete resnSlots; 85 delete inferParams; 86 } 74 87 } data; 75 88 76 89 /// initializes from other InferUnion 77 90 void init_from( const InferUnion& o ) { 78 switch ( o.mode ) { 79 case Empty: return; 80 case Slots: new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return; 81 case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return; 91 if (o.data.resnSlots) { 92 data.resnSlots = new ResnSlots(*o.data.resnSlots); 93 } 94 if (o.data.inferParams) { 95 data.inferParams = new InferredParams(*o.data.inferParams); 82 96 } 83 97 } … … 85 99 /// initializes from other InferUnion (move semantics) 86 100 void init_from( InferUnion&& o ) { 87 switch ( o.mode ) { 88 case Empty: return; 89 case Slots: new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return; 90 case Params: 91 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return; 92 } 93 } 94 95 /// clears variant fields 96 void reset() { 97 switch( mode ) { 98 case Empty: return; 99 case Slots: data.resnSlots.~ResnSlots(); return; 100 case Params: data.inferParams.~InferredParams(); return; 101 } 101 data.resnSlots = o.data.resnSlots; 102 data.inferParams = o.data.inferParams; 103 o.data.resnSlots = nullptr; 104 o.data.inferParams = nullptr; 102 105 } 103 106 … … 107 110 InferUnion& operator= ( const InferUnion& ) = delete; 108 111 InferUnion& operator= ( InferUnion&& ) = delete; 109 ~InferUnion() { reset(); } 112 113 bool hasSlots() const { return data.resnSlots; } 110 114 111 115 ResnSlots& resnSlots() { 112 switch (mode) { 113 case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough 114 case Slots: return data.resnSlots; 115 case Params: assertf(false, "Cannot return to resnSlots from Params"); abort(); 116 if (!data.resnSlots) { 117 data.resnSlots = new ResnSlots(); 116 118 } 117 assertf(false, "unreachable");119 return *data.resnSlots; 118 120 } 119 121 120 122 const ResnSlots& resnSlots() const { 121 if ( mode ==Slots) {122 return data.resnSlots;123 if (data.resnSlots) { 124 return *data.resnSlots; 123 125 } 124 126 assertf(false, "Mode was not already resnSlots"); … … 127 129 128 130 InferredParams& inferParams() { 129 switch (mode) { 130 case Slots: data.resnSlots.~ResnSlots(); // fallthrough 131 case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough 132 case Params: return data.inferParams; 131 if (!data.inferParams) { 132 data.inferParams = new InferredParams(); 133 133 } 134 assertf(false, "unreachable");134 return *data.inferParams; 135 135 } 136 136 137 137 const InferredParams& inferParams() const { 138 if ( mode ==Params) {139 return data.inferParams;138 if (data.inferParams) { 139 return *data.inferParams; 140 140 } 141 141 assertf(false, "Mode was not already Params"); … … 143 143 } 144 144 145 void set_inferParams( InferredParams && ps ) { 146 switch(mode) { 147 case Slots: 148 data.resnSlots.~ResnSlots(); 149 // fallthrough 150 case Empty: 151 new(&data.inferParams) InferredParams{ std::move( ps ) }; 152 mode = Params; 153 break; 154 case Params: 155 data.inferParams = std::move( ps ); 156 break; 157 } 145 void set_inferParams( InferredParams * ps ) { 146 delete data.resnSlots; 147 data.resnSlots = nullptr; 148 delete data.inferParams; 149 data.inferParams = ps; 158 150 } 159 151 … … 161 153 /// and the other is in `Params`. 162 154 void splice( InferUnion && o ) { 163 if ( o.mode == Empty ) return; 164 if ( mode == Empty ) { init_from( o ); return; } 165 assert( mode == o.mode && "attempt to splice incompatible InferUnion" ); 166 167 if ( mode == Slots ){ 168 data.resnSlots.insert( 169 data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() ); 170 } else if ( mode == Params ) { 171 for ( const auto & p : o.data.inferParams ) { 172 data.inferParams[p.first] = std::move(p.second); 155 if (o.data.resnSlots) { 156 if (data.resnSlots) { 157 data.resnSlots->insert( 158 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() ); 159 delete o.data.resnSlots; 173 160 } 174 } else assertf(false, "invalid mode"); 161 else { 162 data.resnSlots = o.data.resnSlots; 163 } 164 o.data.resnSlots = nullptr; 165 } 166 167 if (o.data.inferParams) { 168 if (data.inferParams) { 169 for ( const auto & p : *o.data.inferParams ) { 170 (*data.inferParams)[p.first] = std::move(p.second); 171 } 172 delete o.data.inferParams; 173 } 174 else { 175 data.inferParams = o.data.inferParams; 176 } 177 o.data.inferParams = nullptr; 178 } 175 179 } 176 180 }; … … 185 189 186 190 Expr * set_extension( bool ex ) { extension = ex; return this; } 191 virtual bool get_lvalue() const; 187 192 188 193 virtual const Expr * accept( Visitor & v ) const override = 0; … … 201 206 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 202 207 208 bool get_lvalue() const final; 209 203 210 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 204 211 private: … … 215 222 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ) 216 223 : Expr( loc ), func( f ), args( std::move(as) ) {} 224 225 bool get_lvalue() const final; 217 226 218 227 /// Creates a new dereference expression … … 291 300 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 292 301 302 bool get_lvalue() const final; 303 293 304 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 294 305 private: … … 338 349 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 339 350 351 bool get_lvalue() const final; 352 340 353 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 341 354 private: … … 352 365 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 353 366 367 bool get_lvalue() const final; 368 354 369 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 355 370 private: 356 371 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 357 372 MUTATE_FRIEND 373 374 // Custructor overload meant only for AST conversion 375 enum NoOpConstruction { NoOpConstructionChosen }; 376 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 377 NoOpConstruction overloadSelector ); 378 friend class ::ConverterOldToNew; 379 friend class ::ConverterNewToOld; 358 380 }; 359 381 … … 365 387 VariableExpr( const CodeLocation & loc ); 366 388 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 389 390 bool get_lvalue() const final; 367 391 368 392 /// generates a function pointer for a given function … … 532 556 533 557 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 558 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 559 this->result = a2->result; 560 } 561 562 bool get_lvalue() const final; 535 563 536 564 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 605 633 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 606 634 635 bool get_lvalue() const final; 636 607 637 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 608 638 private: … … 660 690 661 691 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 692 693 bool get_lvalue() const final; 662 694 663 695 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
Note:
See TracChangeset
for help on using the changeset viewer.