#include "builtins/builtins.h"
using namespace empathy::sema;
namespace empathy::builtins
{
class OverloadSetInvocationRule : public InvocationRule
{
public:
optional< Value > resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Value& args ) const final
{
auto pOvlSet = *FromValue< ptr< OverloadSet > >( callee );
UnificationContext uc( c );
optional< UnificationContext > bestUC;
optional< Term > bestSol;
const OverloadSet::Overload* bestOvl = nullptr;
bool ambiguous = false;
auto rtPat = MkHole( "_"_sid );
for( auto&& [s,ovl,uc] : pOvlSet->fullUnify( c.domain(), args.val(), rtPat, uc ) )
{
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 nullopt;
}
if( !bestSol )
{
// TODO display details
DiagnosticsManager::GetInstance().emitErrorMessage( loc,
"function arguments mismatch." );
return nullopt;
}
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() );
}
}