Changes in / [9795142:c378e5e]
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/ResolveAssertions.cc
r9795142 rc378e5e 35 35 #include "SynTree/Expression.h" // for InferredParams 36 36 #include "TypeEnvironment.h" // for TypeEnvironment, etc. 37 #include "typeops.h" // for adjustExprType , specCost37 #include "typeops.h" // for adjustExprType 38 38 #include "Unify.h" // for unify 39 39 … … 58 58 using CandidateList = std::vector<AssnCandidate>; 59 59 60 /// Unique identifier for a yet-to-be-resolved assertion 61 struct AssnId { 62 DeclarationWithType* decl; ///< Declaration of assertion 63 AssertionSetValue info; ///< Information about assertion 64 65 AssnId(DeclarationWithType* decl, const AssertionSetValue& info) : decl(decl), info(info) {} 66 }; 67 68 /// Cached assertion items 69 struct AssnCacheItem { 70 CandidateList matches; ///< Possible matches for this assertion 71 std::vector<AssnId> deferIds; ///< Deferred assertions which resolve to this item 72 73 AssnCacheItem( CandidateList&& m ) : matches(std::move(m)), deferIds() {} 74 }; 75 76 /// Cache of resolved assertions 77 using AssnCache = std::unordered_map<std::string, AssnCacheItem>; 78 60 79 /// Reference to single deferred item 61 80 struct DeferRef { 62 const DeclarationWithType* decl; 63 const AssertionSetValue& info; 81 const AssnCacheItem& item; 64 82 const AssnCandidate& match; 65 83 }; … … 68 86 /// Acts like indexed list of DeferRef 69 87 struct DeferItem { 70 const DeclarationWithType* decl; 71 const AssertionSetValue& info; 72 CandidateList matches; 73 74 DeferItem( DeclarationWithType* decl, const AssertionSetValue& info, CandidateList&& matches ) 75 : decl(decl), info(info), matches(std::move(matches)) {} 76 77 bool empty() const { return matches.empty(); } 78 79 CandidateList::size_type size() const { return matches.size(); } 80 81 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; } 88 const AssnCache* cache; ///< Cache storing assertion item 89 std::string key; ///< Key into cache 90 91 DeferItem( const AssnCache& cache, const std::string& key ) : cache(&cache), key(key) {} 92 93 bool empty() const { return cache->at(key).matches.empty(); } 94 95 CandidateList::size_type size() const { return cache->at(key).matches.size(); } 96 97 DeferRef operator[] ( unsigned i ) const { 98 const AssnCacheItem& item = cache->at(key); 99 return { item, item.matches[i] }; 100 } 101 102 const DeclarationWithType* get_decl() const { return cache->at(key).deferIds[0].decl; } 103 104 // sortable by key 105 // TODO look into optimizing combination process with other sort orders (e.g. by number 106 // of matches in candidate) 107 bool operator< ( const DeferItem& o ) const { return key < o.key; } 108 bool operator== ( const DeferItem& o ) const { return key == o.key; } 82 109 }; 83 110 … … 154 181 for ( const auto& assn : x.assns ) { 155 182 k += computeConversionCost( 156 assn.match.adjType, assn.decl->get_type(), indexer, x.env ); 183 assn.match.adjType, assn.item.deferIds[0].decl->get_type(), indexer, 184 x.env ); 157 185 } 158 186 it = cache.emplace_hint( it, &x, k ); … … 225 253 226 254 /// Resolve a single assertion, in context 227 bool resolveAssertion( AssertionItem& assn, ResnState& resn ) {255 bool resolveAssertion( AssertionItem& assn, ResnState& resn, AssnCache& cache ) { 228 256 // skip unused assertions 229 257 if ( ! assn.info.isUsed ) return true; 230 258 231 // lookup candidates for this assertion 232 std::list< SymTab::Indexer::IdData > candidates; 233 resn.indexer.lookupId( assn.decl->name, candidates ); 234 235 // find the candidates that unify with the desired type 236 CandidateList matches; 237 for ( const auto& cdata : candidates ) { 238 DeclarationWithType* candidate = cdata.id; 239 240 // build independent unification context for candidate 241 AssertionSet have, newNeed; 242 TypeEnvironment newEnv{ resn.alt.env }; 243 OpenVarSet newOpenVars{ resn.alt.openVars }; 244 Type* adjType = candidate->get_type()->clone(); 245 adjustExprType( adjType, newEnv, resn.indexer ); 246 renameTyVars( adjType ); 247 248 // keep unifying candidates 249 if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars, 250 resn.indexer ) ) { 251 // set up binding slot for recursive assertions 252 UniqueId crntResnSlot = 0; 253 if ( ! newNeed.empty() ) { 254 crntResnSlot = ++globalResnSlot; 255 for ( auto& a : newNeed ) { 256 a.second.resnSlot = crntResnSlot; 259 // check cache for this assertion 260 std::string assnKey = SymTab::Mangler::mangleAssnKey( assn.decl, resn.alt.env ); 261 auto it = cache.find( assnKey ); 262 263 // attempt to resolve assertion if this is the first time seen 264 if ( it == cache.end() ) { 265 // lookup candidates for this assertion 266 std::list< SymTab::Indexer::IdData > candidates; 267 resn.indexer.lookupId( assn.decl->name, candidates ); 268 269 // find the candidates that unify with the desired type 270 CandidateList matches; 271 for ( const auto& cdata : candidates ) { 272 DeclarationWithType* candidate = cdata.id; 273 274 // build independent unification context for candidate 275 AssertionSet have, newNeed; 276 TypeEnvironment newEnv{ resn.alt.env }; 277 OpenVarSet newOpenVars{ resn.alt.openVars }; 278 Type* adjType = candidate->get_type()->clone(); 279 adjustExprType( adjType, newEnv, resn.indexer ); 280 renameTyVars( adjType ); 281 282 // keep unifying candidates 283 if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars, 284 resn.indexer ) ) { 285 // set up binding slot for recursive assertions 286 UniqueId crntResnSlot = 0; 287 if ( ! newNeed.empty() ) { 288 crntResnSlot = ++globalResnSlot; 289 for ( auto& a : newNeed ) { 290 a.second.resnSlot = crntResnSlot; 291 } 257 292 } 258 } 259 260 matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have),261 std::move(newNeed), std::move(newOpenVars), crntResnSlot );262 } else {263 delete adjType;293 294 matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have), 295 std::move(newNeed), std::move(newOpenVars), crntResnSlot ); 296 } else { 297 delete adjType; 298 } 264 299 } 265 } 300 301 it = cache.emplace_hint( it, assnKey, AssnCacheItem{ std::move(matches) } ); 302 } 303 304 CandidateList& matches = it->second.matches; 266 305 267 306 // break if no suitable assertion … … 270 309 // defer if too many suitable assertions 271 310 if ( matches.size() > 1 ) { 272 resn.deferred.emplace_back( assn.decl, assn.info, std::move(matches) ); 311 it->second.deferIds.emplace_back( assn.decl, assn.info ); 312 resn.deferred.emplace_back( cache, assnKey ); 273 313 return true; 274 314 } … … 278 318 addToIndexer( match.have, resn.indexer ); 279 319 resn.newNeed.insert( match.need.begin(), match.need.end() ); 280 resn.alt.env = std::move(match.env);281 resn.alt.openVars = std::move(match.openVars);320 resn.alt.env = match.env; 321 resn.alt.openVars = match.openVars; 282 322 283 323 bindAssertion( assn.decl, assn.info, resn.alt, match, resn.inferred ); … … 340 380 ResnList resns{ ResnState{ alt, root_indexer } }; 341 381 ResnList new_resns{}; 382 AssnCache assnCache; 342 383 343 384 // resolve assertions in breadth-first-order up to a limited number of levels deep … … 348 389 for ( auto& assn : resn.need ) { 349 390 // fail early if any assertion is not resolvable 350 if ( ! resolveAssertion( assn, resn ) ) {391 if ( ! resolveAssertion( assn, resn, assnCache ) ) { 351 392 Indenter tabs{ Indenter::tabsize, 3 }; 352 393 std::ostringstream ss; … … 369 410 } 370 411 } else { 412 // only resolve each deferred assertion once 413 std::sort( resn.deferred.begin(), resn.deferred.end() ); 414 auto last = std::unique( resn.deferred.begin(), resn.deferred.end() ); 415 resn.deferred.erase( last, resn.deferred.end() ); 371 416 // resolve deferred assertions by mutual compatibility 372 417 std::vector<CandidateEnvMerger::OutType> compatible = filterCombos( … … 382 427 ++tabs; 383 428 for ( const auto& d : resn.deferred ) { 384 d. decl->print( ss, tabs );429 d.get_decl()->print( ss, tabs ); 385 430 } 386 431 … … 413 458 new_resn.newNeed.insert( match.need.begin(), match.need.end() ); 414 459 415 bindAssertion( r.decl, r.info, new_resn.alt, match, new_resn.inferred ); 460 // for each deferred assertion with the same form 461 for ( AssnId id : r.item.deferIds ) { 462 bindAssertion( 463 id.decl, id.info, new_resn.alt, match, new_resn.inferred ); 464 } 416 465 } 417 466 -
src/SymTab/Mangler.cc
r9795142 rc378e5e 38 38 struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards { 39 39 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ); 40 Mangler( const ResolvExpr::TypeEnvironment& env ); 40 41 Mangler( const Mangler & ) = delete; 41 42 … … 66 67 private: 67 68 std::ostringstream mangleName; ///< Mangled name being constructed 68 typedef std::map< std::string, std::pair< int, int > > VarMapType;69 typedef std::map< std::string, std::pair< std::string, int > > VarMapType; 69 70 VarMapType varNums; ///< Map of type variables to indices 70 71 int nextVarNum; ///< Next type variable index 72 const ResolvExpr::TypeEnvironment* env; ///< optional environment for substitutions 71 73 bool isTopLevel; ///< Is the Mangler at the top level 72 74 bool mangleOverridable; ///< Specially mangle overridable built-in methods … … 78 80 public: 79 81 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 80 int nextVarNum, const VarMapType& varNums ); 82 int nextVarNum, const ResolvExpr::TypeEnvironment* env, 83 const VarMapType& varNums ); 81 84 82 85 private: … … 106 109 } 107 110 111 std::string mangleAssnKey( DeclarationWithType* decl, 112 const ResolvExpr::TypeEnvironment& env ) { 113 PassVisitor<Mangler> mangler( env ); 114 maybeAccept( decl, mangler ); 115 return mangler.pass.get_mangleName(); 116 } 117 108 118 namespace { 109 119 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 110 : nextVarNum( 0 ), isTopLevel( true ),120 : nextVarNum( 0 ), env(nullptr), isTopLevel( true ), 111 121 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 112 122 mangleGenericParams( mangleGenericParams ) {} 113 123 124 Mangler::Mangler( const ResolvExpr::TypeEnvironment& env ) 125 : nextVarNum( 0 ), env( &env ), isTopLevel( true ), mangleOverridable( false ), 126 typeMode( false ), mangleGenericParams( true ) {} 127 114 128 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 115 int nextVarNum, const VarMapType& varNums ) 116 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 129 int nextVarNum, const ResolvExpr::TypeEnvironment* env, 130 const VarMapType& varNums ) 131 : varNums( varNums ), nextVarNum( nextVarNum ), env( env ), isTopLevel( false ), 117 132 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 118 133 mangleGenericParams( mangleGenericParams ) {} … … 343 358 assert( false ); 344 359 } // switch 345 varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() ); 360 std::string varName; 361 // replace type with substitution name if environment is available and bound 362 if ( env ) { 363 const ResolvExpr::EqvClass* varClass = env->lookup( (*i)->name ); 364 if ( varClass && varClass->type ) { 365 PassVisitor<Mangler> sub_mangler( 366 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, 367 env, varNums ); 368 varClass->type->accept( sub_mangler ); 369 varName = std::string{"%"} + sub_mangler.pass.get_mangleName(); 370 } 371 } 372 // otherwise just give type numeric name 373 if ( varName.empty() ) { 374 varName = std::to_string( nextVarNum++ ); 375 } 376 varNums[ (*i)->name ] = std::make_pair( varName, (int)(*i)->get_kind() ); 346 377 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 347 378 PassVisitor<Mangler> sub_mangler( 348 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 379 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, env, 380 varNums ); 349 381 (*assert)->accept( sub_mangler ); 350 382 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); -
src/SymTab/Mangler.h
r9795142 rc378e5e 44 44 /// Mangle ignoring generic type parameters 45 45 std::string mangleConcrete( Type* ty ); 46 /// Mangle for assertion key 47 std::string mangleAssnKey( DeclarationWithType* decl, 48 const ResolvExpr::TypeEnvironment& env ); 46 49 47 50 namespace Encoding {
Note:
See TracChangeset
for help on using the changeset viewer.