Goose  Artifact [07082611d3]

Artifact 07082611d382f5891ed9bf15a255ef08fa3875c8afa64349105762525e97bd3f:

  • File bs/builtins/types/overloadset/invoke.cpp — part of check-in [51c6751b6d] at 2020-05-21 17:26:11 on branch trunk — Created a new term type to represent holes in IR expressions. The old system of representing holes using a vector of two values led to ambiguousness when creating some rule patterns: a tuple whose both type vector and payload vector were holes would be indistinguishable from a tuple containing two elements. (user: achavasse size: 2392)

#include "builtins/builtins.h"

using namespace goose::sema;

namespace goose::builtins
{
    class OverloadSetInvocationRule : public InvocationRule
    {
        public:
            Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
            {
                auto pOvlSet = *FromValue< ptr< OverloadSet > >( callee );

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

                auto rtPat = HOLE( "_"_sid );
                for( auto&& [s,ovl,uc] : pOvlSet->fullUnify( c.domain(), args.val(), rtPat, c ) )
                {
                    if( !bestSol || uc.score() > bestUC->score() )
                    {
                        bestUC = uc;
                        bestSol = s;
                        bestOvl = &ovl;
                        ambiguous = false;
                        continue;
                    }

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

                    if( bestOvl != &ovl )
                        ambiguous = true;
                }

                if( ambiguous )
                {
                    // TODO display details
                    DiagnosticsManager::GetInstance().emitErrorMessage( loc,
                        "ambiguous function call." );
                    return PoisonValue();
                }

                if( !bestSol )
                {
                    // TODO display details
                    DiagnosticsManager::GetInstance().emitErrorMessage( loc,
                        "function arguments mismatch." );
                    return PoisonValue();
                }

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

    ptr< InvocationRule >& GetOverloadSetInvocationRule()
    {
        static ptr< InvocationRule > pRule = make_shared< OverloadSetInvocationRule >();
        return pRule;
    }

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