Changes in src/ResolvExpr/Unify.cc [c6b4432:8f31be6]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
rc6b4432 r8f31be6 33 33 #include "AST/TypeEnvironment.hpp" 34 34 #include "Common/Eval.h" // for eval 35 #include "Common/PassVisitor.h" // for PassVisitor 35 36 #include "CommonType.hpp" // for commonType 36 37 #include "FindOpenVars.h" // for findOpenVars 37 38 #include "SpecCost.hpp" // for SpecCost 39 #include "SynTree/LinkageSpec.h" // for C 40 #include "SynTree/Constant.h" // for Constant 41 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Declarati... 42 #include "SynTree/Expression.h" // for TypeExpr, Expression, ConstantExpr 43 #include "SynTree/Mutator.h" // for Mutator 44 #include "SynTree/Type.h" // for Type, TypeInstType, FunctionType 45 #include "SynTree/Visitor.h" // for Visitor 38 46 #include "Tuples/Tuples.h" // for isTtype 47 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 39 48 #include "typeops.h" // for flatten, occurs 40 49 … … 43 52 } 44 53 54 namespace SymTab { 55 class Indexer; 56 } // namespace SymTab 57 45 58 // #define DEBUG 46 59 47 60 namespace ResolvExpr { 61 62 // Template Helpers: 63 template< typename Iterator1, typename Iterator2 > 64 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) { 65 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 66 Type *commonType = 0; 67 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 68 return false; 69 } // if 70 commonTypes.push_back( commonType ); 71 } // for 72 return ( list1Begin == list1End && list2Begin == list2End ); 73 } 74 75 template< typename Iterator1, typename Iterator2 > 76 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 77 std::list< Type* > commonTypes; 78 if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) { 79 deleteAll( commonTypes ); 80 return true; 81 } else { 82 return false; 83 } // if 84 } 85 86 struct Unify_old : public WithShortCircuiting { 87 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 88 89 bool get_result() const { return result; } 90 91 void previsit( BaseSyntaxNode * ) { visit_children = false; } 92 93 void postvisit( VoidType * voidType ); 94 void postvisit( BasicType * basicType ); 95 void postvisit( PointerType * pointerType ); 96 void postvisit( ArrayType * arrayType ); 97 void postvisit( ReferenceType * refType ); 98 void postvisit( FunctionType * functionType ); 99 void postvisit( StructInstType * aggregateUseType ); 100 void postvisit( UnionInstType * aggregateUseType ); 101 void postvisit( EnumInstType * aggregateUseType ); 102 void postvisit( TraitInstType * aggregateUseType ); 103 void postvisit( TypeInstType * aggregateUseType ); 104 void postvisit( TupleType * tupleType ); 105 void postvisit( VarArgsType * varArgsType ); 106 void postvisit( ZeroType * zeroType ); 107 void postvisit( OneType * oneType ); 108 109 private: 110 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 111 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); 112 113 bool result; 114 Type *type2; // inherited 115 TypeEnvironment &env; 116 AssertionSet &needAssertions; 117 AssertionSet &haveAssertions; 118 const OpenVarSet &openVars; 119 WidenMode widen; 120 const SymTab::Indexer &indexer; 121 }; 122 123 /// Attempts an inexact unification of type1 and type2. 124 /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers) 125 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 126 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 127 128 bool unifyExact( 129 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 130 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 131 WidenMode widen ); 132 133 bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 134 TypeEnvironment newEnv; 135 OpenVarSet openVars, closedVars; // added closedVars 136 AssertionSet needAssertions, haveAssertions; 137 Type * newFirst = first->clone(), * newSecond = second->clone(); 138 env.apply( newFirst ); 139 env.apply( newSecond ); 140 141 // do we need to do this? Seems like we do, types should be able to be compatible if they 142 // have free variables that can unify 143 findOpenVars( newFirst, openVars, closedVars, needAssertions, haveAssertions, false ); 144 findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true ); 145 146 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 147 delete newFirst; 148 delete newSecond; 149 return result; 150 } 48 151 49 152 bool typesCompatible( … … 62 165 63 166 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() ); 167 } 168 169 bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 170 TypeEnvironment newEnv; 171 OpenVarSet openVars; 172 AssertionSet needAssertions, haveAssertions; 173 Type *newFirst = first->clone(), *newSecond = second->clone(); 174 env.apply( newFirst ); 175 env.apply( newSecond ); 176 newFirst->get_qualifiers() = Type::Qualifiers(); 177 newSecond->get_qualifiers() = Type::Qualifiers(); 178 179 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 180 delete newFirst; 181 delete newSecond; 182 return result; 64 183 } 65 184 … … 99 218 subSecond, 100 219 newEnv, need, have, open, noWiden() ); 220 } 221 222 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 223 OpenVarSet closedVars; 224 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false ); 225 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true ); 226 Type *commonType = 0; 227 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) { 228 if ( commonType ) { 229 delete commonType; 230 } // if 231 return true; 232 } else { 233 return false; 234 } // if 235 } 236 237 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ) { 238 OpenVarSet closedVars; 239 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false ); 240 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true ); 241 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ); 242 } 243 244 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) { 245 #ifdef DEBUG 246 TypeEnvironment debugEnv( env ); 247 #endif 248 if ( type1->get_qualifiers() != type2->get_qualifiers() ) { 249 return false; 250 } 251 252 bool result; 253 TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 ); 254 TypeInstType *var2 = dynamic_cast< TypeInstType* >( type2 ); 255 OpenVarSet::const_iterator entry1, entry2; 256 if ( var1 ) { 257 entry1 = openVars.find( var1->get_name() ); 258 } // if 259 if ( var2 ) { 260 entry2 = openVars.find( var2->get_name() ); 261 } // if 262 bool isopen1 = var1 && ( entry1 != openVars.end() ); 263 bool isopen2 = var2 && ( entry2 != openVars.end() ); 264 265 if ( isopen1 && isopen2 ) { 266 if ( entry1->second.kind != entry2->second.kind ) { 267 result = false; 268 } else { 269 result = env.bindVarToVar( 270 var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions, 271 haveAssertions, openVars, widen, indexer ); 272 } 273 } else if ( isopen1 ) { 274 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer ); 275 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped? 276 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer ); 277 } else { 278 PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer ); 279 type1->accept( comparator ); 280 result = comparator.pass.get_result(); 281 } // if 282 #ifdef DEBUG 283 std::cerr << "============ unifyExact" << std::endl; 284 std::cerr << "type1 is "; 285 type1->print( std::cerr ); 286 std::cerr << std::endl << "type2 is "; 287 type2->print( std::cerr ); 288 std::cerr << std::endl << "openVars are "; 289 printOpenVarSet( openVars, std::cerr, 8 ); 290 std::cerr << std::endl << "input env is " << std::endl; 291 debugEnv.print( std::cerr, 8 ); 292 std::cerr << std::endl << "result env is " << std::endl; 293 env.print( std::cerr, 8 ); 294 std::cerr << "result is " << result << std::endl; 295 #endif 296 return result; 297 } 298 299 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 300 return unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 301 } 302 303 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) { 304 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers(); 305 type1->get_qualifiers() = Type::Qualifiers(); 306 type2->get_qualifiers() = Type::Qualifiers(); 307 bool result; 308 #ifdef DEBUG 309 std::cerr << "unifyInexact type 1 is "; 310 type1->print( std::cerr ); 311 std::cerr << " type 2 is "; 312 type2->print( std::cerr ); 313 std::cerr << std::endl; 314 #endif 315 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) { 316 #ifdef DEBUG 317 std::cerr << "unifyInexact: no exact unification found" << std::endl; 318 #endif 319 if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) { 320 common->tq = tq1.unify( tq2 ); 321 #ifdef DEBUG 322 std::cerr << "unifyInexact: common type is "; 323 common->print( std::cerr ); 324 std::cerr << std::endl; 325 #endif 326 result = true; 327 } else { 328 #ifdef DEBUG 329 std::cerr << "unifyInexact: no common type found" << std::endl; 330 #endif 331 result = false; 332 } // if 333 } else { 334 if ( tq1 != tq2 ) { 335 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) { 336 common = type1->clone(); 337 common->tq = tq1.unify( tq2 ); 338 result = true; 339 } else { 340 result = false; 341 } // if 342 } else { 343 common = type1->clone(); 344 common->tq = tq1.unify( tq2 ); 345 result = true; 346 } // if 347 } // if 348 type1->get_qualifiers() = tq1; 349 type2->get_qualifiers() = tq2; 350 return result; 351 } 352 353 Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) 354 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) { 355 } 356 357 void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) { 358 result = dynamic_cast< VoidType* >( type2 ); 359 } 360 361 void Unify_old::postvisit(BasicType *basicType) { 362 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 363 result = basicType->get_kind() == otherBasic->get_kind(); 364 } // if 365 } 366 367 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 368 AssertionSet::iterator i = assertions.find( assert ); 369 if ( i != assertions.end() ) { 370 i->second.isUsed = true; 371 } // if 372 } 373 374 void markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type ) { 375 for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) { 376 for ( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) { 377 markAssertionSet( assertion1, *assert ); 378 markAssertionSet( assertion2, *assert ); 379 } // for 380 } // for 381 } 382 383 void Unify_old::postvisit(PointerType *pointerType) { 384 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 385 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 386 markAssertions( haveAssertions, needAssertions, pointerType ); 387 markAssertions( haveAssertions, needAssertions, otherPointer ); 388 } // if 389 } 390 391 void Unify_old::postvisit(ReferenceType *refType) { 392 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 393 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 394 markAssertions( haveAssertions, needAssertions, refType ); 395 markAssertions( haveAssertions, needAssertions, otherRef ); 396 } // if 397 } 398 399 void Unify_old::postvisit(ArrayType *arrayType) { 400 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 401 // to unify, array types must both be VLA or both not VLA 402 // and must both have a dimension expression or not have a dimension 403 if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) { 404 405 if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() && 406 arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) { 407 ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() ); 408 ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( otherArray->get_dimension() ); 409 // see C11 Reference Manual 6.7.6.2.6 410 // two array types with size specifiers that are integer constant expressions are 411 // compatible if both size specifiers have the same constant value 412 if ( ce1 && ce2 ) { 413 Constant * c1 = ce1->get_constant(); 414 Constant * c2 = ce2->get_constant(); 415 416 if ( c1->get_value() != c2->get_value() ) { 417 // does not unify if the dimension is different 418 return; 419 } 420 } 421 } 422 423 result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 424 } // if 425 } 426 427 template< typename Iterator, typename Func > 428 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) { 429 std::list< Type * > types; 430 for ( ; begin != end; ++begin ) { 431 // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple 432 flatten( toType( *begin ), back_inserter( types ) ); 433 } 434 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 435 } 436 437 template< typename Iterator1, typename Iterator2 > 438 bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 439 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); }; 440 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 441 Type * t1 = (*list1Begin)->get_type(); 442 Type * t2 = (*list2Begin)->get_type(); 443 bool isTtype1 = Tuples::isTtype( t1 ); 444 bool isTtype2 = Tuples::isTtype( t2 ); 445 // xxx - assumes ttype must be last parameter 446 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 447 if ( isTtype1 && ! isTtype2 ) { 448 // combine all of the things in list2, then unify 449 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 450 } else if ( isTtype2 && ! isTtype1 ) { 451 // combine all of the things in list1, then unify 452 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 453 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 454 return false; 455 } // if 456 } // for 457 // 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 458 if ( list1Begin != list1End ) { 459 // try unifying empty tuple type with ttype 460 Type * t1 = (*list1Begin)->get_type(); 461 if ( Tuples::isTtype( t1 ) ) { 462 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 463 } else return false; 464 } else if ( list2Begin != list2End ) { 465 // try unifying empty tuple type with ttype 466 Type * t2 = (*list2Begin)->get_type(); 467 if ( Tuples::isTtype( t2 ) ) { 468 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 469 } else return false; 470 } else { 471 return true; 472 } // if 473 } 474 475 /// Finds ttypes and replaces them with their expansion, if known. 476 /// This needs to be done so that satisfying ttype assertions is easier. 477 /// If this isn't done then argument lists can have wildly different 478 /// size and structure, when they should be compatible. 479 struct TtypeExpander_old : public WithShortCircuiting { 480 TypeEnvironment & tenv; 481 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {} 482 void premutate( TypeInstType * ) { visit_children = false; } 483 Type * postmutate( TypeInstType * typeInst ) { 484 if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) { 485 // expand ttype parameter into its actual type 486 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) { 487 delete typeInst; 488 return eqvClass->type->clone(); 489 } 490 } 491 return typeInst; 492 } 493 }; 494 495 /// flattens a list of declarations, so that each tuple type has a single declaration. 496 /// makes use of TtypeExpander to ensure ttypes are flat as well. 497 void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) { 498 dst.clear(); 499 for ( DeclarationWithType * dcl : src ) { 500 PassVisitor<TtypeExpander_old> expander( env ); 501 dcl->acceptMutator( expander ); 502 std::list< Type * > types; 503 flatten( dcl->get_type(), back_inserter( types ) ); 504 for ( Type * t : types ) { 505 // outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable. 506 // Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function. 507 t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic); 508 509 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) ); 510 } 511 delete dcl; 512 } 513 } 514 515 void Unify_old::postvisit(FunctionType *functionType) { 516 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 517 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 518 // flatten the parameter lists for both functions so that tuple structure 519 // doesn't affect unification. Must be a clone so that the types don't change. 520 std::unique_ptr<FunctionType> flatFunc( functionType->clone() ); 521 std::unique_ptr<FunctionType> flatOther( otherFunction->clone() ); 522 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 523 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); 524 525 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 526 if ( 527 (flatFunc->parameters.size() == flatOther->parameters.size() && 528 flatFunc->returnVals.size() == flatOther->returnVals.size()) 529 || flatFunc->isTtype() 530 || flatOther->isTtype() 531 ) { 532 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 533 if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 534 535 // the original types must be used in mark assertions, since pointer comparisons are used 536 markAssertions( haveAssertions, needAssertions, functionType ); 537 markAssertions( haveAssertions, needAssertions, otherFunction ); 538 539 result = true; 540 } // if 541 } // if 542 } // if 543 } // if 544 } 545 546 template< typename RefType > 547 void Unify_old::handleRefType( RefType *inst, Type *other ) { 548 // check that other type is compatible and named the same 549 RefType *otherStruct = dynamic_cast< RefType* >( other ); 550 result = otherStruct && inst->name == otherStruct->name; 551 } 552 553 template< typename RefType > 554 void Unify_old::handleGenericRefType( RefType *inst, Type *other ) { 555 // Check that other type is compatible and named the same 556 handleRefType( inst, other ); 557 if ( ! result ) return; 558 // Check that parameters of types unify, if any 559 std::list< Expression* > params = inst->parameters; 560 std::list< Expression* > otherParams = ((RefType*)other)->parameters; 561 562 std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin(); 563 for ( ; it != params.end() && jt != otherParams.end(); ++it, ++jt ) { 564 TypeExpr *param = dynamic_cast< TypeExpr* >(*it); 565 assertf(param, "Aggregate parameters should be type expressions"); 566 TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt); 567 assertf(otherParam, "Aggregate parameters should be type expressions"); 568 569 Type* paramTy = param->get_type(); 570 Type* otherParamTy = otherParam->get_type(); 571 572 bool tupleParam = Tuples::isTtype( paramTy ); 573 bool otherTupleParam = Tuples::isTtype( otherParamTy ); 574 575 if ( tupleParam && otherTupleParam ) { 576 ++it; ++jt; // skip ttype parameters for break 577 } else if ( tupleParam ) { 578 // bundle other parameters into tuple to match 579 std::list< Type * > binderTypes; 580 581 do { 582 binderTypes.push_back( otherParam->get_type()->clone() ); 583 ++jt; 584 585 if ( jt == otherParams.end() ) break; 586 587 otherParam = dynamic_cast< TypeExpr* >(*jt); 588 assertf(otherParam, "Aggregate parameters should be type expressions"); 589 } while (true); 590 591 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes }; 592 ++it; // skip ttype parameter for break 593 } else if ( otherTupleParam ) { 594 // bundle parameters into tuple to match other 595 std::list< Type * > binderTypes; 596 597 do { 598 binderTypes.push_back( param->get_type()->clone() ); 599 ++it; 600 601 if ( it == params.end() ) break; 602 603 param = dynamic_cast< TypeExpr* >(*it); 604 assertf(param, "Aggregate parameters should be type expressions"); 605 } while (true); 606 607 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes }; 608 ++jt; // skip ttype parameter for break 609 } 610 611 if ( ! unifyExact( paramTy, otherParamTy, env, needAssertions, haveAssertions, openVars, WidenMode(false, false), indexer ) ) { 612 result = false; 613 return; 614 } 615 616 // ttype parameter should be last 617 if ( tupleParam || otherTupleParam ) break; 618 } 619 result = ( it == params.end() && jt == otherParams.end() ); 620 } 621 622 void Unify_old::postvisit(StructInstType *structInst) { 623 handleGenericRefType( structInst, type2 ); 624 } 625 626 void Unify_old::postvisit(UnionInstType *unionInst) { 627 handleGenericRefType( unionInst, type2 ); 628 } 629 630 void Unify_old::postvisit(EnumInstType *enumInst) { 631 handleRefType( enumInst, type2 ); 632 } 633 634 void Unify_old::postvisit(TraitInstType *contextInst) { 635 handleRefType( contextInst, type2 ); 636 } 637 638 void Unify_old::postvisit(TypeInstType *typeInst) { 639 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 640 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); 641 if ( otherInst && typeInst->get_name() == otherInst->get_name() ) { 642 result = true; 643 /// } else { 644 /// NamedTypeDecl *nt = indexer.lookupType( typeInst->get_name() ); 645 /// if ( nt ) { 646 /// TypeDecl *type = dynamic_cast< TypeDecl* >( nt ); 647 /// assert( type ); 648 /// if ( type->get_base() ) { 649 /// result = unifyExact( type->get_base(), typeInst, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 650 /// } 651 /// } 652 } // if 653 } 654 655 template< typename Iterator1, typename Iterator2 > 656 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 657 auto get_type = [](Type * t) { return t; }; 658 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 659 Type * t1 = *list1Begin; 660 Type * t2 = *list2Begin; 661 bool isTtype1 = Tuples::isTtype( t1 ); 662 bool isTtype2 = Tuples::isTtype( t2 ); 663 // xxx - assumes ttype must be last parameter 664 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 665 if ( isTtype1 && ! isTtype2 ) { 666 // combine all of the things in list2, then unify 667 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 668 } else if ( isTtype2 && ! isTtype1 ) { 669 // combine all of the things in list1, then unify 670 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 671 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 672 return false; 673 } // if 674 675 } // for 676 if ( list1Begin != list1End ) { 677 // try unifying empty tuple type with ttype 678 Type * t1 = *list1Begin; 679 if ( Tuples::isTtype( t1 ) ) { 680 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 681 } else return false; 682 } else if ( list2Begin != list2End ) { 683 // try unifying empty tuple type with ttype 684 Type * t2 = *list2Begin; 685 if ( Tuples::isTtype( t2 ) ) { 686 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 687 } else return false; 688 } else { 689 return true; 690 } // if 691 } 692 693 void Unify_old::postvisit(TupleType *tupleType) { 694 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 695 std::unique_ptr<TupleType> flat1( tupleType->clone() ); 696 std::unique_ptr<TupleType> flat2( otherTuple->clone() ); 697 std::list<Type *> types1, types2; 698 699 PassVisitor<TtypeExpander_old> expander( env ); 700 flat1->acceptMutator( expander ); 701 flat2->acceptMutator( expander ); 702 703 flatten( flat1.get(), back_inserter( types1 ) ); 704 flatten( flat2.get(), back_inserter( types2 ) ); 705 706 result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer ); 707 } // if 708 } 709 710 void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 711 result = dynamic_cast< VarArgsType* >( type2 ); 712 } 713 714 void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 715 result = dynamic_cast< ZeroType* >( type2 ); 716 } 717 718 void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) { 719 result = dynamic_cast< OneType* >( type2 ); 720 } 721 722 Type * extractResultType( FunctionType * function ) { 723 if ( function->get_returnVals().size() == 0 ) { 724 return new VoidType( Type::Qualifiers() ); 725 } else if ( function->get_returnVals().size() == 1 ) { 726 return function->get_returnVals().front()->get_type()->clone(); 727 } else { 728 std::list< Type * > types; 729 for ( DeclarationWithType * decl : function->get_returnVals() ) { 730 types.push_back( decl->get_type()->clone() ); 731 } // for 732 return new TupleType( Type::Qualifiers(), types ); 733 } 101 734 } 102 735
Note:
See TracChangeset
for help on using the changeset viewer.