Changeset c84dd61 for src/ResolvExpr/SatisfyAssertions.cpp
- Timestamp:
- Jun 21, 2023, 2:38:55 AM (2 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/SatisfyAssertions.cpp
r0b0a285 rc84dd61 16 16 #include "SatisfyAssertions.hpp" 17 17 18 #include <iostream> 18 19 #include <algorithm> 19 20 #include <cassert> … … 45 46 #include "SymTab/Mangler.h" 46 47 48 49 47 50 namespace ResolvExpr { 48 51 … … 65 68 ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs ) 66 69 : 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 } 68 75 }; 69 76 … … 139 146 }; 140 147 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} ; 147 149 148 150 /// Binds a single assertion, updating satisfaction state … … 155 157 "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 156 158 157 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->c vtCost );159 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost ); 158 160 varExpr->result = match.adjType; 159 161 if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); } … … 165 167 166 168 /// 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) { 168 170 // 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 170 175 171 176 // find candidates that unify with the desired type 172 AssnCandidateList matches ;177 AssnCandidateList matches, inexactMatches; 173 178 174 179 std::vector<ast::SymbolTable::IdData> candidates; … … 179 184 .strict_as<ast::FunctionType>()->params[0] 180 185 .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 } 182 192 183 193 std::string otypeKey = ""; 184 194 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 185 195 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; 187 197 188 198 candidates = sat.symtab.specialLookupId(kind, otypeKey); … … 212 222 213 223 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(); 217 244 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 218 245 // set up binding slot for recursive assertions … … 223 250 } 224 251 225 matches.emplace_back(252 inexactMatches.emplace_back( 226 253 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 227 254 std::move( newOpen ), crntResnSlot ); 228 255 } 229 256 } 230 else {231 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {232 // set up binding slot for recursive assertions233 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 }244 257 } 245 258 246 259 // 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; 248 262 249 263 // defer if too many satisfying matches 250 264 if ( matches.size() > 1 ) { 251 265 sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) ); 252 return true;266 return AssertionResult::Success; 253 267 } 254 268 255 269 // otherwise bind unique match in ongoing scope 256 270 AssnCandidate & match = matches.front(); 257 addToSymbolTable( match.have, sat.symtab );271 // addToSymbolTable( match.have, sat.symtab ); 258 272 sat.newNeed.insert( match.need.begin(), match.need.end() ); 259 273 sat.cand->env = std::move( match.env ); … … 261 275 262 276 bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred ); 263 return true;277 return AssertionResult::Success; 264 278 } 265 279 … … 438 452 // for each current mutually-compatible set of assertions 439 453 for ( SatState & sat : sats ) { 440 bool allowConversion = false;441 454 // stop this branch if a better option is already found 442 455 auto it = thresholds.find( pruneKey( *sat.cand ) ); … … 447 460 for (unsigned resetCount = 0; ; ++resetCount) { 448 461 ast::AssertionList next; 449 resetTyVarRenaming();450 462 // make initial pass at matching assertions 451 463 for ( auto & assn : sat.need ) { 464 resetTyVarRenaming(); 452 465 // 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 ) { 463 468 Indenter tabs{ 3 }; 464 469 std::ostringstream ss; … … 466 471 print( ss, *sat.cand, ++tabs ); 467 472 ss << (tabs-1) << "Could not satisfy assertion:\n"; 468 ast::print( ss, next[0].first, tabs );473 ast::print( ss, assn.first, tabs ); 469 474 470 475 errors.emplace_back( ss.str() ); 471 476 goto nextSat; 472 477 } 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 480 486 sat.need = std::move(next); 481 487 } … … 531 537 sat.cand->expr, std::move( compat.env ), std::move( compat.open ), 532 538 ast::AssertionSet{} /* need moved into satisfaction state */, 533 sat.cand->cost , sat.cand->cvtCost);539 sat.cand->cost ); 534 540 535 541 ast::AssertionSet nextNewNeed{ sat.newNeed }; … … 544 550 for ( DeferRef r : compat.assns ) { 545 551 AssnCandidate match = r.match; 546 addToSymbolTable( match.have, nextSymtab );552 // addToSymbolTable( match.have, nextSymtab ); 547 553 nextNewNeed.insert( match.need.begin(), match.need.end() ); 548 554
Note:
See TracChangeset
for help on using the changeset viewer.