- File:
-
- 1 edited
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/SatisfyAssertions.cpp
r34b4268 r251ce80 16 16 #include "SatisfyAssertions.hpp" 17 17 18 #include <iostream>19 18 #include <algorithm> 20 19 #include <cassert> … … 24 23 #include <vector> 25 24 25 #include "AdjustExprType.hpp" 26 26 #include "Candidate.hpp" 27 27 #include "CandidateFinder.hpp" 28 #include "CommonType.hpp" 28 29 #include "Cost.h" 29 30 #include "RenameVars.h" 31 #include "SpecCost.hpp" 30 32 #include "typeops.h" 31 33 #include "Unify.h" … … 43 45 #include "SymTab/Mangler.h" 44 46 45 46 47 47 namespace ResolvExpr { 48 48 … … 65 65 ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs ) 66 66 : 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 ) {} 72 68 }; 73 69 … … 143 139 }; 144 140 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 } 146 147 147 148 /// Binds a single assertion, updating satisfaction state … … 154 155 "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 155 156 156 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->c ost );157 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cvtCost ); 157 158 varExpr->result = match.adjType; 158 159 if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); } … … 164 165 165 166 /// 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) { 167 168 // 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; 172 170 173 171 // find candidates that unify with the desired type 174 AssnCandidateList matches , inexactMatches;172 AssnCandidateList matches; 175 173 176 174 std::vector<ast::SymbolTable::IdData> candidates; … … 186 184 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 187 185 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; 189 187 190 188 candidates = sat.symtab.specialLookupId(kind, otypeKey); … … 214 212 215 213 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} ) ) { 237 218 // set up binding slot for recursive assertions 238 219 ast::UniqueId crntResnSlot = 0; … … 242 223 } 243 224 244 inexactMatches.emplace_back(225 matches.emplace_back( 245 226 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 246 227 std::move( newOpen ), crntResnSlot ); 247 228 } 248 229 } 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 } 249 244 } 250 245 251 246 // 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; 254 248 255 249 // defer if too many satisfying matches 256 250 if ( matches.size() > 1 ) { 257 251 sat.deferred.emplace_back( assn.first, assn.second, std::move( matches ) ); 258 return AssertionResult::Success;252 return true; 259 253 } 260 254 261 255 // otherwise bind unique match in ongoing scope 262 256 AssnCandidate & match = matches.front(); 263 //addToSymbolTable( match.have, sat.symtab );257 addToSymbolTable( match.have, sat.symtab ); 264 258 sat.newNeed.insert( match.need.begin(), match.need.end() ); 265 259 sat.cand->env = std::move( match.env ); … … 267 261 268 262 bindAssertion( assn.first, assn.second, sat.cand, match, sat.inferred ); 269 return AssertionResult::Success;263 return true; 270 264 } 271 265 … … 398 392 mergeOpenVars( open, i.match.open ); 399 393 400 if ( ! env.combine( i.match.env, open , symtab) ) return false;394 if ( ! env.combine( i.match.env, open ) ) return false; 401 395 402 396 crnt.emplace_back( i ); … … 444 438 // for each current mutually-compatible set of assertions 445 439 for ( SatState & sat : sats ) { 440 bool allowConversion = false; 446 441 // stop this branch if a better option is already found 447 442 auto it = thresholds.find( pruneKey( *sat.cand ) ); … … 452 447 for (unsigned resetCount = 0; ; ++resetCount) { 453 448 ast::AssertionList next; 449 resetTyVarRenaming(); 454 450 // make initial pass at matching assertions 455 451 for ( auto & assn : sat.need ) { 456 resetTyVarRenaming();457 452 // 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) { 460 463 Indenter tabs{ 3 }; 461 464 std::ostringstream ss; … … 463 466 print( ss, *sat.cand, ++tabs ); 464 467 ss << (tabs-1) << "Could not satisfy assertion:\n"; 465 ast::print( ss, assn.first, tabs );468 ast::print( ss, next[0].first, tabs ); 466 469 467 470 errors.emplace_back( ss.str() ); 468 471 goto nextSat; 469 472 } 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; 478 480 sat.need = std::move(next); 479 481 } … … 529 531 sat.cand->expr, std::move( compat.env ), std::move( compat.open ), 530 532 ast::AssertionSet{} /* need moved into satisfaction state */, 531 sat.cand->cost );533 sat.cand->cost, sat.cand->cvtCost ); 532 534 533 535 ast::AssertionSet nextNewNeed{ sat.newNeed }; … … 542 544 for ( DeferRef r : compat.assns ) { 543 545 AssnCandidate match = r.match; 544 //addToSymbolTable( match.have, nextSymtab );546 addToSymbolTable( match.have, nextSymtab ); 545 547 nextNewNeed.insert( match.need.begin(), match.need.end() ); 546 548
Note:
See TracChangeset
for help on using the changeset viewer.