- File:
-
- 1 edited
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/SatisfyAssertions.cpp
r1958fec rb69233ac 9 9 // Author : Aaron B. Moss 10 10 // Created On : Mon Jun 10 17:45:00 2019 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Tue Oct 1 13:56:00 201913 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 10 17:45:00 2019 13 // Update Count : 1 14 14 // 15 15 … … 69 69 /// Reference to a single deferred item 70 70 struct DeferRef { 71 const ast:: VariableExpr * expr;71 const ast::DeclWithType * decl; 72 72 const ast::AssertionSetValue & info; 73 73 const AssnCandidate & match; … … 77 77 /// Acts like an indexed list of DeferRef 78 78 struct DeferItem { 79 const ast:: VariableExpr * expr;79 const ast::DeclWithType * decl; 80 80 const ast::AssertionSetValue & info; 81 81 AssnCandidateList matches; 82 82 83 83 DeferItem( 84 const ast:: VariableExpr* d, const ast::AssertionSetValue & i, AssnCandidateList && ms )85 : expr( d ), info( i ), matches( std::move( ms ) ) {}84 const ast::DeclWithType * d, const ast::AssertionSetValue & i, AssnCandidateList && ms ) 85 : decl( d ), info( i ), matches( std::move( ms ) ) {} 86 86 87 87 bool empty() const { return matches.empty(); } … … 89 89 AssnCandidateList::size_type size() const { return matches.size(); } 90 90 91 DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; }91 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; } 92 92 }; 93 93 … … 138 138 void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) { 139 139 for ( auto & i : have ) { 140 if ( i.second.isUsed ) { symtab.addId( i.first ->var); }140 if ( i.second.isUsed ) { symtab.addId( i.first ); } 141 141 } 142 142 } … … 144 144 /// Binds a single assertion, updating satisfaction state 145 145 void bindAssertion( 146 const ast:: VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand,146 const ast::DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand, 147 147 AssnCandidate & match, InferCache & inferred 148 148 ) { … … 156 156 157 157 // place newly-inferred assertion in proper location in cache 158 inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{159 candidate->uniqueId, candidate, match.adjType, expr->result, varExpr };158 inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{ 159 candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr }; 160 160 } 161 161 … … 167 167 // find candidates that unify with the desired type 168 168 AssnCandidateList matches; 169 170 std::vector<ast::SymbolTable::IdData> candidates; 171 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name); 172 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 173 // prefilter special decls by argument type, if already known 174 ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base 175 .strict_as<ast::FunctionType>()->params[0] 176 .strict_as<ast::ReferenceType>()->base; 177 sat.cand->env.apply(thisArgType); 178 179 std::string otypeKey = ""; 180 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 181 else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams); 182 183 candidates = sat.symtab.specialLookupId(kind, otypeKey); 184 } 185 else { 186 candidates = sat.symtab.lookupId(assn.first->var->name); 187 } 188 for ( const ast::SymbolTable::IdData & cdata : candidates ) { 169 for ( const ast::SymbolTable::IdData & cdata : sat.symtab.lookupId( assn.first->name ) ) { 189 170 const ast::DeclWithType * candidate = cdata.id; 190 191 // ignore deleted candidates.192 // NOTE: this behavior is different from main resolver.193 // further investigations might be needed to determine194 // if we should implement the same rule here195 // (i.e. error if unique best match is deleted)196 if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue;197 171 198 172 // build independent unification context for candidate … … 200 174 ast::TypeEnvironment newEnv{ sat.cand->env }; 201 175 ast::OpenVarSet newOpen{ sat.cand->open }; 202 ast::ptr< ast::Type > toType = assn.first-> result;176 ast::ptr< ast::Type > toType = assn.first->get_type(); 203 177 ast::ptr< ast::Type > adjType = 204 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) , GEN_USAGE, false);178 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) ); 205 179 206 180 // only keep candidates which unify … … 214 188 215 189 matches.emplace_back( 216 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),190 cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ), 217 191 std::move( newOpen ), crntResnSlot ); 218 192 } … … 255 229 InferMatcher( InferCache & inferred ) : inferred( inferred ) {} 256 230 257 const ast::Expr * post visit( const ast::Expr * expr ) {231 const ast::Expr * postmutate( const ast::Expr * expr ) { 258 232 // Skip if no slots to find 259 if ( !expr->inferred.hasSlots() ) return expr; 260 // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 261 std::vector<UniqueId> missingSlots; 233 if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr; 234 262 235 // find inferred parameters for resolution slots 263 ast::InferredParams * newInferred = new ast::InferredParams();236 ast::InferredParams newInferred; 264 237 for ( UniqueId slot : expr->inferred.resnSlots() ) { 265 238 // fail if no matching assertions found 266 239 auto it = inferred.find( slot ); 267 240 if ( it == inferred.end() ) { 268 // std::cerr << "missing assertion " << slot << std::endl; 269 missingSlots.push_back(slot); 270 continue; 241 assert(!"missing assertion"); 271 242 } 272 243 … … 274 245 for ( auto & entry : it->second ) { 275 246 // recurse on inferParams of resolved expressions 276 entry.second.expr = post visit( entry.second.expr );277 auto res = newInferred ->emplace( entry );247 entry.second.expr = postmutate( entry.second.expr ); 248 auto res = newInferred.emplace( entry ); 278 249 assert( res.second && "all assertions newly placed" ); 279 250 } … … 281 252 282 253 ast::Expr * ret = mutate( expr ); 283 ret->inferred.set_inferParams( newInferred ); 284 if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots; 254 ret->inferred.set_inferParams( std::move( newInferred ) ); 285 255 return ret; 286 256 } … … 329 299 Cost cost; 330 300 331 OutType( 332 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 301 OutType( 302 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 333 303 const std::vector< DeferRef > & as, const ast::SymbolTable & symtab ) 334 304 : env( e ), open( o ), assns( as ), cost( Cost::zero ) { … … 336 306 for ( const DeferRef & assn : assns ) { 337 307 // compute conversion cost from satisfying decl to assertion 338 cost += computeConversionCost( 339 assn.match.adjType, assn. expr->result, false, symtab, env );340 308 cost += computeConversionCost( 309 assn.match.adjType, assn.decl->get_type(), symtab, env ); 310 341 311 // mark vars+specialization on function-type assertions 342 const ast::FunctionType * func = 312 const ast::FunctionType * func = 343 313 GenPoly::getFunctionType( assn.match.cdata.id->get_type() ); 344 314 if ( ! func ) continue; 345 315 346 for ( const a uto ¶m : func->params ) {347 cost.decSpec( specCost( param ) );316 for ( const ast::DeclWithType * param : func->params ) { 317 cost.decSpec( specCost( param->get_type() ) ); 348 318 } 349 319 350 320 cost.incVar( func->forall.size() ); 351 352 cost.decSpec( func->assertions.size() ); 321 322 for ( const ast::TypeDecl * td : func->forall ) { 323 cost.decSpec( td->assertions.size() ); 324 } 353 325 } 354 326 } … … 357 329 }; 358 330 359 CandidateEnvMerger( 360 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 331 CandidateEnvMerger( 332 const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 361 333 const ast::SymbolTable & syms ) 362 334 : crnt(), envs{ env }, opens{ open }, symtab( syms ) {} … … 385 357 386 358 /// Limit to depth of recursion of assertion satisfaction 387 static const int recursionLimit = 8;359 static const int recursionLimit = 4; 388 360 /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of 389 361 static const int deferLimit = 10; … … 417 389 if ( it != thresholds.end() && it->second < sat.costs ) goto nextSat; 418 390 419 // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen. 420 for (unsigned resetCount = 0; ; ++resetCount) { 421 ast::AssertionList next; 422 resetTyVarRenaming(); 423 // make initial pass at matching assertions 424 for ( auto & assn : sat.need ) { 425 // fail early if any assertion is not satisfiable 426 if ( ! satisfyAssertion( assn, sat ) ) { 427 next.emplace_back(assn); 428 // goto nextSat; 429 } 430 } 431 // success 432 if (next.empty()) break; 433 // fail if nothing resolves 434 else if (next.size() == sat.need.size()) { 391 // make initial pass at matching assertions 392 for ( auto & assn : sat.need ) { 393 // fail early if any assertion is not satisfiable 394 if ( ! satisfyAssertion( assn, sat ) ) { 435 395 Indenter tabs{ 3 }; 436 396 std::ostringstream ss; … … 438 398 print( ss, *sat.cand, ++tabs ); 439 399 ss << (tabs-1) << "Could not satisfy assertion:\n"; 440 ast::print( ss, next[0].first, tabs );400 ast::print( ss, assn.first, tabs ); 441 401 442 402 errors.emplace_back( ss.str() ); 443 403 goto nextSat; 444 404 } 445 sat.need = std::move(next);446 405 } 447 406 … … 462 421 ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n"; 463 422 for ( const auto & d : sat.deferred ) { 464 ast::print( ss, d. expr, tabs );423 ast::print( ss, d.decl, tabs ); 465 424 } 466 425 … … 480 439 ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n"; 481 440 for ( const auto& d : sat.deferred ) { 482 ast::print( ss, d. expr, tabs );441 ast::print( ss, d.decl, tabs ); 483 442 } 484 443 … … 512 471 nextNewNeed.insert( match.need.begin(), match.need.end() ); 513 472 514 bindAssertion( r. expr, r.info, nextCand, match, nextInferred );473 bindAssertion( r.decl, r.info, nextCand, match, nextInferred ); 515 474 } 516 475
Note:
See TracChangeset
for help on using the changeset viewer.