Changeset 58fe85a for src/AST/Expr.hpp
- Timestamp:
- Jan 7, 2021, 3:27:00 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:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (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
r3c64c668 r58fe85a 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; } 114 bool hasParams() const { return data.inferParams; } 110 115 111 116 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(); 117 if (!data.resnSlots) { 118 data.resnSlots = new ResnSlots(); 116 119 } 117 assertf(false, "unreachable");120 return *data.resnSlots; 118 121 } 119 122 120 123 const ResnSlots& resnSlots() const { 121 if ( mode ==Slots) {122 return data.resnSlots;124 if (data.resnSlots) { 125 return *data.resnSlots; 123 126 } 124 127 assertf(false, "Mode was not already resnSlots"); … … 127 130 128 131 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; 132 if (!data.inferParams) { 133 data.inferParams = new InferredParams(); 133 134 } 134 assertf(false, "unreachable");135 return *data.inferParams; 135 136 } 136 137 137 138 const InferredParams& inferParams() const { 138 if ( mode ==Params) {139 return data.inferParams;139 if (data.inferParams) { 140 return *data.inferParams; 140 141 } 141 142 assertf(false, "Mode was not already Params"); … … 143 144 } 144 145 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 } 146 void set_inferParams( InferredParams * ps ) { 147 delete data.resnSlots; 148 data.resnSlots = nullptr; 149 delete data.inferParams; 150 data.inferParams = ps; 158 151 } 159 152 … … 161 154 /// and the other is in `Params`. 162 155 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); 156 if (o.data.resnSlots) { 157 if (data.resnSlots) { 158 data.resnSlots->insert( 159 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() ); 160 delete o.data.resnSlots; 173 161 } 174 } else assertf(false, "invalid mode"); 162 else { 163 data.resnSlots = o.data.resnSlots; 164 } 165 o.data.resnSlots = nullptr; 166 } 167 168 if (o.data.inferParams) { 169 if (data.inferParams) { 170 for ( const auto & p : *o.data.inferParams ) { 171 (*data.inferParams)[p.first] = std::move(p.second); 172 } 173 delete o.data.inferParams; 174 } 175 else { 176 data.inferParams = o.data.inferParams; 177 } 178 o.data.inferParams = nullptr; 179 } 175 180 } 176 181 }; … … 185 190 186 191 Expr * set_extension( bool ex ) { extension = ex; return this; } 192 virtual bool get_lvalue() const; 187 193 188 194 virtual const Expr * accept( Visitor & v ) const override = 0; … … 201 207 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 202 208 209 bool get_lvalue() const final; 210 203 211 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 204 212 private: … … 216 224 : Expr( loc ), func( f ), args( std::move(as) ) {} 217 225 226 bool get_lvalue() const final; 227 218 228 /// Creates a new dereference expression 219 static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );229 static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg ); 220 230 /// Creates a new assignment expression 221 static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs,Expr * rhs );231 static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ); 222 232 223 233 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 241 251 }; 242 252 253 /// A reference to a named variable. 254 class VariableExpr final : public Expr { 255 public: 256 readonly<DeclWithType> var; 257 258 VariableExpr( const CodeLocation & loc ); 259 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 260 261 bool get_lvalue() const final; 262 263 /// generates a function pointer for a given function 264 static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl ); 265 266 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 267 private: 268 VariableExpr * clone() const override { return new VariableExpr{ *this }; } 269 MUTATE_FRIEND 270 }; 271 243 272 /// Address-of expression `&e` 244 273 class AddressExpr final : public Expr { … … 271 300 }; 272 301 273 /// Whether a cast existed in the program source or not 302 /// Inidicates whether the cast is introduced by the CFA type system. 303 /// GeneratedCast for casts that the resolver introduces to force a return type 304 /// ExplicitCast for casts from user code 305 /// ExplicitCast for casts from desugaring advanced CFA features into simpler CFA 306 /// example 307 /// int * p; // declaration 308 /// (float *) p; // use, with subject cast 309 /// subject cast being GeneratedCast means we are considering an interpretation with a type mismatch 310 /// subject cast being ExplicitCast means someone in charge wants it that way 274 311 enum GeneratedFlag { ExplicitCast, GeneratedCast }; 275 312 … … 291 328 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 292 329 330 bool get_lvalue() const final; 331 293 332 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 294 333 private: … … 301 340 public: 302 341 ptr<Expr> arg; 342 struct Concrete { 343 std::string field; 344 std::string getter; 345 346 Concrete() = default; 347 Concrete(const Concrete &) = default; 348 }; 303 349 ast::AggregateDecl::Aggregate target; 350 Concrete concrete_target; 351 304 352 305 353 KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t ) 306 354 : Expr( loc ), arg( a ), target( t ) {} 307 355 356 KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t, const Concrete & ct ) 357 : Expr( loc ), arg( a ), target( t ), concrete_target( ct ) {} 358 308 359 /// Get a name for the target type 309 360 const char * targetString() const; … … 338 389 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 339 390 391 bool get_lvalue() const final; 392 340 393 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 341 394 private: … … 352 405 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 353 406 407 bool get_lvalue() const final; 408 354 409 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 355 410 private: 356 411 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 357 412 MUTATE_FRIEND 358 }; 359 360 /// A reference to a named variable. 361 class VariableExpr final : public Expr { 362 public: 363 readonly<DeclWithType> var; 364 365 VariableExpr( const CodeLocation & loc ); 366 VariableExpr( const CodeLocation & loc, const DeclWithType * v ); 367 368 /// generates a function pointer for a given function 369 static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl ); 370 371 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 372 private: 373 VariableExpr * clone() const override { return new VariableExpr{ *this }; } 374 MUTATE_FRIEND 413 414 // Custructor overload meant only for AST conversion 415 enum NoOpConstruction { NoOpConstructionChosen }; 416 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg, 417 NoOpConstruction overloadSelector ); 418 friend class ::ConverterOldToNew; 419 friend class ::ConverterNewToOld; 375 420 }; 376 421 … … 386 431 const CodeLocation & loc, const Type * ty, const std::string & r, 387 432 std::optional<unsigned long long> i ) 388 : Expr( loc, ty ), rep( r ), ival( i ) {}433 : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {} 389 434 390 435 /// Gets the integer value of this constant, if one is appropriate to its type. … … 532 577 533 578 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 579 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 580 this->result = a2->result; 581 } 582 583 bool get_lvalue() const final; 535 584 536 585 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 577 626 578 627 ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call ) 579 : Expr( loc, call->result ) { assert( call); }628 : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); } 580 629 581 630 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 605 654 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 606 655 656 bool get_lvalue() const final; 657 607 658 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 608 659 private: … … 660 711 661 712 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 713 714 bool get_lvalue() const final; 662 715 663 716 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 698 751 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s) 699 752 753 readonly<ExprStmt> resultExpr; 754 700 755 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss ); 701 756
Note:
See TracChangeset
for help on using the changeset viewer.