#include "builtins/builtins.h"
using namespace empathy::builtins;
bool OverloadSet::add( const Env& e, const Value& callee )
{
auto pInvRule = GetInvocationRule( e, callee );
assert( 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::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&& [uniParamsVec,rtTrie,uc] : paramUTrie->unify( *argDecomp->get(), uc ) )
{
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 };
}
}
}
}
}
}