Changes in src/ResolvExpr/Unify.cc [d286cf68:8e18b8e]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
rd286cf68 r8e18b8e 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:27:10 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Mon Jun 18 11:58:00 201813 // Update Count : 4 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 16 16:22:54 2017 13 // Update Count : 42 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_ptr20 19 #include <set> // for set 21 20 #include <string> // for string, operator==, operator!=, bas... … … 99 98 findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true ); 100 99 101 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 102 delete newFirst; 103 delete newSecond; 104 return result; 100 return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 105 101 } 106 102 … … 123 119 /// newSecond->print( std::cerr ); 124 120 /// std::cerr << std::endl; 125 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 126 delete newFirst; 127 delete newSecond; 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 128 269 return result; 129 270 } … … 134 275 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true ); 135 276 Type *commonType = 0; 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 277 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ); 144 278 } 145 279 … … 173 307 174 308 if ( isopen1 && isopen2 && entry1->second == entry2->second ) { 175 result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );309 result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 176 310 } else if ( isopen1 ) { 177 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );311 result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 178 312 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped? 179 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );313 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 180 314 } else { 181 315 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); … … 335 469 336 470 template< typename Iterator, typename Func > 337 std::unique_ptr<Type>combineTypes( Iterator begin, Iterator end, Func & toType ) {471 Type* combineTypes( Iterator begin, Iterator end, Func & toType ) { 338 472 std::list< Type * > types; 339 473 for ( ; begin != end; ++begin ) { … … 341 475 flatten( toType( *begin ), back_inserter( types ) ); 342 476 } 343 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );477 return new TupleType{ Type::Qualifiers(), types }; 344 478 } 345 479 … … 356 490 if ( isTtype1 && ! isTtype2 ) { 357 491 // combine all of the things in list2, then unify 358 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) .get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );492 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 359 493 } else if ( isTtype2 && ! isTtype1 ) { 360 494 // combine all of the things in list1, then unify 361 return unifyExact( combineTypes( list1Begin, list1End, get_type ) .get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );495 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 362 496 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 363 497 return false; … … 369 503 Type * t1 = (*list1Begin)->get_type(); 370 504 if ( Tuples::isTtype( t1 ) ) { 371 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) .get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );505 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 372 506 } else return false; 373 507 } else if ( list2Begin != list2End ) { … … 375 509 Type * t2 = (*list2Begin)->get_type(); 376 510 if ( Tuples::isTtype( t2 ) ) { 377 return unifyExact( combineTypes( list1Begin, list1End, get_type ) .get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );511 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 378 512 } else return false; 379 513 } else { … … 394 528 // expand ttype parameter into its actual type 395 529 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) { 396 delete typeInst;397 530 return eqvClass->type->clone(); 398 531 } … … 418 551 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) ); 419 552 } 420 delete dcl;421 553 } 422 554 } … … 427 559 // flatten the parameter lists for both functions so that tuple structure 428 560 // doesn't affect unification. Must be a clone so that the types don't change. 429 std::unique_ptr<FunctionType> flatFunc( functionType->clone());430 std::unique_ptr<FunctionType> flatOther( otherFunction->clone());561 FunctionType* flatFunc = functionType->clone(); 562 FunctionType* flatOther = otherFunction->clone(); 431 563 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 432 564 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); … … 569 701 if ( isTtype1 && ! isTtype2 ) { 570 702 // combine all of the things in list2, then unify 571 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) .get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );703 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 572 704 } else if ( isTtype2 && ! isTtype1 ) { 573 705 // combine all of the things in list1, then unify 574 return unifyExact( combineTypes( list1Begin, list1End, get_type ) .get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );706 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 575 707 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 576 708 return false; … … 582 714 Type * t1 = *list1Begin; 583 715 if ( Tuples::isTtype( t1 ) ) { 584 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ) .get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );716 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 585 717 } else return false; 586 718 } else if ( list2Begin != list2End ) { … … 588 720 Type * t2 = *list2Begin; 589 721 if ( Tuples::isTtype( t2 ) ) { 590 return unifyExact( combineTypes( list1Begin, list1End, get_type ) .get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );722 return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 591 723 } else return false; 592 724 } else { … … 597 729 void Unify::postvisit(TupleType *tupleType) { 598 730 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 599 std::unique_ptr<TupleType> flat1( tupleType->clone());600 std::unique_ptr<TupleType> flat2( otherTuple->clone());731 TupleType* flat1 = tupleType->clone(); 732 TupleType* flat2 = otherTuple->clone(); 601 733 std::list<Type *> types1, types2; 602 734 … … 605 737 flat2->acceptMutator( expander ); 606 738 607 flatten( flat1 .get(), back_inserter( types1 ) );608 flatten( flat2 .get(), back_inserter( types2 ) );739 flatten( flat1, back_inserter( types1 ) ); 740 flatten( flat2, back_inserter( types2 ) ); 609 741 610 742 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.