Changeset c0d00b6 for src/ResolvExpr
- Timestamp:
- Nov 25, 2017, 3:22:18 PM (8 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, stuck-waitfor-destruct
- Children:
- c6e2c18
- Parents:
- 9d06142 (diff), 3de176d (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. - Location:
- src/ResolvExpr
- Files:
-
- 2 added
- 12 edited
-
Alternative.cc (modified) (2 diffs)
-
Alternative.h (modified) (4 diffs)
-
AlternativeFinder.cc (modified) (20 diffs)
-
AlternativeFinder.h (modified) (3 diffs)
-
ExplodedActual.cc (added)
-
ExplodedActual.h (added)
-
PtrsAssignable.cc (modified) (1 diff)
-
RenameVars.cc (modified) (3 diffs)
-
RenameVars.h (modified) (1 diff)
-
Resolver.cc (modified) (2 diffs)
-
TypeEnvironment.cc (modified) (1 diff)
-
TypeEnvironment.h (modified) (2 diffs)
-
module.mk (modified) (1 diff)
-
typeops.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Alternative.cc
r9d06142 rc0d00b6 18 18 #include <ostream> // for operator<<, ostream, basic_o... 19 19 #include <string> // for operator<<, char_traits, string 20 #include <utility> // for move 20 21 21 22 #include "Common/utility.h" // for maybeClone … … 81 82 os << std::endl; 82 83 } 84 85 void splice( AltList& dst, AltList& src ) { 86 dst.reserve( dst.size() + src.size() ); 87 for ( Alternative& alt : src ) { 88 dst.push_back( std::move(alt) ); 89 } 90 src.clear(); 91 } 92 93 void spliceBegin( AltList& dst, AltList& src ) { 94 splice( src, dst ); 95 dst.swap( src ); 96 } 97 83 98 } // namespace ResolvExpr 84 99 -
src/ResolvExpr/Alternative.h
r9d06142 rc0d00b6 17 17 18 18 #include <iosfwd> // for ostream 19 #include < list> // for list19 #include <vector> // for vector 20 20 21 21 #include "Cost.h" // for Cost … … 25 25 26 26 namespace ResolvExpr { 27 struct Alternative;28 29 typedef std::list< Alternative > AltList;30 31 27 struct Alternative { 32 28 Alternative(); … … 41 37 void print( std::ostream &os, Indenter indent = {} ) const; 42 38 39 /// Returns the stored expression, but released from management of this Alternative 40 Expression* release_expr() { 41 Expression* tmp = expr; 42 expr = nullptr; 43 return tmp; 44 } 45 43 46 Cost cost; 44 47 Cost cvtCost; … … 46 49 TypeEnvironment env; 47 50 }; 51 52 typedef std::vector< Alternative > AltList; 53 54 /// Moves all elements from src to the end of dst 55 void splice( AltList& dst, AltList& src ); 56 57 /// Moves all elements from src to the beginning of dst 58 void spliceBegin( AltList& dst, AltList& src ); 48 59 } // namespace ResolvExpr 49 60 -
src/ResolvExpr/AlternativeFinder.cc
r9d06142 rc0d00b6 16 16 #include <algorithm> // for copy 17 17 #include <cassert> // for strict_dynamic_cast, assert, assertf 18 #include <cstddef> // for size_t 18 19 #include <iostream> // for operator<<, cerr, ostream, endl 19 20 #include <iterator> // for back_insert_iterator, back_inserter 20 21 #include <list> // for _List_iterator, list, _List_const_... 21 22 #include <map> // for _Rb_tree_iterator, map, _Rb_tree_c... 22 #include <memory> // for allocator_traits<>::value_type 23 #include <memory> // for allocator_traits<>::value_type, unique_ptr 23 24 #include <utility> // for pair 25 #include <vector> // for vector 24 26 25 27 #include "Alternative.h" // for AltList, Alternative … … 28 30 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 29 31 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 32 #include "ExplodedActual.h" // for ExplodedActual 30 33 #include "InitTweak/InitTweak.h" // for getFunctionName 31 34 #include "RenameVars.h" // for RenameVars, global_renamer … … 49 52 #define PRINT( text ) if ( resolvep ) { text } 50 53 //#define DEBUG_COST 54 55 using std::move; 56 57 /// copies any copyable type 58 template<typename T> 59 T copy(const T& x) { return x; } 51 60 52 61 namespace ResolvExpr { … … 178 187 expr->accept( *this ); 179 188 if ( failFast && alternatives.empty() ) { 189 PRINT( 190 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 191 ) 180 192 throw SemanticError( "No reasonable alternatives for expression ", expr ); 181 193 } … … 186 198 printAlts( alternatives, std::cerr ); 187 199 ) 188 AltList ::iterator oldBegin = alternatives.begin();189 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives) );190 if ( failFast && alternatives.begin() == oldBegin) {200 AltList pruned; 201 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 202 if ( failFast && pruned.empty() ) { 191 203 std::ostringstream stream; 192 204 AltList winners; … … 198 210 throw SemanticError( stream.str() ); 199 211 } 200 alternatives .erase( oldBegin, alternatives.end());212 alternatives = move(pruned); 201 213 PRINT( 202 214 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; … … 333 345 tmpCost.incPoly( -tmpCost.get_polyCost() ); 334 346 if ( tmpCost != Cost::zero ) { 335 // if ( convCost != Cost::zero ) {336 347 Type *newType = formalType->clone(); 337 348 env.apply( newType ); … … 405 416 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 406 417 } 407 }408 409 /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,410 /// producing expression(s) in out and their total cost in cost.411 template< typename AltIterator, typename OutputIterator >412 bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) {413 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {414 // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType415 std::list< Expression * > exprs;416 for ( Type * type : *tupleType ) {417 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( exprs ) ) ) {418 deleteAll( exprs );419 return false;420 }421 }422 *out++ = new TupleExpr( exprs );423 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {424 // xxx - mixing default arguments with variadic??425 std::list< Expression * > exprs;426 for ( ; actualIt != actualEnd; ++actualIt ) {427 exprs.push_back( actualIt->expr->clone() );428 cost += actualIt->cost;429 }430 Expression * arg = nullptr;431 if ( exprs.size() == 1 && Tuples::isTtype( exprs.front()->get_result() ) ) {432 // the case where a ttype value is passed directly is special, e.g. for argument forwarding purposes433 // xxx - what if passing multiple arguments, last of which is ttype?434 // xxx - what would happen if unify was changed so that unifying tuple types flattened both before unifying lists? then pass in TupleType(ttype) below.435 arg = exprs.front();436 } else {437 arg = new TupleExpr( exprs );438 }439 assert( arg && arg->get_result() );440 if ( ! unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {441 return false;442 }443 *out++ = arg;444 } else if ( actualIt != actualEnd ) {445 // both actualType and formalType are atomic (non-tuple) types - if they unify446 // then accept actual as an argument, otherwise return false (fail to instantiate argument)447 Expression * actual = actualIt->expr;448 Type * actualType = actual->get_result();449 450 PRINT(451 std::cerr << "formal type is ";452 formalType->print( std::cerr );453 std::cerr << std::endl << "actual type is ";454 actualType->print( std::cerr );455 std::cerr << std::endl;456 )457 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {458 // std::cerr << "unify failed" << std::endl;459 return false;460 }461 // move the expression from the alternative to the output iterator462 *out++ = actual;463 actualIt->expr = nullptr;464 cost += actualIt->cost;465 ++actualIt;466 } else {467 // End of actuals - Handle default values468 if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {469 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( si->get_value() ) ) {470 // so far, only constant expressions are accepted as default values471 if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( castExpr->get_arg() ) ) {472 if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {473 if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {474 *out++ = cnstexpr->clone();475 return true;476 } // if477 } // if478 } // if479 }480 } // if481 return false;482 } // if483 return true;484 }485 486 bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) {487 simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );488 // make sure we don't widen any existing bindings489 for ( TypeEnvironment::iterator i = resultEnv.begin(); i != resultEnv.end(); ++i ) {490 i->allowWidening = false;491 }492 resultEnv.extractOpenVars( openVars );493 494 // flatten actuals so that each actual has an atomic (non-tuple) type495 AltList exploded;496 Tuples::explode( actuals, indexer, back_inserter( exploded ) );497 498 AltList::iterator actualExpr = exploded.begin();499 AltList::iterator actualEnd = exploded.end();500 for ( DeclarationWithType * formal : formals ) {501 // match flattened actuals with formal parameters - actuals will be grouped to match502 // with formals as appropriate503 Cost cost = Cost::zero;504 std::list< Expression * > newExprs;505 ObjectDecl * obj = strict_dynamic_cast< ObjectDecl * >( formal );506 if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {507 deleteAll( newExprs );508 return false;509 }510 // success - produce argument as a new alternative511 assert( newExprs.size() == 1 );512 out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );513 }514 if ( actualExpr != actualEnd ) {515 // there are still actuals remaining, but we've run out of formal parameters to match against516 // this is okay only if the function is variadic517 if ( ! isVarArgs ) {518 return false;519 }520 out.splice( out.end(), exploded, actualExpr, actualEnd );521 }522 return true;523 418 } 524 419 … … 675 570 } 676 571 677 template< typename OutputIterator > 678 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) { 679 OpenVarSet openVars; 680 AssertionSet resultNeed, resultHave; 681 TypeEnvironment resultEnv( func.env ); 682 makeUnifiableVars( funcType, openVars, resultNeed ); 683 resultEnv.add( funcType->get_forall() ); // add all type variables as open variables now so that those not used in the parameter list are still considered open 684 AltList instantiatedActuals; // filled by instantiate function 572 /// Gets a default value from an initializer, nullptr if not present 573 ConstantExpr* getDefaultValue( Initializer* init ) { 574 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() ); 577 } 578 } 579 return nullptr; 580 } 581 582 /// State to iteratively build a match of parameter expressions to arguments 583 struct ArgPack { 584 std::size_t parent; ///< Index of parent pack 585 std::unique_ptr<Expression> expr; ///< The argument stored here 586 Cost cost; ///< The cost of this argument 587 TypeEnvironment env; ///< Environment for this pack 588 AssertionSet need; ///< Assertions outstanding for this pack 589 AssertionSet have; ///< Assertions found for this pack 590 OpenVarSet openVars; ///< Open variables for this pack 591 unsigned nextArg; ///< Index of next argument in arguments list 592 unsigned tupleStart; ///< Number of tuples that start at this index 593 unsigned nextExpl; ///< Index of next exploded element 594 unsigned explAlt; ///< Index of alternative for nextExpl > 0 595 596 ArgPack() 597 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 599 tupleStart(0), nextExpl(0), explAlt(0) {} 600 601 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 602 const OpenVarSet& openVars) 603 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 604 openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {} 605 606 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 607 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 608 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 609 unsigned explAlt = 0 ) 610 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 611 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 612 nextExpl(nextExpl), explAlt(explAlt) {} 613 614 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 615 OpenVarSet&& openVars, unsigned nextArg, Cost added ) 616 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 617 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 618 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 619 620 /// true iff this pack is in the middle of an exploded argument 621 bool hasExpl() const { return nextExpl > 0; } 622 623 /// Gets the list of exploded alternatives for this pack 624 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 625 return args[nextArg-1][explAlt]; 626 } 627 628 /// Ends a tuple expression, consolidating the appropriate actuals 629 void endTuple( const std::vector<ArgPack>& packs ) { 630 // add all expressions in tuple to list, summing cost 631 std::list<Expression*> exprs; 632 const ArgPack* pack = this; 633 if ( expr ) { exprs.push_front( expr.release() ); } 634 while ( pack->tupleStart == 0 ) { 635 pack = &packs[pack->parent]; 636 exprs.push_front( pack->expr->clone() ); 637 cost += pack->cost; 638 } 639 // reset pack to appropriate tuple 640 expr.reset( new TupleExpr( exprs ) ); 641 tupleStart = pack->tupleStart - 1; 642 parent = pack->parent; 643 } 644 }; 645 646 /// Instantiates an argument to match a formal, returns false if no results left 647 bool instantiateArgument( Type* formalType, Initializer* initializer, 648 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 649 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 650 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 651 // formalType is a TupleType - group actuals into a TupleExpr 652 ++nTuples; 653 for ( Type* type : *tupleType ) { 654 // xxx - dropping initializer changes behaviour from previous, but seems correct 655 if ( ! instantiateArgument( 656 type, nullptr, args, results, genStart, indexer, nTuples ) ) 657 return false; 658 nTuples = 0; 659 } 660 // re-consititute tuples for final generation 661 for ( auto i = genStart; i < results.size(); ++i ) { 662 results[i].endTuple( results ); 663 } 664 return true; 665 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) { 666 // formalType is a ttype, consumes all remaining arguments 667 // xxx - mixing default arguments with variadic?? 668 669 // completed tuples; will be spliced to end of results to finish 670 std::vector<ArgPack> finalResults{}; 671 672 // iterate until all results completed 673 std::size_t genEnd; 674 ++nTuples; 675 do { 676 genEnd = results.size(); 677 678 // add another argument to results 679 for ( std::size_t i = genStart; i < genEnd; ++i ) { 680 auto nextArg = results[i].nextArg; 681 682 // use next element of exploded tuple if present 683 if ( results[i].hasExpl() ) { 684 const ExplodedActual& expl = results[i].getExpl( args ); 685 686 unsigned nextExpl = results[i].nextExpl + 1; 687 if ( nextExpl == expl.exprs.size() ) { 688 nextExpl = 0; 689 } 690 691 results.emplace_back( 692 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 693 copy(results[i].need), copy(results[i].have), 694 copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, 695 results[i].explAlt ); 696 697 continue; 698 } 699 700 // finish result when out of arguments 701 if ( nextArg >= args.size() ) { 702 ArgPack newResult{ 703 results[i].env, results[i].need, results[i].have, 704 results[i].openVars }; 705 newResult.nextArg = nextArg; 706 Type* argType; 707 708 if ( nTuples > 0 ) { 709 // first iteration, push empty tuple expression 710 newResult.parent = i; 711 std::list<Expression*> emptyList; 712 newResult.expr.reset( new TupleExpr( emptyList ) ); 713 argType = newResult.expr->get_result(); 714 } else { 715 // clone result to collect tuple 716 newResult.parent = results[i].parent; 717 newResult.cost = results[i].cost; 718 newResult.tupleStart = results[i].tupleStart; 719 newResult.expr.reset( results[i].expr->clone() ); 720 argType = newResult.expr->get_result(); 721 722 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 723 // the case where a ttype value is passed directly is special, 724 // e.g. for argument forwarding purposes 725 // xxx - what if passing multiple arguments, last of which is 726 // ttype? 727 // xxx - what would happen if unify was changed so that unifying 728 // tuple 729 // types flattened both before unifying lists? then pass in 730 // TupleType (ttype) below. 731 --newResult.tupleStart; 732 } else { 733 // collapse leftover arguments into tuple 734 newResult.endTuple( results ); 735 argType = newResult.expr->get_result(); 736 } 737 } 738 739 // check unification for ttype before adding to final 740 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 741 newResult.openVars, indexer ) ) { 742 finalResults.push_back( move(newResult) ); 743 } 744 745 continue; 746 } 747 748 // add each possible next argument 749 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 750 const ExplodedActual& expl = args[nextArg][j]; 751 752 // fresh copies of parent parameters for this iteration 753 TypeEnvironment env = results[i].env; 754 OpenVarSet openVars = results[i].openVars; 755 756 env.addActual( expl.env, openVars ); 757 758 // skip empty tuple arguments by (near-)cloning parent into next gen 759 if ( expl.exprs.empty() ) { 760 results.emplace_back( 761 results[i], move(env), copy(results[i].need), 762 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 763 764 continue; 765 } 766 767 // add new result 768 results.emplace_back( 769 i, expl.exprs.front().get(), move(env), copy(results[i].need), 770 copy(results[i].have), move(openVars), nextArg + 1, 771 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 772 } 773 } 774 775 // reset for next round 776 genStart = genEnd; 777 nTuples = 0; 778 } while ( genEnd != results.size() ); 779 780 // splice final results onto results 781 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 782 results.push_back( move(finalResults[i]) ); 783 } 784 return ! finalResults.empty(); 785 } 786 787 // iterate each current subresult 788 std::size_t genEnd = results.size(); 789 for ( std::size_t i = genStart; i < genEnd; ++i ) { 790 auto nextArg = results[i].nextArg; 791 792 // use remainder of exploded tuple if present 793 if ( results[i].hasExpl() ) { 794 const ExplodedActual& expl = results[i].getExpl( args ); 795 Expression* expr = expl.exprs[results[i].nextExpl].get(); 796 797 TypeEnvironment env = results[i].env; 798 AssertionSet need = results[i].need, have = results[i].have; 799 OpenVarSet openVars = results[i].openVars; 800 801 Type* actualType = expr->get_result(); 802 803 PRINT( 804 std::cerr << "formal type is "; 805 formalType->print( std::cerr ); 806 std::cerr << std::endl << "actual type is "; 807 actualType->print( std::cerr ); 808 std::cerr << std::endl; 809 ) 810 811 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 812 unsigned nextExpl = results[i].nextExpl + 1; 813 if ( nextExpl == expl.exprs.size() ) { 814 nextExpl = 0; 815 } 816 817 results.emplace_back( 818 i, expr, move(env), move(need), move(have), move(openVars), nextArg, 819 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 820 } 821 822 continue; 823 } 824 825 // use default initializers if out of arguments 826 if ( nextArg >= args.size() ) { 827 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 828 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 829 TypeEnvironment env = results[i].env; 830 AssertionSet need = results[i].need, have = results[i].have; 831 OpenVarSet openVars = results[i].openVars; 832 833 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 834 indexer ) ) { 835 results.emplace_back( 836 i, cnstExpr, move(env), move(need), move(have), 837 move(openVars), nextArg, nTuples ); 838 } 839 } 840 } 841 842 continue; 843 } 844 845 // Check each possible next argument 846 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 847 const ExplodedActual& expl = args[nextArg][j]; 848 849 // fresh copies of parent parameters for this iteration 850 TypeEnvironment env = results[i].env; 851 AssertionSet need = results[i].need, have = results[i].have; 852 OpenVarSet openVars = results[i].openVars; 853 854 env.addActual( expl.env, openVars ); 855 856 // skip empty tuple arguments by (near-)cloning parent into next gen 857 if ( expl.exprs.empty() ) { 858 results.emplace_back( 859 results[i], move(env), move(need), move(have), move(openVars), 860 nextArg + 1, expl.cost ); 861 862 continue; 863 } 864 865 // consider only first exploded actual 866 Expression* expr = expl.exprs.front().get(); 867 Type* actualType = expr->get_result()->clone(); 868 869 PRINT( 870 std::cerr << "formal type is "; 871 formalType->print( std::cerr ); 872 std::cerr << std::endl << "actual type is "; 873 actualType->print( std::cerr ); 874 std::cerr << std::endl; 875 ) 876 877 // attempt to unify types 878 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 879 // add new result 880 results.emplace_back( 881 i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1, 882 nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 883 } 884 } 885 } 886 887 // reset for next parameter 888 genStart = genEnd; 889 890 return genEnd != results.size(); 891 } 892 893 template<typename OutputIterator> 894 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 const std::vector<ArgPack>& results, OutputIterator out ) { 896 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 897 // sum cost and accumulate actuals 898 std::list<Expression*>& args = appExpr->get_args(); 899 Cost cost = Cost::zero; 900 const ArgPack* pack = &result; 901 while ( pack->expr ) { 902 args.push_front( pack->expr->clone() ); 903 cost += pack->cost; 904 pack = &results[pack->parent]; 905 } 906 // build and validate new alternative 907 Alternative newAlt( appExpr, result.env, cost ); 908 PRINT( 909 std::cerr << "instantiate function success: " << appExpr << std::endl; 910 std::cerr << "need assertions:" << std::endl; 911 printAssertionSet( result.need, std::cerr, 8 ); 912 ) 913 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 914 } 915 916 template<typename OutputIterator> 917 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 918 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 919 OpenVarSet funcOpenVars; 920 AssertionSet funcNeed, funcHave; 921 TypeEnvironment funcEnv( func.env ); 922 makeUnifiableVars( funcType, funcOpenVars, funcNeed ); 923 // add all type variables as open variables now so that those not used in the parameter 924 // list are still considered open. 925 funcEnv.add( funcType->get_forall() ); 926 685 927 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) { 686 928 // attempt to narrow based on expected target type 687 929 Type * returnType = funcType->get_returnVals().front()->get_type(); 688 if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 689 // unification failed, don't pursue this alternative 930 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 931 indexer ) ) { 932 // unification failed, don't pursue this function alternative 690 933 return; 691 934 } 692 935 } 693 936 694 if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) { 695 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 696 Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) ); 697 makeExprList( instantiatedActuals, appExpr->get_args() ); 698 PRINT( 699 std::cerr << "instantiate function success: " << appExpr << std::endl; 700 std::cerr << "need assertions:" << std::endl; 701 printAssertionSet( resultNeed, std::cerr, 8 ); 702 ) 703 inferParameters( resultNeed, resultHave, newAlt, openVars, out ); 937 // iteratively build matches, one parameter at a time 938 std::vector<ArgPack> results; 939 results.push_back( ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } ); 940 std::size_t genStart = 0; 941 942 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 943 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 944 if ( ! instantiateArgument( 945 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) ) 946 return; 947 } 948 949 if ( funcType->get_isVarArgs() ) { 950 // append any unused arguments to vararg pack 951 std::size_t genEnd; 952 do { 953 genEnd = results.size(); 954 955 // iterate results 956 for ( std::size_t i = genStart; i < genEnd; ++i ) { 957 auto nextArg = results[i].nextArg; 958 959 // use remainder of exploded tuple if present 960 if ( results[i].hasExpl() ) { 961 const ExplodedActual& expl = results[i].getExpl( args ); 962 963 unsigned nextExpl = results[i].nextExpl + 1; 964 if ( nextExpl == expl.exprs.size() ) { 965 nextExpl = 0; 966 } 967 968 results.emplace_back( 969 i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 970 copy(results[i].need), copy(results[i].have), 971 copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, 972 results[i].explAlt ); 973 974 continue; 975 } 976 977 // finish result when out of arguments 978 if ( nextArg >= args.size() ) { 979 validateFunctionAlternative( func, results[i], results, out ); 980 981 continue; 982 } 983 984 // add each possible next argument 985 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 986 const ExplodedActual& expl = args[nextArg][j]; 987 988 // fresh copies of parent parameters for this iteration 989 TypeEnvironment env = results[i].env; 990 OpenVarSet openVars = results[i].openVars; 991 992 env.addActual( expl.env, openVars ); 993 994 // skip empty tuple arguments by (near-)cloning parent into next gen 995 if ( expl.exprs.empty() ) { 996 results.emplace_back( 997 results[i], move(env), copy(results[i].need), 998 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 999 1000 continue; 1001 } 1002 1003 // add new result 1004 results.emplace_back( 1005 i, expl.exprs.front().get(), move(env), copy(results[i].need), 1006 copy(results[i].have), move(openVars), nextArg + 1, 0, 1007 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 1008 } 1009 } 1010 1011 genStart = genEnd; 1012 } while ( genEnd != results.size() ); 1013 } else { 1014 // filter out results that don't use all the arguments 1015 for ( std::size_t i = genStart; i < results.size(); ++i ) { 1016 ArgPack& result = results[i]; 1017 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 1018 validateFunctionAlternative( func, result, results, out ); 1019 } 1020 } 704 1021 } 705 1022 } … … 711 1028 if ( funcFinder.alternatives.empty() ) return; 712 1029 713 std::list< AlternativeFinder > argAlternatives; 714 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) ); 715 716 std::list< AltList > possibilities; 717 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 1030 std::vector< AlternativeFinder > argAlternatives; 1031 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 1032 back_inserter( argAlternatives ) ); 718 1033 719 1034 // take care of possible tuple assignments 720 1035 // if not tuple assignment, assignment is taken care of as a normal function call 721 Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );1036 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives ); 722 1037 723 1038 // find function operators … … 730 1045 printAlts( funcOpFinder.alternatives, std::cerr, 1 ); 731 1046 ) 1047 1048 // pre-explode arguments 1049 ExplodedArgs argExpansions; 1050 argExpansions.reserve( argAlternatives.size() ); 1051 1052 for ( const AlternativeFinder& arg : argAlternatives ) { 1053 argExpansions.emplace_back(); 1054 auto& argE = argExpansions.back(); 1055 argE.reserve( arg.alternatives.size() ); 1056 1057 for ( const Alternative& actual : arg ) { 1058 argE.emplace_back( actual, indexer ); 1059 } 1060 } 732 1061 733 1062 AltList candidates; … … 744 1073 Alternative newFunc( *func ); 745 1074 referenceToRvalueConversion( newFunc.expr ); 746 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 747 // XXX 748 //Designators::check_alternative( function, *actualAlt ); 749 makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) ); 750 } 1075 makeFunctionAlternatives( newFunc, function, argExpansions, 1076 std::back_inserter( candidates ) ); 751 1077 } 752 1078 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) … … 756 1082 Alternative newFunc( *func ); 757 1083 referenceToRvalueConversion( newFunc.expr ); 758 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 759 makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) ); 760 } // for 1084 makeFunctionAlternatives( newFunc, function, argExpansions, 1085 std::back_inserter( candidates ) ); 761 1086 } // if 762 1087 } // if 763 1088 } 764 765 // try each function operator ?() with the current function alternative and each of the argument combinations 766 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 767 // check if the type is pointer to function 768 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 769 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 1089 } catch ( SemanticError &e ) { 1090 errors.append( e ); 1091 } 1092 } // for 1093 1094 // try each function operator ?() with each function alternative 1095 if ( ! funcOpFinder.alternatives.empty() ) { 1096 // add exploded function alternatives to front of argument list 1097 std::vector<ExplodedActual> funcE; 1098 funcE.reserve( funcFinder.alternatives.size() ); 1099 for ( const Alternative& actual : funcFinder ) { 1100 funcE.emplace_back( actual, indexer ); 1101 } 1102 argExpansions.insert( argExpansions.begin(), move(funcE) ); 1103 1104 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); 1105 funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 1106 try { 1107 // check if type is a pointer to function 1108 if ( PointerType* pointer = dynamic_cast<PointerType*>( 1109 funcOp->expr->get_result()->stripReferences() ) ) { 1110 if ( FunctionType* function = 1111 dynamic_cast<FunctionType*>( pointer->get_base() ) ) { 770 1112 Alternative newFunc( *funcOp ); 771 1113 referenceToRvalueConversion( newFunc.expr ); 772 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 773 AltList currentAlt; 774 currentAlt.push_back( *func ); 775 currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() ); 776 makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) ); 777 } // for 778 } // if 779 } // if 780 } // for 781 } catch ( SemanticError &e ) { 782 errors.append( e ); 783 } 784 } // for 1114 makeFunctionAlternatives( newFunc, function, argExpansions, 1115 std::back_inserter( candidates ) ); 1116 } 1117 } 1118 } catch ( SemanticError &e ) { 1119 errors.append( e ); 1120 } 1121 } 1122 } 785 1123 786 1124 // Implement SFINAE; resolution errors are only errors if there aren't any non-erroneous resolutions … … 788 1126 789 1127 // compute conversionsion costs 790 for ( Alt List::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc) {791 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer );1128 for ( Alternative& withFunc : candidates ) { 1129 Cost cvtCost = computeApplicationConversionCost( withFunc, indexer ); 792 1130 793 1131 PRINT( 794 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc ->expr );1132 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr ); 795 1133 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 796 1134 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); … … 801 1139 printAll( appExpr->get_args(), std::cerr, 8 ); 802 1140 std::cerr << "bindings are:" << std::endl; 803 withFunc ->env.print( std::cerr, 8 );1141 withFunc.env.print( std::cerr, 8 ); 804 1142 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 805 1143 ) 806 1144 if ( cvtCost != Cost::infinity ) { 807 withFunc ->cvtCost = cvtCost;808 alternatives.push_back( *withFunc );1145 withFunc.cvtCost = cvtCost; 1146 alternatives.push_back( withFunc ); 809 1147 } // if 810 1148 } // for 811 1149 812 candidates.clear(); 813 candidates.splice( candidates.end(), alternatives ); 814 815 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) ); 816 817 // function may return struct or union value, in which case we need to add alternatives for implicit 818 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions 819 // are never the cheapest expression 820 for ( const Alternative & alt : alternatives ) { 1150 candidates = move(alternatives); 1151 1152 // use a new list so that alternatives are not examined by addAnonConversions twice. 1153 AltList winners; 1154 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1155 1156 // function may return struct or union value, in which case we need to add alternatives 1157 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1158 // since anon conversions are never the cheapest expression 1159 for ( const Alternative & alt : winners ) { 821 1160 addAnonConversions( alt ); 822 1161 } 1162 spliceBegin( alternatives, winners ); 823 1163 824 1164 if ( alternatives.empty() && targetType && ! targetType->isVoid() ) { … … 844 1184 AlternativeFinder finder( indexer, env ); 845 1185 finder.find( addressExpr->get_arg() ); 846 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 847 if ( isLvalue( i->expr ) ) { 848 alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) ); 1186 for ( Alternative& alt : finder.alternatives ) { 1187 if ( isLvalue( alt.expr ) ) { 1188 alternatives.push_back( 1189 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 849 1190 } // if 850 1191 } // for … … 852 1193 853 1194 void AlternativeFinder::visit( LabelAddressExpr * expr ) { 854 alternatives.push_back( Alternative ( expr->clone(), env, Cost::zero));1195 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 855 1196 } 856 1197 … … 894 1235 895 1236 AltList candidates; 896 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i) {1237 for ( Alternative & alt : finder.alternatives ) { 897 1238 AssertionSet needAssertions, haveAssertions; 898 1239 OpenVarSet openVars; … … 902 1243 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 903 1244 // to. 904 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size();1245 int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size(); 905 1246 if ( discardedValues < 0 ) continue; 906 1247 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 907 1248 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 908 1249 // unification run for side-effects 909 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 910 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 1250 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1251 haveAssertions, openVars, indexer ); 1252 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1253 alt.env ); 1254 PRINT( 1255 std::cerr << "working on cast with result: " << castExpr->result << std::endl; 1256 std::cerr << "and expr type: " << alt.expr->result << std::endl; 1257 std::cerr << "env: " << alt.env << std::endl; 1258 ) 911 1259 if ( thisCost != Cost::infinity ) { 1260 PRINT( 1261 std::cerr << "has finite cost." << std::endl; 1262 ) 912 1263 // count one safe conversion for each value that is thrown away 913 1264 thisCost.incSafe( discardedValues ); 914 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 915 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1265 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1266 alt.cost, thisCost ); 1267 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1268 back_inserter( candidates ) ); 916 1269 } // if 917 1270 } // for … … 1200 1553 1201 1554 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1202 std::list< AlternativeFinder > subExprAlternatives; 1203 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) ); 1204 std::list< AltList > possibilities; 1205 combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) ); 1206 for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) { 1555 std::vector< AlternativeFinder > subExprAlternatives; 1556 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1557 back_inserter( subExprAlternatives ) ); 1558 std::vector< AltList > possibilities; 1559 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1560 back_inserter( possibilities ) ); 1561 for ( const AltList& alts : possibilities ) { 1207 1562 std::list< Expression * > exprs; 1208 makeExprList( *i, exprs );1563 makeExprList( alts, exprs ); 1209 1564 1210 1565 TypeEnvironment compositeEnv; 1211 simpleCombineEnvironments( i->begin(), i->end(), compositeEnv ); 1212 alternatives.push_back( Alternative( new TupleExpr( exprs ) , compositeEnv, sumCost( *i ) ) ); 1566 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1567 alternatives.push_back( 1568 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1213 1569 } // for 1214 1570 } -
src/ResolvExpr/AlternativeFinder.h
r9d06142 rc0d00b6 21 21 22 22 #include "Alternative.h" // for AltList, Alternative 23 #include "ExplodedActual.h" // for ExplodedActual 23 24 #include "ResolvExpr/Cost.h" // for Cost, Cost::infinity 24 25 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet … … 31 32 32 33 namespace ResolvExpr { 34 struct ArgPack; 35 36 /// First index is which argument, second index is which alternative for that argument, 37 /// third index is which exploded element of that alternative 38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >; 39 33 40 class AlternativeFinder : public Visitor { 34 41 public: 35 42 AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env ); 43 44 AlternativeFinder( const AlternativeFinder& o ) 45 : indexer(o.indexer), alternatives(o.alternatives), env(o.env), 46 targetType(o.targetType) {} 47 48 AlternativeFinder( AlternativeFinder&& o ) 49 : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env), 50 targetType(o.targetType) {} 51 52 AlternativeFinder& operator= ( const AlternativeFinder& o ) { 53 if (&o == this) return *this; 54 55 // horrific nasty hack to rebind references... 56 alternatives.~AltList(); 57 new(this) AlternativeFinder(o); 58 return *this; 59 } 60 61 AlternativeFinder& operator= ( AlternativeFinder&& o ) { 62 if (&o == this) return *this; 63 64 // horrific nasty hack to rebind references... 65 alternatives.~AltList(); 66 new(this) AlternativeFinder(std::move(o)); 67 return *this; 68 } 69 36 70 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true ); 37 71 /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types … … 99 133 /// Adds alternatives for offsetof expressions, given the base type and name of the member 100 134 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 101 bool instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ); 102 template< typename OutputIterator > 103 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ); 135 /// Takes a final result and checks if its assertions can be satisfied 136 template<typename OutputIterator> 137 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 138 /// Finds matching alternatives for a function, given a set of arguments 139 template<typename OutputIterator> 140 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 141 /// Checks if assertion parameters match for a new alternative 104 142 template< typename OutputIterator > 105 143 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); -
src/ResolvExpr/PtrsAssignable.cc
r9d06142 rc0d00b6 68 68 69 69 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) { 70 if ( ! dynamic_cast< FunctionType* >( dest ) ) { 71 // T * = void * is safe for any T that is not a function type. 72 // xxx - this should be unsafe... 73 result = 1; 74 } // if 70 // T * = void * is disallowed - this is a change from C, where any 71 // void * can be assigned or passed to a non-void pointer without a cast. 75 72 } 76 73 -
src/ResolvExpr/RenameVars.cc
r9d06142 rc0d00b6 29 29 RenameVars global_renamer; 30 30 31 RenameVars::RenameVars() : level( 0 ) {31 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 32 32 mapStack.push_front( std::map< std::string, std::string >() ); 33 33 } … … 35 35 void RenameVars::reset() { 36 36 level = 0; 37 resetCount++; 37 38 } 38 39 … … 130 131 for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) { 131 132 std::ostringstream output; 132 output << "_" << level << "_" << (*i)->get_name();133 output << "_" << resetCount << "_" << level << "_" << (*i)->get_name(); 133 134 std::string newname( output.str() ); 134 135 mapStack.front()[ (*i)->get_name() ] = newname; -
src/ResolvExpr/RenameVars.h
r9d06142 rc0d00b6 48 48 void typeBefore( Type *type ); 49 49 void typeAfter( Type *type ); 50 int level ;50 int level, resetCount; 51 51 std::list< std::map< std::string, std::string > > mapStack; 52 52 }; -
src/ResolvExpr/Resolver.cc
r9d06142 rc0d00b6 18 18 #include <memory> // for allocator, allocator_traits<... 19 19 #include <tuple> // for get 20 #include <vector> 20 21 21 22 #include "Alternative.h" // for Alternative, AltList … … 411 412 412 413 // Find all alternatives for all arguments in canonical form 413 std:: list< AlternativeFinder > argAlternatives;414 std::vector< AlternativeFinder > argAlternatives; 414 415 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 415 416 416 417 // List all combinations of arguments 417 std:: list< AltList > possibilities;418 std::vector< AltList > possibilities; 418 419 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 419 420 -
src/ResolvExpr/TypeEnvironment.cc
r9d06142 rc0d00b6 201 201 } 202 202 203 void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) { 204 for ( const EqvClass& c : actualEnv ) { 205 EqvClass c2 = c; 206 c2.allowWidening = false; 207 for ( const std::string& var : c2.vars ) { 208 openVars[ var ] = c2.data; 209 } 210 env.push_back( std::move(c2) ); 211 } 212 } 213 214 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) { 215 env.print( out ); 216 return out; 217 } 203 218 } // namespace ResolvExpr 204 219 -
src/ResolvExpr/TypeEnvironment.h
r9d06142 rc0d00b6 86 86 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } 87 87 88 /// Iteratively adds the environment of a new actual (with allowWidening = false), 89 /// and extracts open variables. 90 void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ); 91 88 92 typedef std::list< EqvClass >::iterator iterator; 89 93 iterator begin() { return env.begin(); } … … 110 114 return sub.applyFree( type ); 111 115 } 116 117 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ); 112 118 } // namespace ResolvExpr 113 119 -
src/ResolvExpr/module.mk
r9d06142 rc0d00b6 32 32 ResolvExpr/Occurs.cc \ 33 33 ResolvExpr/TypeEnvironment.cc \ 34 ResolvExpr/CurrentObject.cc 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc -
src/ResolvExpr/typeops.h
r9d06142 rc0d00b6 16 16 #pragma once 17 17 18 #include <vector> 19 18 20 #include "SynTree/SynTree.h" 19 21 #include "SynTree/Type.h" … … 28 30 void combos( InputIterator begin, InputIterator end, OutputIterator out ) { 29 31 typedef typename InputIterator::value_type SetType; 30 typedef typename std:: list< typename SetType::value_type > ListType;32 typedef typename std::vector< typename SetType::value_type > ListType; 31 33 32 34 if ( begin == end ) { … … 38 40 begin++; 39 41 40 std:: list< ListType > recursiveResult;42 std::vector< ListType > recursiveResult; 41 43 combos( begin, end, back_inserter( recursiveResult ) ); 42 44 43 for ( typename std::list< ListType >::const_iterator i = recursiveResult.begin(); i != recursiveResult.end(); ++i ) { 44 for ( typename ListType::const_iterator j = current->begin(); j != current->end(); ++j ) { 45 ListType result; 46 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 47 *inserter++ = *j; 48 std::copy( i->begin(), i->end(), inserter ); 49 *out++ = result; 50 } // for 51 } // for 45 for ( const auto& i : recursiveResult ) for ( const auto& j : *current ) { 46 ListType result; 47 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 48 *inserter++ = j; 49 std::copy( i.begin(), i.end(), inserter ); 50 *out++ = result; 51 } 52 52 } 53 53
Note:
See TracChangeset
for help on using the changeset viewer.