#include "builtins/builtins.h"
using namespace empathy::sema;
namespace empathy::builtins
{
class FunctionInvocationRule : public InvocationRule
{
public:
virtual optional< Value > resolveInvocation( const ptr< Env >& env, const Value& callee, const Value& args ) const override
{
PerformLazyFuncParsing( env, callee );
UnificationContext uc( env );
optional< UnificationContext > bestUC;
optional< Term > bestSol;
bool ambiguous = false;
auto&& [sig, rtype] = getSignatureAndRType( env, callee );
for( auto&& [s, uc] : Unify( sig, args.val(), uc ) )
{
if( !bestSol || uc.score() > bestUC->score() )
{
bestUC = uc;
bestSol = s;
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;
}
auto unifiedArgs = Substitute( *bestSol, *bestUC );
return Value( rtype, make_shared< llr::Element >( llr::Call( callee, unifiedArgs ) ) );
}
virtual Term getSignature( const ptr< Env >& env, const Value& callee ) const override
{
return getSignatureAndRType( env, callee ).first;
}
private:
pair< Term, Term > getSignatureAndRType( const ptr< Env >& env, const Value& callee ) const
{
// Extract the signature from the type
auto valType = ValueFromIRExpr( callee.type() );
assert( valType );
auto decomp = Decompose( valType->val(),
Vec(
Lit( "func"_sid ),
SubTerm(), // kind
SubTerm(), // return type
SubTerm(), // param types
SubTerm() // signature
)
);
assert( decomp );
auto&& [kind, rtype, ptypes, sig] = *decomp;
return { sig, rtype };
}
};
void SetupFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( Value( TSID( type ), TVEC( TSID( func ),
ANYTERM( k ), ANYTERM( rt ), ANYTERM( p ), ANYTERM( sig ) ) ) ),
make_shared< FunctionInvocationRule >() );
}
}