Ignore:
Timestamp:
Jun 7, 2024, 4:53:25 PM (4 weeks ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
0188539c
Parents:
bf64de3
Message:

Noticing that a function could have an early exit to save a level of indentation lead to a larger refactor. Slight code improvements besides the formatting change.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cpp

    rbf64de3 r405dbb3  
    241241        ResolvExpr::CandidateFinder & crntFinder;
    242242        std::string fname;
    243         std::unique_ptr< Matcher > matcher;
    244243
    245244public:
    246245        TupleAssignSpotter( ResolvExpr::CandidateFinder & f )
    247         : crntFinder( f ), fname(), matcher() {}
    248 
    249         // Find left- and right-hand-sides for mass or multiple assignment.
     246        : crntFinder( f ), fname() {}
     247
     248        /// Find left- and right-hand-sides for mass or multiple assignment.
    250249        void spot(
    251250                const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
    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 ) );
     251        );
     252        /// Wrapper around matcher.match.
     253        void match( Matcher & matcher );
     254};
     255
     256void TupleAssignSpotter::spot(
     257        const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
     258) {
     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 LHS
     276                // 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 in
     287                        // 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 );
    273312                                }
    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         }
    376 };
     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
     330void 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 tuple
     335                // 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 assignments
     365        // that together form a sigle candidate
     366        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}
    377378
    378379} // anonymous namespace
Note: See TracChangeset for help on using the changeset viewer.