Changes in src/ResolvExpr/Unify.cc [6c3a988f:a2a77af]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r6c3a988f ra2a77af 26 26 #include "SymTab/Indexer.h" 27 27 #include "Common/utility.h" 28 #include "Tuples/Tuples.h" 28 29 29 30 30 // #define DEBUG … … 99 99 newFirst->get_qualifiers() = Type::Qualifiers(); 100 100 newSecond->get_qualifiers() = Type::Qualifiers(); 101 /// std::c err<< "first is ";102 /// first->print( std::c err);103 /// std::c err<< std::endl << "second is ";104 /// second->print( std::c err);105 /// std::c err<< std::endl << "newFirst is ";106 /// newFirst->print( std::c err);107 /// std::c err<< std::endl << "newSecond is ";108 /// newSecond->print( std::c err);109 /// std::c err<< std::endl;101 /// std::cout << "first is "; 102 /// first->print( std::cout ); 103 /// std::cout << std::endl << "second is "; 104 /// second->print( std::cout ); 105 /// std::cout << std::endl << "newFirst is "; 106 /// newFirst->print( std::cout ); 107 /// std::cout << std::endl << "newSecond is "; 108 /// newSecond->print( std::cout ); 109 /// std::cout << 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 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 ) { 125 bool tyVarCompatible( TypeDecl::Kind kind, Type *type, const SymTab::Indexer &indexer ) { 126 switch ( kind ) { 154 127 case TypeDecl::Any: 155 128 case TypeDecl::Dtype: 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 )); 129 return ! isFtype( type, indexer ); 130 161 131 case TypeDecl::Ftype: 162 132 return isFtype( type, indexer ); 163 case TypeDecl::Ttype:164 // ttype unifies with any tuple type165 return dynamic_cast< TupleType * >( type );166 133 } // switch 134 assert( false ); 167 135 return false; 168 136 } 169 137 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 ) {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 ) { 171 139 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() ); 172 140 assert( tyvar != openVars.end() ); … … 207 175 newClass.type->get_qualifiers() = Type::Qualifiers(); 208 176 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 209 newClass. data = data;177 newClass.kind = kind; 210 178 env.add( newClass ); 211 179 } // if … … 213 181 } 214 182 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 ) {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 ) { 216 184 bool result = true; 217 185 EqvClass class1, class2; … … 242 210 243 211 if ( type1 && type2 ) { 244 // std::c err<< "has type1 && type2" << std::endl;212 // std::cout << "has type1 && type2" << std::endl; 245 213 WidenMode newWidenMode ( widen1, widen2 ); 246 214 Type *common = 0; … … 280 248 newClass.vars.insert( var2->get_name() ); 281 249 newClass.allowWidening = widen1 && widen2; 282 newClass. data = data;250 newClass.kind = kind; 283 251 env.add( newClass ); 284 252 } // if … … 343 311 } // if 344 312 #ifdef DEBUG 345 std::c err<< "============ unifyExact" << std::endl;346 std::c err<< "type1 is ";347 type1->print( std::c err);348 std::c err<< std::endl << "type2 is ";349 type2->print( std::c err);350 std::c err<< std::endl << "openVars are ";351 printOpenVarSet( openVars, std::c err, 8 );352 std::c err<< std::endl << "input env is " << std::endl;353 debugEnv.print( std::c err, 8 );354 std::c err<< std::endl << "result env is " << std::endl;355 env.print( std::c err, 8 );356 std::c err<< "result is " << result << std::endl;313 std::cout << "============ unifyExact" << std::endl; 314 std::cout << "type1 is "; 315 type1->print( std::cout ); 316 std::cout << std::endl << "type2 is "; 317 type2->print( std::cout ); 318 std::cout << std::endl << "openVars are "; 319 printOpenVarSet( openVars, std::cout, 8 ); 320 std::cout << std::endl << "input env is " << std::endl; 321 debugEnv.print( std::cout, 8 ); 322 std::cout << std::endl << "result env is " << std::endl; 323 env.print( std::cout, 8 ); 324 std::cout << "result is " << result << std::endl; 357 325 #endif 358 326 return result; … … 369 337 bool result; 370 338 #ifdef DEBUG 371 std::c err<< "unifyInexact type 1 is ";372 type1->print( std::c err);373 std::c err<< "type 2 is ";374 type2->print( std::c err);375 std::c err<< std::endl;339 std::cout << "unifyInexact type 1 is "; 340 type1->print( std::cout ); 341 std::cout << "type 2 is "; 342 type2->print( std::cout ); 343 std::cout << std::endl; 376 344 #endif 377 345 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) { 378 346 #ifdef DEBUG 379 std::c err<< "unifyInexact: no exact unification found" << std::endl;347 std::cout << "unifyInexact: no exact unification found" << std::endl; 380 348 #endif 381 349 if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) { 382 350 common->get_qualifiers() = tq1 + tq2; 383 351 #ifdef DEBUG 384 std::c err<< "unifyInexact: common type is ";385 common->print( std::c err);386 std::c err<< std::endl;352 std::cout << "unifyInexact: common type is "; 353 common->print( std::cout ); 354 std::cout << std::endl; 387 355 #endif 388 356 result = true; 389 357 } else { 390 358 #ifdef DEBUG 391 std::c err<< "unifyInexact: no common type found" << std::endl;359 std::cout << "unifyInexact: no common type found" << std::endl; 392 360 #endif 393 361 result = false; … … 426 394 427 395 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 428 /// std::c err<< "assertion set is" << std::endl;429 /// printAssertionSet( assertions, std::c err, 8 );430 /// std::c err<< "looking for ";431 /// assert->print( std::c err);432 /// std::c err<< std::endl;396 /// std::cout << "assertion set is" << std::endl; 397 /// printAssertionSet( assertions, std::cout, 8 ); 398 /// std::cout << "looking for "; 399 /// assert->print( std::cout ); 400 /// std::cout << std::endl; 433 401 AssertionSet::iterator i = assertions.find( assert ); 434 402 if ( i != assertions.end() ) { 435 /// std::c err<< "found it!" << std::endl;436 i->second .isUsed= true;403 /// std::cout << "found it!" << std::endl; 404 i->second = true; 437 405 } // if 438 406 } … … 488 456 } 489 457 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 tuple495 flatten( (*begin)->get_type(), back_inserter( types ) );496 }497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );498 }499 500 458 template< typename Iterator1, typename Iterator2 > 501 459 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 502 460 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 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 ) ) { 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 ) ) { 516 464 return false; 517 465 } // if 518 466 } // for 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; 467 if ( list1Begin != list1End || list2Begin != list2End ) { 468 return false; 532 469 } else { 533 470 return true; 534 471 } // 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 different540 /// 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 type549 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 }573 472 } 574 473 … … 576 475 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 577 476 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 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 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 591 481 markAssertions( haveAssertions, needAssertions, functionType ); 592 482 markAssertions( haveAssertions, needAssertions, otherFunction );
Note:
See TracChangeset
for help on using the changeset viewer.