Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r1389810 r0292aa4  
    15951595                                        // unification run for side-effects
    15961596                                        bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
    1597                     (void) canUnify;
     1597                                        (void) canUnify;
    15981598                                        Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    15991599                                                symtab, env );
     
    16451645        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    16461646        /// return type. Skips ambiguous candidates.
    1647 
    1648 } // anonymous namespace
    1649 
    1650 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {
    1651         struct PruneStruct {
    1652                 CandidateRef candidate;
    1653                 bool ambiguous;
    1654 
    1655                 PruneStruct() = default;
    1656                 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
    1657         };
    1658 
    1659         // find lowest-cost candidate for each type
    1660         std::unordered_map< std::string, PruneStruct > selected;
    1661         // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found
    1662         std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});
    1663         for ( CandidateRef & candidate : candidates ) {
    1664                 std::string mangleName;
    1665                 {
    1666                         ast::ptr< ast::Type > newType = candidate->expr->result;
    1667                         assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    1668                         candidate->env.apply( newType );
    1669                         mangleName = Mangle::mangle( newType );
    1670                 }
    1671 
    1672                 auto found = selected.find( mangleName );
    1673                 if (found != selected.end() && found->second.candidate->cost < candidate->cost) {
    1674                         PRINT(
    1675                                 std::cerr << "cost " << candidate->cost << " loses to "
    1676                                         << found->second.candidate->cost << std::endl;
    1677                         )
    1678                         continue;
    1679                 }
    1680 
    1681                 // xxx - when do satisfyAssertions produce more than 1 result?
    1682                 // this should only happen when initial result type contains
    1683                 // unbound type parameters, then it should never be pruned by
    1684                 // the previous step, since renameTyVars guarantees the mangled name
    1685                 // is unique.
    1686                 CandidateList satisfied;
    1687                 satisfyAssertions(candidate, localSyms, satisfied, errors);
    1688 
    1689                 for (auto & newCand : satisfied) {
    1690                         // recomputes type key, if satisfyAssertions changed it
     1647        CandidateList pruneCandidates( CandidateList & candidates ) {
     1648                struct PruneStruct {
     1649                        CandidateRef candidate;
     1650                        bool ambiguous;
     1651
     1652                        PruneStruct() = default;
     1653                        PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
     1654                };
     1655
     1656                // find lowest-cost candidate for each type
     1657                std::unordered_map< std::string, PruneStruct > selected;
     1658                for ( CandidateRef & candidate : candidates ) {
     1659                        std::string mangleName;
    16911660                        {
    1692                                 ast::ptr< ast::Type > newType = newCand->expr->result;
    1693                                 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());
    1694                                 newCand->env.apply( newType );
     1661                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1662                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
     1663                                candidate->env.apply( newType );
    16951664                                mangleName = Mangle::mangle( newType );
    16961665                        }
     1666
    16971667                        auto found = selected.find( mangleName );
    16981668                        if ( found != selected.end() ) {
    1699                                 if ( newCand->cost < found->second.candidate->cost ) {
     1669                                if ( candidate->cost < found->second.candidate->cost ) {
    17001670                                        PRINT(
    1701                                                 std::cerr << "cost " << newCand->cost << " beats "
     1671                                                std::cerr << "cost " << candidate->cost << " beats "
    17021672                                                        << found->second.candidate->cost << std::endl;
    17031673                                        )
    17041674
    1705                                         found->second = PruneStruct{ newCand };
    1706                                 } else if ( newCand->cost == found->second.candidate->cost ) {
     1675                                        found->second = PruneStruct{ candidate };
     1676                                } else if ( candidate->cost == found->second.candidate->cost ) {
    17071677                                        // if one of the candidates contains a deleted identifier, can pick the other,
    17081678                                        // since deleted expressions should not be ambiguous if there is another option
    17091679                                        // that is at least as good
    1710                                         if ( findDeletedExpr( newCand->expr ) ) {
     1680                                        if ( findDeletedExpr( candidate->expr ) ) {
    17111681                                                // do nothing
    17121682                                                PRINT( std::cerr << "candidate is deleted" << std::endl; )
    17131683                                        } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
    17141684                                                PRINT( std::cerr << "current is deleted" << std::endl; )
    1715                                                 found->second = PruneStruct{ newCand };
     1685                                                found->second = PruneStruct{ candidate };
    17161686                                        } else {
    17171687                                                PRINT( std::cerr << "marking ambiguous" << std::endl; )
    17181688                                                found->second.ambiguous = true;
    17191689                                        }
    1720                                 } else {
    1721                                         // xxx - can satisfyAssertions increase the cost?
     1690                                } else {
    17221691                                        PRINT(
    1723                                                 std::cerr << "cost " << newCand->cost << " loses to "
     1692                                                std::cerr << "cost " << candidate->cost << " loses to "
    17241693                                                        << found->second.candidate->cost << std::endl;
    1725                                         )       
     1694                                        )
    17261695                                }
    17271696                        } else {
    1728                                 selected.emplace_hint( found, mangleName, newCand );
    1729                         }
    1730                 }
     1697                                selected.emplace_hint( found, mangleName, candidate );
     1698                        }
     1699                }
     1700
     1701                // report unambiguous min-cost candidates
     1702                CandidateList out;
     1703                for ( auto & target : selected ) {
     1704                        if ( target.second.ambiguous ) continue;
     1705
     1706                        CandidateRef cand = target.second.candidate;
     1707
     1708                        ast::ptr< ast::Type > newResult = cand->expr->result;
     1709                        cand->env.applyFree( newResult );
     1710                        cand->expr = ast::mutate_field(
     1711                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
     1712
     1713                        out.emplace_back( cand );
     1714                }
     1715                return out;
    17311716        }
    17321717
    1733         // report unambiguous min-cost candidates
    1734         // CandidateList out;
    1735         for ( auto & target : selected ) {
    1736                 if ( target.second.ambiguous ) continue;
    1737 
    1738                 CandidateRef cand = target.second.candidate;
    1739 
    1740                 ast::ptr< ast::Type > newResult = cand->expr->result;
    1741                 cand->env.applyFree( newResult );
    1742                 cand->expr = ast::mutate_field(
    1743                         cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1744 
    1745                 out.emplace_back( cand );
    1746         }
    1747         // if everything is lost in satisfyAssertions, report the error
    1748         return !selected.empty();
    1749 }
     1718} // anonymous namespace
    17501719
    17511720void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {
     
    17701739        }
    17711740
    1772         /*
    17731741        if ( mode.satisfyAssns || mode.prune ) {
    17741742                // trim candidates to just those where the assertions are satisfiable
     
    17931761                candidates = move( satisfied );
    17941762        }
    1795         */
    17961763
    17971764        if ( mode.prune ) {
     
    18021769                )
    18031770
    1804                 CandidateList pruned;
    1805                 std::vector<std::string> errors;
    1806                 bool found = pruneCandidates( candidates, pruned, errors );
     1771                CandidateList pruned = pruneCandidates( candidates );
    18071772
    18081773                if ( mode.failFast && pruned.empty() ) {
    18091774                        std::ostringstream stream;
    1810                         if (found) {           
    1811                                 CandidateList winners = findMinCost( candidates );
    1812                                 stream << "Cannot choose between " << winners.size() << " alternatives for "
    1813                                         "expression\n";
    1814                                 ast::print( stream, expr );
    1815                                 stream << " Alternatives are:\n";
    1816                                 print( stream, winners, 1 );
    1817                                 SemanticError( expr->location, stream.str() );
    1818                         }
    1819                         else {
    1820                                 stream << "No alternatives with satisfiable assertions for " << expr << "\n";
    1821                                 for ( const auto& err : errors ) {
    1822                                         stream << err;
    1823                                 }
    1824                                 SemanticError( expr->location, stream.str() );
    1825                         }
     1775                        CandidateList winners = findMinCost( candidates );
     1776                        stream << "Cannot choose between " << winners.size() << " alternatives for "
     1777                                "expression\n";
     1778                        ast::print( stream, expr );
     1779                        stream << " Alternatives are:\n";
     1780                        print( stream, winners, 1 );
     1781                        SemanticError( expr->location, stream.str() );
    18261782                }
    18271783
Note: See TracChangeset for help on using the changeset viewer.