#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 Term& args ) const final
{
auto pOvlSet = *FromValue< ptr< OverloadSet > >( callee );
optional< TypeCheckingContext > bestTCC;
optional< Term > bestSol;
const OverloadSet::Overload* bestOvl = nullptr;
bool ambiguous = false;
auto rtPat = HOLE( "_"_sid );
TypeCheckingContext tcc( c );
for( auto&& [s,ovl,tcc] : pOvlSet->typeCheck( args, rtPat, tcc ) )
{
if( tcc.numUnknownValues() )
continue;
if( bestTCC && tcc.score() < bestTCC->score() )
continue;
auto pps = Postprocess( s, tcc );
if( !pps )
continue;
if( bestTCC && tcc.score() == bestTCC->score() )
{
ambiguous = true;
continue;
}
bestTCC = tcc;
bestSol = move( *pps );
bestOvl = &ovl;
ambiguous = false;
}
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, args, *bestSol, *bestTCC );
}
};
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() );
}
}