Changes in src/ResolvExpr/Unify.cc [8e18b8e:d286cf68]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r8e18b8e rd286cf68 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:27:10 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 16:22:54 201713 // Update Count : 4 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 43 14 14 // 15 15 … … 17 17 #include <iterator> // for back_insert_iterator, back_inserter 18 18 #include <map> // for _Rb_tree_const_iterator, _Rb_tree_i... 19 #include <memory> // for unique_ptr 19 20 #include <set> // for set 20 21 #include <string> // for string, operator==, operator!=, bas... … … 98 99 findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true ); 99 100 100 return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 101 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 102 delete newFirst; 103 delete newSecond; 104 return result; 101 105 } 102 106 … … 119 123 /// newSecond->print( std::cerr ); 120 124 /// std::cerr << std::endl; 121 return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 122 } 123 124 bool isFtype( Type *type ) { 125 if ( dynamic_cast< FunctionType* >( type ) ) { 126 return true; 127 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) { 128 return typeInst->get_isFtype(); 129 } // if 130 return false; 131 } 132 133 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) { 134 switch ( data.kind ) { 135 case TypeDecl::Dtype: 136 // to bind to an object type variable, the type must not be a function type. 137 // if the type variable is specified to be a complete type then the incoming 138 // type must also be complete 139 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 140 return ! isFtype( type ) && (! data.isComplete || type->isComplete() ); 141 case TypeDecl::Ftype: 142 return isFtype( type ); 143 case TypeDecl::Ttype: 144 // ttype unifies with any tuple type 145 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type ); 146 } // switch 147 return false; 148 } 149 150 bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 151 // remove references from other, so that type variables can only bind to value types 152 other = other->stripReferences(); 153 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 154 assert( tyvar != openVars.end() ); 155 if ( ! tyVarCompatible( tyvar->second, other ) ) { 156 return false; 157 } // if 158 if ( occurs( other, typeInst->get_name(), env ) ) { 159 return false; 160 } // if 161 if ( const EqvClass *curClass = env.lookup( typeInst->get_name() ) ) { 162 if ( curClass->type ) { 163 Type *common = 0; 164 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to 165 Type* newType = curClass->type->clone(); 166 newType->get_qualifiers() = typeInst->get_qualifiers(); 167 if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) { 168 if ( common ) { 169 common->get_qualifiers() = Type::Qualifiers(); 170 EqvClass newClass = *curClass; 171 newClass.type = common; 172 env.add( std::move(newClass) ); 173 } // if 174 return true; 175 } else { 176 return false; 177 } // if 178 } else { 179 EqvClass newClass = *curClass; 180 newClass.type = other->clone(); 181 newClass.type->get_qualifiers() = Type::Qualifiers(); 182 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 183 env.add( std::move(newClass) ); 184 } // if 185 } else { 186 EqvClass newClass; 187 newClass.vars.insert( typeInst->get_name() ); 188 newClass.type = other->clone(); 189 newClass.type->get_qualifiers() = Type::Qualifiers(); 190 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 191 newClass.data = data; 192 env.add( newClass ); 193 } // if 194 return true; 195 } 196 197 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 198 bool result = true; 199 const EqvClass *class1 = env.lookup( var1->get_name() ); 200 const EqvClass *class2 = env.lookup( var2->get_name() ); 201 bool widen1 = false, widen2 = false; 202 Type *type1 = nullptr, *type2 = nullptr; 203 204 if ( class1 ) { 205 if ( class1->type ) { 206 if ( occurs( class1->type, var2->get_name(), env ) ) { 207 return false; 208 } // if 209 type1 = class1->type->clone(); 210 } // if 211 widen1 = widenMode.widenFirst && class1->allowWidening; 212 } // if 213 if ( class2 ) { 214 if ( class2->type ) { 215 if ( occurs( class2->type, var1->get_name(), env ) ) { 216 return false; 217 } // if 218 type2 = class2->type->clone(); 219 } // if 220 widen2 = widenMode.widenSecond && class2->allowWidening; 221 } // if 222 223 if ( type1 && type2 ) { 224 // std::cerr << "has type1 && type2" << std::endl; 225 WidenMode newWidenMode ( widen1, widen2 ); 226 Type *common = 0; 227 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) { 228 EqvClass newClass1 = *class1; 229 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() ); 230 newClass1.allowWidening = widen1 && widen2; 231 if ( common ) { 232 common->get_qualifiers() = Type::Qualifiers(); 233 newClass1.type = common; 234 } // if 235 env.add( std::move(newClass1) ); 236 } else { 237 result = false; 238 } // if 239 } else if ( class1 && class2 ) { 240 if ( type1 ) { 241 EqvClass newClass1 = *class1; 242 newClass1.vars.insert( class2->vars.begin(), class2->vars.end() ); 243 newClass1.allowWidening = widen1; 244 env.add( std::move(newClass1) ); 245 } else { 246 EqvClass newClass2 = *class2; 247 newClass2.vars.insert( class1->vars.begin(), class1->vars.end() ); 248 newClass2.allowWidening = widen2; 249 env.add( std::move(newClass2) ); 250 } // if 251 } else if ( class1 ) { 252 EqvClass newClass1 = *class1; 253 newClass1.vars.insert( var2->get_name() ); 254 newClass1.allowWidening = widen1; 255 env.add( std::move(newClass1) ); 256 } else if ( class2 ) { 257 EqvClass newClass2 = *class2; 258 newClass2.vars.insert( var1->get_name() ); 259 newClass2.allowWidening = widen2; 260 env.add( std::move(newClass2) ); 261 } else { 262 EqvClass newClass; 263 newClass.vars.insert( var1->get_name() ); 264 newClass.vars.insert( var2->get_name() ); 265 newClass.allowWidening = widen1 && widen2; 266 newClass.data = data; 267 env.add( newClass ); 268 } // if 125 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 126 delete newFirst; 127 delete newSecond; 269 128 return result; 270 129 } … … 275 134 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true ); 276 135 Type *commonType = 0; 277 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ); 136 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) { 137 if ( commonType ) { 138 delete commonType; 139 } // if 140 return true; 141 } else { 142 return false; 143 } // if 278 144 } 279 145 … … 307 173 308 174 if ( isopen1 && isopen2 && entry1->second == entry2->second ) { 309 result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );175 result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 310 176 } else if ( isopen1 ) { 311 result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );177 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 312 178 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped? 313 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );179 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 314 180 } else { 315 181 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); … … 469 335 470 336 template< typename Iterator, typename Func > 471 Type*combineTypes( Iterator begin, Iterator end, Func & toType ) {337 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) { 472 338 std::list< Type * > types; 473 339 for ( ; begin != end; ++begin ) { … … 475 341 flatten( toType( *begin ), back_inserter( types ) ); 476 342 } 477 return new TupleType{ Type::Qualifiers(), types };343 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 478 344 } 479 345 … … 490 356 if ( isTtype1 && ! isTtype2 ) { 491 357 // combine all of the things in list2, then unify 492 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) , env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );358 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 493 359 } else if ( isTtype2 && ! isTtype1 ) { 494 360 // combine all of the things in list1, then unify 495 return unifyExact( combineTypes( list1Begin, list1End, get_type ) , t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );361 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 496 362 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 497 363 return false; … … 503 369 Type * t1 = (*list1Begin)->get_type(); 504 370 if ( Tuples::isTtype( t1 ) ) { 505 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) , env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );371 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 506 372 } else return false; 507 373 } else if ( list2Begin != list2End ) { … … 509 375 Type * t2 = (*list2Begin)->get_type(); 510 376 if ( Tuples::isTtype( t2 ) ) { 511 return unifyExact( combineTypes( list1Begin, list1End, get_type ) , t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );377 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 512 378 } else return false; 513 379 } else { … … 528 394 // expand ttype parameter into its actual type 529 395 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) { 396 delete typeInst; 530 397 return eqvClass->type->clone(); 531 398 } … … 551 418 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) ); 552 419 } 420 delete dcl; 553 421 } 554 422 } … … 559 427 // flatten the parameter lists for both functions so that tuple structure 560 428 // doesn't affect unification. Must be a clone so that the types don't change. 561 FunctionType* flatFunc = functionType->clone();562 FunctionType* flatOther = otherFunction->clone();429 std::unique_ptr<FunctionType> flatFunc( functionType->clone() ); 430 std::unique_ptr<FunctionType> flatOther( otherFunction->clone() ); 563 431 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 564 432 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); … … 701 569 if ( isTtype1 && ! isTtype2 ) { 702 570 // combine all of the things in list2, then unify 703 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) , env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );571 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 704 572 } else if ( isTtype2 && ! isTtype1 ) { 705 573 // combine all of the things in list1, then unify 706 return unifyExact( combineTypes( list1Begin, list1End, get_type ) , t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );574 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 707 575 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 708 576 return false; … … 714 582 Type * t1 = *list1Begin; 715 583 if ( Tuples::isTtype( t1 ) ) { 716 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) , env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );584 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 717 585 } else return false; 718 586 } else if ( list2Begin != list2End ) { … … 720 588 Type * t2 = *list2Begin; 721 589 if ( Tuples::isTtype( t2 ) ) { 722 return unifyExact( combineTypes( list1Begin, list1End, get_type ) , t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );590 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 723 591 } else return false; 724 592 } else { … … 729 597 void Unify::postvisit(TupleType *tupleType) { 730 598 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 731 TupleType* flat1 = tupleType->clone();732 TupleType* flat2 = otherTuple->clone();599 std::unique_ptr<TupleType> flat1( tupleType->clone() ); 600 std::unique_ptr<TupleType> flat2( otherTuple->clone() ); 733 601 std::list<Type *> types1, types2; 734 602 … … 737 605 flat2->acceptMutator( expander ); 738 606 739 flatten( flat1 , back_inserter( types1 ) );740 flatten( flat2 , back_inserter( types2 ) );607 flatten( flat1.get(), back_inserter( types1 ) ); 608 flatten( flat2.get(), back_inserter( types2 ) ); 741 609 742 610 result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
Note:
See TracChangeset
for help on using the changeset viewer.