Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    rda4a570 r251ce80  
    1616#include "SatisfyAssertions.hpp"
    1717
    18 #include <iostream>
    1918#include <algorithm>
    2019#include <cassert>
     
    4645#include "SymTab/Mangler.h"
    4746
    48 
    49 
    5047namespace ResolvExpr {
    5148
     
    6865                        ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs )
    6966                : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ),
    70                   need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {
    71                         if (!have.empty()) {
    72                                 // std::cerr << c.id->location << ':' << c.id->name << std::endl; // I think this was debugging code so I commented it
    73                         }
    74                   }
     67                  need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
    7568        };
    7669
     
    146139        };
    147140
    148         enum AssertionResult {Fail, Skip, Success} ;
     141        /// Adds a captured assertion to the symbol table
     142        void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
     143                for ( auto & i : have ) {
     144                        if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
     145                }
     146        }
    149147
    150148        /// Binds a single assertion, updating satisfaction state
     
    157155                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    158156
    159                 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost );
     157                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
    160158                varExpr->result = match.adjType;
    161159                if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); }
     
    167165
    168166        /// Satisfy a single assertion
    169         AssertionResult satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) {
     167        bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
    170168                // skip unused assertions
    171                 // static unsigned int cnt = 0; // I think this was debugging code so I commented it
    172                 if ( ! assn.second.isUsed ) return AssertionResult::Success;
    173 
    174                 // if (assn.first->var->name[1] == '|') std::cerr << ++cnt << std::endl; // I think this was debugging code so I commented it
     169                if ( ! assn.second.isUsed ) return true;
    175170
    176171                // find candidates that unify with the desired type
    177                 AssnCandidateList matches, inexactMatches;
     172                AssnCandidateList matches;
    178173
    179174                std::vector<ast::SymbolTable::IdData> candidates;
     
    184179                                .strict_as<ast::FunctionType>()->params[0]
    185180                                .strict_as<ast::ReferenceType>()->base;
    186                         // sat.cand->env.apply(thisArgType);
    187 
    188                         if (auto inst = thisArgType.as<ast::TypeInstType>()) {
    189                                 auto cls = sat.cand->env.lookup(*inst);
    190                                 if (cls && cls->bound) thisArgType = cls->bound;
    191                         }
     181                        sat.cand->env.apply(thisArgType);
    192182
    193183                        std::string otypeKey = "";
    194184                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    195185                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    196                         else if (skipUnbound) return AssertionResult::Skip;
     186                        else if (skipUnbound) return false;
    197187
    198188                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    222212
    223213                        ast::OpenVarSet closed;
    224                         // findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
    225                         findOpenVars( adjType, newOpen, closed, newNeed, have, newEnv, FirstOpen );
    226                         ast::TypeEnvironment tempNewEnv {newEnv};
    227 
    228                         if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    229                                 // set up binding slot for recursive assertions
    230                                 ast::UniqueId crntResnSlot = 0;
    231                                 if ( ! newNeed.empty() ) {
    232                                         crntResnSlot = ++globalResnSlot;
    233                                         for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
    234                                 }
    235 
    236                                 matches.emplace_back(
    237                                         cdata, adjType, std::move( tempNewEnv ), std::move( have ), std::move( newNeed ),
    238                                         std::move( newOpen ), crntResnSlot );
    239                         }
    240                         else if ( matches.empty() ) {
    241                                 // restore invalidated env
    242                                 // newEnv = sat.cand->env;
    243                                 // newNeed.clear();
     214                        findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     215                        findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
     216                        if ( allowConversion ) {
    244217                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    245218                                        // set up binding slot for recursive assertions
     
    250223                                        }
    251224
    252                                         inexactMatches.emplace_back(
     225                                        matches.emplace_back(
    253226                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    254227                                                std::move( newOpen ), crntResnSlot );
    255228                                }
    256229                        }
     230                        else {
     231                                if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
     232                                        // set up binding slot for recursive assertions
     233                                        ast::UniqueId crntResnSlot = 0;
     234                                        if ( ! newNeed.empty() ) {
     235                                                crntResnSlot = ++globalResnSlot;
     236                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     237                                        }
     238
     239                                        matches.emplace_back(
     240                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     241                                                std::move( newOpen ), crntResnSlot );
     242                                }
     243                        }
    257244                }
    258245
    259246                // break if no satisfying match
    260                 if ( matches.empty() ) matches = std::move(inexactMatches);
    261                 if ( matches.empty() ) return AssertionResult::Fail;
     247                if ( matches.empty() ) return false;
    262248
    263249                // defer if too many satisfying matches
    264250                if ( matches.size() > 1 ) {
    265251                        sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) );
    266                         return AssertionResult::Success;
     252                        return true;
    267253                }
    268254
    269255                // otherwise bind unique match in ongoing scope
    270256                AssnCandidate & match = matches.front();
    271                 // addToSymbolTable( match.have, sat.symtab );
     257                addToSymbolTable( match.have, sat.symtab );
    272258                sat.newNeed.insert( match.need.begin(), match.need.end() );
    273259                sat.cand->env = std::move( match.env );
     
    275261
    276262                bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred );
    277                 return AssertionResult::Success;
     263                return true;
    278264        }
    279265
     
    452438                // for each current mutually-compatible set of assertions
    453439                for ( SatState & sat : sats ) {
     440                        bool allowConversion = false;
    454441                        // stop this branch if a better option is already found
    455442                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    460447                        for (unsigned resetCount = 0; ; ++resetCount) {
    461448                                ast::AssertionList next;
     449                                resetTyVarRenaming();
    462450                                // make initial pass at matching assertions
    463451                                for ( auto & assn : sat.need ) {
    464                                         resetTyVarRenaming();
    465452                                        // fail early if any assertion is not satisfiable
    466                                         auto result = satisfyAssertion( assn, sat, !next.empty() );
    467                                         if ( result == AssertionResult::Fail ) {
     453                                        if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) {
     454                                                next.emplace_back(assn);
     455                                                // goto nextSat;
     456                                        }
     457                                }
     458                                // success
     459                                if (next.empty()) break;
     460                                // fail if nothing resolves
     461                                else if (next.size() == sat.need.size()) {
     462                                        if (allowConversion) {
    468463                                                Indenter tabs{ 3 };
    469464                                                std::ostringstream ss;
     
    471466                                                print( ss, *sat.cand, ++tabs );
    472467                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
    473                                                 ast::print( ss, assn.first, tabs );
     468                                                ast::print( ss, next[0].first, tabs );
    474469
    475470                                                errors.emplace_back( ss.str() );
    476471                                                goto nextSat;
    477472                                        }
    478                                         else if ( result == AssertionResult::Skip ) {
    479                                                 next.emplace_back(assn);
    480                                                 // goto nextSat;
    481                                         }
    482                                 }
    483                                 // success
    484                                 if (next.empty()) break;
    485 
     473
     474                                        else {
     475                                                allowConversion = true;
     476                                                continue;
     477                                        }
     478                                }
     479                                allowConversion = false;
    486480                                sat.need = std::move(next);
    487481                        }
     
    537531                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    538532                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    539                                                 sat.cand->cost );
     533                                                sat.cand->cost, sat.cand->cvtCost );
    540534
    541535                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
     
    550544                                        for ( DeferRef r : compat.assns ) {
    551545                                                AssnCandidate match = r.match;
    552                                                 // addToSymbolTable( match.have, nextSymtab );
     546                                                addToSymbolTable( match.have, nextSymtab );
    553547                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    554548
Note: See TracChangeset for help on using the changeset viewer.