Ignore:
Timestamp:
Jan 7, 2021, 5:06:22 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5ad381b
Parents:
42f6e07 (diff), 58fe85a (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r42f6e07 r2b4daf2  
    5757                ast::UniqueId resnSlot;          ///< Slot for any recursive assertion IDs
    5858
    59                 AssnCandidate( 
    60                         const ast::SymbolTable::IdData c, const ast::Type * at, ast::TypeEnvironment && e, 
     59                AssnCandidate(
     60                        const ast::SymbolTable::IdData c, const ast::Type * at, ast::TypeEnvironment && e,
    6161                        ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs )
    62                 : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ), 
     62                : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ),
    6363                  need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
    6464        };
     
    6969        /// Reference to a single deferred item
    7070        struct DeferRef {
    71                 const ast::DeclWithType * decl;
     71                const ast::VariableExpr * expr;
    7272                const ast::AssertionSetValue & info;
    7373                const AssnCandidate & match;
    7474        };
    75        
    76         /// Wrapper for the deferred items from a single assertion satisfaction. 
     75
     76        /// Wrapper for the deferred items from a single assertion satisfaction.
    7777        /// Acts like an indexed list of DeferRef
    7878        struct DeferItem {
    79                 const ast::DeclWithType * decl;
     79                const ast::VariableExpr * expr;
    8080                const ast::AssertionSetValue & info;
    8181                AssnCandidateList matches;
    8282
    83                 DeferItem( 
    84                         const ast::DeclWithType * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
    85                 : decl( d ), info( i ), matches( std::move( ms ) ) {}
     83                DeferItem(
     84                        const ast::VariableExpr * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
     85                : expr( d ), info( i ), matches( std::move( ms ) ) {}
    8686
    8787                bool empty() const { return matches.empty(); }
     
    8989                AssnCandidateList::size_type size() const { return matches.size(); }
    9090
    91                 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }
     91                DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; }
    9292        };
    9393
     
    117117                /// Initial satisfaction state for a candidate
    118118                SatState( CandidateRef & c, const ast::SymbolTable & syms )
    119                 : cand( c ), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero }, 
     119                : cand( c ), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero },
    120120                  symtab( syms ) { need.swap( c->need ); }
    121                
     121
    122122                /// Update satisfaction state for next step after previous state
    123123                SatState( SatState && o, IterateFlag )
    124                 : cand( std::move( o.cand ) ), need( o.newNeed.begin(), o.newNeed.end() ), newNeed(), 
    125                   deferred(), inferred( std::move( o.inferred ) ), costs( std::move( o.costs ) ), 
     124                : cand( std::move( o.cand ) ), need( o.newNeed.begin(), o.newNeed.end() ), newNeed(),
     125                  deferred(), inferred( std::move( o.inferred ) ), costs( std::move( o.costs ) ),
    126126                  symtab( o.symtab ) { costs.emplace_back( Cost::zero ); }
    127                
     127
    128128                /// Field-wise next step constructor
    129129                SatState(
    130                         CandidateRef && c, ast::AssertionSet && nn, InferCache && i, CostVec && cs, 
     130                        CandidateRef && c, ast::AssertionSet && nn, InferCache && i, CostVec && cs,
    131131                        ast::SymbolTable && syms )
    132                 : cand( std::move( c ) ), need( nn.begin(), nn.end() ), newNeed(), deferred(), 
     132                : cand( std::move( c ) ), need( nn.begin(), nn.end() ), newNeed(), deferred(),
    133133                  inferred( std::move( i ) ), costs( std::move( cs ) ), symtab( std::move( syms ) )
    134134                  { costs.emplace_back( Cost::zero ); }
     
    138138        void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
    139139                for ( auto & i : have ) {
    140                         if ( i.second.isUsed ) { symtab.addId( i.first ); }
     140                        if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
    141141                }
    142142        }
    143143
    144144        /// Binds a single assertion, updating satisfaction state
    145         void bindAssertion( 
    146                 const ast::DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,
     145        void bindAssertion(
     146                const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand,
    147147                AssnCandidate & match, InferCache & inferred
    148148        ) {
    149149                const ast::DeclWithType * candidate = match.cdata.id;
    150                 assertf( candidate->uniqueId, 
     150                assertf( candidate->uniqueId,
    151151                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    152                
     152
    153153                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
    154154                varExpr->result = match.adjType;
     
    156156
    157157                // place newly-inferred assertion in proper location in cache
    158                 inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{
    159                         candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr };
     158                inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{
     159                        candidate->uniqueId, candidate, match.adjType, expr->result, varExpr };
    160160        }
    161161
     
    169169
    170170                std::vector<ast::SymbolTable::IdData> candidates;
    171                 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->name);
     171                auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name);
    172172                if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
    173173                        // prefilter special decls by argument type, if already known
    174                         ast::ptr<ast::Type> thisArgType = strict_dynamic_cast<const ast::PointerType *>(assn.first->get_type())->base
     174                        ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base
    175175                                .strict_as<ast::FunctionType>()->params[0]
    176176                                .strict_as<ast::ReferenceType>()->base;
     
    184184                }
    185185                else {
    186                         candidates = sat.symtab.lookupId(assn.first->name);
     186                        candidates = sat.symtab.lookupId(assn.first->var->name);
    187187                }
    188188                for ( const ast::SymbolTable::IdData & cdata : candidates ) {
     
    200200                        ast::TypeEnvironment newEnv{ sat.cand->env };
    201201                        ast::OpenVarSet newOpen{ sat.cand->open };
    202                         ast::ptr< ast::Type > toType = assn.first->get_type();
    203                         ast::ptr< ast::Type > adjType = 
    204                                 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) );
     202                        ast::ptr< ast::Type > toType = assn.first->result;
     203                        ast::ptr< ast::Type > adjType =
     204                                renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ), GEN_USAGE, false );
    205205
    206206                        // only keep candidates which unify
     
    213213                                }
    214214
    215                                 matches.emplace_back( 
     215                                matches.emplace_back(
    216216                                        cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    217217                                        std::move( newOpen ), crntResnSlot );
     
    287287        };
    288288
    289         /// Replace ResnSlots with InferParams and add alternative to output list, if it meets pruning 
     289        /// Replace ResnSlots with InferParams and add alternative to output list, if it meets pruning
    290290        /// threshold.
    291         void finalizeAssertions( 
    292                 CandidateRef & cand, InferCache & inferred, PruneMap & thresholds, CostVec && costs, 
    293                 CandidateList & out 
     291        void finalizeAssertions(
     292                CandidateRef & cand, InferCache & inferred, PruneMap & thresholds, CostVec && costs,
     293                CandidateList & out
    294294        ) {
    295295                // prune if cheaper alternative for same key has already been generated
     
    308308        }
    309309
    310         /// Combo iterator that combines candidates into an output list, merging their environments. 
    311         /// Rejects an appended candidate if environments cannot be merged. See `Common/FilterCombos.h` 
     310        /// Combo iterator that combines candidates into an output list, merging their environments.
     311        /// Rejects an appended candidate if environments cannot be merged. See `Common/FilterCombos.h`
    312312        /// for description of "combo iterator".
    313313        class CandidateEnvMerger {
     
    337337                                        // compute conversion cost from satisfying decl to assertion
    338338                                        cost += computeConversionCost(
    339                                                 assn.match.adjType, assn.decl->get_type(), false, symtab, env );
     339                                                assn.match.adjType, assn.expr->result, false, symtab, env );
    340340
    341341                                        // mark vars+specialization on function-type assertions
     
    350350                                        cost.incVar( func->forall.size() );
    351351
    352                                         for ( const ast::TypeDecl * td : func->forall ) {
    353                                                 cost.decSpec( td->assertions.size() );
    354                                         }
     352                                        cost.decSpec( func->assertions.size() );
    355353                                }
    356354                        }
     
    387385
    388386        /// Limit to depth of recursion of assertion satisfaction
    389         static const int recursionLimit = 4;
     387        static const int recursionLimit = 8;
    390388        /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
    391389        static const int deferLimit = 10;
    392390} // anonymous namespace
    393391
    394 void satisfyAssertions( 
    395         CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 
     392void satisfyAssertions(
     393        CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out,
    396394        std::vector<std::string> & errors
    397395) {
     
    419417                        if ( it != thresholds.end() && it->second < sat.costs ) goto nextSat;
    420418
    421                         // make initial pass at matching assertions
    422                         for ( auto & assn : sat.need ) {
    423                                 // fail early if any assertion is not satisfiable
    424                                 if ( ! satisfyAssertion( assn, sat ) ) {
     419                        // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen.
     420                        for (unsigned resetCount = 0; ; ++resetCount) {
     421                                ast::AssertionList next;
     422                                resetTyVarRenaming();
     423                                // make initial pass at matching assertions
     424                                for ( auto & assn : sat.need ) {
     425                                        // fail early if any assertion is not satisfiable
     426                                        if ( ! satisfyAssertion( assn, sat ) ) {
     427                                                next.emplace_back(assn);
     428                                                // goto nextSat;
     429                                        }
     430                                }
     431                                // success
     432                                if (next.empty()) break;
     433                                // fail if nothing resolves
     434                                else if (next.size() == sat.need.size()) {
    425435                                        Indenter tabs{ 3 };
    426436                                        std::ostringstream ss;
     
    428438                                        print( ss, *sat.cand, ++tabs );
    429439                                        ss << (tabs-1) << "Could not satisfy assertion:\n";
    430                                         ast::print( ss, assn.first, tabs );
     440                                        ast::print( ss, next[0].first, tabs );
    431441
    432442                                        errors.emplace_back( ss.str() );
    433443                                        goto nextSat;
    434444                                }
     445                                sat.need = std::move(next);
    435446                        }
    436447
     
    438449                                // either add successful match or push back next state
    439450                                if ( sat.newNeed.empty() ) {
    440                                         finalizeAssertions( 
     451                                        finalizeAssertions(
    441452                                                sat.cand, sat.inferred, thresholds, std::move( sat.costs ), out );
    442453                                } else {
     
    451462                                ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n";
    452463                                for ( const auto & d : sat.deferred ) {
    453                                         ast::print( ss, d.decl, tabs );
     464                                        ast::print( ss, d.expr, tabs );
    454465                                }
    455466
     
    460471                                std::vector< CandidateEnvMerger::OutType > compatible = filterCombos(
    461472                                        sat.deferred, CandidateEnvMerger{ sat.cand->env, sat.cand->open, sat.symtab } );
    462                                
     473
    463474                                // fail early if no mutually-compatible assertion satisfaction
    464475                                if ( compatible.empty() ) {
     
    469480                                        ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
    470481                                        for ( const auto& d : sat.deferred ) {
    471                                                 ast::print( ss, d.decl, tabs );
     482                                                ast::print( ss, d.expr, tabs );
    472483                                        }
    473484
     
    483494                                        // set up next satisfaction state
    484495                                        CandidateRef nextCand = std::make_shared<Candidate>(
    485                                                 sat.cand->expr, std::move( compat.env ), std::move( compat.open ), 
     496                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    486497                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    487498                                                sat.cand->cost, sat.cand->cvtCost );
     
    489500                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
    490501                                        InferCache nextInferred{ sat.inferred };
    491                                        
     502
    492503                                        CostVec nextCosts{ sat.costs };
    493504                                        nextCosts.back() += compat.cost;
    494                                                                
     505
    495506                                        ast::SymbolTable nextSymtab{ sat.symtab };
    496507
     
    501512                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    502513
    503                                                 bindAssertion( r.decl, r.info, nextCand, match, nextInferred );
     514                                                bindAssertion( r.expr, r.info, nextCand, match, nextInferred );
    504515                                        }
    505516
    506517                                        // either add successful match or push back next state
    507518                                        if ( nextNewNeed.empty() ) {
    508                                                 finalizeAssertions( 
     519                                                finalizeAssertions(
    509520                                                        nextCand, nextInferred, thresholds, std::move( nextCosts ), out );
    510521                                        } else {
    511                                                 nextSats.emplace_back( 
    512                                                         std::move( nextCand ), std::move( nextNewNeed ), 
    513                                                         std::move( nextInferred ), std::move( nextCosts ), 
     522                                                nextSats.emplace_back(
     523                                                        std::move( nextCand ), std::move( nextNewNeed ),
     524                                                        std::move( nextInferred ), std::move( nextCosts ),
    514525                                                        std::move( nextSymtab ) );
    515526                                        }
     
    523534                nextSats.clear();
    524535        }
    525        
     536
    526537        // exceeded recursion limit if reaches here
    527538        if ( out.empty() ) {
Note: See TracChangeset for help on using the changeset viewer.