Goose  Artifact [86a2d1f16a]

Artifact 86a2d1f16a4d8ef98faec75fb8940b85127635cd759ac0c64a0cc44b1b76ae7f:

  • File bs/builtins/types/overloadset/invoke.cpp — part of check-in [0ecc71a91f] at 2019-03-22 20:13:10 on branch trunk — Use the entire callee value to look up invocation rules rather than just their type, and restricted template invocation to constant tfunc values. (user: achavasse size: 2335)

#include "builtins/builtins.h"

using namespace empathy::sema;

namespace empathy::builtins
{
    class OverloadSetInvocationRule : public InvocationRule
    {
        public:
            virtual optional< Value > resolveInvocation( const Context& c, const Value& callee, const Value& args ) const final
            {
                const auto& env = c.env();

                auto pOvlSet = FromValue< ptr< OverloadSet > >( callee );
                assert( pOvlSet );

                UnificationContext uc( env );

                optional< UnificationContext > bestUC;
                optional< Term > bestSol;
                optional< OverloadSet::Overload > bestOvl;
                bool ambiguous = false;

                auto rtPat = sema::MkHole( "_"_sid );

                for( auto&& [s,ovl,uc] : pOvlSet->unify( args.val(), rtPat, uc ) )
                {
                    if( uc.numUnknownValues() )
                        continue;

                    auto ssol = Substitute( s, uc );
                    if( !ssol )
                        continue;

                    if( !bestSol || uc.score() > bestUC->score() )
                    {
                        bestUC = uc;
                        bestSol = ssol;
                        bestOvl = ovl;
                        ambiguous = false;
                        continue;
                    }

                    if( uc.score() < bestUC->score() )
                        continue;

                    ambiguous = true;
                }

                if( ambiguous )
                {
                    // TODO error mgmt
                    cout << "ambiguous function call.\n";
                    return nullopt;
                }

                if( !bestSol )
                {
                    // TODO error mgmt
                    cout << "function arguments mismatch.\n";
                    return nullopt;
                }

                return bestOvl->pInvRule->invoke( c, *bestOvl->callee, *bestSol, *bestUC );
            }
    };

    void SetupOverloadSetInvocationRule( Env& e )
    {
        e.invocationRuleSet()->addRule(
            ValueToIRExpr( Value(
                GetValueType< ptr< OverloadSet > >(),
                ANYTERM( ovls ) ) ),
            make_shared< OverloadSetInvocationRule >() );
    }
}