Changes in src/AST/Expr.hpp [b3a0df6:312029a]
- File:
-
- 1 edited
-
src/AST/Expr.hpp (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.hpp
rb3a0df6 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; } 114 bool hasParams() const { return data.inferParams; } 109 ~InferUnion() { reset(); } 115 110 116 111 ResnSlots& resnSlots() { 117 if (!data.resnSlots) { 118 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(); 119 116 } 120 return *data.resnSlots;117 assertf(false, "unreachable"); 121 118 } 122 119 123 120 const ResnSlots& resnSlots() const { 124 if ( data.resnSlots) {125 return *data.resnSlots;121 if (mode == Slots) { 122 return data.resnSlots; 126 123 } 127 124 assertf(false, "Mode was not already resnSlots"); … … 130 127 131 128 InferredParams& inferParams() { 132 if (!data.inferParams) { 133 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; 134 133 } 135 return *data.inferParams;134 assertf(false, "unreachable"); 136 135 } 137 136 138 137 const InferredParams& inferParams() const { 139 if ( data.inferParams) {140 return *data.inferParams;138 if (mode == Params) { 139 return data.inferParams; 141 140 } 142 141 assertf(false, "Mode was not already Params"); … … 144 143 } 145 144 146 void set_inferParams( InferredParams * ps ) { 147 delete data.resnSlots; 148 data.resnSlots = nullptr; 149 delete data.inferParams; 150 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 } 151 158 } 152 159 … … 154 161 /// and the other is in `Params`. 155 162 void splice( InferUnion && o ) { 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; 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); 161 173 } 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 } 174 } else assertf(false, "invalid mode"); 180 175 } 181 176 }; … … 190 185 191 186 Expr * set_extension( bool ex ) { extension = ex; return this; } 192 virtual bool get_lvalue() const;193 187 194 188 virtual const Expr * accept( Visitor & v ) const override = 0; … … 207 201 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} ); 208 202 209 bool get_lvalue() const final;210 211 203 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 212 204 private: … … 224 216 : Expr( loc ), func( f ), args( std::move(as) ) {} 225 217 226 bool get_lvalue() const final;227 228 218 /// Creates a new dereference expression 229 static UntypedExpr * createDeref( const CodeLocation & loc, constExpr * arg );219 static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg ); 230 220 /// Creates a new assignment expression 231 static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, constExpr * rhs );221 static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ); 232 222 233 223 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 251 241 }; 252 242 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 function264 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_FRIEND270 };271 272 243 /// Address-of expression `&e` 273 244 class AddressExpr final : public Expr { … … 300 271 }; 301 272 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 273 /// Whether a cast existed in the program source or not 311 274 enum GeneratedFlag { ExplicitCast, GeneratedCast }; 312 275 … … 328 291 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 329 292 330 bool get_lvalue() const final;331 332 293 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 333 294 private: … … 340 301 public: 341 302 ptr<Expr> arg; 342 struct Concrete {343 std::string field;344 std::string getter;345 346 Concrete() = default;347 Concrete(const Concrete &) = default;348 };349 303 ast::AggregateDecl::Aggregate target; 350 Concrete concrete_target;351 352 304 353 305 KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t ) 354 306 : Expr( loc ), arg( a ), target( t ) {} 355 307 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 359 308 /// Get a name for the target type 360 309 const char * targetString() const; … … 389 338 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); } 390 339 391 bool get_lvalue() const final;392 393 340 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 394 341 private: … … 405 352 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg ); 406 353 407 bool get_lvalue() const final;408 409 354 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 410 355 private: 411 356 MemberExpr * clone() const override { return new MemberExpr{ *this }; } 412 357 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; 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 420 375 }; 421 376 … … 431 386 const CodeLocation & loc, const Type * ty, const std::string & r, 432 387 std::optional<unsigned long long> i ) 433 : Expr( loc, ty ), rep( r ), ival( i ) , underlyer(ty){}388 : Expr( loc, ty ), rep( r ), ival( i ) {} 434 389 435 390 /// Gets the integer value of this constant, if one is appropriate to its type. … … 577 532 578 533 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 579 : Expr( loc ), arg1( a1 ), arg2( a2 ) { 580 this->result = a2->result; 581 } 582 583 bool get_lvalue() const final; 534 : Expr( loc ), arg1( a1 ), arg2( a2 ) {} 584 535 585 536 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 626 577 627 578 ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call ) 628 : Expr( loc, call->result ) , callExpr(call) { assert( call ); assert(call->result); }579 : Expr( loc, call->result ) { assert( call ); } 629 580 630 581 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 654 605 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i ); 655 606 656 bool get_lvalue() const final;657 658 607 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 659 608 private: … … 711 660 712 661 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i ); 713 714 bool get_lvalue() const final;715 662 716 663 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } … … 751 698 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s) 752 699 753 readonly<ExprStmt> resultExpr;754 755 700 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss ); 756 701
Note:
See TracChangeset
for help on using the changeset viewer.