#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;
if( !bestSol || uc.score() > bestUC->score() )
{
bestUC = uc;
bestSol = s;
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( GetValueType< ptr< OverloadSet > >(),
make_shared< OverloadSetInvocationRule >() );
}
}