#include "sema.h"
namespace goose::sema
{
ptr< TemplateRule > GetTemplateRuleSet( const Context& c, const Term& tpl )
{
const auto& rules = c.env()->templateRuleSet()->rules();
MatchScore bestScore;
ptr< TemplateRule > pBestRule;
bool ambiguous = false;
for( auto&& [s, rule] : Match( tpl, rules ) )
{
auto score = s.score();
if( !pBestRule || score > bestScore )
{
bestScore = score;
pBestRule = rule;
ambiguous = false;
continue;
}
if( score < bestScore )
continue;
ambiguous = true;
}
if( ambiguous )
G_ERROR( "ambiguous template rule" );
return pBestRule;
}
bool PrepareTemplate( TemplateContext& c, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c.semaContext(), tpl );
if( !pTemplateRuleSet )
return true;
return pTemplateRuleSet->prepare( c, tpl );
}
optional< Term > BuildTemplateSignature( const TemplateContext& c, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c.semaContext(), tpl );
if( !pTemplateRuleSet )
return nullopt;
return pTemplateRuleSet->buildSignature( c, tpl );
}
Generator< Value > BuildTemplateParamDecls( const Context& c, const Term& tpl, TermGen& args )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c, tpl );
if( !pTemplateRuleSet )
co_return;
co_yield pTemplateRuleSet->buildParamDecls( c, tpl, args );
}
void TemplateSetup( const Context& c, TypeCheckingContext& tcc, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c, tpl );
if( !pTemplateRuleSet )
return;
pTemplateRuleSet->setup( c, tcc, tpl );
}
uint64_t TemplateHashTypePredicates( const Context& c, const TypeCheckingContext& tcc, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c, tpl );
if( !pTemplateRuleSet )
return 0;
return pTemplateRuleSet->hashTypePredicates( c, tcc, tpl );
}
extern optional< Term > BuildTemplateArgPattern( const Context& c, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c, tpl );
if( !pTemplateRuleSet )
return nullopt;
return pTemplateRuleSet->buildArgPattern( c, tpl );
}
extern bool IsTemplatePackExpr( const Context& c, const Term& tpl )
{
const auto pTemplateRuleSet = GetTemplateRuleSet( c, tpl );
if( !pTemplateRuleSet )
return false;
return pTemplateRuleSet->isPackExpr( c, tpl );
}
}