#include "builtins/builtins.h"
#include "common.h"
using namespace goose::sema;
namespace goose::builtins
{
class RegularFuncInvocationRule : public BaseFuncInvocationRule
{
public:
Value invoke( Context& c, LocationId loc, const Value& callee, const Term& args,
const Term& typeCheckedCallPat, TypeCheckingContext& tcc ) const final
{
auto preparedCallee = prepareFunc( c, 0, callee, typeCheckedCallPat, tcc );
if( preparedCallee.isPoison() )
return PoisonValue();
auto callDecomp = Decompose( typeCheckedCallPat, Val< pvec >() );
const auto& typeCheckedRType = callDecomp->get()->terms().front();
auto typeCheckedArgs = DropVectorTerm( typeCheckedCallPat, 1 );
preparedCallee.setLocationId( loc );
auto argList = BuildArgListForCall( c, preparedCallee, typeCheckedArgs );
if( !argList )
return PoisonValue();
auto argsInstrSeq = BuildArgsInstrSeq( *argList );
auto argCount = VecSize( *argList );
auto result = BuildComputedValue(
typeCheckedRType, argsInstrSeq, preparedCallee, cir::Call( argCount, loc ) )
.setLocationId( loc );
if( IsExternalFunc( callee ) )
{
// No dependency handling or eager evaluation on external funcs,
// so we're done.
return result;
}
bool comptime = false;
// If we are part of call chain involving a comptime function, we need the call to be
// comptime as well.
for( auto&& fi : Func::FuncStack() | views::reverse )
{
if( fi.kind == FuncType::Kind::Comptime )
{
comptime = true;
break;
}
}
if( !comptime )
return result;
if( HaveUnmetDependencies( preparedCallee ) || !EvaluateComptimeCall( c, result ) )
{
DiagnosticsManager::GetInstance().emitErrorMessage(
loc, "this call couldn't be evaluated at compilation time." );
return PoisonValue();
}
return result;
}
Value prepareFunc( const Context& c, LocationId funcValLocation, const Value& callee,
const Term& typeCheckedCallPat, TypeCheckingContext& tcc ) const final
{
// 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 );
}
};
void SetupRegularFuncInvocationRule( Env& e )
{
e.invocationRuleSet()->addRule( ValueToEIR( ValuePattern( ANYTERM( _ ),
ValueToEIR( Value( TypeType(),
VEC( TSID( func ), ANYTERM( _ ), ANYTERM( _ ),
ANYTERM( _ ), ANYTERM( _ ), ANYTERM( _ ) ) ) ),
ANYTERM( _ ) ) ),
make_shared< RegularFuncInvocationRule >() );
}
} // namespace goose::builtins