Changes in src/ResolvExpr/Resolver.cc [8b11840:8f98b78]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r8b11840 r8f98b78 40 40 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 41 41 #include "typeops.h" // for extractResultType 42 #include "Unify.h" // for unify 42 43 43 44 using namespace std; … … 71 72 void previsit( ThrowStmt *throwStmt ); 72 73 void previsit( CatchStmt *catchStmt ); 74 void previsit( WaitForStmt * stmt ); 73 75 74 76 void previsit( SingleInit *singleInit ); … … 93 95 PassVisitor<Resolver> resolver; 94 96 acceptAll( translationUnit, resolver ); 95 }96 97 void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {98 PassVisitor<Resolver> resolver( indexer );99 maybeAccept( decl, resolver );100 97 } 101 98 … … 121 118 } 122 119 120 Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) { 121 TypeEnvironment env; 122 AlternativeFinder finder( indexer, env ); 123 finder.find( untyped ); 124 #if 0 125 if ( finder.get_alternatives().size() != 1 ) { 126 std::cout << "untyped expr is "; 127 untyped->print( std::cout ); 128 std::cout << std::endl << "alternatives are:"; 129 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 130 i->print( std::cout ); 131 } // for 132 } // if 133 #endif 134 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." ); 135 Alternative &choice = finder.get_alternatives().front(); 136 Expression *newExpr = choice.expr->clone(); 137 finishExpr( newExpr, choice.env ); 138 return newExpr; 139 } 140 123 141 namespace { 124 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {125 TypeEnvironment env;126 AlternativeFinder finder( indexer, env );127 finder.find( untyped );128 #if 0129 if ( finder.get_alternatives().size() != 1 ) {130 std::cout << "untyped expr is ";131 untyped->print( std::cout );132 std::cout << std::endl << "alternatives are:";133 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {134 i->print( std::cout );135 } // for136 } // if137 #endif138 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );139 Alternative &choice = finder.get_alternatives().front();140 Expression *newExpr = choice.expr->clone();141 finishExpr( newExpr, choice.env );142 return newExpr;143 }144 145 142 bool isIntegralType( Type *type ) { 146 143 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 396 393 } 397 394 395 inline void resolveAsIf( Expression *& expr, SymTab::Indexer & indexer ) { 396 if( !expr ) return; 397 Expression * newExpr = findSingleExpression( expr, indexer ); 398 delete expr; 399 expr = newExpr; 400 } 401 402 inline void resolveAsType( Expression *& expr, Type * type, SymTab::Indexer & indexer ) { 403 if( !expr ) return; 404 Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), indexer ); 405 delete expr; 406 expr = newExpr; 407 } 408 409 template< typename iterator_t > 410 inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) { 411 while( it != end && !(*it)->get_type()->get_mutex() ) { 412 it++; 413 } 414 415 return it != end; 416 } 417 418 void Resolver::previsit( WaitForStmt * stmt ) { 419 visit_children = false; 420 421 // Resolve all clauses first 422 for( auto& clause : stmt->clauses ) { 423 424 TypeEnvironment env; 425 AlternativeFinder funcFinder( indexer, env ); 426 427 // Find all alternatives for a function in canonical form 428 funcFinder.findWithAdjustment( clause.target.function ); 429 430 if ( funcFinder.get_alternatives().empty() ) { 431 stringstream ss; 432 ss << "Use of undeclared indentifier '"; 433 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 434 ss << "' in call to waitfor"; 435 throw SemanticError( ss.str() ); 436 } 437 438 // Find all alternatives for all arguments in canonical form 439 std::list< AlternativeFinder > argAlternatives; 440 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 441 442 // List all combinations of arguments 443 std::list< AltList > possibilities; 444 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 445 446 AltList func_candidates; 447 std::vector< AltList > args_candidates; 448 449 // For every possible function : 450 // try matching the arguments to the parameters 451 // not the other way around because we have more arguments than parameters 452 SemanticError errors; 453 for ( Alternative & func : funcFinder.get_alternatives() ) { 454 try { 455 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 456 if( !pointer ) { 457 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() ); 458 } 459 460 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 461 if( !function ) { 462 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() ); 463 } 464 465 466 { 467 auto param = function->parameters.begin(); 468 auto param_end = function->parameters.end(); 469 470 if( !advance_to_mutex( param, param_end ) ) { 471 throw SemanticError("candidate function not viable: no mutex parameters\n", function); 472 } 473 } 474 475 Alternative newFunc( func ); 476 // Strip reference from function 477 referenceToRvalueConversion( newFunc.expr ); 478 479 // For all the set of arguments we have try to match it with the parameter of the current function alternative 480 for ( auto & argsList : possibilities ) { 481 482 try { 483 // Declare data structures need for resolution 484 OpenVarSet openVars; 485 AssertionSet resultNeed, resultHave; 486 TypeEnvironment resultEnv; 487 488 // Load type variables from arguemnts into one shared space 489 simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv ); 490 491 // Make sure we don't widen any existing bindings 492 for ( auto & i : resultEnv ) { 493 i.allowWidening = false; 494 } 495 496 // Find any unbound type variables 497 resultEnv.extractOpenVars( openVars ); 498 499 auto param = function->parameters.begin(); 500 auto param_end = function->parameters.end(); 501 502 // For every arguments of its set, check if it matches one of the parameter 503 // The order is important 504 for( auto & arg : argsList ) { 505 506 // Ignore non-mutex arguments 507 if( !advance_to_mutex( param, param_end ) ) { 508 // We ran out of parameters but still have arguments 509 // this function doesn't match 510 throw SemanticError("candidate function not viable: too many mutex arguments\n", function); 511 } 512 513 // Check if the argument matches the parameter type in the current scope 514 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) { 515 // Type doesn't match 516 stringstream ss; 517 ss << "candidate function not viable: no known convertion from '"; 518 arg.expr->get_result()->print( ss ); 519 ss << "' to '"; 520 (*param)->get_type()->print( ss ); 521 ss << "'\n"; 522 throw SemanticError(ss.str(), function); 523 } 524 525 param++; 526 } 527 528 // All arguments match ! 529 530 // Check if parameters are missing 531 if( advance_to_mutex( param, param_end ) ) { 532 // We ran out of arguments but still have parameters left 533 // this function doesn't match 534 throw SemanticError("candidate function not viable: too few mutex arguments\n", function); 535 } 536 537 // All parameters match ! 538 539 // Finish the expressions to tie in the proper environments 540 finishExpr( newFunc.expr, resultEnv ); 541 for( Alternative & alt : argsList ) { 542 finishExpr( alt.expr, resultEnv ); 543 } 544 545 // This is a match store it and save it for later 546 func_candidates.push_back( newFunc ); 547 args_candidates.push_back( argsList ); 548 549 } 550 catch( SemanticError &e ) { 551 errors.append( e ); 552 } 553 } 554 } 555 catch( SemanticError &e ) { 556 errors.append( e ); 557 } 558 } 559 560 // Make sure we got the right number of arguments 561 if( func_candidates.empty() ) { SemanticError top( "No alternatives for function in call to waitfor" ); top.append( errors ); throw top; } 562 if( args_candidates.empty() ) { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; } 563 if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 564 if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 565 566 567 // Swap the results from the alternative with the unresolved values. 568 // Alternatives will handle deletion on destruction 569 std::swap( clause.target.function, func_candidates.front().expr ); 570 for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) { 571 std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr ); 572 } 573 574 // Resolve the conditions as if it were an IfStmt 575 // Resolve the statments normally 576 resolveAsIf( clause.condition, this->indexer ); 577 clause.statement->accept( *visitor ); 578 } 579 580 581 if( stmt->timeout.statement ) { 582 // Resolve the timeout as an size_t for now 583 // Resolve the conditions as if it were an IfStmt 584 // Resolve the statments normally 585 resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer ); 586 resolveAsIf ( stmt->timeout.condition, this->indexer ); 587 stmt->timeout.statement->accept( *visitor ); 588 } 589 590 if( stmt->orelse.statement ) { 591 // Resolve the conditions as if it were an IfStmt 592 // Resolve the statments normally 593 resolveAsIf( stmt->orelse.condition, this->indexer ); 594 stmt->orelse.statement->accept( *visitor ); 595 } 596 } 597 398 598 template< typename T > 399 599 bool isCharType( T t ) {
Note:
See TracChangeset
for help on using the changeset viewer.