#include "builtins/builtins.h"
using namespace goose::sema;
namespace goose::builtins
{
class FunctionInvocationRule : public InvocationRule
{
public:
Value resolveInvocation( const Context& c, uint32_t loc, const Value& callee, const Term& args ) const final
{
optional< TypeCheckingContext > bestTCC;
optional< Term > bestSol;
bool ambiguous = false;
auto sig = GetFuncSig( callee );
auto callPat = VEC( args, HOLE( "_"_sid ) );
auto us = FindBestTyping( sig, callPat, c );
if( holds_alternative< NoUnification >( us ) )
{
// TODO display details
DiagnosticsManager::GetInstance().emitErrorMessage( loc,
"function arguments mismatch." );
return PoisonValue();
}
if( holds_alternative< AmbiguousTypeCheck >( us ) )
{
// TODO display details
DiagnosticsManager::GetInstance().emitErrorMessage( loc,
"ambiguous function call." );
return PoisonValue();
}
auto&& [s,tcc] = get< TCSol >( us );
return invoke( c, loc, callee, args, s, tcc );
}
Value invoke( const Context& c, uint32_t loc, const Value& callee, const Term& args, const Term& unifiedCallPat, TypeCheckingContext& tcc ) const final
{
auto newCallee = prepareFunc( c, 0, callee, unifiedCallPat, tcc );
if( newCallee.isPoison() )
return PoisonValue();
auto callDecomp = Decompose( unifiedCallPat,
Vec(
SubTerm(), // args
SubTerm() // return type
)
);
auto&& [unifiedArgs, unifiedRType] = *callDecomp;
newCallee.setLocationId( loc );
if( IsBuiltinFunc( newCallee ) )
return BuildComputedValue( unifiedRType, cir::Call( newCallee, unifiedArgs ) );
if( IsIntrinsicFunc( newCallee ) )
return GetBuiltinIntrinsicFuncWrapper( newCallee )( c, unifiedArgs );
auto ft = *FromValue< FuncType >( *ValueFromIRExpr( newCallee.type() ) );
auto argList = BuildArgListForCall( ft, unifiedArgs );
return BuildComputedValue( unifiedRType, cir::Call( newCallee, argList ) );
}
optional< Term > getSignature( const Value& callee ) const final
{
return GetFuncSig( callee );
}
Value prepareFunc( const Context& c, uint32_t funcValLocation, const Value& callee, const Term& unifiedCallPat, TypeCheckingContext& tcc ) const final
{
if( IsBuiltinFunc( callee ) || IsIntrinsicFunc( callee ) )
return callee;
// TODO better description with the function's name if possible (we may need to explicitely store it in the func)
DiagnosticsContext dc( 0, true );
VerbosityContext vc( Verbosity::Normal, true );
return CompileFunc( c, callee );
}
};
ptr< InvocationRule >& GetFuncInvocationRule()
{
static ptr< InvocationRule > pRule = make_shared< FunctionInvocationRule >();
return pRule;
}
void SetupFunctionInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule(
ValueToIRExpr( ValuePattern( ANYTERM( _ ),
ValueToIRExpr( Value( TypeType(), VEC( TSID( func ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ),
ANYTERM( _ ), ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
GetFuncInvocationRule() );
}
}