Changeset 58fe85a for src/AST/TypeEnvironment.cpp
- Timestamp:
- Jan 7, 2021, 3:27:00 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (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/AST/TypeEnvironment.cpp
r3c64c668 r58fe85a 34 34 #include "ResolvExpr/Unify.h" // for unifyInexact 35 35 #include "Tuples/Tuples.h" // for isTtype 36 #include "CompilationState.h" 36 37 37 38 using ResolvExpr::WidenMode; … … 51 52 for ( const auto & i : open ) { 52 53 if ( first ) { first = false; } else { out << ' '; } 53 out << i.first << "(" << i.second << ")";54 out << i.first.typeString() << "(" << i.second << ")"; 54 55 } 55 56 } 56 57 57 58 void print( std::ostream & out, const EqvClass & clz, Indenter indent ) { 58 out << "( "; 59 std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) ); 59 out << "("; 60 bool first = true; 61 for(const auto & var : clz.vars) { 62 if(first) first = false; 63 else out << " "; 64 65 if( deterministic_output ) out << "[unbound]"; 66 else out << "_" << var.formal_usage << "_" << var.expr_id << "_"; 67 68 out << var.base->name; 69 } 60 70 out << ")"; 61 71 62 72 if ( clz.bound ) { 63 73 out << " -> "; … … 72 82 } 73 83 74 const EqvClass * TypeEnvironment::lookup( const std::string& var ) const {84 const EqvClass * TypeEnvironment::lookup( const TypeInstType::TypeEnvKey & var ) const { 75 85 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) { 76 86 if ( i->vars.find( var ) != i->vars.end() ) return &*i; … … 92 102 } 93 103 } 94 104 95 105 i = next; // go to next node even if this removed 96 106 } … … 98 108 } 99 109 100 void TypeEnvironment::add( const ParameterizedType::ForallList & tyDecls ) {101 for ( const TypeDecl *tyDecl : tyDecls ) {110 void TypeEnvironment::add( const FunctionType::ForallList & tyDecls ) { 111 for ( auto & tyDecl : tyDecls ) { 102 112 env.emplace_back( tyDecl ); 103 113 } … … 112 122 void TypeEnvironment::writeToSubstitution( TypeSubstitution & sub ) const { 113 123 for ( const auto & clz : env ) { 114 std::string clzRep; 124 TypeInstType::TypeEnvKey clzRep; 125 bool first = true; 115 126 for ( const auto & var : clz.vars ) { 116 127 if ( clz.bound ) { 117 128 sub.add( var, clz.bound ); 118 } else if ( clzRep.empty()) {129 } else if ( first ) { 119 130 clzRep = var; 131 first = false; 120 132 } else { 121 sub.add( var, new TypeInstType{ clzRep , clz.data.kind} );133 sub.add( var, new TypeInstType{ clzRep } ); 122 134 } 123 135 } … … 134 146 struct Occurs : public ast::WithVisitorRef<Occurs> { 135 147 bool result; 136 std:: set< std::string> vars;148 std::unordered_set< TypeInstType::TypeEnvKey > vars; 137 149 const TypeEnvironment & tenv; 138 150 139 Occurs( const std::string& var, const TypeEnvironment & env )151 Occurs( const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) 140 152 : result( false ), vars(), tenv( env ) { 141 153 if ( const EqvClass * clz = tenv.lookup( var ) ) { … … 147 159 148 160 void previsit( const TypeInstType * typeInst ) { 149 if ( vars.count( typeInst->name) ) {161 if ( vars.count( *typeInst ) ) { 150 162 result = true; 151 } else if ( const EqvClass * clz = tenv.lookup( typeInst->name) ) {163 } else if ( const EqvClass * clz = tenv.lookup( *typeInst ) ) { 152 164 if ( clz->bound ) { 153 165 clz->bound->accept( *visitor ); … … 158 170 159 171 /// true if `var` occurs in `ty` under `env` 160 bool occurs( const Type * ty, const std::string& var, const TypeEnvironment & env ) {172 bool occurs( const Type * ty, const TypeInstType::TypeEnvKey & var, const TypeEnvironment & env ) { 161 173 Pass<Occurs> occur{ var, env }; 162 174 maybe_accept( ty, occur ); 163 return occur. pass.result;164 } 165 } 166 167 bool TypeEnvironment::combine( 175 return occur.core.result; 176 } 177 } 178 179 bool TypeEnvironment::combine( 168 180 const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) { 169 181 // short-circuit easy cases … … 199 211 auto st = internal_lookup( *vt ); 200 212 if ( st == env.end() ) { 201 // unbound, safe to add if occurs 213 // unbound, safe to add if occurs 202 214 if ( r.bound && occurs( r.bound, *vt, *this ) ) return false; 203 215 r.vars.emplace( *vt ); … … 266 278 } 267 279 268 bool TypeEnvironment::bindVar( 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 280 bool TypeEnvironment::bindVar( 281 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 282 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 283 const SymbolTable & symtab 272 284 ) { 273 285 // remove references from bound type, so that type variables can only bind to value types 274 286 ptr<Type> target = bindTo->stripReferences(); 275 auto tyvar = open.find( typeInst->name);287 auto tyvar = open.find( *typeInst ); 276 288 assert( tyvar != open.end() ); 277 289 if ( ! tyVarCompatible( tyvar->second, target ) ) return false; 278 if ( occurs( target, typeInst->name, *this ) ) return false;279 280 auto it = internal_lookup( typeInst->name);290 if ( occurs( target, *typeInst, *this ) ) return false; 291 292 auto it = internal_lookup( *typeInst ); 281 293 if ( it != env.end() ) { 282 294 if ( it->bound ) { … … 286 298 ptr<Type> newType = it->bound; 287 299 reset_qualifiers( newType, typeInst->qualifiers ); 288 if ( unifyInexact( 289 newType, target, *this, need, have, open, 300 if ( unifyInexact( 301 newType, target, *this, need, have, open, 290 302 widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) { 291 303 if ( common ) { … … 300 312 } 301 313 } else { 302 env.emplace_back( 303 typeInst->name, target, widen.first && widen.second, data );314 env.emplace_back( 315 *typeInst, target, widen.first && widen.second, data ); 304 316 } 305 317 return true; 306 318 } 307 319 308 bool TypeEnvironment::bindVarToVar( 309 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 320 bool TypeEnvironment::bindVarToVar( 321 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 322 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 323 WidenMode widen, const SymbolTable & symtab 312 324 ) { 313 auto c1 = internal_lookup( var1->name);314 auto c2 = internal_lookup( var2->name);315 325 auto c1 = internal_lookup( *var1 ); 326 auto c2 = internal_lookup( *var2 ); 327 316 328 // exit early if variables already bound together 317 329 if ( c1 != env.end() && c1 == c2 ) { … … 326 338 if ( c1 != env.end() ) { 327 339 if ( c1->bound ) { 328 if ( occurs( c1->bound, var2->name, *this ) ) return false;340 if ( occurs( c1->bound, *var2, *this ) ) return false; 329 341 type1 = c1->bound; 330 342 } … … 333 345 if ( c2 != env.end() ) { 334 346 if ( c2->bound ) { 335 if ( occurs( c2->bound, var1->name, *this ) ) return false;347 if ( occurs( c2->bound, *var1, *this ) ) return false; 336 348 type2 = c2->bound; 337 349 } … … 371 383 } else if ( c1 != env.end() ) { 372 384 // var2 unbound, add to env[c1] 373 c1->vars.emplace( var2->name);385 c1->vars.emplace( *var2 ); 374 386 c1->allowWidening = widen1; 375 387 c1->data.isComplete |= data.isComplete; 376 388 } else if ( c2 != env.end() ) { 377 389 // var1 unbound, add to env[c2] 378 c2->vars.emplace( var1->name);390 c2->vars.emplace( *var1 ); 379 391 c2->allowWidening = widen2; 380 392 c2->data.isComplete |= data.isComplete; 381 393 } else { 382 394 // neither var bound, create new class 383 env.emplace_back( var1->name, var2->name, widen1 && widen2, data );395 env.emplace_back( *var1, *var2, widen1 && widen2, data ); 384 396 } 385 397 … … 396 408 } 397 409 398 bool TypeEnvironment::mergeBound( 410 bool TypeEnvironment::mergeBound( 399 411 EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) { 400 412 if ( from.bound ) { … … 406 418 AssertionSet need, have; 407 419 408 if ( unifyInexact( 420 if ( unifyInexact( 409 421 toType, fromType, *this, need, have, open, widen, symtab, common ) ) { 410 422 // unifies, set common type if necessary … … 424 436 } 425 437 426 bool TypeEnvironment::mergeClasses( 438 bool TypeEnvironment::mergeClasses( 427 439 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab 428 440 ) { … … 445 457 } 446 458 447 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string& var ) {459 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const TypeInstType::TypeEnvKey & var ) { 448 460 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) { 449 461 if ( i->vars.count( var ) ) return i;
Note:
See TracChangeset
for help on using the changeset viewer.