Ignore:
Timestamp:
Sep 20, 2022, 6:34:55 PM (2 years ago)
Author:
Fangren Yu <f37yu@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
79ae13d, a065f1f
Parents:
8f1e035
Message:

try to make parameter qualifier conversion work for assertions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r8f1e035 ref1da0e2  
    3636#include "AST/SymbolTable.hpp"
    3737#include "AST/TypeEnvironment.hpp"
     38#include "FindOpenVars.h"
    3839#include "Common/FilterCombos.h"
    3940#include "Common/Indenter.h"
     
    161162
    162163        /// Satisfy a single assertion
    163         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat ) {
     164        bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
    164165                // skip unused assertions
    165166                if ( ! assn.second.isUsed ) return true;
     
    180181                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    181182                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
     183                        else if (skipUnbound) return false;
    182184
    183185                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    205207
    206208                        // only keep candidates which unify
    207                         if ( unify( toType, adjType, newEnv, newNeed, have, newOpen, sat.symtab ) ) {
    208                                 // set up binding slot for recursive assertions
    209                                 ast::UniqueId crntResnSlot = 0;
    210                                 if ( ! newNeed.empty() ) {
    211                                         crntResnSlot = ++globalResnSlot;
    212                                         for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
    213                                 }
    214 
    215                                 matches.emplace_back(
    216                                         cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    217                                         std::move( newOpen ), crntResnSlot );
     209
     210                        ast::OpenVarSet closed;
     211                        findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     212                        findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
     213                        if ( allowConversion ) {
     214                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     215                                        // set up binding slot for recursive assertions
     216                                        ast::UniqueId crntResnSlot = 0;
     217                                        if ( ! newNeed.empty() ) {
     218                                                crntResnSlot = ++globalResnSlot;
     219                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     220                                        }
     221
     222                                        matches.emplace_back(
     223                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     224                                                std::move( newOpen ), crntResnSlot );
     225                                }
     226                        }
     227                        else {
     228                                if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     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( newEnv ), std::move( have ), std::move( newNeed ),
     238                                                std::move( newOpen ), crntResnSlot );
     239                                }
    218240                        }
    219241                }
     
    413435                // for each current mutually-compatible set of assertions
    414436                for ( SatState & sat : sats ) {
     437                        bool allowConversion = false;
    415438                        // stop this branch if a better option is already found
    416439                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    418441
    419442                        // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen.
     443
    420444                        for (unsigned resetCount = 0; ; ++resetCount) {
    421445                                ast::AssertionList next;
     
    424448                                for ( auto & assn : sat.need ) {
    425449                                        // fail early if any assertion is not satisfiable
    426                                         if ( ! satisfyAssertion( assn, sat ) ) {
     450                                        if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) {
    427451                                                next.emplace_back(assn);
    428452                                                // goto nextSat;
     
    433457                                // fail if nothing resolves
    434458                                else if (next.size() == sat.need.size()) {
    435                                         Indenter tabs{ 3 };
    436                                         std::ostringstream ss;
    437                                         ss << tabs << "Unsatisfiable alternative:\n";
    438                                         print( ss, *sat.cand, ++tabs );
    439                                         ss << (tabs-1) << "Could not satisfy assertion:\n";
    440                                         ast::print( ss, next[0].first, tabs );
    441 
    442                                         errors.emplace_back( ss.str() );
    443                                         goto nextSat;
    444                                 }
     459                                        if (allowConversion) {
     460                                                Indenter tabs{ 3 };
     461                                                std::ostringstream ss;
     462                                                ss << tabs << "Unsatisfiable alternative:\n";
     463                                                print( ss, *sat.cand, ++tabs );
     464                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
     465                                                ast::print( ss, next[0].first, tabs );
     466
     467                                                errors.emplace_back( ss.str() );
     468                                                goto nextSat;
     469                                        }
     470
     471                                        else {
     472                                                allowConversion = true;
     473                                                continue;
     474                                        }
     475                                }
     476                                allowConversion = false;
    445477                                sat.need = std::move(next);
    446478                        }
Note: See TracChangeset for help on using the changeset viewer.