Changes in / [0188539c:8d26b7a]
- File:
-
- 1 edited
-
src/Tuples/TupleAssignment.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cpp
r0188539c r8d26b7a 241 241 ResolvExpr::CandidateFinder & crntFinder; 242 242 std::string fname; 243 std::unique_ptr< Matcher > matcher; 243 244 244 245 public: 245 246 TupleAssignSpotter( ResolvExpr::CandidateFinder & f ) 246 : crntFinder( f ), fname() {}247 248 // /Find left- and right-hand-sides for mass or multiple assignment.247 : crntFinder( f ), fname(), matcher() {} 248 249 // Find left- and right-hand-sides for mass or multiple assignment. 249 250 void spot( 250 251 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 251 ); 252 /// Wrapper around matcher.match. 253 void match( Matcher & matcher ); 252 ) { 253 if ( auto op = expr->func.as< ast::NameExpr >() ) { 254 // Skip non-assignment functions. 255 if ( !CodeGen::isCtorDtorAssign( op->name ) ) return; 256 fname = op->name; 257 258 // Handled by CandidateFinder if applicable (both odd cases). 259 if ( args.empty() || ( 1 == args.size() && CodeGen::isAssignment( fname ) ) ) { 260 return; 261 } 262 263 // Look over all possible left-hand-side. 264 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) { 265 // Skip non-tuple LHS. 266 if ( !refToTuple( lhsCand->expr ) ) continue; 267 268 // Explode is aware of casts - ensure every LHS 269 // is sent into explode with a reference cast. 270 if ( !lhsCand->expr.as< ast::CastExpr >() ) { 271 lhsCand->expr = new ast::CastExpr( 272 lhsCand->expr, new ast::ReferenceType( lhsCand->expr->result ) ); 273 } 274 275 // Explode the LHS so that each field of a tuple-valued expr is assigned. 276 ResolvExpr::CandidateList lhs; 277 explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true ); 278 for ( ResolvExpr::CandidateRef & cand : lhs ) { 279 // Each LHS value must be a reference - some come in 280 // with a cast, if not just cast to reference here. 281 if ( !cand->expr->result.as< ast::ReferenceType >() ) { 282 cand->expr = new ast::CastExpr( 283 cand->expr, new ast::ReferenceType( cand->expr->result ) ); 284 } 285 } 286 287 if ( 1 == args.size() ) { 288 // Mass default-initialization/destruction. 289 ResolvExpr::CandidateList rhs{}; 290 matcher.reset( new MassAssignMatcher( *this, expr->location, lhs, rhs ) ); 291 match(); 292 } else if ( 2 == args.size() ) { 293 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) { 294 ResolvExpr::CandidateList rhs; 295 if ( isTuple( rhsCand->expr ) ) { 296 // Multiple assignment: 297 explode( *rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true ); 298 matcher.reset( 299 new MultipleAssignMatcher( *this, expr->location, lhs, rhs ) ); 300 } else { 301 // Mass assignment: 302 rhs.emplace_back( rhsCand ); 303 matcher.reset( 304 new MassAssignMatcher( *this, expr->location, lhs, rhs ) ); 305 } 306 match(); 307 } 308 } else { 309 // Expand all possible RHS possibilities. 310 std::vector< ResolvExpr::CandidateList > rhsCands; 311 combos( 312 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) ); 313 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) { 314 // Multiple assignment: 315 ResolvExpr::CandidateList rhs; 316 explode( rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true ); 317 matcher.reset( 318 new MultipleAssignMatcher( *this, expr->location, lhs, rhs ) ); 319 match(); 320 } 321 } 322 } 323 } 324 } 325 326 void match() { 327 assert( matcher ); 328 329 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match(); 330 331 if ( !( matcher->lhs.empty() && matcher->rhs.empty() ) ) { 332 // If both LHS and RHS are empty than this is the empty tuple 333 // case, wherein it's okay for newAssigns to be empty. Otherwise, 334 // return early so that no new candidates are generated. 335 if ( newAssigns.empty() ) return; 336 } 337 338 ResolvExpr::CandidateList crnt; 339 // Now resolve new assignments. 340 for ( const ast::Expr * expr : newAssigns ) { 341 PRINT( 342 std::cerr << "== resolving tuple assign ==" << std::endl; 343 std::cerr << expr << std::endl; 344 ) 345 346 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env ); 347 finder.allowVoid = true; 348 349 try { 350 finder.find( expr, ResolvExpr::ResolveMode::withAdjustment() ); 351 } catch (...) { 352 // No match is not failure, just that this tuple assignment is invalid. 353 return; 354 } 355 356 ResolvExpr::CandidateList & cands = finder.candidates; 357 assert( 1 == cands.size() ); 358 assert( cands.front()->expr ); 359 crnt.emplace_back( std::move( cands.front() ) ); 360 } 361 362 // extract expressions from the assignment candidates to produce a list of assignments 363 // that together form a sigle candidate 364 std::vector< ast::ptr< ast::Expr > > solved; 365 for ( ResolvExpr::CandidateRef & cand : crnt ) { 366 solved.emplace_back( cand->expr ); 367 matcher->combineState( *cand ); 368 } 369 370 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >( 371 new ast::TupleAssignExpr( 372 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) ), 373 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 374 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) ); 375 } 254 376 }; 255 256 void TupleAssignSpotter::spot(257 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args258 ) {259 // Skip non-"assignment" functions.260 auto op = expr->func.as< ast::NameExpr >();261 if ( nullptr == op || !CodeGen::isCtorDtorAssign( op->name ) ) return;262 263 // Handled by CandidateFinder if applicable (both odd cases).264 if ( args.empty() || ( 1 == args.size() && CodeGen::isAssignment( op->name ) ) ) {265 return;266 }267 268 fname = op->name;269 270 // Look over all possible left-hand-side.271 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) {272 // Skip non-tuple LHS.273 if ( !refToTuple( lhsCand->expr ) ) continue;274 275 // Explode is aware of casts - ensure every LHS276 // is sent into explode with a reference cast.277 if ( !lhsCand->expr.as< ast::CastExpr >() ) {278 lhsCand->expr = new ast::CastExpr(279 lhsCand->expr, new ast::ReferenceType( lhsCand->expr->result ) );280 }281 282 // Explode the LHS so that each field of a tuple-valued expr is assigned.283 ResolvExpr::CandidateList lhs;284 explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );285 for ( ResolvExpr::CandidateRef & cand : lhs ) {286 // Each LHS value must be a reference - some come in287 // with a cast, if not just cast to reference here.288 if ( !cand->expr->result.as< ast::ReferenceType >() ) {289 cand->expr = new ast::CastExpr(290 cand->expr, new ast::ReferenceType( cand->expr->result ) );291 }292 }293 294 if ( 1 == args.size() ) {295 // Mass default-initialization/destruction.296 ResolvExpr::CandidateList rhs{};297 MassAssignMatcher matcher( *this, expr->location, lhs, rhs );298 match( matcher );299 } else if ( 2 == args.size() ) {300 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) {301 ResolvExpr::CandidateList rhs;302 if ( isTuple( rhsCand->expr ) ) {303 // Multiple assignment:304 explode( *rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );305 MultipleAssignMatcher matcher( *this, expr->location, lhs, rhs );306 match( matcher );307 } else {308 // Mass assignment:309 rhs.emplace_back( rhsCand );310 MassAssignMatcher matcher( *this, expr->location, lhs, rhs );311 match( matcher );312 }313 }314 } else {315 // Expand all possible RHS possibilities.316 std::vector< ResolvExpr::CandidateList > rhsCands;317 combos(318 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );319 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {320 // Multiple assignment:321 ResolvExpr::CandidateList rhs;322 explode( rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );323 MultipleAssignMatcher matcher( *this, expr->location, lhs, rhs );324 match( matcher );325 }326 }327 }328 }329 330 void TupleAssignSpotter::match( TupleAssignSpotter::Matcher & matcher ) {331 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher.match();332 333 if ( !( matcher.lhs.empty() && matcher.rhs.empty() ) ) {334 // If both LHS and RHS are empty than this is the empty tuple335 // case, wherein it's okay for newAssigns to be empty. Otherwise,336 // return early so that no new candidates are generated.337 if ( newAssigns.empty() ) return;338 }339 340 ResolvExpr::CandidateList crnt;341 // Now resolve new assignments.342 for ( const ast::Expr * expr : newAssigns ) {343 PRINT(344 std::cerr << "== resolving tuple assign ==" << std::endl;345 std::cerr << expr << std::endl;346 )347 348 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher.env );349 finder.allowVoid = true;350 351 try {352 finder.find( expr, ResolvExpr::ResolveMode::withAdjustment() );353 } catch (...) {354 // No match is not failure, just that this tuple assignment is invalid.355 return;356 }357 358 ResolvExpr::CandidateList & cands = finder.candidates;359 assert( 1 == cands.size() );360 assert( cands.front()->expr );361 crnt.emplace_back( std::move( cands.front() ) );362 }363 364 // extract expressions from the assignment candidates to produce a list of assignments365 // that together form a sigle candidate366 std::vector< ast::ptr< ast::Expr > > solved;367 for ( ResolvExpr::CandidateRef & cand : crnt ) {368 solved.emplace_back( cand->expr );369 matcher.combineState( *cand );370 }371 372 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(373 new ast::TupleAssignExpr(374 matcher.location, std::move( solved ), std::move( matcher.tmpDecls ) ),375 std::move( matcher.env ), std::move( matcher.open ), std::move( matcher.need ),376 ResolvExpr::sumCost( crnt ) + matcher.baseCost ) );377 }378 377 379 378 } // anonymous namespace
Note:
See TracChangeset
for help on using the changeset viewer.