Changes in src/ResolvExpr/Resolver.cc [a4ca48c:bb666f64]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
ra4ca48c rbb666f64 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; … … 52 53 void previsit( FunctionDecl *functionDecl ); 53 54 void postvisit( FunctionDecl *functionDecl ); 54 void previsit( ObjectDecl * functionDecl );55 void previsit( ObjectDecl *objectDecll ); 55 56 void previsit( TypeDecl *typeDecl ); 56 57 void previsit( EnumDecl * enumDecl ); … … 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 ); … … 95 97 } 96 98 99 void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) { 100 PassVisitor<Resolver> resolver( indexer ); 101 maybeAccept( decl, resolver ); 102 } 103 97 104 // used in resolveTypeof 98 105 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) { … … 102 109 103 110 namespace { 104 void finishExpr( Expression *expr, const TypeEnvironment &env ) {105 expr-> set_env( new TypeSubstitution );111 void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) { 112 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 106 113 env.makeSubstitution( *expr->get_env() ); 107 114 } 115 116 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 117 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 118 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 119 // cast is to the same type as its argument, so it's unnecessary -- remove it 120 expr = castExpr->arg; 121 castExpr->arg = nullptr; 122 std::swap( expr->env, castExpr->env ); 123 delete castExpr; 124 } 125 } 126 } 108 127 } // namespace 109 128 110 Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {129 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 111 130 global_renamer.reset(); 112 131 TypeEnvironment env; 113 132 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); 114 finishExpr( newExpr, env ); 115 return newExpr; 133 finishExpr( newExpr, env, untyped->env ); 134 delete untyped; 135 untyped = newExpr; 136 } 137 138 void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) { 139 if ( ! untyped ) return; 140 TypeEnvironment env; 141 AlternativeFinder finder( indexer, env ); 142 finder.find( untyped ); 143 #if 0 144 if ( finder.get_alternatives().size() != 1 ) { 145 std::cerr << "untyped expr is "; 146 untyped->print( std::cerr ); 147 std::cerr << std::endl << "alternatives are:"; 148 for ( const Alternative & alt : finder.get_alternatives() ) { 149 alt.print( std::cerr ); 150 } // for 151 } // if 152 #endif 153 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." ); 154 Alternative &choice = finder.get_alternatives().front(); 155 Expression *newExpr = choice.expr->clone(); 156 finishExpr( newExpr, choice.env, untyped->env ); 157 delete untyped; 158 untyped = newExpr; 159 } 160 161 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) { 162 assert( untyped && type ); 163 untyped = new CastExpr( untyped, type ); 164 findSingleExpression( untyped, indexer ); 165 removeExtraneousCast( untyped, indexer ); 116 166 } 117 167 118 168 namespace { 119 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {120 TypeEnvironment env;121 AlternativeFinder finder( indexer, env );122 finder.find( untyped );123 #if 0124 if ( finder.get_alternatives().size() != 1 ) {125 std::cout << "untyped expr is ";126 untyped->print( std::cout );127 std::cout << std::endl << "alternatives are:";128 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {129 i->print( std::cout );130 } // for131 } // if132 #endif133 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );134 Alternative &choice = finder.get_alternatives().front();135 Expression *newExpr = choice.expr->clone();136 finishExpr( newExpr, choice.env );137 return newExpr;138 }139 140 169 bool isIntegralType( Type *type ) { 141 170 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 150 179 } 151 180 152 Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) {181 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 153 182 TypeEnvironment env; 154 183 AlternativeFinder finder( indexer, env ); … … 179 208 throw SemanticError( "No interpretations for case control expression", untyped ); 180 209 } // if 181 finishExpr( newExpr, *newEnv ); 182 return newExpr; 210 finishExpr( newExpr, *newEnv, untyped->env ); 211 delete untyped; 212 untyped = newExpr; 183 213 } 184 214 … … 205 235 void Resolver::handlePtrType( PtrType * type ) { 206 236 if ( type->get_dimension() ) { 207 CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() ); 208 Expression *newExpr = findSingleExpression( castExpr, indexer ); 209 delete type->get_dimension(); 210 type->set_dimension( newExpr ); 237 findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer ); 211 238 } 212 239 } … … 238 265 functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() ); 239 266 } 240 241 267 242 268 void Resolver::postvisit( FunctionDecl *functionDecl ) { … … 262 288 void Resolver::previsit( ExprStmt *exprStmt ) { 263 289 visit_children = false; 264 assertf( exprStmt->get_expr(), "ExprStmt has null Expression in resolver" ); 265 Expression *newExpr = findVoidExpression( exprStmt->get_expr(), indexer ); 266 delete exprStmt->get_expr(); 267 exprStmt->set_expr( newExpr ); 290 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); 291 findVoidExpression( exprStmt->expr, indexer ); 268 292 } 269 293 270 294 void Resolver::previsit( AsmExpr *asmExpr ) { 271 295 visit_children = false; 272 Expression *newExpr = findVoidExpression( asmExpr->get_operand(), indexer ); 273 delete asmExpr->get_operand(); 274 asmExpr->set_operand( newExpr ); 296 findVoidExpression( asmExpr->operand, indexer ); 275 297 if ( asmExpr->get_inout() ) { 276 newExpr = findVoidExpression( asmExpr->get_inout(), indexer ); 277 delete asmExpr->get_inout(); 278 asmExpr->set_inout( newExpr ); 298 findVoidExpression( asmExpr->inout, indexer ); 279 299 } // if 280 300 } … … 287 307 288 308 void Resolver::previsit( IfStmt *ifStmt ) { 289 Expression *newExpr = findSingleExpression( ifStmt->get_condition(), indexer ); 290 delete ifStmt->get_condition(); 291 ifStmt->set_condition( newExpr ); 309 findSingleExpression( ifStmt->condition, indexer ); 292 310 } 293 311 294 312 void Resolver::previsit( WhileStmt *whileStmt ) { 295 Expression *newExpr = findSingleExpression( whileStmt->get_condition(), indexer ); 296 delete whileStmt->get_condition(); 297 whileStmt->set_condition( newExpr ); 313 findSingleExpression( whileStmt->condition, indexer ); 298 314 } 299 315 300 316 void Resolver::previsit( ForStmt *forStmt ) { 301 if ( forStmt->get_condition() ) { 302 Expression * newExpr = findSingleExpression( forStmt->get_condition(), indexer ); 303 delete forStmt->get_condition(); 304 forStmt->set_condition( newExpr ); 317 if ( forStmt->condition ) { 318 findSingleExpression( forStmt->condition, indexer ); 305 319 } // if 306 320 307 if ( forStmt->get_increment() ) { 308 Expression * newExpr = findVoidExpression( forStmt->get_increment(), indexer ); 309 delete forStmt->get_increment(); 310 forStmt->set_increment( newExpr ); 321 if ( forStmt->increment ) { 322 findVoidExpression( forStmt->increment, indexer ); 311 323 } // if 312 324 } … … 314 326 void Resolver::previsit( SwitchStmt *switchStmt ) { 315 327 GuardValue( currentObject ); 316 Expression *newExpr; 317 newExpr = findIntegralExpression( switchStmt->get_condition(), indexer ); 318 delete switchStmt->get_condition(); 319 switchStmt->set_condition( newExpr ); 320 321 currentObject = CurrentObject( newExpr->get_result() ); 328 findIntegralExpression( switchStmt->condition, indexer ); 329 330 currentObject = CurrentObject( switchStmt->condition->result ); 322 331 } 323 332 … … 326 335 std::list< InitAlternative > initAlts = currentObject.getOptions(); 327 336 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); 328 CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() ); 329 Expression * newExpr = findSingleExpression( castExpr, indexer ); 330 castExpr = strict_dynamic_cast< CastExpr * >( newExpr ); 331 caseStmt->set_condition( castExpr->get_arg() ); 332 castExpr->set_arg( nullptr ); 337 // must remove cast from case statement because RangeExpr cannot be cast. 338 Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() ); 339 findSingleExpression( newExpr, indexer ); 340 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr ); 341 caseStmt->condition = castExpr->arg; 342 castExpr->arg = nullptr; 333 343 delete castExpr; 334 344 } … … 339 349 // must resolve the argument for a computed goto 340 350 if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement 341 if ( Expression * arg = branchStmt->get_computedTarget() ) { 342 VoidType v = Type::Qualifiers(); // cast to void * for the alternative finder 343 PointerType pt( Type::Qualifiers(), v.clone() ); 344 CastExpr * castExpr = new CastExpr( arg, pt.clone() ); 345 Expression * newExpr = findSingleExpression( castExpr, indexer ); // find best expression 346 branchStmt->set_target( newExpr ); 351 if ( branchStmt->computedTarget ) { 352 // computed goto argument is void * 353 findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer ); 347 354 } // if 348 355 } // if … … 351 358 void Resolver::previsit( ReturnStmt *returnStmt ) { 352 359 visit_children = false; 353 if ( returnStmt->get_expr() ) { 354 CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() ); 355 Expression *newExpr = findSingleExpression( castExpr, indexer ); 356 delete castExpr; 357 returnStmt->set_expr( newExpr ); 360 if ( returnStmt->expr ) { 361 findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer ); 358 362 } // if 359 363 } … … 366 370 indexer.lookupStruct( "__cfaehm__base_exception_t" ); 367 371 assert( exception_decl ); 368 Expression * wrapped = new CastExpr( 369 throwStmt->get_expr(), 370 new PointerType( 371 noQualifiers, 372 new StructInstType( 373 noQualifiers, 374 exception_decl 375 ) 376 ) 377 ); 378 Expression * newExpr = findSingleExpression( wrapped, indexer ); 379 throwStmt->set_expr( newExpr ); 372 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) ); 373 findSingleExpression( throwStmt->expr, exceptType, indexer ); 380 374 } 381 375 } 382 376 383 377 void Resolver::previsit( CatchStmt *catchStmt ) { 384 if ( catchStmt->get_cond() ) { 385 Expression * wrapped = new CastExpr( 386 catchStmt->get_cond(), 387 new BasicType( noQualifiers, BasicType::Bool ) 388 ); 389 catchStmt->set_cond( findSingleExpression( wrapped, indexer ) ); 378 if ( catchStmt->cond ) { 379 findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer ); 380 } 381 } 382 383 template< typename iterator_t > 384 inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) { 385 while( it != end && !(*it)->get_type()->get_mutex() ) { 386 it++; 387 } 388 389 return it != end; 390 } 391 392 void Resolver::previsit( WaitForStmt * stmt ) { 393 visit_children = false; 394 395 // Resolve all clauses first 396 for( auto& clause : stmt->clauses ) { 397 398 TypeEnvironment env; 399 AlternativeFinder funcFinder( indexer, env ); 400 401 // Find all alternatives for a function in canonical form 402 funcFinder.findWithAdjustment( clause.target.function ); 403 404 if ( funcFinder.get_alternatives().empty() ) { 405 stringstream ss; 406 ss << "Use of undeclared indentifier '"; 407 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 408 ss << "' in call to waitfor"; 409 throw SemanticError( ss.str() ); 410 } 411 412 // Find all alternatives for all arguments in canonical form 413 std::list< AlternativeFinder > argAlternatives; 414 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 415 416 // List all combinations of arguments 417 std::list< AltList > possibilities; 418 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 419 420 AltList func_candidates; 421 std::vector< AltList > args_candidates; 422 423 // For every possible function : 424 // try matching the arguments to the parameters 425 // not the other way around because we have more arguments than parameters 426 SemanticError errors; 427 for ( Alternative & func : funcFinder.get_alternatives() ) { 428 try { 429 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 430 if( !pointer ) { 431 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() ); 432 } 433 434 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 435 if( !function ) { 436 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() ); 437 } 438 439 440 { 441 auto param = function->parameters.begin(); 442 auto param_end = function->parameters.end(); 443 444 if( !advance_to_mutex( param, param_end ) ) { 445 throw SemanticError("candidate function not viable: no mutex parameters\n", function); 446 } 447 } 448 449 Alternative newFunc( func ); 450 // Strip reference from function 451 referenceToRvalueConversion( newFunc.expr ); 452 453 // For all the set of arguments we have try to match it with the parameter of the current function alternative 454 for ( auto & argsList : possibilities ) { 455 456 try { 457 // Declare data structures need for resolution 458 OpenVarSet openVars; 459 AssertionSet resultNeed, resultHave; 460 TypeEnvironment resultEnv; 461 462 // Load type variables from arguemnts into one shared space 463 simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv ); 464 465 // Make sure we don't widen any existing bindings 466 for ( auto & i : resultEnv ) { 467 i.allowWidening = false; 468 } 469 470 // Find any unbound type variables 471 resultEnv.extractOpenVars( openVars ); 472 473 auto param = function->parameters.begin(); 474 auto param_end = function->parameters.end(); 475 476 // For every arguments of its set, check if it matches one of the parameter 477 // The order is important 478 for( auto & arg : argsList ) { 479 480 // Ignore non-mutex arguments 481 if( !advance_to_mutex( param, param_end ) ) { 482 // We ran out of parameters but still have arguments 483 // this function doesn't match 484 throw SemanticError("candidate function not viable: too many mutex arguments\n", function); 485 } 486 487 // Check if the argument matches the parameter type in the current scope 488 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) { 489 // Type doesn't match 490 stringstream ss; 491 ss << "candidate function not viable: no known convertion from '"; 492 arg.expr->get_result()->print( ss ); 493 ss << "' to '"; 494 (*param)->get_type()->print( ss ); 495 ss << "'\n"; 496 throw SemanticError(ss.str(), function); 497 } 498 499 param++; 500 } 501 502 // All arguments match ! 503 504 // Check if parameters are missing 505 if( advance_to_mutex( param, param_end ) ) { 506 // We ran out of arguments but still have parameters left 507 // this function doesn't match 508 throw SemanticError("candidate function not viable: too few mutex arguments\n", function); 509 } 510 511 // All parameters match ! 512 513 // Finish the expressions to tie in the proper environments 514 finishExpr( newFunc.expr, resultEnv ); 515 for( Alternative & alt : argsList ) { 516 finishExpr( alt.expr, resultEnv ); 517 } 518 519 // This is a match store it and save it for later 520 func_candidates.push_back( newFunc ); 521 args_candidates.push_back( argsList ); 522 523 } 524 catch( SemanticError &e ) { 525 errors.append( e ); 526 } 527 } 528 } 529 catch( SemanticError &e ) { 530 errors.append( e ); 531 } 532 } 533 534 // Make sure we got the right number of arguments 535 if( func_candidates.empty() ) { SemanticError top( "No alternatives for function in call to waitfor" ); top.append( errors ); throw top; } 536 if( args_candidates.empty() ) { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; } 537 if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 538 if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 539 540 541 // Swap the results from the alternative with the unresolved values. 542 // Alternatives will handle deletion on destruction 543 std::swap( clause.target.function, func_candidates.front().expr ); 544 for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) { 545 std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr ); 546 } 547 548 // Resolve the conditions as if it were an IfStmt 549 // Resolve the statments normally 550 findSingleExpression( clause.condition, this->indexer ); 551 clause.statement->accept( *visitor ); 552 } 553 554 555 if( stmt->timeout.statement ) { 556 // Resolve the timeout as an size_t for now 557 // Resolve the conditions as if it were an IfStmt 558 // Resolve the statments normally 559 findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer ); 560 findSingleExpression( stmt->timeout.condition, this->indexer ); 561 stmt->timeout.statement->accept( *visitor ); 562 } 563 564 if( stmt->orelse.statement ) { 565 // Resolve the conditions as if it were an IfStmt 566 // Resolve the statments normally 567 findSingleExpression( stmt->orelse.condition, this->indexer ); 568 stmt->orelse.statement->accept( *visitor ); 390 569 } 391 570 } … … 403 582 visit_children = false; 404 583 // resolve initialization using the possibilities as determined by the currentObject cursor 405 UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() );406 Expression * newExpr = findSingleExpression( untyped, indexer );584 Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() ); 585 findSingleExpression( newExpr, indexer ); 407 586 InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr ); 408 587 … … 411 590 412 591 // discard InitExpr wrapper and retain relevant pieces 413 newExpr = initExpr-> get_expr();414 newExpr->set_env( initExpr->get_env() );415 initExpr->set_expr( nullptr);416 initExpr->set_env( nullptr );592 newExpr = initExpr->expr; 593 initExpr->expr = nullptr; 594 std::swap( initExpr->env, newExpr->env ); 595 std::swap( initExpr->inferParams, newExpr->inferParams ) ; 417 596 delete initExpr; 418 597 419 598 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 420 599 Type * initContext = currentObject.getCurrentType(); 600 601 removeExtraneousCast( newExpr, indexer ); 421 602 422 603 // check if actual object's type is char[] … … 426 607 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 427 608 if ( isCharType( pt->get_base() ) ) { 428 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 429 CastExpr *ce = strict_dynamic_cast< CastExpr * >( newExpr ); 430 newExpr = ce->get_arg(); 431 ce->set_arg( nullptr ); 432 delete ce; 609 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 610 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 611 newExpr = ce->get_arg(); 612 ce->set_arg( nullptr ); 613 std::swap( ce->env, newExpr->env ); 614 delete ce; 615 } 433 616 } 434 617 } … … 437 620 438 621 // set initializer expr to resolved express 439 singleInit-> set_value( newExpr );622 singleInit->value = newExpr; 440 623 441 624 // move cursor to next object in preparation for next initializer
Note:
See TracChangeset
for help on using the changeset viewer.