Changes in src/ResolvExpr/Unify.cc [a2a77af:6c3a988f]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
ra2a77af r6c3a988f 26 26 #include "SymTab/Indexer.h" 27 27 #include "Common/utility.h" 28 28 #include "Tuples/Tuples.h" 29 29 30 30 // #define DEBUG … … 99 99 newFirst->get_qualifiers() = Type::Qualifiers(); 100 100 newSecond->get_qualifiers() = Type::Qualifiers(); 101 /// std::c out<< "first is ";102 /// first->print( std::c out);103 /// std::c out<< std::endl << "second is ";104 /// second->print( std::c out);105 /// std::c out<< std::endl << "newFirst is ";106 /// newFirst->print( std::c out);107 /// std::c out<< std::endl << "newSecond is ";108 /// newSecond->print( std::c out);109 /// std::c out<< std::endl;101 /// std::cerr << "first is "; 102 /// first->print( std::cerr ); 103 /// std::cerr << std::endl << "second is "; 104 /// second->print( std::cerr ); 105 /// std::cerr << std::endl << "newFirst is "; 106 /// newFirst->print( std::cerr ); 107 /// std::cerr << std::endl << "newSecond is "; 108 /// newSecond->print( std::cerr ); 109 /// std::cerr << std::endl; 110 110 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 111 111 delete newFirst; … … 123 123 } 124 124 125 bool tyVarCompatible( TypeDecl::Kind kind, Type *type, const SymTab::Indexer &indexer ) { 126 switch ( kind ) { 125 struct CompleteTypeChecker : public Visitor { 126 virtual void visit( VoidType *basicType ) { status = false; } 127 virtual void visit( BasicType *basicType ) {} 128 virtual void visit( PointerType *pointerType ) {} 129 virtual void visit( ArrayType *arrayType ) { status = ! arrayType->get_isVarLen(); } 130 virtual void visit( FunctionType *functionType ) {} 131 virtual void visit( StructInstType *aggregateUseType ) { status = aggregateUseType->get_baseStruct()->has_body(); } 132 virtual void visit( UnionInstType *aggregateUseType ) { status = aggregateUseType->get_baseUnion()->has_body(); } 133 // xxx - enum inst does not currently contain a pointer to base, this should be fixed. 134 virtual void visit( EnumInstType *aggregateUseType ) { /* status = aggregateUseType->get_baseEnum()->hasBody(); */ } 135 virtual void visit( TraitInstType *aggregateUseType ) { assert( false ); } 136 virtual void visit( TypeInstType *aggregateUseType ) { status = aggregateUseType->get_baseType()->isComplete(); } 137 virtual void visit( TupleType *tupleType ) {} // xxx - not sure if this is right, might need to recursively check complete-ness 138 virtual void visit( TypeofType *typeofType ) { assert( false ); } 139 virtual void visit( AttrType *attrType ) { assert( false ); } // xxx - not sure what to do here 140 virtual void visit( VarArgsType *varArgsType ){} // xxx - is this right? 141 virtual void visit( ZeroType *zeroType ) {} 142 virtual void visit( OneType *oneType ) {} 143 bool status = true; 144 }; 145 bool isComplete( Type * type ) { 146 CompleteTypeChecker checker; 147 assert( type ); 148 type->accept( checker ); 149 return checker.status; 150 } 151 152 bool tyVarCompatible( const TypeDecl::Data & data, Type *type, const SymTab::Indexer &indexer ) { 153 switch ( data.kind ) { 127 154 case TypeDecl::Any: 128 155 case TypeDecl::Dtype: 129 return ! isFtype( type, indexer ); 130 156 // to bind to an object type variable, the type must not be a function type. 157 // if the type variable is specified to be a complete type then the incoming 158 // type must also be complete 159 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 160 return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type )); 131 161 case TypeDecl::Ftype: 132 162 return isFtype( type, indexer ); 163 case TypeDecl::Ttype: 164 // ttype unifies with any tuple type 165 return dynamic_cast< TupleType * >( type ); 133 166 } // switch 134 assert( false );135 167 return false; 136 168 } 137 169 138 bool bindVar( TypeInstType *typeInst, Type *other, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {170 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 ) { 139 171 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 140 172 assert( tyvar != openVars.end() ); … … 175 207 newClass.type->get_qualifiers() = Type::Qualifiers(); 176 208 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 177 newClass. kind = kind;209 newClass.data = data; 178 210 env.add( newClass ); 179 211 } // if … … 181 213 } 182 214 183 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {215 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 ) { 184 216 bool result = true; 185 217 EqvClass class1, class2; … … 210 242 211 243 if ( type1 && type2 ) { 212 // std::c out<< "has type1 && type2" << std::endl;244 // std::cerr << "has type1 && type2" << std::endl; 213 245 WidenMode newWidenMode ( widen1, widen2 ); 214 246 Type *common = 0; … … 248 280 newClass.vars.insert( var2->get_name() ); 249 281 newClass.allowWidening = widen1 && widen2; 250 newClass. kind = kind;282 newClass.data = data; 251 283 env.add( newClass ); 252 284 } // if … … 311 343 } // if 312 344 #ifdef DEBUG 313 std::c out<< "============ unifyExact" << std::endl;314 std::c out<< "type1 is ";315 type1->print( std::c out);316 std::c out<< std::endl << "type2 is ";317 type2->print( std::c out);318 std::c out<< std::endl << "openVars are ";319 printOpenVarSet( openVars, std::c out, 8 );320 std::c out<< std::endl << "input env is " << std::endl;321 debugEnv.print( std::c out, 8 );322 std::c out<< std::endl << "result env is " << std::endl;323 env.print( std::c out, 8 );324 std::c out<< "result is " << result << std::endl;345 std::cerr << "============ unifyExact" << std::endl; 346 std::cerr << "type1 is "; 347 type1->print( std::cerr ); 348 std::cerr << std::endl << "type2 is "; 349 type2->print( std::cerr ); 350 std::cerr << std::endl << "openVars are "; 351 printOpenVarSet( openVars, std::cerr, 8 ); 352 std::cerr << std::endl << "input env is " << std::endl; 353 debugEnv.print( std::cerr, 8 ); 354 std::cerr << std::endl << "result env is " << std::endl; 355 env.print( std::cerr, 8 ); 356 std::cerr << "result is " << result << std::endl; 325 357 #endif 326 358 return result; … … 337 369 bool result; 338 370 #ifdef DEBUG 339 std::c out<< "unifyInexact type 1 is ";340 type1->print( std::c out);341 std::c out<< "type 2 is ";342 type2->print( std::c out);343 std::c out<< std::endl;371 std::cerr << "unifyInexact type 1 is "; 372 type1->print( std::cerr ); 373 std::cerr << "type 2 is "; 374 type2->print( std::cerr ); 375 std::cerr << std::endl; 344 376 #endif 345 377 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) { 346 378 #ifdef DEBUG 347 std::c out<< "unifyInexact: no exact unification found" << std::endl;379 std::cerr << "unifyInexact: no exact unification found" << std::endl; 348 380 #endif 349 381 if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) { 350 382 common->get_qualifiers() = tq1 + tq2; 351 383 #ifdef DEBUG 352 std::c out<< "unifyInexact: common type is ";353 common->print( std::c out);354 std::c out<< std::endl;384 std::cerr << "unifyInexact: common type is "; 385 common->print( std::cerr ); 386 std::cerr << std::endl; 355 387 #endif 356 388 result = true; 357 389 } else { 358 390 #ifdef DEBUG 359 std::c out<< "unifyInexact: no common type found" << std::endl;391 std::cerr << "unifyInexact: no common type found" << std::endl; 360 392 #endif 361 393 result = false; … … 394 426 395 427 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 396 /// std::c out<< "assertion set is" << std::endl;397 /// printAssertionSet( assertions, std::c out, 8 );398 /// std::c out<< "looking for ";399 /// assert->print( std::c out);400 /// std::c out<< std::endl;428 /// std::cerr << "assertion set is" << std::endl; 429 /// printAssertionSet( assertions, std::cerr, 8 ); 430 /// std::cerr << "looking for "; 431 /// assert->print( std::cerr ); 432 /// std::cerr << std::endl; 401 433 AssertionSet::iterator i = assertions.find( assert ); 402 434 if ( i != assertions.end() ) { 403 /// std::c out<< "found it!" << std::endl;404 i->second = true;435 /// std::cerr << "found it!" << std::endl; 436 i->second.isUsed = true; 405 437 } // if 406 438 } … … 456 488 } 457 489 490 template< typename Iterator > 491 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) { 492 std::list< Type * > types; 493 for ( ; begin != end; ++begin ) { 494 // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple 495 flatten( (*begin)->get_type(), back_inserter( types ) ); 496 } 497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 498 } 499 458 500 template< typename Iterator1, typename Iterator2 > 459 501 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 460 502 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 461 // Type * commonType; 462 // if ( ! unifyInexact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) { 463 if ( ! unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 503 Type * t1 = (*list1Begin)->get_type(); 504 Type * t2 = (*list2Begin)->get_type(); 505 bool isTtype1 = Tuples::isTtype( t1 ); 506 bool isTtype2 = Tuples::isTtype( t2 ); 507 // xxx - assumes ttype must be last parameter 508 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 509 if ( isTtype1 && ! isTtype2 ) { 510 // combine all of the things in list2, then unify 511 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 512 } else if ( isTtype2 && ! isTtype1 ) { 513 // combine all of the things in list1, then unify 514 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 515 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 464 516 return false; 465 517 } // if 466 518 } // for 467 if ( list1Begin != list1End || list2Begin != list2End ) { 468 return false; 519 // may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype 520 if ( list1Begin != list1End ) { 521 // try unifying empty tuple type with ttype 522 Type * t1 = (*list1Begin)->get_type(); 523 if ( Tuples::isTtype( t1 ) ) { 524 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 525 } else return false; 526 } else if ( list2Begin != list2End ) { 527 // try unifying empty tuple type with ttype 528 Type * t2 = (*list2Begin)->get_type(); 529 if ( Tuples::isTtype( t2 ) ) { 530 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 531 } else return false; 469 532 } else { 470 533 return true; 471 534 } // if 535 } 536 537 /// Finds ttypes and replaces them with their expansion, if known. 538 /// This needs to be done so that satisfying ttype assertions is easier. 539 /// If this isn't done then argument lists can have wildly different 540 /// size and structure, when they should be compatible. 541 struct TtypeExpander : public Mutator { 542 TypeEnvironment & env; 543 TtypeExpander( TypeEnvironment & env ) : env( env ) {} 544 Type * mutate( TypeInstType * typeInst ) { 545 EqvClass eqvClass; 546 if ( env.lookup( typeInst->get_name(), eqvClass ) ) { 547 if ( eqvClass.data.kind == TypeDecl::Ttype ) { 548 // expand ttype parameter into its actual type 549 if ( eqvClass.type ) { 550 delete typeInst; 551 return eqvClass.type->clone(); 552 } 553 } 554 } 555 return typeInst; 556 } 557 }; 558 559 /// flattens a list of declarations, so that each tuple type has a single declaration. 560 /// makes use of TtypeExpander to ensure ttypes are flat as well. 561 void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) { 562 dst.clear(); 563 for ( DeclarationWithType * dcl : src ) { 564 TtypeExpander expander( env ); 565 dcl->acceptMutator( expander ); 566 std::list< Type * > types; 567 flatten( dcl->get_type(), back_inserter( types ) ); 568 for ( Type * t : types ) { 569 dst.push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t, nullptr ) ); 570 } 571 delete dcl; 572 } 472 573 } 473 574 … … 475 576 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 476 577 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 477 if ( functionType->get_parameters().size() == otherFunction->get_parameters().size() && functionType->get_returnVals().size() == otherFunction->get_returnVals().size() ) { 478 if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 479 if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 480 578 // flatten the parameter lists for both functions so that tuple structure 579 // doesn't affect unification. Must be a clone so that the types don't change. 580 std::unique_ptr<FunctionType> flatFunc( functionType->clone() ); 581 std::unique_ptr<FunctionType> flatOther( otherFunction->clone() ); 582 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 583 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); 584 585 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 586 if ( (flatFunc->get_parameters().size() == flatOther->get_parameters().size() && flatFunc->get_returnVals().size() == flatOther->get_returnVals().size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 587 if ( unifyDeclList( flatFunc->get_parameters().begin(), flatFunc->get_parameters().end(), flatOther->get_parameters().begin(), flatOther->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 588 if ( unifyDeclList( flatFunc->get_returnVals().begin(), flatFunc->get_returnVals().end(), flatOther->get_returnVals().begin(), flatOther->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 589 590 // the original types must be used in mark assertions, since pointer comparisons are used 481 591 markAssertions( haveAssertions, needAssertions, functionType ); 482 592 markAssertions( haveAssertions, needAssertions, otherFunction );
Note:
See TracChangeset
for help on using the changeset viewer.