Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r34b4268 r251ce80  
    1616#include "SatisfyAssertions.hpp"
    1717
    18 #include <iostream>
    1918#include <algorithm>
    2019#include <cassert>
     
    2423#include <vector>
    2524
     25#include "AdjustExprType.hpp"
    2626#include "Candidate.hpp"
    2727#include "CandidateFinder.hpp"
     28#include "CommonType.hpp"
    2829#include "Cost.h"
    2930#include "RenameVars.h"
     31#include "SpecCost.hpp"
    3032#include "typeops.h"
    3133#include "Unify.h"
     
    4345#include "SymTab/Mangler.h"
    4446
    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 ) {
    68                         if (!have.empty()) {
    69                                 std::cerr << c.id->location << ':' << c.id->name << std::endl;
    70                         }
    71                   }
     67                  need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
    7268        };
    7369
     
    143139        };
    144140
    145         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        }
    146147
    147148        /// Binds a single assertion, updating satisfaction state
     
    154155                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    155156
    156                 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost );
     157                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
    157158                varExpr->result = match.adjType;
    158159                if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); }
     
    164165
    165166        /// Satisfy a single assertion
    166         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) {
    167168                // skip unused assertions
    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;
     169                if ( ! assn.second.isUsed ) return true;
    172170
    173171                // find candidates that unify with the desired type
    174                 AssnCandidateList matches, inexactMatches;
     172                AssnCandidateList matches;
    175173
    176174                std::vector<ast::SymbolTable::IdData> candidates;
     
    186184                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    187185                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    188                         else if (skipUnbound) return AssertionResult::Skip;
     186                        else if (skipUnbound) return false;
    189187
    190188                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    214212
    215213                        ast::OpenVarSet closed;
    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 ) ) {
     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} ) ) {
    237218                                        // set up binding slot for recursive assertions
    238219                                        ast::UniqueId crntResnSlot = 0;
     
    242223                                        }
    243224
    244                                         inexactMatches.emplace_back(
     225                                        matches.emplace_back(
    245226                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    246227                                                std::move( newOpen ), crntResnSlot );
    247228                                }
    248229                        }
     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                        }
    249244                }
    250245
    251246                // break if no satisfying match
    252                 if ( matches.empty() ) matches = std::move(inexactMatches);
    253                 if ( matches.empty() ) return AssertionResult::Fail;
     247                if ( matches.empty() ) return false;
    254248
    255249                // defer if too many satisfying matches
    256250                if ( matches.size() > 1 ) {
    257251                        sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) );
    258                         return AssertionResult::Success;
     252                        return true;
    259253                }
    260254
    261255                // otherwise bind unique match in ongoing scope
    262256                AssnCandidate & match = matches.front();
    263                 // addToSymbolTable( match.have, sat.symtab );
     257                addToSymbolTable( match.have, sat.symtab );
    264258                sat.newNeed.insert( match.need.begin(), match.need.end() );
    265259                sat.cand->env = std::move( match.env );
     
    267261
    268262                bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred );
    269                 return AssertionResult::Success;
     263                return true;
    270264        }
    271265
     
    398392                        mergeOpenVars( open, i.match.open );
    399393
    400                         if ( ! env.combine( i.match.env, open, symtab ) ) return false;
     394                        if ( ! env.combine( i.match.env, open ) ) return false;
    401395
    402396                        crnt.emplace_back( i );
     
    444438                // for each current mutually-compatible set of assertions
    445439                for ( SatState & sat : sats ) {
     440                        bool allowConversion = false;
    446441                        // stop this branch if a better option is already found
    447442                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    452447                        for (unsigned resetCount = 0; ; ++resetCount) {
    453448                                ast::AssertionList next;
     449                                resetTyVarRenaming();
    454450                                // make initial pass at matching assertions
    455451                                for ( auto & assn : sat.need ) {
    456                                         resetTyVarRenaming();
    457452                                        // fail early if any assertion is not satisfiable
    458                                         auto result = satisfyAssertion( assn, sat, !next.empty() );
    459                                         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) {
    460463                                                Indenter tabs{ 3 };
    461464                                                std::ostringstream ss;
     
    463466                                                print( ss, *sat.cand, ++tabs );
    464467                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
    465                                                 ast::print( ss, assn.first, tabs );
     468                                                ast::print( ss, next[0].first, tabs );
    466469
    467470                                                errors.emplace_back( ss.str() );
    468471                                                goto nextSat;
    469472                                        }
    470                                         else if ( result == AssertionResult::Skip ) {
    471                                                 next.emplace_back(assn);
    472                                                 // goto nextSat;
    473                                         }
    474                                 }
    475                                 // success
    476                                 if (next.empty()) break;
    477 
     473
     474                                        else {
     475                                                allowConversion = true;
     476                                                continue;
     477                                        }
     478                                }
     479                                allowConversion = false;
    478480                                sat.need = std::move(next);
    479481                        }
     
    529531                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    530532                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    531                                                 sat.cand->cost );
     533                                                sat.cand->cost, sat.cand->cvtCost );
    532534
    533535                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
     
    542544                                        for ( DeferRef r : compat.assns ) {
    543545                                                AssnCandidate match = r.match;
    544                                                 // addToSymbolTable( match.have, nextSymtab );
     546                                                addToSymbolTable( match.have, nextSymtab );
    545547                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    546548
Note: See TracChangeset for help on using the changeset viewer.