Changeset e1f7eef
- Timestamp:
- Jan 18, 2019, 3:49:02 PM (6 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- 4cf2472, c018b85
- Parents:
- 95b8aa7
- Location:
- src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/ResolveAssertions.cc
r95b8aa7 re1f7eef 20 20 #include <list> // for list 21 21 #include <memory> // for unique_ptr 22 #include <string> 22 23 #include <unordered_map> // for unordered_map, unordered_multimap 23 24 #include <utility> // for move … … 55 56 using CandidateList = std::vector<AssnCandidate>; 56 57 58 /// Unique identifier for a yet-to-be-resolved assertion 59 struct AssnId { 60 DeclarationWithType* decl; ///< Declaration of assertion 61 AssertionSetValue info; ///< Information about assertion 62 63 AssnId(DeclarationWithType* decl, const AssertionSetValue& info) : decl(decl), info(info) {} 64 }; 65 66 /// Cached assertion items 67 struct AssnCacheItem { 68 CandidateList matches; ///< Possible matches for this assertion 69 std::vector<AssnId> deferIds; ///< Deferred assertions which resolve to this item 70 71 AssnCacheItem( CandidateList&& m ) : matches(std::move(m)), deferIds() {} 72 }; 73 74 /// Cache of resolved assertions 75 using AssnCache = std::unordered_map<std::string, AssnCacheItem>; 76 57 77 /// Reference to single deferred item 58 78 struct DeferRef { 59 const DeclarationWithType* decl; 60 const AssertionSetValue& info; 79 const AssnCacheItem& item; 61 80 const AssnCandidate& match; 62 81 }; … … 65 84 /// Acts like indexed list of DeferRef 66 85 struct DeferItem { 67 DeclarationWithType* decl; 68 AssertionSetValue info; 69 CandidateList matches; 70 71 DeferItem( DeclarationWithType* decl, const AssertionSetValue& info, 72 CandidateList&& matches ) 73 : decl(decl), info(info), matches(std::move(matches)) {} 74 75 bool empty() const { return matches.empty(); } 76 77 CandidateList::size_type size() const { return matches.size(); } 78 79 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; } 86 const AssnCache* cache; ///< Cache storing assertion item 87 std::string key; ///< Key into cache 88 89 DeferItem( const AssnCache& cache, const std::string& key ) : cache(&cache), key(key) {} 90 91 bool empty() const { return cache->at(key).matches.empty(); } 92 93 CandidateList::size_type size() const { return cache->at(key).matches.size(); } 94 95 DeferRef operator[] ( unsigned i ) const { 96 const AssnCacheItem& item = cache->at(key); 97 return { item, item.matches[i] }; 98 } 99 100 // sortable by key 101 // TODO look into optimizing combination process with other sort orders (e.g. by number 102 // of matches in candidate) 103 bool operator< ( const DeferItem& o ) const { return key < o.key; } 104 bool operator== ( const DeferItem& o ) const { return key == o.key; } 80 105 }; 81 106 … … 152 177 for ( const auto& assn : x.assns ) { 153 178 k += computeConversionCost( 154 assn.match.adjType, assn.decl->get_type(), indexer, x.env ); 179 assn.match.adjType, assn.item.deferIds[0].decl->get_type(), indexer, 180 x.env ); 155 181 } 156 182 it = cache.emplace_hint( it, &x, k ); … … 208 234 candidate->get_uniqueId(), match.adjType->clone(), decl->get_type()->clone(), 209 235 varExpr }; 210 211 // // follow the current assertion's ID chain to find the correct set of inferred parameters212 // // to add the candidate o (i.e. the set of inferred parameters belonging to the entity213 // // which requested the assertion parameter)214 // InferredParams* inferParams = &alt.expr->inferParams;215 // for ( UniqueId id : info.idChain ) {216 // inferParams = (*inferParams)[ id ].inferParams.get();217 // }218 219 // (*inferParams)[ decl->get_uniqueId() ] = ParamEntry{220 // candidate->get_uniqueId(), match.adjType, decl->get_type()->clone(), varExpr };221 236 } 222 237 223 238 /// Adds a captured assertion to the symbol table 224 239 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 225 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i) {226 if ( i ->second.isUsed ) {227 indexer.addId( i ->first );240 for ( auto& i : assertSet ) { 241 if ( i.second.isUsed ) { 242 indexer.addId( i.first ); 228 243 } 229 244 } … … 234 249 235 250 /// Resolve a single assertion, in context 236 bool resolveAssertion( AssertionItem& assn, ResnState& resn ) {251 bool resolveAssertion( AssertionItem& assn, ResnState& resn, AssnCache& cache ) { 237 252 // skip unused assertions 238 253 if ( ! assn.info.isUsed ) return true; 239 254 240 // lookup candidates for this assertion 241 std::list< SymTab::Indexer::IdData > candidates; 242 resn.indexer.lookupId( assn.decl->name, candidates ); 243 244 // find the candidates that unify with the desired type 245 CandidateList matches; 246 for ( const auto& cdata : candidates ) { 247 DeclarationWithType* candidate = cdata.id; 248 249 // build independent unification context for candidate 250 AssertionSet have, newNeed; 251 TypeEnvironment newEnv{ resn.alt.env }; 252 OpenVarSet newOpenVars{ resn.alt.openVars }; 253 Type* adjType = candidate->get_type()->clone(); 254 adjustExprType( adjType, newEnv, resn.indexer ); 255 renameTyVars( adjType ); 256 257 // keep unifying candidates 258 if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars, 259 resn.indexer ) ) { 260 // set up binding slot for recursive assertions 261 UniqueId crntResnSlot = 0; 262 if ( ! newNeed.empty() ) { 263 crntResnSlot = ++globalResnSlot; 264 for ( auto& a : newNeed ) { 265 a.second.resnSlot = crntResnSlot; 255 // check cache for this assertion 256 std::string assnKey = SymTab::Mangler::mangleAssnKey( assn.decl, resn.alt.env ); 257 auto it = cache.find( assnKey ); 258 259 // attempt to resolve assertion if this is the first time seen 260 if ( it == cache.end() ) { 261 // lookup candidates for this assertion 262 std::list< SymTab::Indexer::IdData > candidates; 263 resn.indexer.lookupId( assn.decl->name, candidates ); 264 265 // find the candidates that unify with the desired type 266 CandidateList matches; 267 for ( const auto& cdata : candidates ) { 268 DeclarationWithType* candidate = cdata.id; 269 270 // build independent unification context for candidate 271 AssertionSet have, newNeed; 272 TypeEnvironment newEnv{ resn.alt.env }; 273 OpenVarSet newOpenVars{ resn.alt.openVars }; 274 Type* adjType = candidate->get_type()->clone(); 275 adjustExprType( adjType, newEnv, resn.indexer ); 276 renameTyVars( adjType ); 277 278 // keep unifying candidates 279 if ( unify( assn.decl->get_type(), adjType, newEnv, newNeed, have, newOpenVars, 280 resn.indexer ) ) { 281 // set up binding slot for recursive assertions 282 UniqueId crntResnSlot = 0; 283 if ( ! newNeed.empty() ) { 284 crntResnSlot = ++globalResnSlot; 285 for ( auto& a : newNeed ) { 286 a.second.resnSlot = crntResnSlot; 287 } 266 288 } 267 } 268 // // set up idChain on new assertions 269 // for ( auto& a : newNeed ) { 270 // a.second.idChain = assn.info.idChain; 271 // a.second.idChain.push_back( assn.decl->get_uniqueId() ); 272 // } 273 274 matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have), 275 std::move(newNeed), std::move(newOpenVars), crntResnSlot ); 276 } else { 277 delete adjType; 289 290 matches.emplace_back( cdata, adjType, std::move(newEnv), std::move(have), 291 std::move(newNeed), std::move(newOpenVars), crntResnSlot ); 292 } else { 293 delete adjType; 294 } 278 295 } 279 } 296 297 it = cache.emplace_hint( it, assnKey, AssnCacheItem{ std::move(matches) } ); 298 } 299 300 CandidateList& matches = it->second.matches; 280 301 281 302 // break if no suitable assertion … … 284 305 // defer if too many suitable assertions 285 306 if ( matches.size() > 1 ) { 286 resn.deferred.emplace_back( assn.decl, assn.info, std::move(matches) ); 307 it->second.deferIds.emplace_back( assn.decl, assn.info ); 308 resn.deferred.emplace_back( cache, assnKey ); 287 309 return true; 288 310 } … … 292 314 addToIndexer( match.have, resn.indexer ); 293 315 resn.newNeed.insert( match.need.begin(), match.need.end() ); 294 resn.alt.env = std::move(match.env);295 resn.alt.openVars = std::move(match.openVars);316 resn.alt.env = match.env; 317 resn.alt.openVars = match.openVars; 296 318 297 319 bindAssertion( assn.decl, assn.info, resn.alt, match, resn.inferred ); … … 354 376 ResnList resns{ ResnState{ alt, root_indexer } }; 355 377 ResnList new_resns{}; 378 AssnCache assnCache; 356 379 357 380 // resolve assertions in breadth-first-order up to a limited number of levels deep … … 362 385 for ( auto& assn : resn.need ) { 363 386 // fail early if any assertion is not resolvable 364 if ( ! resolveAssertion( assn, resn ) ) goto nextResn;387 if ( ! resolveAssertion( assn, resn, assnCache ) ) goto nextResn; 365 388 } 366 389 … … 373 396 } 374 397 } else { 398 // only resolve each deferred assertion once 399 std::sort( resn.deferred.begin(), resn.deferred.end() ); 400 auto last = std::unique( resn.deferred.begin(), resn.deferred.end() ); 401 resn.deferred.erase( last, resn.deferred.end() ); 375 402 // resolve deferred assertions by mutual compatibility 376 403 std::vector<CandidateEnvMerger::OutType> compatible = filterCombos( … … 380 407 CandidateCost coster{ resn.indexer }; 381 408 std::sort( compatible.begin(), compatible.end(), coster ); 382 // // sort by cost if pruning383 // if ( pruneAssertions ) {384 // auto lmin = sort_mins( compatible.begin(), compatible.end(),385 // CandidateCost{resn.indexer} );386 // compatible.erase( lmin, compatible.end() );387 // }388 409 389 410 // keep map of detected options … … 408 429 new_resn.newNeed.insert( match.need.begin(), match.need.end() ); 409 430 410 bindAssertion( r.decl, r.info, new_resn.alt, match, new_resn.inferred ); 431 // for each deferred assertion with the same form 432 for ( AssnId id : r.item.deferIds ) { 433 bindAssertion( 434 id.decl, id.info, new_resn.alt, match, new_resn.inferred ); 435 } 411 436 } 412 437 -
src/SymTab/Mangler.cc
r95b8aa7 re1f7eef 69 69 typedef std::map< std::string, std::pair< std::string, int > > VarMapType; 70 70 VarMapType varNums; ///< Map of type variables to indices 71 int nextVarNum; ///< Next type variable index 71 72 const ResolvExpr::TypeEnvironment* env; ///< optional environment for substitutions 72 int nextVarNum; ///< Next type variable index73 73 bool isTopLevel; ///< Is the Mangler at the top level 74 74 bool mangleOverridable; ///< Specially mangle overridable built-in methods … … 78 78 bool inQualifiedType = false; ///< Add start/end delimiters around qualified type 79 79 80 public: 80 81 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 81 82 int nextVarNum, const ResolvExpr::TypeEnvironment* env, 82 83 const VarMapType& varNums ); 83 84 85 private: 84 86 void mangleDecl( DeclarationWithType *declaration ); 85 87 void mangleRef( ReferenceToType *refType, std::string prefix ); … … 127 129 int nextVarNum, const ResolvExpr::TypeEnvironment* env, 128 130 const VarMapType& varNums ) 129 : nextVarNum( nextVarNum ), varNums( varNums), env( env ), isTopLevel( false ),131 : varNums( varNums ), nextVarNum( nextVarNum ), env( env ), isTopLevel( false ), 130 132 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 131 133 mangleGenericParams( mangleGenericParams ) {} … … 359 361 // replace type with substitution name if environment is available and bound 360 362 if ( env ) { 361 const EqvClass* varClass = env->lookup( (*i)->name );363 const ResolvExpr::EqvClass* varClass = env->lookup( (*i)->name ); 362 364 if ( varClass && varClass->type ) { 363 365 PassVisitor<Mangler> sub_mangler(
Note: See TracChangeset
for help on using the changeset viewer.