Changeset 9160cb2
- Timestamp:
- Jul 25, 2018, 5:33:21 PM (7 years ago)
- Branches:
- new-env
- Children:
- 5a3e1f1
- Parents:
- f89a111
- git-author:
- Aaron Moss <a3moss@…> (07/25/18 13:49:26)
- git-committer:
- Aaron Moss <a3moss@…> (07/25/18 17:33:21)
- Location:
- src
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rf89a111 r9160cb2 37 37 #include "ResolveTypeof.h" // for resolveTypeof 38 38 #include "Resolver.h" // for resolveStmtExpr 39 #include "Common/FilterCombos.h" // for filterCombos 39 40 #include "Common/GC.h" // for new_static_root 40 41 #include "SymTab/Indexer.h" // for Indexer … … 118 119 /// Checks if assertion parameters match for a new alternative 119 120 template< typename OutputIterator > 120 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative&newAlt, OpenVarSet &openVars, OutputIterator out );121 void inferParameters( const AssertionSet &need, AssertionSet &have, Alternative &&newAlt, OpenVarSet &openVars, OutputIterator out ); 121 122 private: 122 123 AlternativeFinder & altFinder; … … 584 585 } 585 586 586 #if !1587 #if 1 587 588 namespace { 588 589 /// Information required to defer resolution of an expression … … 600 601 : cdata(cdata), adjType(adjType), env(std::move(env)), have(std::move(have)), 601 602 need(std::move(need)), openVars(std::move(openVars)) {} 603 604 class iterator { 605 friend AssertionPack; 606 public: 607 const AssertionPack& pack; 608 private: 609 AssertionSet::iterator it; 610 611 iterator(const AssertionPack& p, AssertionSet::iterator i) : pack{p}, it{i} {} 612 public: 613 iterator& operator++ () { ++it; return *this; } 614 iterator operator++ (int) { iterator tmp = *this; ++it; return tmp; } 615 AssertionSet::value_type& operator* () { return *it; } 616 AssertionSet::value_type* operator-> () { return it.operator->(); } 617 bool operator== (const iterator& o) const { return this == &o && it == o.it; } 618 bool operator!= (const iterator& o) const { return !(*this == o); } 619 }; 620 621 iterator begin() { return { *this, need.begin() }; } 622 iterator end() { return { *this, need.end() }; } 602 623 }; 603 624 … … 605 626 using DeferList = std::vector<AssertionPack>; 606 627 628 /// Single deferred item 629 struct DeferElement { 630 const DeclarationWithType* curDecl; 631 const AssertionSetValue& assnInfo; 632 const AssertionPack& match; 633 }; 634 635 /// Wrapper for the DeferList of a single assertion resolution 636 struct DeferItem { 637 DeclarationWithType* curDecl; 638 AssertionSetValue assnInfo; 639 DeferList matches; 640 641 DeferItem(DeclarationWithType* cd, const AssertionSetValue& ai, DeferList&& m ) 642 : curDecl{cd}, assnInfo{ai}, matches(std::move(m)) {} 643 644 bool empty() const { return matches.empty(); } 645 646 DeferList::size_type size() const { return matches.size(); } 647 648 DeferElement operator[] ( unsigned i ) const { 649 return { curDecl, assnInfo, matches[i] }; 650 } 651 }; 652 653 /// Flag for state iteration 654 enum CopyFlag { IterateState }; 655 607 656 /// Intermediate state for assertion resolution 608 657 struct AssertionResnState { 609 using DeferItem = std::tuple<DeclarationWithType*, AssertionSetValue, DeferList>; 610 611 const Alternative& alt; ///< Alternative being built from 658 Alternative alt; ///< Alternative being built from 659 AssertionSet need; ///< Assertions to find 612 660 AssertionSet newNeed; ///< New assertions found from current assertions 613 661 OpenVarSet openVars; ///< Open variables in current context 614 662 std::vector<DeferItem> deferred; ///< Possible deferred assertion resolutions 615 const SymTab::Indexer& indexer; ///< Name lookup 616 617 AssertionResnState(const Alternative& alt, const OpenVarSet& openVars, 618 const SymTab::Indexer& indexer ) 619 : alt{alt}, have{}, newNeed{}, openVars{openVars}, indexer{indexer} {} 663 SymTab::Indexer& indexer; ///< Name lookup 664 665 /// field-wise constructor (some fields defaulted) 666 AssertionResnState(Alternative&& alt, const AssertionSet& need, 667 const OpenVarSet& openVars, SymTab::Indexer& indexer ) 668 : alt{std::move(alt)}, need{need}, newNeed{}, openVars{openVars}, deferred{}, 669 indexer{indexer} {} 670 671 /// construct iterated state object from previous state 672 AssertionResnState(AssertionResnState&& o, CopyFlag) 673 : alt{std::move(o.alt)}, need{std::move(o.newNeed)}, newNeed{}, 674 openVars{std::move(o.openVars)}, deferred{}, indexer{o.indexer} {} 675 676 /// copy resn state updated with specified data 677 AssertionResnState(const AssertionResnState& o, const AssertionSet& need, 678 const OpenVarSet& openVars, TypeEnvironment& env ) 679 : alt{o.alt}, need{}, newNeed{o.newNeed}, openVars{openVars}, deferred{}, 680 indexer{o.indexer} { 681 newNeed.insert( need.begin(), need.end() ); 682 alt.env = env; 683 } 620 684 }; 621 685 622 686 /// Binds a single assertion from a compatible AssertionPack, updating resolution state 623 687 /// as appropriate. 624 void bindAssertion( DeclarationWithType* curDecl,AssertionSetValue& assnInfo,688 void bindAssertion( const DeclarationWithType* curDecl, const AssertionSetValue& assnInfo, 625 689 AssertionResnState& resn, AssertionPack&& match ) { 626 DeclarationWithType* candidate = match.cdata.id;627 628 690 addToIndexer( match.have, resn.indexer ); 629 691 resn.newNeed.insert( match.need.begin(), match.need.end() ); … … 631 693 resn.alt.env = std::move(match.env); 632 694 695 DeclarationWithType* candidate = match.cdata.id; 633 696 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 634 697 for ( auto& a : match.need ) { … … 664 727 // lookup candidates for this assertion 665 728 std::list< SymTab::Indexer::IdData > candidates; 666 decls.lookupId( curDecl->name, candidates );729 resn.indexer.lookupId( curDecl->name, candidates ); 667 730 668 731 // find the ones that unify with the desired type … … 697 760 // otherwise bind current match in ongoing scope 698 761 bindAssertion( curDecl, assnInfo, resn, std::move(matches.front()) ); 699 700 762 return true; 701 763 } 764 765 /// Combo iterator that combines interpretations into an interpretation list, merging 766 /// their environments. Rejects an appended interpretation if the environments cannot 767 /// be merged. 768 class InterpretationEnvMerger { 769 /// Current list of merged interpretations 770 std::vector<DeferElement> crnt; 771 /// Stack of environments, to support backtracking 772 std::vector<TypeEnvironment> envs; 773 /// Indexer to use for environment merges 774 const SymTab::Indexer& indexer; 775 public: 776 /// Outputs a pair consisting of the merged environment and the list of interpretations 777 using OutType = std::pair<TypeEnvironment, std::vector<DeferElement>>; 778 779 InterpretationEnvMerger( const TypeEnvironment& env, const SymTab::Indexer& indexer ) 780 : crnt{}, envs{}, indexer{indexer} { envs.push_back( env ); } 781 782 ComboResult append( DeferElement i ) { 783 TypeEnvironment env = envs.back(); 784 if ( ! env.combine( i.match.env, indexer ) ) return ComboResult::REJECT_THIS; 785 crnt.push_back( i ); 786 envs.push_back( env ); 787 return ComboResult::ACCEPT; 788 } 789 790 void backtrack() { 791 crnt.pop_back(); 792 envs.pop_back(); 793 } 794 795 OutType finalize() { return { envs.back(), crnt }; } 796 }; 702 797 } 703 798 #endif 704 799 705 800 template< typename OutputIterator > 706 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative&newAlt, OpenVarSet &openVars, OutputIterator out ) {801 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, Alternative &&newAlt, OpenVarSet &openVars, OutputIterator out ) { 707 802 // PRINT( 708 803 // std::cerr << "inferParameters: assertions needed are" << std::endl; … … 717 812 // ) 718 813 addToIndexer( have, decls ); 719 #if !1 720 AssertionResnState resn{ newAlt, openVars, indexer }; 814 #if 1 815 using ResnList = std::vector<AssertionResnState>; 816 ResnList resns{ AssertionResnState{ std::move(newAlt), need, openVars, decls } }; 817 ResnList new_resns{}; 721 818 722 819 // resolve assertions in breadth-first-order up to a limited number of levels deep 723 int level; 724 for ( level = 0; level < recursionLimit; ++level ) { 725 // make initial pass at matching assertions 726 for ( auto& assn : need ) { 727 if ( ! resolveAssertion( assn.first, assn.second, resn ) ) { 728 // fail early if any assertion fails to resolve 729 return; 730 } 731 } 732 733 // resolve deferred assertions by mutual compatibility and min-cost 734 if ( ! resn.deferred.empty() ) { 735 // TODO 736 assert(false && "TODO: deferred assertions unimplemented"); 737 738 // reset for next round 739 resn.deferred.clear(); 740 } 741 742 // quit resolving assertions if done 743 if ( resn.newNeed.empty() ) break; 744 745 // otherwise start on next group of recursive assertions 746 need.swap( resn.newNeed ); 747 resn.newNeed.clear(); 748 } 749 if ( level >= recursionLimit ) { 750 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 751 } 752 753 // add completed assertion to output 754 *out++ = newAlt; 820 for ( int level = 0; level < recursionLimit; ++level ) { 821 // scan over all mutually-compatible resolutions 822 for ( auto& resn : resns ) { 823 // make initial pass at matching assertions 824 for ( auto& assn : resn.need ) { 825 if ( ! resolveAssertion( assn.first, assn.second, resn ) ) { 826 // fail early if any assertion fails to resolve 827 goto nextResn; 828 } 829 } 830 831 if ( ! resn.deferred.empty() ) { 832 // resolve deferred assertions by mutual compatibility 833 834 std::vector<InterpretationEnvMerger::OutType> compatible = filterCombos( 835 resn.deferred, InterpretationEnvMerger{ resn.alt.env, resn.indexer }); 836 837 for ( auto& compat : compatible ) { 838 AssertionResnState new_resn = resn; 839 840 // add compatible assertions to new resolution state 841 for ( DeferElement el : compat.second ) { 842 bindAssertion( 843 el.curDecl, el.assnInfo, new_resn, AssertionPack{el.match} ); 844 } 845 846 // set mutual environment into resolution state 847 new_resn.alt.env = std::move(compat.first); 848 849 // add successful match or push back next state 850 if ( new_resn.newNeed.empty() ) { 851 *out++ = new_resn.alt; 852 } else { 853 new_resns.emplace_back( std::move(new_resn), IterateState ); 854 } 855 } 856 } else { 857 // add successful match or push back next state 858 if ( resn.newNeed.empty() ) { 859 *out++ = resn.alt; 860 } else { 861 new_resns.emplace_back( std::move(resn), IterateState ); 862 } 863 } 864 nextResn:; } 865 866 // finish or reset for next round 867 if ( new_resns.empty() ) return; 868 resns.swap( new_resns ); 869 new_resns.clear(); 870 } 871 // if reaches here, exceeded recursion limit 872 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 755 873 756 874 #else … … 1255 1373 printAssertionSet( result.need, std::cerr, 8 ); 1256 1374 ) 1257 inferParameters( result.need, result.have, newAlt, result.openVars, out );1375 inferParameters( result.need, result.have, std::move(newAlt), result.openVars, out ); 1258 1376 } 1259 1377 … … 1619 1737 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env, 1620 1738 alt.cost, thisCost ); 1621 inferParameters( needAssertions, haveAssertions, newAlt, openVars,1739 inferParameters( needAssertions, haveAssertions, std::move(newAlt), openVars, 1622 1740 back_inserter( candidates ) ); 1623 1741 } // if … … 1900 2018 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1901 2019 newAlt.expr = newExpr; 1902 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );2020 inferParameters( needAssertions, haveAssertions, std::move(newAlt), openVars, back_inserter( alternatives ) ); 1903 2021 } // if 1904 2022 } // for … … 1938 2056 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1939 2057 newAlt.expr = newExpr; 1940 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );2058 inferParameters( needAssertions, haveAssertions, std::move(newAlt), openVars, back_inserter( alternatives ) ); 1941 2059 } // if 1942 2060 } // for … … 2045 2163 thisCost.incSafe( discardedValues ); 2046 2164 Alternative newAlt( new InitExpr( restructureCast( alt.expr, toType, true ), initAlt.designation ), newEnv, alt.cost, thisCost ); 2047 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );2165 inferParameters( needAssertions, haveAssertions, std::move(newAlt), openVars, back_inserter( candidates ) ); 2048 2166 } 2049 2167 } -
src/ResolvExpr/TypeEnvironment.cc
rf89a111 r9160cb2 411 411 } 412 412 413 bool TypeEnv rionment::combine( const TypeEnvironment& o, const SymTab::Indexer& indexer ) {413 bool TypeEnvironment::combine( const TypeEnvironment& o, const SymTab::Indexer& indexer ) { 414 414 // short-circuit for empty cases 415 415 if ( o.isEmpty() ) return true; … … 479 479 case Classes::ADDTO: { 480 480 // later unmerged from same class, no net change to classes 481 ass ume( nmode == Classes::REMFROM, "inconsistent mode" );482 ass ume( oclasses->get_root() == next->second.root, "inconsistent tree" );481 assertf( nmode == Classes::REMFROM, "inconsistent mode" ); 482 assertf( oclasses->get_root() == next->second.root, "inconsistent tree" ); 483 483 edits.erase( next ); 484 484 forKey.pop_back(); … … 539 539 // newly seen key, mark operation 540 540 if ( bmode == Bindings::REM ) { 541 bedits.emplace_ back( it, key, BEdit{ bmode } );541 bedits.emplace_hint( it, key, BEdit{ bmode } ); 542 542 } else { 543 bedits.emplace_ back( it, key, BEdit{ bmode, bbindings->get_val() } );543 bedits.emplace_hint( it, key, BEdit{ bmode, bbindings->get_val() } ); 544 544 } 545 545 } else { … … 575 575 bmode = bbindings->get_mode(); 576 576 } 577 ass ume( bbindings == bindings, "bindings must be versions of same map" );577 assertf( bbindings == bindings, "bindings must be versions of same map" ); 578 578 579 579 // merge typeclasses (always possible, can always merge all classes into one if the
Note: See TracChangeset
for help on using the changeset viewer.