Changeset 90152a4 for src/ResolvExpr/Resolver.cc
- Timestamp:
- Aug 27, 2018, 4:40:34 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b7c89aa
- Parents:
- f9feab8 (diff), 305581d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tus Aug 8 16:06:00 201713 // Update Count : 21 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:40 2018 13 // Update Count : 213 14 14 // 15 15 … … 30 30 #include "RenameVars.h" // for RenameVars, global_renamer 31 31 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 #include "ResolveTypeof.h" // for resolveTypeof33 32 #include "Resolver.h" 34 33 #include "SymTab/Autogen.h" // for SizeType … … 57 56 void postvisit( FunctionDecl *functionDecl ); 58 57 void previsit( ObjectDecl *objectDecll ); 59 void previsit( TypeDecl *typeDecl );60 58 void previsit( EnumDecl * enumDecl ); 59 void previsit( StaticAssertDecl * assertDecl ); 61 60 62 61 void previsit( ArrayType * at ); … … 76 75 void previsit( CatchStmt *catchStmt ); 77 76 void previsit( WaitForStmt * stmt ); 78 void previsit( WithStmt * withStmt );79 77 80 78 void previsit( SingleInit *singleInit ); … … 82 80 void previsit( ConstructorInit *ctorInit ); 83 81 private: 84 82 typedef std::list< Initializer * >::iterator InitIterator; 85 83 86 84 template< typename PtrType > 87 85 void handlePtrType( PtrType * type ); 88 86 89 void resolveAggrInit( ReferenceToType *, InitIterator &, InitIterator & ); 90 void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator &, TypeSubstitution sub ); 91 void fallbackInit( ConstructorInit * ctorInit ); 87 void fallbackInit( ConstructorInit * ctorInit ); 92 88 93 89 Type * functionReturn = nullptr; … … 96 92 }; 97 93 94 struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd { 95 void previsit( FunctionDecl * ); 96 void previsit( WithStmt * ); 97 98 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ); 99 }; 100 98 101 void resolve( std::list< Declaration * > translationUnit ) { 99 102 PassVisitor<Resolver> resolver; … … 106 109 } 107 110 108 // used in resolveTypeof109 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {110 TypeEnvironment env;111 return resolveInVoidContext( expr, indexer, env );112 }113 114 111 namespace { 115 void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) { 112 struct DeleteFinder : public WithShortCircuiting { 113 DeletedExpr * delExpr = nullptr; 114 void previsit( DeletedExpr * expr ) { 115 if ( delExpr ) visit_children = false; 116 else delExpr = expr; 117 } 118 119 void previsit( Expression * ) { 120 if ( delExpr ) visit_children = false; 121 } 122 }; 123 } 124 125 DeletedExpr * findDeletedExpr( Expression * expr ) { 126 PassVisitor<DeleteFinder> finder; 127 expr->accept( finder ); 128 return finder.pass.delExpr; 129 } 130 131 namespace { 132 struct StripCasts { 133 Expression * postmutate( CastExpr * castExpr ) { 134 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { 135 // generated cast is to the same type as its argument, so it's unnecessary -- remove it 136 Expression * expr = castExpr->arg; 137 castExpr->arg = nullptr; 138 std::swap( expr->env, castExpr->env ); 139 return expr; 140 } 141 return castExpr; 142 } 143 144 static void strip( Expression *& expr ) { 145 PassVisitor<StripCasts> stripper; 146 expr = expr->acceptMutator( stripper ); 147 } 148 }; 149 150 void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) { 116 151 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 117 env.makeSubstitution( *expr->get_env() ); 152 env.makeSubstitution( *expr->env ); 153 StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression 118 154 } 119 155 … … 131 167 } // namespace 132 168 169 namespace { 170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) { 171 assertf( untyped, "expected a non-null expression." ); 172 TypeEnvironment env; 173 AlternativeFinder finder( indexer, env ); 174 finder.find( untyped, adjust, prune, failFast ); 175 176 #if 0 177 if ( finder.get_alternatives().size() != 1 ) { 178 std::cerr << "untyped expr is "; 179 untyped->print( std::cerr ); 180 std::cerr << std::endl << "alternatives are:"; 181 for ( const Alternative & alt : finder.get_alternatives() ) { 182 alt.print( std::cerr ); 183 } // for 184 } // if 185 #endif 186 187 AltList candidates; 188 for ( Alternative & alt : finder.get_alternatives() ) { 189 if ( pred( alt ) ) { 190 candidates.push_back( std::move( alt ) ); 191 } 192 } 193 194 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 195 // choose the lowest cost expression among the candidates 196 AltList winners; 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 198 if ( winners.size() == 0 ) { 199 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 200 } else if ( winners.size() != 1 ) { 201 std::ostringstream stream; 202 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; 203 untyped->print( stream ); 204 stream << " Alternatives are:\n"; 205 printAlts( winners, stream, 1 ); 206 SemanticError( untyped->location, stream.str() ); 207 } 208 209 // there is one unambiguous interpretation - move the expression into the with statement 210 Alternative & choice = winners.front(); 211 if ( findDeletedExpr( choice.expr ) ) { 212 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 213 } 214 alt = std::move( choice ); 215 } 216 217 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 218 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) { 219 if ( ! untyped ) return; 220 Alternative choice; 221 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast ); 222 finishExpr( choice.expr, choice.env, untyped->env ); 223 delete untyped; 224 untyped = choice.expr; 225 choice.expr = nullptr; 226 } 227 228 bool standardAlternativeFilter( const Alternative & ) { 229 // currently don't need to filter, under normal circumstances. 230 // in the future, this may be useful for removing deleted expressions 231 return true; 232 } 233 } // namespace 234 235 // used in resolveTypeof 236 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) { 237 TypeEnvironment env; 238 return resolveInVoidContext( expr, indexer, env ); 239 } 240 241 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 242 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 243 // interpretations, an exception has already been thrown. 244 assertf( expr, "expected a non-null expression." ); 245 246 static CastExpr untyped( nullptr ); // cast to void 247 untyped.location = expr->location; 248 249 // set up and resolve expression cast to void 250 untyped.arg = expr; 251 Alternative choice; 252 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true ); 253 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 254 env = std::move( choice.env ); 255 256 // clean up resolved expression 257 Expression * ret = castExpr->arg; 258 castExpr->arg = nullptr; 259 260 // unlink the arg so that it isn't deleted twice at the end of the program 261 untyped.arg = nullptr; 262 return ret; 263 } 264 133 265 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 134 global_renamer.reset();266 resetTyVarRenaming(); 135 267 TypeEnvironment env; 136 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );268 Expression * newExpr = resolveInVoidContext( untyped, indexer, env ); 137 269 finishExpr( newExpr, env, untyped->env ); 138 270 delete untyped; … … 141 273 142 274 void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) { 143 if ( ! untyped ) return; 144 TypeEnvironment env; 145 AlternativeFinder finder( indexer, env ); 146 finder.find( untyped ); 147 #if 0 148 if ( finder.get_alternatives().size() != 1 ) { 149 std::cerr << "untyped expr is "; 150 untyped->print( std::cerr ); 151 std::cerr << std::endl << "alternatives are:"; 152 for ( const Alternative & alt : finder.get_alternatives() ) { 153 alt.print( std::cerr ); 154 } // for 155 } // if 156 #endif 157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." ); 158 Alternative &choice = finder.get_alternatives().front(); 159 Expression *newExpr = choice.expr->clone(); 160 finishExpr( newExpr, choice.env, untyped->env ); 161 delete untyped; 162 untyped = newExpr; 275 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 163 276 } 164 277 165 278 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) { 166 279 assert( untyped && type ); 280 // transfer location to generated cast for error purposes 281 CodeLocation location = untyped->location; 167 282 untyped = new CastExpr( untyped, type ); 283 untyped->location = location; 168 284 findSingleExpression( untyped, indexer ); 169 285 removeExtraneousCast( untyped, indexer ); … … 171 287 172 288 namespace { 173 bool isIntegralType( Type *type ) { 289 bool isIntegralType( const Alternative & alt ) { 290 Type * type = alt.expr->result; 174 291 if ( dynamic_cast< EnumInstType * >( type ) ) { 175 292 return true; … … 184 301 185 302 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 186 TypeEnvironment env; 187 AlternativeFinder finder( indexer, env ); 188 finder.find( untyped ); 189 #if 0 190 if ( finder.get_alternatives().size() != 1 ) { 191 std::cout << "untyped expr is "; 192 untyped->print( std::cout ); 193 std::cout << std::endl << "alternatives are:"; 194 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 195 i->print( std::cout ); 196 } // for 197 } // if 198 #endif 199 Expression *newExpr = 0; 200 const TypeEnvironment *newEnv = 0; 201 for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 202 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) { 203 if ( newExpr ) { 204 throw SemanticError( "Too many interpretations for case control expression", untyped ); 205 } else { 206 newExpr = i->expr->clone(); 207 newEnv = &i->env; 208 } // if 209 } // if 210 } // for 211 if ( ! newExpr ) { 212 throw SemanticError( "No interpretations for case control expression", untyped ); 213 } // if 214 finishExpr( newExpr, *newEnv, untyped->env ); 215 delete untyped; 216 untyped = newExpr; 217 } 218 303 findKindExpression( untyped, indexer, "condition", isIntegralType ); 304 } 305 } 306 307 308 bool isStructOrUnion( const Alternative & alt ) { 309 Type * t = alt.expr->result->stripReferences(); 310 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 311 } 312 313 void resolveWithExprs( std::list< Declaration * > & translationUnit ) { 314 PassVisitor<ResolveWithExprs> resolver; 315 acceptAll( translationUnit, resolver ); 316 } 317 318 void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 319 for ( Expression *& expr : withExprs ) { 320 // only struct- and union-typed expressions are viable candidates 321 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 322 323 // if with expression might be impure, create a temporary so that it is evaluated once 324 if ( Tuples::maybeImpure( expr ) ) { 325 static UniqueName tmpNamer( "_with_tmp_" ); 326 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 327 expr = new VariableExpr( tmp ); 328 newStmts.push_back( new DeclStmt( tmp ) ); 329 if ( InitTweak::isConstructable( tmp->type ) ) { 330 // generate ctor/dtor and resolve them 331 tmp->init = InitTweak::genCtorInit( tmp ); 332 tmp->accept( *visitor ); 333 } 334 } 335 } 336 } 337 338 void ResolveWithExprs::previsit( WithStmt * withStmt ) { 339 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 340 } 341 342 void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) { 343 { 344 // resolve with-exprs with parameters in scope and add any newly generated declarations to the 345 // front of the function body. 346 auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } ); 347 indexer.addFunctionType( functionDecl->type ); 348 std::list< Statement * > newStmts; 349 resolveWithExprs( functionDecl->withExprs, newStmts ); 350 if ( functionDecl->statements ) { 351 functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts ); 352 } else { 353 assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() ); 354 } 355 } 219 356 } 220 357 221 358 void Resolver::previsit( ObjectDecl *objectDecl ) { 222 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );223 objectDecl->set_type( new_type );224 359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 225 360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes … … 251 386 } 252 387 253 void Resolver::previsit( TypeDecl *typeDecl ) {254 if ( typeDecl->get_base() ) {255 Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );256 typeDecl->set_base( new_type );257 } // if258 }259 260 388 void Resolver::previsit( FunctionDecl *functionDecl ) { 261 389 #if 0 … … 264 392 std::cerr << std::endl; 265 393 #endif 266 Type *new_type = resolveTypeof( functionDecl->get_type(), indexer );267 functionDecl->set_type( new_type );268 394 GuardValue( functionReturn ); 269 functionReturn = ResolvExpr::extractResultType( functionDecl-> get_functionType());395 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 270 396 } 271 397 … … 274 400 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 275 401 // see how it's useful. 276 for ( Declaration * d : functionDecl-> get_functionType()->get_parameters()) {402 for ( Declaration * d : functionDecl->type->parameters ) { 277 403 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { 278 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj-> get_init()) ) {279 delete init-> get_value()->get_env();280 init-> get_value()->set_env( nullptr );404 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) { 405 delete init->value->env; 406 init->value->env = nullptr; 281 407 } 282 408 } … … 290 416 } 291 417 418 void Resolver::previsit( StaticAssertDecl * assertDecl ) { 419 findIntegralExpression( assertDecl->condition, indexer ); 420 } 421 292 422 void Resolver::previsit( ExprStmt *exprStmt ) { 293 423 visit_children = false; … … 311 441 312 442 void Resolver::previsit( IfStmt *ifStmt ) { 313 find SingleExpression( ifStmt->condition, indexer );443 findIntegralExpression( ifStmt->condition, indexer ); 314 444 } 315 445 316 446 void Resolver::previsit( WhileStmt *whileStmt ) { 317 find SingleExpression( whileStmt->condition, indexer );447 findIntegralExpression( whileStmt->condition, indexer ); 318 448 } 319 449 320 450 void Resolver::previsit( ForStmt *forStmt ) { 321 451 if ( forStmt->condition ) { 322 find SingleExpression( forStmt->condition, indexer );452 findIntegralExpression( forStmt->condition, indexer ); 323 453 } // if 324 454 … … 336 466 337 467 void Resolver::previsit( CaseStmt *caseStmt ) { 338 if ( caseStmt-> get_condition()) {468 if ( caseStmt->condition ) { 339 469 std::list< InitAlternative > initAlts = currentObject.getOptions(); 340 470 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); … … 342 472 Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() ); 343 473 findSingleExpression( newExpr, indexer ); 344 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr ); 345 caseStmt->condition = castExpr->arg; 346 castExpr->arg = nullptr; 347 delete castExpr; 474 // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion. 475 // Ideally we would perform the conversion internally here. 476 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) { 477 newExpr = castExpr->arg; 478 castExpr->arg = nullptr; 479 std::swap( newExpr->env, castExpr->env ); 480 delete castExpr; 481 } 482 caseStmt->condition = newExpr; 348 483 } 349 484 } … … 411 546 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 412 547 ss << "' in call to waitfor"; 413 throw SemanticError( ss.str() ); 548 SemanticError( stmt->location, ss.str() ); 549 } 550 551 if(clause.target.arguments.empty()) { 552 SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter"); 414 553 } 415 554 … … 428 567 // try matching the arguments to the parameters 429 568 // not the other way around because we have more arguments than parameters 430 SemanticError errors;569 SemanticErrorException errors; 431 570 for ( Alternative & func : funcFinder.get_alternatives() ) { 432 571 try { 433 572 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 434 573 if( !pointer ) { 435 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result());574 SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" ); 436 575 } 437 576 438 577 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 439 578 if( !function ) { 440 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base());579 SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" ); 441 580 } 442 581 … … 447 586 448 587 if( !advance_to_mutex( param, param_end ) ) { 449 throw SemanticError("candidate function not viable: no mutex parameters\n", function);588 SemanticError(function, "candidate function not viable: no mutex parameters\n"); 450 589 } 451 590 } … … 453 592 Alternative newFunc( func ); 454 593 // Strip reference from function 455 referenceToRvalueConversion( newFunc.expr );594 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 456 595 457 596 // For all the set of arguments we have try to match it with the parameter of the current function alternative … … 462 601 OpenVarSet openVars; 463 602 AssertionSet resultNeed, resultHave; 464 TypeEnvironment resultEnv; 603 TypeEnvironment resultEnv( func.env ); 604 makeUnifiableVars( function, openVars, resultNeed ); 605 // add all type variables as open variables now so that those not used in the parameter 606 // list are still considered open. 607 resultEnv.add( function->forall ); 465 608 466 609 // Load type variables from arguemnts into one shared space … … 468 611 469 612 // Make sure we don't widen any existing bindings 470 for ( auto & i : resultEnv ) { 471 i.allowWidening = false; 472 } 613 resultEnv.forbidWidening(); 473 614 474 615 // Find any unbound type variables … … 477 618 auto param = function->parameters.begin(); 478 619 auto param_end = function->parameters.end(); 620 621 int n_mutex_param = 0; 479 622 480 623 // For every arguments of its set, check if it matches one of the parameter … … 486 629 // We ran out of parameters but still have arguments 487 630 // this function doesn't match 488 throw SemanticError("candidate function not viable: too many mutex arguments\n", function);631 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" )); 489 632 } 490 633 634 n_mutex_param++; 635 491 636 // Check if the argument matches the parameter type in the current scope 492 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {637 if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) { 493 638 // Type doesn't match 494 639 stringstream ss; 495 640 ss << "candidate function not viable: no known convertion from '"; 641 (*param)->get_type()->print( ss ); 642 ss << "' to '"; 496 643 arg.expr->get_result()->print( ss ); 497 ss << "' to'";498 (*param)->get_type()->print( ss);644 ss << "' with env '"; 645 resultEnv.print(ss); 499 646 ss << "'\n"; 500 throw SemanticError(ss.str(), function);647 SemanticError( function, ss.str() ); 501 648 } 502 649 … … 508 655 // Check if parameters are missing 509 656 if( advance_to_mutex( param, param_end ) ) { 657 do { 658 n_mutex_param++; 659 param++; 660 } while( advance_to_mutex( param, param_end ) ); 661 510 662 // We ran out of arguments but still have parameters left 511 663 // this function doesn't match 512 throw SemanticError("candidate function not viable: too few mutex arguments\n", function);664 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" )); 513 665 } 514 666 … … 526 678 527 679 } 528 catch( SemanticError &e ) {680 catch( SemanticErrorException &e ) { 529 681 errors.append( e ); 530 682 } 531 683 } 532 684 } 533 catch( SemanticError &e ) {685 catch( SemanticErrorException &e ) { 534 686 errors.append( e ); 535 687 } … … 537 689 538 690 // Make sure we got the right number of arguments 539 if( func_candidates.empty() ) { SemanticError top("No alternatives for function in call to waitfor" ); top.append( errors ); throw top; }540 if( args_candidates.empty() ) { SemanticError top("No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }541 if( func_candidates.size() > 1 ) { SemanticError top("Ambiguous function in call to waitfor" ); top.append( errors ); throw top; }542 if( args_candidates.size() > 1 ) { SemanticError top("Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; }543 691 if( func_candidates.empty() ) { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor" ); top.append( errors ); throw top; } 692 if( args_candidates.empty() ) { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; } 693 if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 694 if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 695 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 544 696 545 697 // Swap the results from the alternative with the unresolved values. … … 574 726 } 575 727 576 bool isStructOrUnion( Type * t ) {577 t = t->stripReferences();578 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );579 }580 581 void Resolver::previsit( WithStmt * withStmt ) {582 for ( Expression *& expr : withStmt->exprs ) {583 TypeEnvironment env;584 AlternativeFinder finder( indexer, env );585 finder.findWithAdjustment( expr );586 587 // only struct- and union-typed expressions are viable candidates588 AltList candidates;589 for ( Alternative & alt : finder.get_alternatives() ) {590 if ( isStructOrUnion( alt.expr->result ) ) {591 candidates.push_back( std::move( alt ) );592 }593 }594 595 // choose the lowest cost expression among the candidates596 AltList winners;597 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );598 if ( winners.size() == 0 ) {599 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );600 } else if ( winners.size() != 1 ) {601 std::ostringstream stream;602 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";603 expr->print( stream );604 stream << "Alternatives are:\n";605 printAlts( winners, stream, 1 );606 throw SemanticError( stream.str() );607 }608 609 // there is one unambiguous interpretation - move the expression into the with statement610 Alternative & alt = winners.front();611 finishExpr( alt.expr, alt.env, expr->env );612 delete expr;613 expr = alt.expr;614 alt.expr = nullptr;615 616 // if with expression might be impure, create a temporary so that it is evaluated once617 if ( Tuples::maybeImpure( expr ) ) {618 static UniqueName tmpNamer( "_with_tmp_" );619 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );620 expr = new VariableExpr( tmp );621 stmtsToAddBefore.push_back( new DeclStmt( tmp ) );622 if ( InitTweak::isConstructable( tmp->type ) ) {623 // generate ctor/dtor and resolve them624 tmp->init = InitTweak::genCtorInit( tmp );625 tmp->accept( *visitor );626 }627 }628 }629 }630 631 728 template< typename T > 632 729 bool isCharType( T t ) { … … 652 749 initExpr->expr = nullptr; 653 750 std::swap( initExpr->env, newExpr->env ); 654 std::swap( initExpr->inferParams, newExpr->inferParams ) ; 751 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 752 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 753 newExpr->spliceInferParams( initExpr ); 655 754 delete initExpr; 656 755 … … 740 839 PassVisitor<Resolver> resolver( indexer ); 741 840 stmtExpr->accept( resolver ); 841 stmtExpr->computeResult(); 842 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead? 742 843 } 743 844 … … 745 846 visit_children = false; 746 847 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit 747 maybeAccept( ctorInit-> get_ctor(), *visitor );748 maybeAccept( ctorInit-> get_dtor(), *visitor );848 maybeAccept( ctorInit->ctor, *visitor ); 849 maybeAccept( ctorInit->dtor, *visitor ); 749 850 750 851 // found a constructor - can get rid of C-style initializer 751 delete ctorInit-> get_init();752 ctorInit-> set_init( NULL );852 delete ctorInit->init; 853 ctorInit->init = nullptr; 753 854 754 855 // intrinsic single parameter constructors and destructors do nothing. Since this was 755 856 // implicitly generated, there's no way for it to have side effects, so get rid of it 756 857 // to clean up generated code. 757 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit-> get_ctor()) ) {758 delete ctorInit-> get_ctor();759 ctorInit-> set_ctor( NULL );760 } 761 762 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit-> get_dtor()) ) {763 delete ctorInit-> get_dtor();764 ctorInit-> set_dtor( NULL );858 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 859 delete ctorInit->ctor; 860 ctorInit->ctor = nullptr; 861 } 862 863 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 864 delete ctorInit->dtor; 865 ctorInit->dtor = nullptr; 765 866 } 766 867
Note:
See TracChangeset
for help on using the changeset viewer.