Ignore:
Timestamp:
Jun 21, 2023, 2:38:55 AM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
92355883
Parents:
0b0a285 (diff), 2de175ce (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SatisfyAssertions.cpp

    r0b0a285 rc84dd61  
    1616#include "SatisfyAssertions.hpp"
    1717
     18#include <iostream>
    1819#include <algorithm>
    1920#include <cassert>
     
    4546#include "SymTab/Mangler.h"
    4647
     48
     49
    4750namespace ResolvExpr {
    4851
     
    6568                        ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs )
    6669                : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ),
    67                   need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {}
     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                  }
    6875        };
    6976
     
    139146        };
    140147
    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         }
     148        enum AssertionResult {Fail, Skip, Success} ;
    147149
    148150        /// Binds a single assertion, updating satisfaction state
     
    155157                        "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    156158
    157                 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost );
     159                ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost );
    158160                varExpr->result = match.adjType;
    159161                if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); }
     
    165167
    166168        /// Satisfy a single assertion
    167         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
     169        AssertionResult satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) {
    168170                // skip unused assertions
    169                 if ( ! assn.second.isUsed ) return true;
     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
    170175
    171176                // find candidates that unify with the desired type
    172                 AssnCandidateList matches;
     177                AssnCandidateList matches, inexactMatches;
    173178
    174179                std::vector<ast::SymbolTable::IdData> candidates;
     
    179184                                .strict_as<ast::FunctionType>()->params[0]
    180185                                .strict_as<ast::ReferenceType>()->base;
    181                         sat.cand->env.apply(thisArgType);
     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                        }
    182192
    183193                        std::string otypeKey = "";
    184194                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    185195                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
    186                         else if (skipUnbound) return false;
     196                        else if (skipUnbound) return AssertionResult::Skip;
    187197
    188198                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    212222
    213223                        ast::OpenVarSet closed;
    214                         findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
    215                         findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
    216                         if ( allowConversion ) {
     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();
    217244                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    218245                                        // set up binding slot for recursive assertions
     
    223250                                        }
    224251
    225                                         matches.emplace_back(
     252                                        inexactMatches.emplace_back(
    226253                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    227254                                                std::move( newOpen ), crntResnSlot );
    228255                                }
    229256                        }
    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                         }
    244257                }
    245258
    246259                // break if no satisfying match
    247                 if ( matches.empty() ) return false;
     260                if ( matches.empty() ) matches = std::move(inexactMatches);
     261                if ( matches.empty() ) return AssertionResult::Fail;
    248262
    249263                // defer if too many satisfying matches
    250264                if ( matches.size() > 1 ) {
    251265                        sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) );
    252                         return true;
     266                        return AssertionResult::Success;
    253267                }
    254268
    255269                // otherwise bind unique match in ongoing scope
    256270                AssnCandidate & match = matches.front();
    257                 addToSymbolTable( match.have, sat.symtab );
     271                // addToSymbolTable( match.have, sat.symtab );
    258272                sat.newNeed.insert( match.need.begin(), match.need.end() );
    259273                sat.cand->env = std::move( match.env );
     
    261275
    262276                bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred );
    263                 return true;
     277                return AssertionResult::Success;
    264278        }
    265279
     
    438452                // for each current mutually-compatible set of assertions
    439453                for ( SatState & sat : sats ) {
    440                         bool allowConversion = false;
    441454                        // stop this branch if a better option is already found
    442455                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    447460                        for (unsigned resetCount = 0; ; ++resetCount) {
    448461                                ast::AssertionList next;
    449                                 resetTyVarRenaming();
    450462                                // make initial pass at matching assertions
    451463                                for ( auto & assn : sat.need ) {
     464                                        resetTyVarRenaming();
    452465                                        // 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) {
     466                                        auto result = satisfyAssertion( assn, sat, !next.empty() );
     467                                        if ( result == AssertionResult::Fail ) {
    463468                                                Indenter tabs{ 3 };
    464469                                                std::ostringstream ss;
     
    466471                                                print( ss, *sat.cand, ++tabs );
    467472                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
    468                                                 ast::print( ss, next[0].first, tabs );
     473                                                ast::print( ss, assn.first, tabs );
    469474
    470475                                                errors.emplace_back( ss.str() );
    471476                                                goto nextSat;
    472477                                        }
    473 
    474                                         else {
    475                                                 allowConversion = true;
    476                                                 continue;
    477                                         }
    478                                 }
    479                                 allowConversion = false;
     478                                        else if ( result == AssertionResult::Skip ) {
     479                                                next.emplace_back(assn);
     480                                                // goto nextSat;
     481                                        }
     482                                }
     483                                // success
     484                                if (next.empty()) break;
     485
    480486                                sat.need = std::move(next);
    481487                        }
     
    531537                                                sat.cand->expr, std::move( compat.env ), std::move( compat.open ),
    532538                                                ast::AssertionSet{} /* need moved into satisfaction state */,
    533                                                 sat.cand->cost, sat.cand->cvtCost );
     539                                                sat.cand->cost );
    534540
    535541                                        ast::AssertionSet nextNewNeed{ sat.newNeed };
     
    544550                                        for ( DeferRef r : compat.assns ) {
    545551                                                AssnCandidate match = r.match;
    546                                                 addToSymbolTable( match.have, nextSymtab );
     552                                                // addToSymbolTable( match.have, nextSymtab );
    547553                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    548554
Note: See TracChangeset for help on using the changeset viewer.