Changes in src/AST/Expr.hpp [07d867b:312029a]
- File:
-
- 1 edited
-
src/AST/Expr.hpp (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.hpp
r07d867b r312029a 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 \ 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 33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node); 37 34 38 35 class ConverterOldToNew; … … 45 42 struct ParamEntry { 46 43 UniqueId decl; 47 readonly<Decl> declptr;44 ptr<Decl> declptr; 48 45 ptr<Type> actualType; 49 46 ptr<Type> formalType; … … 65 62 class Expr : public ParseNode { 66 63 public: 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 */ 64 /// Saves space (~16 bytes) by combining ResnSlots and InferredParams 73 65 struct InferUnion { 74 // mode is now unused75 66 enum { Empty, Slots, Params } mode; 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 } 67 union data_t { 68 char def; 69 ResnSlots resnSlots; 70 InferredParams inferParams; 71 72 data_t() : def('\0') {} 73 ~data_t() {} 87 74 } data; 88 75 89 76 /// initializes from other InferUnion 90 77 void init_from( const InferUnion& o ) { 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); 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; 96 82 } 97 83 } … … 99 85 /// initializes from other InferUnion (move semantics) 100 86 void init_from( InferUnion&& o ) { 101 data.resnSlots = o.data.resnSlots; 102 data.inferParams = o.data.inferParams; 103 o.data.resnSlots = nullptr; 104 o.data.inferParams = nullptr; 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 } 105 102 } 106 103 … … 110 107 InferUnion& operator= ( const InferUnion& ) = delete; 111 108 InferUnion& operator= ( InferUnion&& ) = delete; 112 113 bool hasSlots() const { return data.resnSlots; } 109 ~InferUnion() { reset(); } 114 110 115 111 ResnSlots& resnSlots() { 116 if (!data.resnSlots) { 117 data.resnSlots = new 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(); 118 116 } 119 return *data.resnSlots;117 assertf(false, "unreachable"); 120 118 } 121 119 122 120 const ResnSlots& resnSlots() const { 123 if ( data.resnSlots) {124 return *data.resnSlots;121 if (mode == Slots) { 122 return data.resnSlots; 125 123 } 126 124 assertf(false, "Mode was not already resnSlots"); … … 129 127 130 128 InferredParams& inferParams() { 131 if (!data.inferParams) { 132 data.inferParams = new InferredParams(); 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; 133 133 } 134 return *data.inferParams;134 assertf(false, "unreachable"); 135 135 } 136 136 137 137 const InferredParams& inferParams() const { 138 if ( data.inferParams) {139 return *data.inferParams;138 if (mode == Params) { 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 delete data.resnSlots; 147 data.resnSlots = nullptr; 148 delete data.inferParams; 149 data.inferParams = ps; 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 } 150 158 } 151 159 … … 153 161 /// and the other is in `Params`. 154 162 void splice( InferUnion && o ) { 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; 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); 160 173 } 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 } 174 } else assertf(false, "invalid mode"); 179 175 } 180 176 }; … … 189 185 190 186 Expr * set_extension( bool ex ) { extension = ex; return this; } 191 virtual bool get_lvalue() const;192 187 193 188 virtual const Expr * accept( Visitor & v ) const override = 0; … … 206 201 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 207 202 208 bool get_lvalue() const final;209 210 203 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 211 204 private: … … 222 215 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ) 223 216 : Expr( loc ), func( f ), args( std::move(as) ) {} 224 225 bool get_lvalue() const final;226 217 227 218 /// Creates a new dereference expression … … 300 291 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 301 292 302 bool get_lvalue() const final;303 304 293 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 305 294 private: … … 349 338 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 350 339 351 bool get_lvalue() const final;352 353 340 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 354 341 private: … … 365 352 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 366 353 367 bool get_lvalue() const final;368 369 354 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 370 355 private: 371 356 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 372 357 MUTATE_FRIEND 373 374 // Custructor overload meant only for AST conversion375 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;380 358 }; 381 359 … … 387 365 VariableExpr( const CodeLocation & loc ); 388 366 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 389 390 bool get_lvalue() const final;391 367 392 368 /// generates a function pointer for a given function … … 556 532 557 533 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 558 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 559 this->result = a2->result; 560 } 561 562 bool get_lvalue() const final; 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 563 535 564 536 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 633 605 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 634 606 635 bool get_lvalue() const final;636 637 607 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 638 608 private: … … 690 660 691 661 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 692 693 bool get_lvalue() const final;694 662 695 663 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
Note:
See TracChangeset
for help on using the changeset viewer.