Changeset 90152a4 for src/ResolvExpr/AlternativeFinder.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/AlternativeFinder.cc
rf9feab8 r90152a4 10 10 // Created On : Sat May 16 23:52:08 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 28 13:47:24 201713 // Update Count : 3 212 // Last Modified On : Sat Feb 17 11:19:39 2018 13 // Update Count : 33 14 14 // 15 15 … … 25 25 #include <vector> // for vector 26 26 27 #include "CompilationState.h" // for resolvep 27 28 #include "Alternative.h" // for AltList, Alternative 28 29 #include "AlternativeFinder.h" … … 49 50 #include "typeops.h" // for adjustExprType, polyCost, castCost 50 51 51 extern bool resolvep;52 52 #define PRINT( text ) if ( resolvep ) { text } 53 53 //#define DEBUG_COST … … 60 60 61 61 namespace ResolvExpr { 62 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 63 CastExpr *castToVoid = new CastExpr( expr ); 64 65 AlternativeFinder finder( indexer, env ); 66 finder.findWithAdjustment( castToVoid ); 67 68 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 69 // interpretations, an exception has already been thrown. 70 assert( finder.get_alternatives().size() == 1 ); 71 CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr ); 72 assert( newExpr ); 73 env = finder.get_alternatives().front().env; 74 return newExpr->get_arg()->clone(); 75 } 62 struct AlternativeFinder::Finder : public WithShortCircuiting { 63 Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType ) {} 64 65 void previsit( BaseSyntaxNode * ) { visit_children = false; } 66 67 void postvisit( ApplicationExpr * applicationExpr ); 68 void postvisit( UntypedExpr * untypedExpr ); 69 void postvisit( AddressExpr * addressExpr ); 70 void postvisit( LabelAddressExpr * labelExpr ); 71 void postvisit( CastExpr * castExpr ); 72 void postvisit( VirtualCastExpr * castExpr ); 73 void postvisit( UntypedMemberExpr * memberExpr ); 74 void postvisit( MemberExpr * memberExpr ); 75 void postvisit( NameExpr * variableExpr ); 76 void postvisit( VariableExpr * variableExpr ); 77 void postvisit( ConstantExpr * constantExpr ); 78 void postvisit( SizeofExpr * sizeofExpr ); 79 void postvisit( AlignofExpr * alignofExpr ); 80 void postvisit( UntypedOffsetofExpr * offsetofExpr ); 81 void postvisit( OffsetofExpr * offsetofExpr ); 82 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr ); 84 void postvisit( LogicalExpr * logicalExpr ); 85 void postvisit( ConditionalExpr * conditionalExpr ); 86 void postvisit( CommaExpr * commaExpr ); 87 void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ); 88 void postvisit( ConstructorExpr * ctorExpr ); 89 void postvisit( RangeExpr * rangeExpr ); 90 void postvisit( UntypedTupleExpr * tupleExpr ); 91 void postvisit( TupleExpr * tupleExpr ); 92 void postvisit( TupleIndexExpr * tupleExpr ); 93 void postvisit( TupleAssignExpr * tupleExpr ); 94 void postvisit( UniqueExpr * unqExpr ); 95 void postvisit( StmtExpr * stmtExpr ); 96 void postvisit( UntypedInitExpr * initExpr ); 97 void postvisit( InitExpr * initExpr ); 98 void postvisit( DeletedExpr * delExpr ); 99 void postvisit( GenericExpr * genExpr ); 100 101 /// Adds alternatives for anonymous members 102 void addAnonConversions( const Alternative & alt ); 103 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ); 105 /// Adds alternatives for member expressions where the left side has tuple type 106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 107 /// Adds alternatives for offsetof expressions, given the base type and name of the member 108 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 109 /// Takes a final result and checks if its assertions can be satisfied 110 template<typename OutputIterator> 111 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 112 /// Finds matching alternatives for a function, given a set of arguments 113 template<typename OutputIterator> 114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 115 /// Checks if assertion parameters match for a new alternative 116 template< typename OutputIterator > 117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 118 private: 119 AlternativeFinder & altFinder; 120 const SymTab::Indexer &indexer; 121 AltList & alternatives; 122 const TypeEnvironment &env; 123 Type *& targetType; 124 }; 76 125 77 126 Cost sumCost( const AltList &in ) { … … 127 176 selected[ mangleName ] = current; 128 177 } else if ( candidate->cost == mapPlace->second.candidate->cost ) { 129 PRINT( 130 std::cerr << "marking ambiguous" << std::endl; 131 ) 132 mapPlace->second.isAmbiguous = true; 178 // if one of the candidates contains a deleted identifier, can pick the other, since 179 // deleted expressions should not be ambiguous if there is another option that is at least as good 180 if ( findDeletedExpr( candidate->expr ) ) { 181 // do nothing 182 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 183 } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) { 184 PRINT( std::cerr << "current is deleted" << std::endl; ) 185 selected[ mangleName ] = current; 186 } else { 187 PRINT( 188 std::cerr << "marking ambiguous" << std::endl; 189 ) 190 mapPlace->second.isAmbiguous = true; 191 } 133 192 } else { 134 193 PRINT( … … 152 211 153 212 void renameTypes( Expression *expr ) { 154 expr->get_result()->accept( global_renamer);213 renameTyVars( expr->result ); 155 214 } 156 215 } // namespace 157 216 158 void referenceToRvalueConversion( Expression *& expr ) {217 void referenceToRvalueConversion( Expression *& expr, Cost & cost ) { 159 218 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 160 219 // cast away reference from expr 161 220 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 221 cost.incReference(); 162 222 } 163 223 } … … 185 245 186 246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 187 expr->accept( *this ); 247 PassVisitor<Finder> finder( *this ); 248 expr->accept( finder ); 188 249 if ( failFast && alternatives.empty() ) { 189 250 PRINT( 190 251 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 191 252 ) 192 throw SemanticError( "No reasonable alternatives for expression ", expr);253 SemanticError( expr, "No reasonable alternatives for expression " ); 193 254 } 194 255 if ( prune ) { … … 206 267 stream << "Cannot choose between " << winners.size() << " alternatives for expression\n"; 207 268 expr->print( stream ); 208 stream << " Alternatives are:\n";269 stream << " Alternatives are:\n"; 209 270 printAlts( winners, stream, 1 ); 210 throw SemanticError(stream.str() );271 SemanticError( expr->location, stream.str() ); 211 272 } 212 273 alternatives = move(pruned); … … 244 305 } 245 306 246 void AlternativeFinder:: addAnonConversions( const Alternative & alt ) {307 void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) { 247 308 // adds anonymous member interpretations whenever an aggregate value type is seen. 248 309 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 249 310 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 250 alt.env.apply( aggrExpr-> get_result());251 Type * aggrType = aggrExpr-> get_result();311 alt.env.apply( aggrExpr->result ); 312 Type * aggrType = aggrExpr->result; 252 313 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 253 314 aggrType = aggrType->stripReferences(); … … 255 316 } 256 317 257 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 258 NameExpr nameExpr( "" ); 259 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 260 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 261 NameExpr nameExpr( "" ); 262 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 318 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 319 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 320 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 321 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 263 322 } // if 264 323 } 265 324 266 325 template< typename StructOrUnionType > 267 void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 268 // by this point, member must be a name expr 269 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); 270 if ( ! nameExpr ) return; 271 const std::string & name = nameExpr->get_name(); 326 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) { 272 327 std::list< Declaration* > members; 273 328 aggInst->lookup( name, members ); 274 329 275 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 276 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 277 alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) ); 278 renameTypes( alternatives.back().expr ); 279 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. 330 for ( Declaration * decl : members ) { 331 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 332 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 333 // can't construct in place and use vector::back 334 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost ); 335 renameTypes( newAlt.expr ); 336 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. 337 alternatives.push_back( std::move(newAlt) ); 280 338 } else { 281 339 assert( false ); … … 284 342 } 285 343 286 void AlternativeFinder:: addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {344 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 287 345 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 288 346 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning 289 // xxx - this should be improved by memoizing the value of constant exprs 290 // during parsing and reusing that information here. 291 std::stringstream ss( constantExpr->get_constant()->get_value() ); 292 int val = 0; 347 auto val = constantExpr->intValue(); 293 348 std::string tmp; 294 if ( ss >> val && ! (ss >> tmp) ) { 295 if ( val >= 0 && (unsigned int)val < tupleType->size() ) { 296 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 297 } // if 349 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 298 351 } // if 299 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {300 // xxx - temporary hack until 0/1 are int constants301 if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {302 std::stringstream ss( nameExpr->get_name() );303 int val;304 ss >> val;305 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );306 }307 352 } // if 308 353 } 309 354 310 void AlternativeFinder:: visit( ApplicationExpr *applicationExpr ) {355 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 311 356 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 312 357 } … … 386 431 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 387 432 // convert reference-typed expressions to value-typed expressions 388 referenceToRvalueConversion( *actualExpr );433 referenceToRvalueConversion( *actualExpr, convCost ); 389 434 continue; 390 435 } else { … … 392 437 } 393 438 } 439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) { 440 // default arguments should be free - don't include conversion cost. 441 // Unwrap them here because they are not relevant to the rest of the system. 442 *actualExpr = def->expr; 443 ++formal; 444 continue; 445 } 394 446 Type * formalType = (*formal)->get_type(); 395 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); … … 409 461 /// Adds type variables to the open variable set and marks their assertions 410 462 void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) { 411 for ( Type::ForallList::const_iterator tyvar = type-> get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {463 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 412 464 unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar }; 413 for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)-> get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {465 for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->assertions.begin(); assert != (*tyvar)->assertions.end(); ++assert ) { 414 466 needAssertions[ *assert ].isUsed = true; 415 467 } … … 418 470 } 419 471 420 // /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included421 //typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;422 423 472 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 424 //static const unsigned recursionParentLimit = 1; ///< Limit to the number of times an assertion can recursively use itself425 473 426 474 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { … … 433 481 434 482 template< typename ForwardIterator, typename OutputIterator > 435 void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/436 int level, const SymTab::Indexer &indexer, OutputIterator out ) {483 void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) { 484 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end 437 485 if ( begin == end ) { 438 486 if ( newNeed.empty() ) { … … 445 493 return; 446 494 } else if ( level >= recursionLimit ) { 447 throw SemanticError("Too many recursive assertions" );495 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 448 496 } else { 449 497 AssertionSet newerNeed; … … 452 500 printAssertionSet( newNeed, std::cerr, 8 ); 453 501 ) 454 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, /*needParents,*/level+1, indexer, out );502 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 455 503 return; 456 504 } … … 459 507 ForwardIterator cur = begin++; 460 508 if ( ! cur->second.isUsed ) { 461 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/level, indexer, out );509 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 462 510 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 463 511 } … … 485 533 Type *adjType = candidate->get_type()->clone(); 486 534 adjustExprType( adjType, newEnv, indexer ); 487 adjType->accept( global_renamer);535 renameTyVars( adjType ); 488 536 PRINT( 489 537 std::cerr << "unifying "; … … 512 560 } 513 561 514 //AssertionParentSet newNeedParents( needParents ); 515 // skip repeatingly-self-recursive assertion satisfaction 516 // DOESN'T WORK: grandchild nodes conflict with their cousins 517 //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue; 518 Expression *varExpr = data.combine(); 562 Expression *varExpr = data.combine( newerAlt.cvtCost ); 519 563 delete varExpr->get_result(); 520 564 varExpr->set_result( adjType->clone() ); … … 533 577 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 534 578 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 535 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/level, indexer, out );579 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 536 580 } else { 537 581 delete adjType; … … 541 585 542 586 template< typename OutputIterator > 543 void AlternativeFinder:: inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {587 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 544 588 // PRINT( 545 589 // std::cerr << "inferParameters: assertions needed are" << std::endl; … … 555 599 addToIndexer( have, decls ); 556 600 AssertionSet newNeed; 557 //AssertionParentSet needParents;558 601 PRINT( 559 602 std::cerr << "env is: " << std::endl; … … 562 605 ) 563 606 564 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/0, indexer, out );607 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 565 608 // PRINT( 566 609 // std::cerr << "declaration 14 is "; … … 573 616 ConstantExpr* getDefaultValue( Initializer* init ) { 574 617 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 575 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 576 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 618 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) { 619 return dynamic_cast<ConstantExpr*>( ce->arg ); 620 } else { 621 return dynamic_cast<ConstantExpr*>( si->value ); 577 622 } 578 623 } … … 596 641 ArgPack() 597 642 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 599 643 tupleStart(0), nextExpl(0), explAlt(0) {} 600 644 … … 648 692 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 649 693 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 650 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {694 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { 651 695 // formalType is a TupleType - group actuals into a TupleExpr 652 696 ++nTuples; 653 697 for ( Type* type : *tupleType ) { 654 698 // xxx - dropping initializer changes behaviour from previous, but seems correct 699 // ^^^ need to handle the case where a tuple has a default argument 655 700 if ( ! instantiateArgument( 656 701 type, nullptr, args, results, genStart, indexer, nTuples ) ) … … 663 708 } 664 709 return true; 665 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {710 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 666 711 // formalType is a ttype, consumes all remaining arguments 667 712 // xxx - mixing default arguments with variadic?? … … 706 751 Type* argType; 707 752 708 if ( nTuples > 0 ) { 709 // first iteration, push empty tuple expression 753 if ( nTuples > 0 || ! results[i].expr ) { 754 // first iteration or no expression to clone, 755 // push empty tuple expression 710 756 newResult.parent = i; 711 757 std::list<Expression*> emptyList; … … 834 880 indexer ) ) { 835 881 results.emplace_back( 836 i, cnstExpr, move(env), move(need), move(have),882 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have), 837 883 move(openVars), nextArg, nTuples ); 838 884 } … … 865 911 // consider only first exploded actual 866 912 Expression* expr = expl.exprs.front().get(); 867 Type* actualType = expr-> get_result()->clone();913 Type* actualType = expr->result->clone(); 868 914 869 915 PRINT( … … 892 938 893 939 template<typename OutputIterator> 894 void AlternativeFinder:: validateFunctionAlternative( const Alternative &func, ArgPack& result,940 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 941 const std::vector<ArgPack>& results, OutputIterator out ) { 896 942 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 897 943 // sum cost and accumulate actuals 898 std::list<Expression*>& args = appExpr-> get_args();944 std::list<Expression*>& args = appExpr->args; 899 945 Cost cost = func.cost; 900 946 const ArgPack* pack = &result; … … 915 961 916 962 template<typename OutputIterator> 917 void AlternativeFinder:: makeFunctionAlternatives( const Alternative &func,963 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 918 964 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 919 965 OpenVarSet funcOpenVars; … … 923 969 // add all type variables as open variables now so that those not used in the parameter 924 970 // list are still considered open. 925 funcEnv.add( funcType-> get_forall());926 927 if ( targetType && ! targetType->isVoid() && ! funcType-> get_returnVals().empty() ) {971 funcEnv.add( funcType->forall ); 972 973 if ( targetType && ! targetType->isVoid() && ! funcType->returnVals.empty() ) { 928 974 // attempt to narrow based on expected target type 929 Type * returnType = funcType-> get_returnVals().front()->get_type();975 Type * returnType = funcType->returnVals.front()->get_type(); 930 976 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 931 977 indexer ) ) { … … 940 986 std::size_t genStart = 0; 941 987 942 for ( DeclarationWithType* formal : funcType-> get_parameters()) {988 for ( DeclarationWithType* formal : funcType->parameters ) { 943 989 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 944 990 if ( ! instantiateArgument( 945 obj-> get_type(), obj->get_init(), args, results, genStart, indexer ) )991 obj->type, obj->init, args, results, genStart, indexer ) ) 946 992 return; 947 993 } … … 1022 1068 } 1023 1069 1024 void AlternativeFinder:: visit( UntypedExpr *untypedExpr ) {1070 void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) { 1025 1071 AlternativeFinder funcFinder( indexer, env ); 1026 funcFinder.findWithAdjustment( untypedExpr-> get_function());1072 funcFinder.findWithAdjustment( untypedExpr->function ); 1027 1073 // if there are no function alternatives, then proceeding is a waste of time. 1074 // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary. 1028 1075 if ( funcFinder.alternatives.empty() ) return; 1029 1076 1030 1077 std::vector< AlternativeFinder > argAlternatives; 1031 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),1078 altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 1032 1079 back_inserter( argAlternatives ) ); 1033 1080 1034 1081 // take care of possible tuple assignments 1035 1082 // if not tuple assignment, assignment is taken care of as a normal function call 1036 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );1083 Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives ); 1037 1084 1038 1085 // find function operators … … 1040 1087 AlternativeFinder funcOpFinder( indexer, env ); 1041 1088 // it's ok if there aren't any defined function ops 1042 funcOpFinder.maybeFind( opExpr );1089 funcOpFinder.maybeFind( opExpr ); 1043 1090 PRINT( 1044 1091 std::cerr << "known function ops:" << std::endl; … … 1053 1100 argExpansions.emplace_back(); 1054 1101 auto& argE = argExpansions.back(); 1055 argE.reserve( arg.alternatives.size() );1102 // argE.reserve( arg.alternatives.size() ); 1056 1103 1057 1104 for ( const Alternative& actual : arg ) { … … 1061 1108 1062 1109 AltList candidates; 1063 SemanticError errors;1110 SemanticErrorException errors; 1064 1111 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 1065 1112 try { … … 1069 1116 ) 1070 1117 // check if the type is pointer to function 1071 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr-> get_result()->stripReferences() ) ) {1072 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer-> get_base()) ) {1118 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) { 1119 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) { 1073 1120 Alternative newFunc( *func ); 1074 referenceToRvalueConversion( newFunc.expr );1121 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1075 1122 makeFunctionAlternatives( newFunc, function, argExpansions, 1076 1123 std::back_inserter( candidates ) ); 1077 1124 } 1078 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 1079 EqvClass eqvClass; 1080 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 1081 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 1125 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 1126 if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) { 1127 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) { 1082 1128 Alternative newFunc( *func ); 1083 referenceToRvalueConversion( newFunc.expr );1129 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1084 1130 makeFunctionAlternatives( newFunc, function, argExpansions, 1085 1131 std::back_inserter( candidates ) ); … … 1087 1133 } // if 1088 1134 } 1089 } catch ( SemanticError &e ) {1135 } catch ( SemanticErrorException &e ) { 1090 1136 errors.append( e ); 1091 1137 } … … 1107 1153 // check if type is a pointer to function 1108 1154 if ( PointerType* pointer = dynamic_cast<PointerType*>( 1109 funcOp->expr-> get_result()->stripReferences() ) ) {1155 funcOp->expr->result->stripReferences() ) ) { 1110 1156 if ( FunctionType* function = 1111 dynamic_cast<FunctionType*>( pointer-> get_base()) ) {1157 dynamic_cast<FunctionType*>( pointer->base ) ) { 1112 1158 Alternative newFunc( *funcOp ); 1113 referenceToRvalueConversion( newFunc.expr );1159 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1114 1160 makeFunctionAlternatives( newFunc, function, argExpansions, 1115 1161 std::back_inserter( candidates ) ); 1116 1162 } 1117 1163 } 1118 } catch ( SemanticError &e ) {1164 } catch ( SemanticErrorException &e ) { 1119 1165 errors.append( e ); 1120 1166 } … … 1131 1177 PRINT( 1132 1178 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr ); 1133 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());1134 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());1135 std::cerr << "Case +++++++++++++ " << appExpr-> get_function()<< std::endl;1179 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 1180 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 1181 std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl; 1136 1182 std::cerr << "formals are:" << std::endl; 1137 printAll( function-> get_parameters(), std::cerr, 8 );1183 printAll( function->parameters, std::cerr, 8 ); 1138 1184 std::cerr << "actuals are:" << std::endl; 1139 printAll( appExpr-> get_args(), std::cerr, 8 );1185 printAll( appExpr->args, std::cerr, 8 ); 1140 1186 std::cerr << "bindings are:" << std::endl; 1141 1187 withFunc.env.print( std::cerr, 8 ); 1188 std::cerr << "cost is: " << withFunc.cost << std::endl; 1142 1189 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1143 1190 ) … … 1172 1219 // fix this issue in a more robust way. 1173 1220 targetType = nullptr; 1174 visit( untypedExpr );1221 postvisit( untypedExpr ); 1175 1222 } 1176 1223 } … … 1178 1225 bool isLvalue( Expression *expr ) { 1179 1226 // xxx - recurse into tuples? 1180 return expr->result && ( expr-> get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result()) );1181 } 1182 1183 void AlternativeFinder:: visit( AddressExpr *addressExpr ) {1227 return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) ); 1228 } 1229 1230 void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) { 1184 1231 AlternativeFinder finder( indexer, env ); 1185 1232 finder.find( addressExpr->get_arg() ); … … 1192 1239 } 1193 1240 1194 void AlternativeFinder:: visit( LabelAddressExpr * expr ) {1241 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1195 1242 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1196 1243 } 1197 1244 1198 Expression * restructureCast( Expression * argExpr, Type * toType ) {1245 Expression * restructureCast( Expression * argExpr, Type * toType, bool isGenerated ) { 1199 1246 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 1200 1247 // Argument expression is a tuple and the target type is not void and not a reference type. … … 1211 1258 // cast each component 1212 1259 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i ); 1213 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) );1260 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 1214 1261 } 1215 1262 delete argExpr; … … 1219 1266 } else { 1220 1267 // handle normally 1221 return new CastExpr( argExpr, toType->clone() ); 1222 } 1223 } 1224 1225 void AlternativeFinder::visit( CastExpr *castExpr ) { 1268 CastExpr * ret = new CastExpr( argExpr, toType->clone() ); 1269 ret->isGenerated = isGenerated; 1270 return ret; 1271 } 1272 } 1273 1274 void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) { 1226 1275 Type *& toType = castExpr->get_result(); 1227 1276 assert( toType ); … … 1232 1281 AlternativeFinder finder( indexer, env ); 1233 1282 finder.targetType = toType; 1234 finder.findWithAdjustment( castExpr-> get_arg());1283 finder.findWithAdjustment( castExpr->arg ); 1235 1284 1236 1285 AltList candidates; … … 1239 1288 OpenVarSet openVars; 1240 1289 1290 alt.env.extractOpenVars( openVars ); 1291 1241 1292 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1242 1293 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1243 1294 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1244 1295 // to. 1245 int discardedValues = alt.expr-> get_result()->size() - castExpr->get_result()->size();1296 int discardedValues = alt.expr->result->size() - castExpr->result->size(); 1246 1297 if ( discardedValues < 0 ) continue; 1247 1298 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1248 1299 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1249 1300 // unification run for side-effects 1250 unify( castExpr-> get_result(), alt.expr->get_result(), alt.env, needAssertions,1301 unify( castExpr->result, alt.expr->result, alt.env, needAssertions, 1251 1302 haveAssertions, openVars, indexer ); 1252 Cost thisCost = castCost( alt.expr-> get_result(), castExpr->get_result(), indexer,1303 Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer, 1253 1304 alt.env ); 1254 1305 PRINT( … … 1263 1314 // count one safe conversion for each value that is thrown away 1264 1315 thisCost.incSafe( discardedValues ); 1265 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env,1316 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env, 1266 1317 alt.cost, thisCost ); 1267 1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars, … … 1278 1329 } 1279 1330 1280 void AlternativeFinder:: visit( VirtualCastExpr * castExpr ) {1331 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1281 1332 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1282 1333 AlternativeFinder finder( indexer, env ); … … 1290 1341 } 1291 1342 1292 void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) { 1343 namespace { 1344 /// Gets name from untyped member expression (member must be NameExpr) 1345 const std::string& get_member_name( UntypedMemberExpr *memberExpr ) { 1346 NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ); 1347 assert( nameExpr ); 1348 return nameExpr->get_name(); 1349 } 1350 } 1351 1352 void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) { 1293 1353 AlternativeFinder funcFinder( indexer, env ); 1294 1354 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 1295 1355 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 1296 1356 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 1297 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 1298 Type * aggrType = aggrExpr->get_result(); 1299 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 1300 aggrType = aggrType->stripReferences(); 1301 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 1302 } 1357 Cost cost = agg->cost; 1358 Expression * aggrExpr = agg->expr->clone(); 1359 referenceToRvalueConversion( aggrExpr, cost ); 1360 std::unique_ptr<Expression> guard( aggrExpr ); 1361 1303 1362 // find member of the given type 1304 1363 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1305 addAggMembers( structInst, aggrExpr .get(), agg->cost, agg->env, memberExpr->get_member() );1364 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1306 1365 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1307 addAggMembers( unionInst, aggrExpr .get(), agg->cost, agg->env, memberExpr->get_member() );1366 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1308 1367 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1309 addTupleMembers( tupleType, aggrExpr .get(), agg->cost, agg->env, memberExpr->get_member() );1368 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() ); 1310 1369 } // if 1311 1370 } // for 1312 1371 } 1313 1372 1314 void AlternativeFinder:: visit( MemberExpr *memberExpr ) {1373 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1315 1374 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1316 1375 } 1317 1376 1318 void AlternativeFinder:: visit( NameExpr *nameExpr ) {1377 void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) { 1319 1378 std::list< SymTab::Indexer::IdData > declList; 1320 indexer.lookupId( nameExpr-> get_name(), declList );1321 PRINT( std::cerr << "nameExpr is " << nameExpr-> get_name()<< std::endl; )1379 indexer.lookupId( nameExpr->name, declList ); 1380 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1322 1381 for ( auto & data : declList ) { 1323 Expression * newExpr = data.combine(); 1324 // xxx - add in extra cost for with-statement exprs? 1325 alternatives.push_back( Alternative( newExpr, env, Cost::zero ) ); 1382 Cost cost = Cost::zero; 1383 Expression * newExpr = data.combine( cost ); 1384 1385 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1386 // can't construct in place and use vector::back 1387 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1326 1388 PRINT( 1327 1389 std::cerr << "decl is "; … … 1332 1394 std::cerr << std::endl; 1333 1395 ) 1334 renameTypes( alternatives.back().expr ); 1335 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression. 1396 renameTypes( newAlt.expr ); 1397 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression. 1398 alternatives.push_back( std::move(newAlt) ); 1336 1399 } // for 1337 1400 } 1338 1401 1339 void AlternativeFinder:: visit( VariableExpr *variableExpr ) {1402 void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) { 1340 1403 // not sufficient to clone here, because variable's type may have changed 1341 1404 // since the VariableExpr was originally created. 1342 alternatives.push_back( Alternative( new VariableExpr( variableExpr-> get_var()), env, Cost::zero ) );1343 } 1344 1345 void AlternativeFinder:: visit( ConstantExpr *constantExpr ) {1405 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) ); 1406 } 1407 1408 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1346 1409 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1347 1410 } 1348 1411 1349 void AlternativeFinder:: visit( SizeofExpr *sizeofExpr ) {1412 void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) { 1350 1413 if ( sizeofExpr->get_isType() ) { 1351 1414 Type * newType = sizeofExpr->get_type()->clone(); … … 1359 1422 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1360 1423 if ( winners.size() != 1 ) { 1361 throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr());1424 SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " ); 1362 1425 } // if 1363 1426 // return the lowest cost alternative for the argument 1364 1427 Alternative &choice = winners.front(); 1365 referenceToRvalueConversion( choice.expr );1428 referenceToRvalueConversion( choice.expr, choice.cost ); 1366 1429 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1367 1430 } // if 1368 1431 } 1369 1432 1370 void AlternativeFinder:: visit( AlignofExpr *alignofExpr ) {1433 void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) { 1371 1434 if ( alignofExpr->get_isType() ) { 1372 1435 Type * newType = alignofExpr->get_type()->clone(); … … 1380 1443 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1381 1444 if ( winners.size() != 1 ) { 1382 throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr());1445 SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " ); 1383 1446 } // if 1384 1447 // return the lowest cost alternative for the argument 1385 1448 Alternative &choice = winners.front(); 1386 referenceToRvalueConversion( choice.expr );1449 referenceToRvalueConversion( choice.expr, choice.cost ); 1387 1450 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1388 1451 } // if … … 1390 1453 1391 1454 template< typename StructOrUnionType > 1392 void AlternativeFinder:: addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {1455 void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) { 1393 1456 std::list< Declaration* > members; 1394 1457 aggInst->lookup( name, members ); … … 1403 1466 } 1404 1467 1405 void AlternativeFinder:: visit( UntypedOffsetofExpr *offsetofExpr ) {1468 void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) { 1406 1469 AlternativeFinder funcFinder( indexer, env ); 1407 1470 // xxx - resolveTypeof? 1408 1471 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) { 1409 addOffsetof( structInst, offsetofExpr-> get_member());1472 addOffsetof( structInst, offsetofExpr->member ); 1410 1473 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( offsetofExpr->get_type() ) ) { 1411 addOffsetof( unionInst, offsetofExpr-> get_member());1412 } 1413 } 1414 1415 void AlternativeFinder:: visit( OffsetofExpr *offsetofExpr ) {1474 addOffsetof( unionInst, offsetofExpr->member ); 1475 } 1476 } 1477 1478 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1416 1479 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1417 1480 } 1418 1481 1419 void AlternativeFinder:: visit( OffsetPackExpr *offsetPackExpr ) {1482 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1420 1483 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1421 1484 } … … 1436 1499 AltList & alternatives = finder.get_alternatives(); 1437 1500 if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) { 1438 alternatives.push_back( Alternative( new AttrExpr( data.combine(), argType->clone() ), env, Cost::zero ) ); 1501 Cost cost = Cost::zero; 1502 Expression * newExpr = data.combine( cost ); 1503 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1439 1504 for ( DeclarationWithType * retVal : function->returnVals ) { 1440 1505 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1444 1509 } 1445 1510 1446 void AlternativeFinder:: visit( AttrExpr *attrExpr ) {1511 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1447 1512 // assume no 'pointer-to-attribute' 1448 1513 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); … … 1458 1523 if ( function->get_parameters().size() == 1 ) { 1459 1524 if ( attrExpr->get_isType() ) { 1460 resolveAttr( data, function, attrExpr->get_type(), env, *this);1525 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1461 1526 } else { 1462 1527 AlternativeFinder finder( indexer, env ); … … 1464 1529 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1465 1530 if ( choice->expr->get_result()->size() == 1 ) { 1466 resolveAttr(data, function, choice->expr->get_result(), choice->env, *this);1531 resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder ); 1467 1532 } // fi 1468 1533 } // for … … 1473 1538 } else { 1474 1539 for ( auto & data : attrList ) { 1475 alternatives.push_back( Alternative( data.combine(), env, Cost::zero ) ); 1540 Cost cost = Cost::zero; 1541 Expression * newExpr = data.combine( cost ); 1542 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1476 1543 renameTypes( alternatives.back().expr ); 1477 1544 } // for … … 1479 1546 } 1480 1547 1481 void AlternativeFinder:: visit( LogicalExpr *logicalExpr ) {1548 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1482 1549 AlternativeFinder firstFinder( indexer, env ); 1483 1550 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); 1484 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1485 AlternativeFinder secondFinder( indexer, first->env ); 1486 secondFinder.findWithAdjustment( logicalExpr->get_arg2() ); 1487 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1488 LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() ); 1489 alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) ); 1490 } 1491 } 1492 } 1493 1494 void AlternativeFinder::visit( ConditionalExpr *conditionalExpr ) { 1551 if ( firstFinder.alternatives.empty() ) return; 1552 AlternativeFinder secondFinder( indexer, env ); 1553 secondFinder.findWithAdjustment( logicalExpr->get_arg2() ); 1554 if ( secondFinder.alternatives.empty() ) return; 1555 for ( const Alternative & first : firstFinder.alternatives ) { 1556 for ( const Alternative & second : secondFinder.alternatives ) { 1557 TypeEnvironment compositeEnv; 1558 compositeEnv.simpleCombine( first.env ); 1559 compositeEnv.simpleCombine( second.env ); 1560 1561 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1562 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1563 } 1564 } 1565 } 1566 1567 void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) { 1495 1568 // find alternatives for condition 1496 1569 AlternativeFinder firstFinder( indexer, env ); 1497 firstFinder.findWithAdjustment( conditionalExpr->get_arg1() ); 1498 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1499 // find alternatives for true expression 1500 AlternativeFinder secondFinder( indexer, first->env ); 1501 secondFinder.findWithAdjustment( conditionalExpr->get_arg2() ); 1502 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1503 // find alterantives for false expression 1504 AlternativeFinder thirdFinder( indexer, second->env ); 1505 thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() ); 1506 for ( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) { 1570 firstFinder.findWithAdjustment( conditionalExpr->arg1 ); 1571 if ( firstFinder.alternatives.empty() ) return; 1572 // find alternatives for true expression 1573 AlternativeFinder secondFinder( indexer, env ); 1574 secondFinder.findWithAdjustment( conditionalExpr->arg2 ); 1575 if ( secondFinder.alternatives.empty() ) return; 1576 // find alterantives for false expression 1577 AlternativeFinder thirdFinder( indexer, env ); 1578 thirdFinder.findWithAdjustment( conditionalExpr->arg3 ); 1579 if ( thirdFinder.alternatives.empty() ) return; 1580 for ( const Alternative & first : firstFinder.alternatives ) { 1581 for ( const Alternative & second : secondFinder.alternatives ) { 1582 for ( const Alternative & third : thirdFinder.alternatives ) { 1583 TypeEnvironment compositeEnv; 1584 compositeEnv.simpleCombine( first.env ); 1585 compositeEnv.simpleCombine( second.env ); 1586 compositeEnv.simpleCombine( third.env ); 1587 1507 1588 // unify true and false types, then infer parameters to produce new alternatives 1508 1589 OpenVarSet openVars; 1509 1590 AssertionSet needAssertions, haveAssertions; 1510 Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );1591 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost ); 1511 1592 Type* commonType = nullptr; 1512 if ( unify( second ->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {1513 ConditionalExpr *newExpr = new ConditionalExpr( first ->expr->clone(), second->expr->clone(), third->expr->clone() );1514 newExpr-> set_result( commonType ? commonType : second->expr->get_result()->clone());1593 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1594 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1595 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1515 1596 // convert both options to the conditional result type 1516 1597 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); … … 1524 1605 } 1525 1606 1526 void AlternativeFinder:: visit( CommaExpr *commaExpr ) {1607 void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) { 1527 1608 TypeEnvironment newEnv( env ); 1528 1609 Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv ); 1529 1610 AlternativeFinder secondFinder( indexer, newEnv ); 1530 1611 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1531 for ( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt) {1532 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt ->expr->clone() ), alt->env, alt->cost ) );1612 for ( const Alternative & alt : secondFinder.alternatives ) { 1613 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1533 1614 } // for 1534 1615 delete newFirstArg; 1535 1616 } 1536 1617 1537 void AlternativeFinder:: visit( RangeExpr * rangeExpr ) {1618 void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) { 1538 1619 // resolve low and high, accept alternatives whose low and high types unify 1539 1620 AlternativeFinder firstFinder( indexer, env ); 1540 firstFinder.findWithAdjustment( rangeExpr->get_low() ); 1541 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) { 1542 AlternativeFinder secondFinder( indexer, first->env ); 1543 secondFinder.findWithAdjustment( rangeExpr->get_high() ); 1544 for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) { 1621 firstFinder.findWithAdjustment( rangeExpr->low ); 1622 if ( firstFinder.alternatives.empty() ) return; 1623 AlternativeFinder secondFinder( indexer, env ); 1624 secondFinder.findWithAdjustment( rangeExpr->high ); 1625 if ( secondFinder.alternatives.empty() ) return; 1626 for ( const Alternative & first : firstFinder.alternatives ) { 1627 for ( const Alternative & second : secondFinder.alternatives ) { 1628 TypeEnvironment compositeEnv; 1629 compositeEnv.simpleCombine( first.env ); 1630 compositeEnv.simpleCombine( second.env ); 1545 1631 OpenVarSet openVars; 1546 1632 AssertionSet needAssertions, haveAssertions; 1547 Alternative newAlt( 0, second->env, first->cost + second->cost );1633 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1548 1634 Type* commonType = nullptr; 1549 if ( unify( first ->expr->get_result(), second->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {1550 RangeExpr * newExpr = new RangeExpr( first->expr->clone(), second->expr->clone() );1551 newExpr-> set_result( commonType ? commonType : first->expr->get_result()->clone());1635 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1636 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1637 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1552 1638 newAlt.expr = newExpr; 1553 1639 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); … … 1557 1643 } 1558 1644 1559 void AlternativeFinder:: visit( UntypedTupleExpr *tupleExpr ) {1645 void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) { 1560 1646 std::vector< AlternativeFinder > subExprAlternatives; 1561 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),1647 altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1562 1648 back_inserter( subExprAlternatives ) ); 1563 1649 std::vector< AltList > possibilities; … … 1575 1661 } 1576 1662 1577 void AlternativeFinder:: visit( TupleExpr *tupleExpr ) {1663 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1578 1664 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1579 1665 } 1580 1666 1581 void AlternativeFinder:: visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {1667 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1582 1668 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1583 1669 } 1584 1670 1585 void AlternativeFinder:: visit( ConstructorExpr * ctorExpr ) {1671 void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) { 1586 1672 AlternativeFinder finder( indexer, env ); 1587 1673 // don't prune here, since it's guaranteed all alternatives will have the same type … … 1593 1679 } 1594 1680 1595 void AlternativeFinder:: visit( TupleIndexExpr *tupleExpr ) {1681 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1596 1682 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1597 1683 } 1598 1684 1599 void AlternativeFinder:: visit( TupleAssignExpr *tupleAssignExpr ) {1685 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1600 1686 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1601 1687 } 1602 1688 1603 void AlternativeFinder:: visit( UniqueExpr *unqExpr ) {1689 void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) { 1604 1690 AlternativeFinder finder( indexer, env ); 1605 1691 finder.findWithAdjustment( unqExpr->get_expr() ); … … 1611 1697 } 1612 1698 1613 void AlternativeFinder:: visit( StmtExpr *stmtExpr ) {1699 void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) { 1614 1700 StmtExpr * newStmtExpr = stmtExpr->clone(); 1615 1701 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); … … 1618 1704 } 1619 1705 1620 void AlternativeFinder:: visit( UntypedInitExpr *initExpr ) {1706 void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) { 1621 1707 // handle each option like a cast 1622 1708 AltList candidates; 1623 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1709 PRINT( 1710 std::cerr << "untyped init expr: " << initExpr << std::endl; 1711 ) 1624 1712 // O(N^2) checks of d-types with e-types 1625 1713 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { … … 1632 1720 AlternativeFinder finder( indexer, env ); 1633 1721 finder.targetType = toType; 1634 finder.findWithAdjustment( initExpr-> get_expr());1722 finder.findWithAdjustment( initExpr->expr ); 1635 1723 for ( Alternative & alt : finder.get_alternatives() ) { 1636 1724 TypeEnvironment newEnv( alt.env ); 1637 1725 AssertionSet needAssertions, haveAssertions; 1638 1726 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1639 PRINT( std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; ) 1727 PRINT( 1728 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1729 ) 1640 1730 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1641 1731 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1642 1732 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1643 1733 // to. 1644 int discardedValues = alt.expr-> get_result()->size() - toType->size();1734 int discardedValues = alt.expr->result->size() - toType->size(); 1645 1735 if ( discardedValues < 0 ) continue; 1646 1736 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1647 1737 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1648 1738 // unification run for side-effects 1649 unify( toType, alt.expr-> get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??1650 1651 Cost thisCost = castCost( alt.expr-> get_result(), toType, indexer, newEnv );1739 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1740 1741 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); 1652 1742 if ( thisCost != Cost::infinity ) { 1653 1743 // count one safe conversion for each value that is thrown away 1654 1744 thisCost.incSafe( discardedValues ); 1655 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );1745 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1656 1746 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1657 1747 } … … 1666 1756 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) ); 1667 1757 } 1758 1759 void AlternativeFinder::Finder::postvisit( InitExpr * ) { 1760 assertf( false, "AlternativeFinder should never see a resolved InitExpr." ); 1761 } 1762 1763 void AlternativeFinder::Finder::postvisit( DeletedExpr * ) { 1764 assertf( false, "AlternativeFinder should never see a DeletedExpr." ); 1765 } 1766 1767 void AlternativeFinder::Finder::postvisit( GenericExpr * ) { 1768 assertf( false, "_Generic is not yet supported." ); 1769 } 1668 1770 } // namespace ResolvExpr 1669 1771
Note:
See TracChangeset
for help on using the changeset viewer.