Changeset 184557e for src/ResolvExpr/TypeEnvironment.cc
- Timestamp:
- Jul 6, 2018, 5:10:14 PM (6 years ago)
- Branches:
- new-env
- Children:
- 5c14030
- Parents:
- b21c77a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/TypeEnvironment.cc
rb21c77a r184557e 21 21 #include "Common/InternedString.h" // for interned_string 22 22 #include "Common/PassVisitor.h" // for PassVisitor<GcTracer> 23 #include "Common/option.h" // for option<T> 23 24 #include "Common/utility.h" // for maybeClone 24 25 #include "SymTab/Indexer.h" // for Indexer … … 49 50 } 50 51 51 #if 052 void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {53 initialize( src, dest, src.type );54 }55 56 void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {57 dest.vars = src.vars;58 dest.type = maybeClone( ty );59 dest.allowWidening = src.allowWidening;60 dest.data = src.data;61 }62 63 EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) {64 }65 66 EqvClass::EqvClass( const EqvClass &other ) {67 initialize( other, *this );68 }69 70 EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {71 initialize( other, *this, ty );72 }73 74 EqvClass::EqvClass( EqvClass &&other )75 : vars{std::move(other.vars)}, type{other.type},76 allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {77 other.type = nullptr;78 }79 80 EqvClass &EqvClass::operator=( const EqvClass &other ) {81 if ( this == &other ) return *this;82 initialize( other, *this );83 return *this;84 }85 86 EqvClass &EqvClass::operator=( EqvClass &&other ) {87 if ( this == &other ) return *this;88 89 vars = std::move(other.vars);90 type = other.type;91 allowWidening = std::move(other.allowWidening);92 data = std::move(other.data);93 94 return *this;95 }96 97 void EqvClass::set_type( Type* ty ) { type = ty; }98 99 void EqvClass::print( std::ostream &os, Indenter indent ) const {100 os << "( ";101 std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );102 os << ")";103 if ( type ) {104 os << " -> ";105 type->print( os, indent+1 );106 } // if107 if ( ! allowWidening ) {108 os << " (no widening)";109 } // if110 os << std::endl;111 }112 113 const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {114 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {115 if ( i->vars.find( var ) != i->vars.end() ) return &*i;116 } // for117 return nullptr;118 }119 #endif120 121 52 std::pair<interned_string, interned_string> TypeEnvironment::mergeClasses( 122 53 interned_string root1, interned_string root2 ) { … … 126 57 // determine new root 127 58 assertf(classes->get_mode() == Classes::REMFROM, "classes updated to REMFROM by merge"); 128 auto ret = std::make_pair( classes->get_root(), classes->get_child );59 auto ret = std::make_pair( classes->get_root(), classes->get_child() ); 129 60 130 61 // finalize classes … … 302 233 } 303 234 304 #if !1305 /// Removes any class from env that intersects eqvClass306 void filterOverlappingClasses( std::list<EqvClass> &env, const EqvClass &eqvClass ) {307 for ( auto i = env.begin(); i != env.end(); ) {308 auto next = i;309 ++next;310 std::set<std::string> intersection;311 std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(),312 std::inserter( intersection, intersection.begin() ) );313 if ( ! intersection.empty() ) { env.erase( i ); }314 i = next;315 }316 }317 318 void TypeEnvironment::add( EqvClass &&eqvClass ) {319 filterOverlappingClasses( env, eqvClass );320 env.push_back( std::move(eqvClass) );321 }322 323 235 void TypeEnvironment::add( const Type::ForallList &tyDecls ) { 324 236 for ( Type::ForallList::const_iterator i = tyDecls.begin(); i != tyDecls.end(); ++i ) { 325 EqvClass newClass; 326 newClass.vars.insert( (*i)->get_name() ); 327 newClass.data = TypeDecl::Data{ (*i) }; 328 env.push_back( std::move(newClass) ); 237 interned_string name = (*i)->get_name(); 238 classes = classes->add( name ); 239 bindings = bindings->set( name, *i ); 329 240 } // for 330 241 } 331 242 332 243 void TypeEnvironment::add( const TypeSubstitution & sub ) { 333 EqvClass newClass; 244 interned_string not_found{nullptr}; 245 334 246 for ( auto p : sub ) { 335 newClass.vars.insert( p.first ); 336 newClass.type = p.second->clone(); 337 newClass.allowWidening = false; 247 interned_string var = p.first; 248 249 // filter overlapping classes out of existing environment 250 // (this is a very shady assumption, but has worked for a long time...) 251 interned_string root = classes->find_or_default( v, not_found ); 252 if ( root != not_found ) { 253 classes = classes->remove_class( root ); 254 bindings = bindings->erase( root ); 255 } 256 338 257 // Minimal assumptions. Not technically correct, but might be good enough, and 339 258 // is the best we can do at the moment since information is lost in the 340 259 // transition to TypeSubstitution 341 newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false }; 342 add( std::move(newClass) ); 260 TypeDecl::Data data{ TypeDecl::Dtype, false }; 261 262 // add variable to class and bindings 263 classes = classes->add( var ); 264 bindings = bindings->set( var, BoundType{ p.second->clone, false, data } ); 343 265 } 344 266 } 345 267 346 268 void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const { 347 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) { 348 for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) { 349 if ( theClass->type ) { 350 sub.add( *theVar, theClass->type ); 351 } else if ( theVar != theClass->vars.begin() ) { 352 TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype ); 353 sub.add( *theVar, newTypeInst ); 354 } // if 355 } // for 356 } // for 269 bindings->apply_to_all([classes, &sub]( interned_string root, const BoundType& bound ){ 270 classes->apply_to_class(root, [&]( interned_string var ) { 271 if ( bound.type ) { 272 sub.add( var, bound.type ); 273 } else if ( var != root ) { 274 sub.add( var, new TypeInstType{ 275 Type::Qualifiers{}, root, bound.data.kind == TypeDecl::Ftype } ); 276 } 277 }); 278 }); 279 357 280 sub.normalize(); 358 281 } 359 282 360 283 void TypeEnvironment::print( std::ostream &os, Indenter indent ) const { 361 for ( const EqvClass & theClass : env ) { 362 theClass.print( os, indent ); 363 } // for 364 } 365 366 std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) { 367 for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) { 368 if ( i->vars.count( var ) ) return i; 369 } // for 370 return env.end(); 371 } 372 373 void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) { 374 env.insert( env.end(), second.env.begin(), second.env.end() ); 284 bindings->apply_to_all([classes,&]( interned_string root, const BoundType& bound ) { 285 os << "( "; 286 classes->apply_to_class( root, [&os]( interned_string var ) { os << var << " "; } ); 287 os << ")"; 288 if ( bound.type ) { 289 os << " -> "; 290 type->print( os, indent+1 ); 291 } 292 if ( ! bound.allowWidening ) { 293 os << " (no widening)"; 294 } 295 os << std::endl; 296 }); 297 } 298 299 void TypeEnvironment::simpleCombine( const TypeEnvironment &o ) { 300 o.bindings->apply_to_all( [&]( interned_string root, const BoundType& bound ) { 301 // add members of new class 302 interned_string new_root{nullptr}; 303 o.classes->apply_to_class( root, [this,&new_root]( interned_string var ) { 304 classes = classes->add( var ); 305 new_root = new_root ? mergeClasses( new_root, var ).first : var; 306 }); 307 // set binding for new class 308 bindings = bindings->set( new_root, bound ); 309 }); 375 310 } 376 311 377 312 void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const { 378 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass) {379 for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {380 openVars[ *var ] = eqvClass->data;381 } // for382 } // for313 bindings->apply_to_all( [classes,&openVars]( interned_string root, const BoundType& bound ) { 314 classes->apply_to_class( root, [&openVars,&bound]( interned_string var ) { 315 openVars[ var ] = bound.data; 316 } ); 317 } ); 383 318 } 384 319 385 320 void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) { 386 for ( const EqvClass& c : actualEnv ) { 387 EqvClass c2 = c; 388 c2.allowWidening = false; 389 for ( const std::string& var : c2.vars ) { 390 openVars[ var ] = c2.data; 391 } 392 env.push_back( std::move(c2) ); 393 } 321 actualEnv.bindings->apply_to_all( [&]( interned_string root, const BoundType& bound ) { 322 // add members of new class, setting openVars concurrently 323 interned_string new_root{nullptr}; 324 actualEnv.classes->apply_to_class( root, [&]( interned_string var ) { 325 classes = classes->add( var ); 326 new_root = new_root ? mergeClasses( new_root, var ).first : var; 327 openVars[ var ] = bound.data; 328 } ); 329 // add new type binding without widening 330 bindings = bindings->set( new_root, 331 BoundType{ maybeClone(bound.type), false, bound.data } ); 332 } ); 333 } 334 335 void TypeEnvironment::forbidWidening() { 336 bindings = bindings->apply_to_all([]( const interned_string& k, BoundType& c ) { 337 if ( c.allowWidening ) { 338 option<BoundType> ret = c; 339 c.allowWidening = false; 340 return ret; 341 } else return option<BoundType>{}; 342 }); 394 343 } 395 344 … … 398 347 return out; 399 348 } 400 #endif401 349 402 350 PassVisitor<GcTracer> & operator<<( PassVisitor<GcTracer> & gc, const TypeEnvironment & env ) {
Note: See TracChangeset
for help on using the changeset viewer.