- Timestamp:
- Jun 20, 2019, 2:32:55 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b8524ca, f5edcb4
- Parents:
- c0f9efe
- Location:
- src
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Init.hpp
rc0f9efe r234b1cb 55 55 ConstructFlag maybeConstructed; 56 56 57 Init( const CodeLocation & loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}57 Init( const CodeLocation & loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {} 58 58 59 const Init * accept( Visitor & v ) const override = 0;59 const Init * accept( Visitor & v ) const override = 0; 60 60 private: 61 61 Init * clone() const override = 0; … … 69 69 ptr<Expr> value; 70 70 71 SingleInit( const CodeLocation & loc, Expr* val, ConstructFlag mc = DoConstruct )71 SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = DoConstruct ) 72 72 : Init( loc, mc ), value( val ) {} 73 73 … … 87 87 std::vector<ptr<Designation>> designations; 88 88 89 ListInit( const CodeLocation & loc, std::vector<ptr<Init>>&& is,90 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct );89 ListInit( const CodeLocation & loc, std::vector<ptr<Init>> && is, 90 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct ); 91 91 92 92 using iterator = std::vector<ptr<Init>>::iterator; … … 114 114 ptr<Init> init; 115 115 116 ConstructorInit( const CodeLocation& loc, Stmt* ctor, Stmt* dtor, Init* init ) 116 ConstructorInit( 117 const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init ) 117 118 : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {} 118 119 -
src/Common/utility.h
rc0f9efe r234b1cb 16 16 #pragma once 17 17 18 #include <cassert> 18 19 #include <cctype> 19 20 #include <algorithm> … … 27 28 #include <type_traits> 28 29 #include <utility> 29 30 #include <cassert> 30 #include <vector> 31 31 32 32 #include "Common/Indenter.h" … … 145 145 return ret; 146 146 } // switch 147 } 148 149 /// Splice src onto the end of dst, clearing src 150 template< typename T > 151 void splice( std::vector< T > & dst, std::vector< T > & src ) { 152 dst.reserve( dst.size() + src.size() ); 153 for ( T & x : src ) { dst.emplace_back( std::move( x ) ); } 154 src.clear(); 155 } 156 157 /// Splice src onto the begining of dst, clearing src 158 template< typename T > 159 void spliceBegin( std::vector< T > & dst, std::vector< T > & src ) { 160 splice( src, dst ); 161 dst.swap( src ); 147 162 } 148 163 -
src/InitTweak/GenInit.cc
rc0f9efe r234b1cb 353 353 GuardScope( managedTypes ); 354 354 } 355 356 ast::ConstructorInit * genCtorInit( const ast::ObjectDecl * objDecl ) { 357 #warning unimplemented 358 (void)objDecl; 359 assert( false ); 360 return nullptr; 361 } 362 355 363 } // namespace InitTweak 356 364 -
src/InitTweak/GenInit.h
rc0f9efe r234b1cb 19 19 #include <string> // for string 20 20 21 #include "AST/Fwd.hpp" 22 #include "GenPoly/ScopedSet.h" // for ScopedSet 21 23 #include "SynTree/SynTree.h" // for Visitor Nodes 22 23 #include "GenPoly/ScopedSet.h" // for ScopedSet24 24 25 25 namespace InitTweak { … … 35 35 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer 36 36 ConstructorInit * genCtorInit( ObjectDecl * objDecl ); 37 ast::ConstructorInit * genCtorInit( const ast::ObjectDecl * objDecl ); 37 38 38 39 class ManagedTypes { -
src/ResolvExpr/Alternative.cc
rc0f9efe r234b1cb 125 125 } 126 126 127 void splice( AltList& dst, AltList& src ) {128 dst.reserve( dst.size() + src.size() );129 for ( Alternative& alt : src ) {130 dst.push_back( std::move(alt) );131 }132 src.clear();133 }134 135 void spliceBegin( AltList& dst, AltList& src ) {136 splice( src, dst );137 dst.swap( src );138 }139 140 127 } // namespace ResolvExpr 141 128 -
src/ResolvExpr/Alternative.h
rc0f9efe r234b1cb 112 112 typedef std::vector< Alternative > AltList; 113 113 114 /// Moves all elements from src to the end of dst115 void splice( AltList& dst, AltList& src );116 117 /// Moves all elements from src to the beginning of dst118 void spliceBegin( AltList& dst, AltList& src );119 120 114 static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) { 121 115 alt.print( os ); -
src/ResolvExpr/Candidate.hpp
rc0f9efe r234b1cb 75 75 using CandidateList = std::vector< CandidateRef >; 76 76 77 /// Splice src after dst, clearing src78 static inline void splice( CandidateList & dst, CandidateList & src ) {79 dst.reserve( dst.size() + src.size() );80 for ( CandidateRef & r : src ) { dst.emplace_back( std::move( r ) ); }81 src.clear();82 }83 84 /// Splice src before dst85 static inline void spliceBegin( CandidateList & dst, CandidateList & src ) {86 splice( src, dst );87 dst.swap( src );88 }89 90 77 /// Sum the cost of a list of candidates 91 78 static inline Cost sumCost( const CandidateList & candidates ) { -
src/ResolvExpr/Resolver.cc
rc0f9efe r234b1cb 1253 1253 } 1254 1254 1255 ast::ptr< ast::Init > resolveCtorInit( 1256 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab 1257 ) { 1258 assert( ctorInit ); 1259 ast::Pass< Resolver_new > resolver{ symtab }; 1260 return ctorInit->accept( resolver ); 1261 } 1262 1255 1263 ast::ptr< ast::Expr > resolveStmtExpr( 1256 1264 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab -
src/ResolvExpr/Resolver.h
rc0f9efe r234b1cb 29 29 30 30 namespace ast { 31 class ConstructorInit; 31 32 class Decl; 32 33 class DeletedExpr; 34 class Init; 33 35 class StmtExpr; 34 36 class SymbolTable; … … 59 61 ast::ptr< ast::Expr > resolveInVoidContext( 60 62 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env ); 63 /// Resolves a constructor init expression 64 ast::ptr< ast::Init > resolveCtorInit( 65 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab ); 61 66 /// Resolves a statement expression 62 67 ast::ptr< ast::Expr > resolveStmtExpr( -
src/Tuples/Explode.h
rc0f9efe r234b1cb 238 238 } 239 239 240 /// explode list of candidates into flattened list of candidates 241 template< typename Output > 242 void explode( 243 const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out, 244 bool isTupleAssign = false 245 ) { 246 for ( const ResolvExpr::CandidateRef & cand : cands ) { 247 explode( *cand, symtab, std::forward< Output >( out ), isTupleAssign ); 248 } 249 } 250 240 251 } // namespace Tuples 241 252 -
src/Tuples/TupleAssignment.cc
rc0f9efe r234b1cb 22 22 #include <vector> 23 23 24 #include "AST/Decl.hpp" 25 #include "AST/Init.hpp" 26 #include "AST/Pass.hpp" 27 #include "AST/Stmt.hpp" 28 #include "AST/TypeEnvironment.hpp" 24 29 #include "CodeGen/OperatorTable.h" 25 30 #include "Common/PassVisitor.h" 26 31 #include "Common/UniqueName.h" // for UniqueName 27 #include "Common/utility.h" // for zipWith32 #include "Common/utility.h" // for splice, zipWith 28 33 #include "Explode.h" // for explode 29 34 #include "InitTweak/GenInit.h" // for genCtorInit … … 51 56 52 57 namespace Tuples { 53 class TupleAssignSpotter {58 class TupleAssignSpotter_old { 54 59 public: 55 60 // dispatcher for Tuple (multiple and mass) assignment operations 56 TupleAssignSpotter ( ResolvExpr::AlternativeFinder & );61 TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & ); 57 62 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args ); 58 63 … … 62 67 struct Matcher { 63 68 public: 64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,69 Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 65 70 const ResolvExpr::AltList& rhs ); 66 71 virtual ~Matcher() {} … … 80 85 81 86 ResolvExpr::AltList lhs, rhs; 82 TupleAssignSpotter &spotter;87 TupleAssignSpotter_old &spotter; 83 88 ResolvExpr::Cost baseCost; 84 89 std::list< ObjectDecl * > tmpDecls; … … 90 95 struct MassAssignMatcher : public Matcher { 91 96 public: 92 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,97 MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 93 98 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 94 99 virtual void match( std::list< Expression * > &out ); … … 97 102 struct MultipleAssignMatcher : public Matcher { 98 103 public: 99 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,104 MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 100 105 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 101 106 virtual void match( std::list< Expression * > &out ); … … 136 141 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 137 142 std::vector<ResolvExpr::AlternativeFinder> &args ) { 138 TupleAssignSpotter spotter( currentFinder );143 TupleAssignSpotter_old spotter( currentFinder ); 139 144 spotter.spot( expr, args ); 140 145 } 141 146 142 TupleAssignSpotter ::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )147 TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f ) 143 148 : currentFinder(f) {} 144 149 145 void TupleAssignSpotter ::spot( UntypedExpr * expr,150 void TupleAssignSpotter_old::spot( UntypedExpr * expr, 146 151 std::vector<ResolvExpr::AlternativeFinder> &args ) { 147 152 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { … … 224 229 } 225 230 226 void TupleAssignSpotter ::match() {231 void TupleAssignSpotter_old::match() { 227 232 assert ( matcher != 0 ); 228 233 … … 275 280 } 276 281 277 TupleAssignSpotter ::Matcher::Matcher( TupleAssignSpotter&spotter,282 TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter, 278 283 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 279 284 : lhs(lhs), rhs(rhs), spotter(spotter), … … 313 318 }; 314 319 315 ObjectDecl * TupleAssignSpotter ::Matcher::newObject( UniqueName & namer, Expression * expr ) {320 ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) { 316 321 assert( expr->result && ! expr->get_result()->isVoid() ); 317 322 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) ); … … 329 334 } 330 335 331 void TupleAssignSpotter ::MassAssignMatcher::match( std::list< Expression * > &out ) {336 void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) { 332 337 static UniqueName lhsNamer( "__massassign_L" ); 333 338 static UniqueName rhsNamer( "__massassign_R" ); … … 347 352 } 348 353 349 void TupleAssignSpotter ::MultipleAssignMatcher::match( std::list< Expression * > &out ) {354 void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) { 350 355 static UniqueName lhsNamer( "__multassign_L" ); 351 356 static UniqueName rhsNamer( "__multassign_R" ); … … 378 383 } 379 384 380 void handleTupleAssignment( 381 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 382 std::vector< ResolvExpr::CandidateFinder > & args 383 ) { 384 #warning unimplmented 385 (void)finder; (void)assign; (void)args; 386 assert(false); 387 } 385 namespace { 386 /// true if `expr` is of tuple type 387 bool isTuple( const ast::Expr * expr ) { 388 if ( ! expr ) return false; 389 assert( expr->result ); 390 return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() ); 391 } 392 393 /// true if `expr` is of tuple type or a reference to one 394 bool refToTuple( const ast::Expr * expr ) { 395 assert( expr->result ); 396 // check for function returning tuple of reference types 397 if ( auto castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) { 398 return refToTuple( castExpr->arg ); 399 } else { 400 return isTuple( expr ); 401 } 402 } 403 404 /// Dispatcher for tuple (multiple and mass) assignment operations 405 class TupleAssignSpotter_new final { 406 /// Actually finds tuple assignment operations, by subclass 407 struct Matcher { 408 ResolvExpr::CandidateList lhs, rhs; 409 TupleAssignSpotter_new & spotter; 410 CodeLocation location; 411 ResolvExpr::Cost baseCost; 412 std::vector< ast::ptr< ast::ObjectDecl > > tmpDecls; 413 ast::TypeEnvironment env; 414 ast::OpenVarSet open; 415 ast::AssertionSet need; 416 417 void combineState( const ResolvExpr::Candidate & cand ) { 418 env.simpleCombine( cand.env ); 419 ast::mergeOpenVars( open, cand.open ); 420 need.insert( cand.need.begin(), cand.need.end() ); 421 } 422 423 Matcher( 424 TupleAssignSpotter_new & s, const CodeLocation & loc, 425 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 426 : lhs( l ), rhs( r ), spotter( s ), location( loc ), 427 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(), 428 env(), open(), need() { 429 for ( auto & cand : lhs ) combineState( *cand ); 430 for ( auto & cand : rhs ) combineState( *cand ); 431 } 432 433 virtual std::vector< ast::ptr< ast::Expr > > match() = 0; 434 435 /// removes environments from subexpressions within statement expressions, which could 436 /// throw off later passes like those in Box which rely on PolyMutator, and adds the 437 /// bindings to the env 438 struct EnvRemover { 439 /// environment to hoist ExprStmt environments to 440 ast::TypeEnvironment & tenv; 441 442 EnvRemover( ast::TypeEnvironment & e ) : tenv( e ) {} 443 444 const ast::ExprStmt * previsit( const ast::ExprStmt * stmt ) { 445 if ( stmt->expr->env ) { 446 tenv.add( *stmt->expr->env ); 447 ast::ExprStmt * mut = mutate( stmt ); 448 mut->expr.get_and_mutate()->env = nullptr; 449 return mut; 450 } 451 return stmt; 452 } 453 }; 454 455 ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) { 456 assert( expr->result && ! expr->result->isVoid() ); 457 458 ast::ObjectDecl * ret = new ast::ObjectDecl{ 459 location, namer.newName(), expr->result, new ast::SingleInit{ location, expr }, 460 ast::Storage::Classes{}, ast::Linkage::Cforall }; 461 462 // if expression type is a reference, just need an initializer, otherwise construct 463 if ( ! expr->result.as< ast::ReferenceType >() ) { 464 // resolve ctor/dtor for the new object 465 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 466 InitTweak::genCtorInit( ret ), spotter.crntFinder.symtab ); 467 // remove environments from subexpressions of stmtExpr 468 ast::Pass< EnvRemover > rm{ env }; 469 ret->init = ctorInit->accept( rm ); 470 } 471 472 PRINT( std::cerr << "new object: " << ret << std::endl; ) 473 return ret; 474 } 475 476 ast::UntypedExpr * createFunc( 477 const std::string & fname, const ast::ObjectDecl * left, 478 const ast::ObjectDecl * right 479 ) { 480 assert( left ); 481 std::vector< ast::ptr< ast::Expr > > args; 482 args.emplace_back( new ast::VariableExpr{ location, left } ); 483 if ( right ) { args.emplace_back( new ast::VariableExpr{ location, right } ); } 484 485 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) { 486 args.front() = new ast::AddressExpr{ location, args.front() }; 487 if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; } 488 return new ast::UntypedExpr{ 489 location, new ast::NameExpr{ location, "?=?" }, std::move(args) }; 490 } else { 491 return new ast::UntypedExpr{ 492 location, new ast::NameExpr{ location, fname }, std::move(args) }; 493 } 494 } 495 }; 496 497 /// Finds mass-assignment operations 498 struct MassAssignMatcher final : public Matcher { 499 MassAssignMatcher( 500 TupleAssignSpotter_new & s, const CodeLocation & loc, 501 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 502 : Matcher( s, loc, l, r ) {} 503 504 std::vector< ast::ptr< ast::Expr > > match() override { 505 static UniqueName lhsNamer( "__massassign_L" ); 506 static UniqueName rhsNamer( "__massassign_R" ); 507 // empty tuple case falls into this matcher 508 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); 509 510 ast::ptr< ast::ObjectDecl > rtmp = 511 rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr; 512 513 std::vector< ast::ptr< ast::Expr > > out; 514 for ( ResolvExpr::CandidateRef & lhsCand : lhs ) { 515 // create a temporary object for each value in the LHS and create a call 516 // involving the RHS 517 ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr ); 518 out.emplace_back( createFunc( spotter.fname, ltmp, rtmp ) ); 519 tmpDecls.emplace_back( std::move( ltmp ) ); 520 } 521 if ( rtmp ) tmpDecls.emplace_back( std::move( rtmp ) ); 522 523 return out; 524 } 525 }; 526 527 /// Finds multiple-assignment operations 528 struct MultipleAssignMatcher final : public Matcher { 529 MultipleAssignMatcher( 530 TupleAssignSpotter_new & s, const CodeLocation & loc, 531 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 532 : Matcher( s, loc, l, r ) {} 533 534 std::vector< ast::ptr< ast::Expr > > match() override { 535 static UniqueName lhsNamer( "__multassign_L" ); 536 static UniqueName rhsNamer( "__multassign_R" ); 537 538 if ( lhs.size() != rhs.size() ) return {}; 539 540 // produce a new temporary object for each value in the LHS and RHS and pairwise 541 // create the calls 542 std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp; 543 544 std::vector< ast::ptr< ast::Expr > > out; 545 for ( unsigned i = 0; i < lhs.size(); ++i ) { 546 ResolvExpr::CandidateRef & lhsCand = lhs[i]; 547 ResolvExpr::CandidateRef & rhsCand = rhs[i]; 548 549 // convert RHS to LHS type minus one reference -- important for case where LHS 550 // is && and RHS is lvalue 551 auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >(); 552 rhsCand->expr = new ast::CastExpr{ 553 rhsCand->expr->location, rhsCand->expr, lhsType->base }; 554 ast::ptr< ast::ObjectDecl > lobj = newObject( lhsNamer, lhsCand->expr ); 555 ast::ptr< ast::ObjectDecl > robj = newObject( rhsNamer, rhsCand->expr ); 556 out.emplace_back( createFunc( spotter.fname, lobj, robj ) ); 557 ltmp.emplace_back( std::move( lobj ) ); 558 rtmp.emplace_back( std::move( robj ) ); 559 560 // resolve the cast expression so that rhsCand return type is bound by the cast 561 // type as needed, and transfer the resulting environment 562 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env }; 563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 564 assert( finder.candidates.size() == 1 ); 565 env = std::move( finder.candidates.front()->env ); 566 } 567 568 splice( tmpDecls, ltmp ); 569 splice( tmpDecls, rtmp ); 570 571 return out; 572 } 573 }; 574 575 ResolvExpr::CandidateFinder & crntFinder; 576 std::string fname; 577 std::unique_ptr< Matcher > matcher; 578 579 public: 580 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 581 : crntFinder( f ), fname(), matcher() {} 582 583 // find left- and right-hand-sides for mass or multiple assignment 584 void spot( 585 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 586 ) { 587 if ( auto op = expr->func.as< ast::NameExpr >() ) { 588 // skip non-assignment functions 589 if ( ! CodeGen::isCtorDtorAssign( op->name ) ) return; 590 fname = op->name; 591 592 // handled by CandidateFinder if applicable (both odd cases) 593 if ( args.empty() || ( args.size() == 1 && CodeGen::isAssignment( fname ) ) ) { 594 return; 595 } 596 597 // look over all possible left-hand-side 598 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) { 599 // skip non-tuple LHS 600 if ( ! refToTuple( lhsCand->expr ) ) continue; 601 602 // explode is aware of casts - ensure every LHS is sent into explode with a 603 // reference cast 604 if ( ! lhsCand->expr.as< ast::CastExpr >() ) { 605 lhsCand->expr = new ast::CastExpr{ 606 lhsCand->expr->location, lhsCand->expr, 607 new ast::ReferenceType{ lhsCand->expr->result } }; 608 } 609 610 // explode the LHS so that each field of a tuple-valued expr is assigned 611 ResolvExpr::CandidateList lhs; 612 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true ); 613 for ( ResolvExpr::CandidateRef & cand : lhs ) { 614 // each LHS value must be a reference - some come in with a cast, if not 615 // just cast to reference here 616 if ( ! cand->expr->result.as< ast::ReferenceType >() ) { 617 cand->expr = new ast::CastExpr{ 618 cand->expr->location, cand->expr, 619 new ast::ReferenceType{ cand->expr->result } }; 620 } 621 } 622 623 if ( args.size() == 1 ) { 624 // mass default-initialization/destruction 625 ResolvExpr::CandidateList rhs{}; 626 matcher.reset( new MassAssignMatcher{ *this, expr->location, lhs, rhs } ); 627 match(); 628 } else if ( args.size() == 2 ) { 629 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) { 630 ResolvExpr::CandidateList rhs; 631 if ( isTuple( rhsCand->expr ) ) { 632 // multiple assignment 633 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 634 matcher.reset( 635 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 636 } else { 637 // mass assignment 638 rhs.emplace_back( rhsCand ); 639 matcher.reset( 640 new MassAssignMatcher{ *this, expr->location, lhs, rhs } ); 641 } 642 match(); 643 } 644 } else { 645 // expand all possible RHS possibilities 646 std::vector< ResolvExpr::CandidateList > rhsCands; 647 combos( 648 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) ); 649 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) { 650 // multiple assignment 651 ResolvExpr::CandidateList rhs; 652 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 653 matcher.reset( 654 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 655 match(); 656 } 657 } 658 } 659 } 660 } 661 662 void match() { 663 assert( matcher ); 664 665 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match(); 666 667 if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) { 668 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's 669 // okay for newAssigns to be empty. Otherwise, return early so that no new 670 // candidates are generated 671 if ( newAssigns.empty() ) return; 672 } 673 674 ResolvExpr::CandidateList crnt; 675 // now resolve new assignments 676 for ( const ast::Expr * expr : newAssigns ) { 677 PRINT( 678 std::cerr << "== resolving tuple assign ==" << std::endl; 679 std::cerr << expr << std::endl; 680 ) 681 682 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env }; 683 684 try { 685 finder.find( expr, ResolvExpr::ResolvMode::withAdjustment() ); 686 } catch (...) { 687 // no match is not failure, just that this tuple assignment is invalid 688 return; 689 } 690 691 ResolvExpr::CandidateList & cands = finder.candidates; 692 assert( cands.size() == 1 ); 693 assert( cands.front()->expr ); 694 crnt.emplace_back( std::move( cands.front() ) ); 695 } 696 697 // extract expressions from the assignment candidates to produce a list of assignments 698 // that together form a sigle candidate 699 std::vector< ast::ptr< ast::Expr > > solved; 700 for ( ResolvExpr::CandidateRef & cand : crnt ) { 701 solved.emplace_back( cand->expr ); 702 matcher->combineState( *cand ); 703 } 704 705 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >( 706 new ast::TupleAssignExpr{ 707 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) }, 708 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 709 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) ); 710 } 711 }; 712 } // anonymous namespace 713 714 void handleTupleAssignment( 715 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 716 std::vector< ResolvExpr::CandidateFinder > & args 717 ) { 718 TupleAssignSpotter_new spotter{ finder }; 719 spotter.spot( assign, args ); 720 } 721 388 722 } // namespace Tuples 389 723
Note: See TracChangeset
for help on using the changeset viewer.