Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r1958fec rb69233ac  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon Jun 10 17:45:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 13:56:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 10 17:45:00 2019
     13// Update Count     : 1
    1414//
    1515
     
    6969        /// Reference to a single deferred item
    7070        struct DeferRef {
    71                 const ast::VariableExpr * expr;
     71                const ast::DeclWithType * decl;
    7272                const ast::AssertionSetValue & info;
    7373                const AssnCandidate & match;
     
    7777        /// Acts like an indexed list of DeferRef
    7878        struct DeferItem {
    79                 const ast::VariableExpr * expr;
     79                const ast::DeclWithType * decl;
    8080                const ast::AssertionSetValue & info;
    8181                AssnCandidateList matches;
    8282
    8383                DeferItem(
    84                         const ast::VariableExpr * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
    85                 : expr( d ), info( i ), matches( std::move( ms ) ) {}
     84                        const ast::DeclWithType * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
     85                : decl( 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 { expr, info, matches[i] }; }
     91                DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }
    9292        };
    9393
     
    138138        void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
    139139                for ( auto & i : have ) {
    140                         if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
     140                        if ( i.second.isUsed ) { symtab.addId( i.first ); }
    141141                }
    142142        }
     
    144144        /// Binds a single assertion, updating satisfaction state
    145145        void bindAssertion(
    146                 const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand,
     146                const ast::DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,
    147147                AssnCandidate & match, InferCache & inferred
    148148        ) {
     
    156156
    157157                // place newly-inferred assertion in proper location in cache
    158                 inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{
    159                         candidate->uniqueId, candidate, match.adjType, expr->result, varExpr };
     158                inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{
     159                        candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr };
    160160        }
    161161
     
    167167                // find candidates that unify with the desired type
    168168                AssnCandidateList matches;
    169 
    170                 std::vector<ast::SymbolTable::IdData> candidates;
    171                 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name);
    172                 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
    173                         // prefilter special decls by argument type, if already known
    174                         ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base
    175                                 .strict_as<ast::FunctionType>()->params[0]
    176                                 .strict_as<ast::ReferenceType>()->base;
    177                         sat.cand->env.apply(thisArgType);
    178 
    179                         std::string otypeKey = "";
    180                         if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    181                         else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    182 
    183                         candidates = sat.symtab.specialLookupId(kind, otypeKey);
    184                 }
    185                 else {
    186                         candidates = sat.symtab.lookupId(assn.first->var->name);
    187                 }
    188                 for ( const ast::SymbolTable::IdData & cdata : candidates ) {
     169                for ( const ast::SymbolTable::IdData & cdata : sat.symtab.lookupId( assn.first->name ) ) {
    189170                        const ast::DeclWithType * candidate = cdata.id;
    190 
    191                         // ignore deleted candidates.
    192                         // NOTE: this behavior is different from main resolver.
    193                         // further investigations might be needed to determine
    194                         // if we should implement the same rule here
    195                         // (i.e. error if unique best match is deleted)
    196                         if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue;
    197171
    198172                        // build independent unification context for candidate
     
    200174                        ast::TypeEnvironment newEnv{ sat.cand->env };
    201175                        ast::OpenVarSet newOpen{ sat.cand->open };
    202                         ast::ptr< ast::Type > toType = assn.first->result;
     176                        ast::ptr< ast::Type > toType = assn.first->get_type();
    203177                        ast::ptr< ast::Type > adjType =
    204                                 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ), GEN_USAGE, false );
     178                                renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) );
    205179
    206180                        // only keep candidates which unify
     
    214188
    215189                                matches.emplace_back(
    216                                         cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     190                                        cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),
    217191                                        std::move( newOpen ), crntResnSlot );
    218192                        }
     
    255229                InferMatcher( InferCache & inferred ) : inferred( inferred ) {}
    256230
    257                 const ast::Expr * postvisit( const ast::Expr * expr ) {
     231                const ast::Expr * postmutate( const ast::Expr * expr ) {
    258232                        // Skip if no slots to find
    259                         if ( !expr->inferred.hasSlots() ) return expr;
    260                         // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
    261                         std::vector<UniqueId> missingSlots;
     233                        if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
     234
    262235                        // find inferred parameters for resolution slots
    263                         ast::InferredParams * newInferred = new ast::InferredParams();
     236                        ast::InferredParams newInferred;
    264237                        for ( UniqueId slot : expr->inferred.resnSlots() ) {
    265238                                // fail if no matching assertions found
    266239                                auto it = inferred.find( slot );
    267240                                if ( it == inferred.end() ) {
    268                                         // std::cerr << "missing assertion " << slot << std::endl;
    269                                         missingSlots.push_back(slot);
    270                                         continue;
     241                                        assert(!"missing assertion");
    271242                                }
    272243
     
    274245                                for ( auto & entry : it->second ) {
    275246                                        // recurse on inferParams of resolved expressions
    276                                         entry.second.expr = postvisit( entry.second.expr );
    277                                         auto res = newInferred->emplace( entry );
     247                                        entry.second.expr = postmutate( entry.second.expr );
     248                                        auto res = newInferred.emplace( entry );
    278249                                        assert( res.second && "all assertions newly placed" );
    279250                                }
     
    281252
    282253                        ast::Expr * ret = mutate( expr );
    283                         ret->inferred.set_inferParams( newInferred );
    284                         if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots;
     254                        ret->inferred.set_inferParams( std::move( newInferred ) );
    285255                        return ret;
    286256                }
     
    329299                        Cost cost;
    330300
    331                         OutType(
    332                                 const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
     301                        OutType( 
     302                                const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
    333303                                const std::vector< DeferRef > & as, const ast::SymbolTable & symtab )
    334304                        : env( e ), open( o ), assns( as ), cost( Cost::zero ) {
     
    336306                                for ( const DeferRef & assn : assns ) {
    337307                                        // compute conversion cost from satisfying decl to assertion
    338                                         cost += computeConversionCost(
    339                                                 assn.match.adjType, assn.expr->result, false, symtab, env );
    340 
     308                                        cost += computeConversionCost( 
     309                                                assn.match.adjType, assn.decl->get_type(), symtab, env );
     310                                       
    341311                                        // mark vars+specialization on function-type assertions
    342                                         const ast::FunctionType * func =
     312                                        const ast::FunctionType * func = 
    343313                                                GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    344314                                        if ( ! func ) continue;
    345315
    346                                         for ( const auto & param : func->params ) {
    347                                                 cost.decSpec( specCost( param ) );
     316                                        for ( const ast::DeclWithType * param : func->params ) {
     317                                                cost.decSpec( specCost( param->get_type() ) );
    348318                                        }
    349 
     319                                       
    350320                                        cost.incVar( func->forall.size() );
    351 
    352                                         cost.decSpec( func->assertions.size() );
     321                                       
     322                                        for ( const ast::TypeDecl * td : func->forall ) {
     323                                                cost.decSpec( td->assertions.size() );
     324                                        }
    353325                                }
    354326                        }
     
    357329                };
    358330
    359                 CandidateEnvMerger(
    360                         const ast::TypeEnvironment & env, const ast::OpenVarSet & open,
     331                CandidateEnvMerger( 
     332                        const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 
    361333                        const ast::SymbolTable & syms )
    362334                : crnt(), envs{ env }, opens{ open }, symtab( syms ) {}
     
    385357
    386358        /// Limit to depth of recursion of assertion satisfaction
    387         static const int recursionLimit = 8;
     359        static const int recursionLimit = 4;
    388360        /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
    389361        static const int deferLimit = 10;
     
    417389                        if ( it != thresholds.end() && it->second < sat.costs ) goto nextSat;
    418390
    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()) {
     391                        // make initial pass at matching assertions
     392                        for ( auto & assn : sat.need ) {
     393                                // fail early if any assertion is not satisfiable
     394                                if ( ! satisfyAssertion( assn, sat ) ) {
    435395                                        Indenter tabs{ 3 };
    436396                                        std::ostringstream ss;
     
    438398                                        print( ss, *sat.cand, ++tabs );
    439399                                        ss << (tabs-1) << "Could not satisfy assertion:\n";
    440                                         ast::print( ss, next[0].first, tabs );
     400                                        ast::print( ss, assn.first, tabs );
    441401
    442402                                        errors.emplace_back( ss.str() );
    443403                                        goto nextSat;
    444404                                }
    445                                 sat.need = std::move(next);
    446405                        }
    447406
     
    462421                                ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n";
    463422                                for ( const auto & d : sat.deferred ) {
    464                                         ast::print( ss, d.expr, tabs );
     423                                        ast::print( ss, d.decl, tabs );
    465424                                }
    466425
     
    480439                                        ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
    481440                                        for ( const auto& d : sat.deferred ) {
    482                                                 ast::print( ss, d.expr, tabs );
     441                                                ast::print( ss, d.decl, tabs );
    483442                                        }
    484443
     
    512471                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    513472
    514                                                 bindAssertion( r.expr, r.info, nextCand, match, nextInferred );
     473                                                bindAssertion( r.decl, r.info, nextCand, match, nextInferred );
    515474                                        }
    516475
Note: See TracChangeset for help on using the changeset viewer.