Goose  Artifact [75af8d3b1e]

Artifact 75af8d3b1ee5a3264b4ce12a99dee889a1e7c603861590f7f87ed33f6cbcc4b5:

  • File bs/sema/overloadset.cpp — part of check-in [2efa23555d] at 2019-08-11 01:26:17 on branch trunk —
    • ir: created a new type for LocationId which is handled in a specific way so that two LocationIds are always considered equal by pattern matching. This prevent the values' locationIds stored in ir expressions from fucking up everything.
    • propagate value locations in a few places: in the parser, when resolving invocations and when doing eager evaluation. There are probably a lot of other places still missing.
    • converted all the builtin statements to use the DiagnosticsManager.
    (user: achavasse size: 3816)

#include "builtins/builtins.h"

using namespace empathy::sema;

bool OverloadSet::add( const Env& e, const Value& callee )
{
    auto pInvRule = GetInvocationRule( e, callee );
    assert( pInvRule );
    return add( e, callee, pInvRule );
}

bool OverloadSet::add( const Env& e, const Value& callee, const ptr< InvocationRule >& pInvRule )
{
    auto signature = pInvRule->getSignature( callee );
    assert( signature );

    auto result = Decompose( *signature,
        Vec(
            SubTerm(),
            Val< pvec >(),
            SubTerm()
        )
    );

    assert( result );

    auto&& [domain, p, rt] = *result;
    const auto& rtype = rt;
    const auto& params = p;

    bool success = false;
    m_trie = Merge( m_trie, domain, [&]< class UT >( const ptr< UT >& paramUTrie )
    {
        auto uTrieMergeFunc = [&]( auto&& rtTrie )
        {
            return Merge( rtTrie, rtype, [&]( auto&& previous ) -> Overload
            {
                if( previous.callee )
                    return move( previous );

                success = true;
                return { pInvRule, callee };
            } );
        };

        if( !paramUTrie )
            return UT().merge( *params, uTrieMergeFunc );

        return paramUTrie->merge( *params, uTrieMergeFunc );
    } );

    return success;
}

OverloadSet::UniGen OverloadSet::fullUnify( const Term& domPat, const Term& argsPat, const Term& rtPat, UnificationContext& uc ) const
{
    auto argDecomp = Decompose( argsPat,
        Val< pvec >()
    );

    if( !argDecomp )
        co_return;

    for( auto&& [domain,paramUTrie] : Enumerate( m_trie ) )
    {
        auto localC = uc;
        for( auto&& [uniDom,uc] : Unify( domain, domPat, localC ) )
        {
            for( auto&& [paramsVec,uniParamsVec,rtTrie,uc] : paramUTrie->unify( *argDecomp->get(), uc ) )
            {
                auto params = TERM( make_shared< Vector >( paramsVec ) );
                auto uniParams = TERM( make_shared< Vector >( uniParamsVec ) );

                for( auto&& [rt,ovl] : Enumerate( rtTrie ) )
                {
                    auto localC = uc;
                    for( auto&& [uniRt,uc] : Unify( rt, rtPat, localC ) )
                    {
                        auto lhs = TERM( Vector::Make( domain, params, rt ) );
                        auto rhs = TERM( Vector::Make( domPat, argsPat, rtPat ) );
                        auto uniCall = TERM( Vector::Make( uniDom, uniParams, uniRt ) );

                        for( auto&& [s, uc] : UnifyPass2( lhs, rhs, uniCall, uc ) )
                            co_yield { s, ovl, uc };
                    }
                }
            }
        }
    }
}

OverloadSet::UniGen OverloadSet::unify( const Term& domPat, const Term& argsPat, const Term& rtPat, UnificationContext& uc ) const
{
    auto argDecomp = Decompose( argsPat,
        Val< pvec >()
    );

    if( !argDecomp )
        co_return;

    for( auto&& [domain,paramUTrie] : Enumerate( m_trie ) )
    {
        auto localC = uc;
        for( auto&& [uniDom,uc] : Unify( domain, domPat, localC ) )
        {
            for( auto&& [paramsVec,uniParamsVec,rtTrie,uc] : paramUTrie->unify( *argDecomp->get(), uc ) )
            {
                auto params = TERM( make_shared< Vector >( paramsVec ) );
                auto uniParams = TERM( make_shared< Vector >( uniParamsVec ) );
                for( auto&& [rt,ovl] : Enumerate( rtTrie ) )
                {
                    auto localC = uc;
                    for( auto&& [uniRt,uc] : Unify( rt, rtPat, localC ) )
                    {
                        auto uniCall = TERM( Vector::Make( uniDom, uniParams, uniRt ) );
                        co_yield { move( uniCall ), ovl, uc };
                    }
                }
            }
        }
    }
}