Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r251ce80 r34b4268  
    1616#include "SatisfyAssertions.hpp"
    1717
     18#include <iostream>
    1819#include <algorithm>
    1920#include <cassert>
     
    2324#include <vector>
    2425
    25 #include "AdjustExprType.hpp"
    2626#include "Candidate.hpp"
    2727#include "CandidateFinder.hpp"
    28 #include "CommonType.hpp"
    2928#include "Cost.h"
    3029#include "RenameVars.h"
    31 #include "SpecCost.hpp"
    3230#include "typeops.h"
    3331#include "Unify.h"
     
    4543#include "SymTab/Mangler.h"
    4644
     45
     46
    4747namespace ResolvExpr {
    4848
     
    6565                        ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs )
    6666                : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ),
    67                   need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
     67                  need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {
     68                        if (!have.empty()) {
     69                                std::cerr << c.id->location << ':' << c.id->name << std::endl;
     70                        }
     71                  }
    6872        };
    6973
     
    139143        };
    140144
    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         }
     145        enum AssertionResult {Fail, Skip, Success} ;
    147146
    148147        /// Binds a single assertion, updating satisfaction state
     
    155154                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    156155
    157                 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
     156                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost );
    158157                varExpr->result = match.adjType;
    159158                if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); }
     
    165164
    166165        /// Satisfy a single assertion
    167         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
     166        AssertionResult satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) {
    168167                // skip unused assertions
    169                 if ( ! assn.second.isUsed ) return true;
     168                static unsigned int cnt = 0;
     169                if ( ! assn.second.isUsed ) return AssertionResult::Success;
     170
     171                if (assn.first->var->name[1] == '|') std::cerr << ++cnt << std::endl;
    170172
    171173                // find candidates that unify with the desired type
    172                 AssnCandidateList matches;
     174                AssnCandidateList matches, inexactMatches;
    173175
    174176                std::vector<ast::SymbolTable::IdData> candidates;
     
    184186                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    185187                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    186                         else if (skipUnbound) return false;
     188                        else if (skipUnbound) return AssertionResult::Skip;
    187189
    188190                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    212214
    213215                        ast::OpenVarSet closed;
    214                         findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
    215                         findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
    216                         if ( allowConversion ) {
    217                                 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
     216                        // findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     217                        findOpenVars( adjType, newOpen, closed, newNeed, have, newEnv, FirstOpen );
     218                        ast::TypeEnvironment tempNewEnv {newEnv};
     219
     220                        if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     221                                // set up binding slot for recursive assertions
     222                                ast::UniqueId crntResnSlot = 0;
     223                                if ( ! newNeed.empty() ) {
     224                                        crntResnSlot = ++globalResnSlot;
     225                                        for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     226                                }
     227
     228                                matches.emplace_back(
     229                                        cdata, adjType, std::move( tempNewEnv ), std::move( have ), std::move( newNeed ),
     230                                        std::move( newOpen ), crntResnSlot );
     231                        }
     232                        else if ( matches.empty() ) {
     233                                // restore invalidated env
     234                                // newEnv = sat.cand->env;
     235                                // newNeed.clear();
     236                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
    218237                                        // set up binding slot for recursive assertions
    219238                                        ast::UniqueId crntResnSlot = 0;
     
    223242                                        }
    224243
    225                                         matches.emplace_back(
     244                                        inexactMatches.emplace_back(
    226245                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    227246                                                std::move( newOpen ), crntResnSlot );
    228247                                }
    229248                        }
    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                         }
    244249                }
    245250
    246251                // break if no satisfying match
    247                 if ( matches.empty() ) return false;
     252                if ( matches.empty() ) matches = std::move(inexactMatches);
     253                if ( matches.empty() ) return AssertionResult::Fail;
    248254
    249255                // defer if too many satisfying matches
    250256                if ( matches.size() > 1 ) {
    251257                        sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) );
    252                         return true;
     258                        return AssertionResult::Success;
    253259                }
    254260
    255261                // otherwise bind unique match in ongoing scope
    256262                AssnCandidate & match = matches.front();
    257                 addToSymbolTable( match.have, sat.symtab );
     263                // addToSymbolTable( match.have, sat.symtab );
    258264                sat.newNeed.insert( match.need.begin(), match.need.end() );
    259265                sat.cand->env = std::move( match.env );
     
    261267
    262268                bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred );
    263                 return true;
     269                return AssertionResult::Success;
    264270        }
    265271
     
    392398                        mergeOpenVars( open, i.match.open );
    393399
    394                         if ( ! env.combine( i.match.env, open ) ) return false;
     400                        if ( ! env.combine( i.match.env, open, symtab ) ) return false;
    395401
    396402                        crnt.emplace_back( i );
     
    438444                // for each current mutually-compatible set of assertions
    439445                for ( SatState & sat : sats ) {
    440                         bool allowConversion = false;
    441446                        // stop this branch if a better option is already found
    442447                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    447452                        for (unsigned resetCount = 0; ; ++resetCount) {
    448453                                ast::AssertionList next;
    449                                 resetTyVarRenaming();
    450454                                // make initial pass at matching assertions
    451455                                for ( auto & assn : sat.need ) {
     456                                        resetTyVarRenaming();
    452457                                        // fail early if any assertion is not satisfiable
    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) {
     458                                        auto result = satisfyAssertion( assn, sat, !next.empty() );
     459                                        if ( result == AssertionResult::Fail ) {
    463460                                                Indenter tabs{ 3 };
    464461                                                std::ostringstream ss;
     
    466463                                                print( ss, *sat.cand, ++tabs );
    467464                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
    468                                                 ast::print( ss, next[0].first, tabs );
     465                                                ast::print( ss, assn.first, tabs );
    469466
    470467                                                errors.emplace_back( ss.str() );
    471468                                                goto nextSat;
    472469                                        }
    473 
    474                                         else {
    475                                                 allowConversion = true;
    476                                                 continue;
    477                                         }
    478                                 }
    479                                 allowConversion = false;
     470                                        else if ( result == AssertionResult::Skip ) {
     471                                                next.emplace_back(assn);
     472                                                // goto nextSat;
     473                                        }
     474                                }
     475                                // success
     476                                if (next.empty()) break;
     477
    480478                                sat.need = std::move(next);
    481479                        }
     
    531529                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    532530                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    533                                                 sat.cand->cost, sat.cand->cvtCost );
     531                                                sat.cand->cost );
    534532
    535533                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
     
    544542                                        for ( DeferRef r : compat.assns ) {
    545543                                                AssnCandidate match = r.match;
    546                                                 addToSymbolTable( match.have, nextSymtab );
     544                                                // addToSymbolTable( match.have, nextSymtab );
    547545                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    548546
Note: See TracChangeset for help on using the changeset viewer.