#include "sema.h"
namespace goose::sema
{
Term WrapWithPostprocFunc( const Term& t, const ptr< PostProcFunc >& pp )
{
return SetComplexity( VEC( TSID( postproc ),
TERM( static_pointer_cast< void >( pp ) ),
t ), 0 );
}
Term WrapWithPostprocFunc( const Term& t, PostProcFunc&& pp )
{
return SetComplexity( VEC( TSID( postproc ),
TERM( static_pointer_cast< void >( make_shared< PostProcFunc >( move( pp ) ) ) ),
t ), 0 );
}
optional< pair< Term, ptr< PostProcFunc > > > UnwrapPostprocFunc( const Term& ppt )
{
auto result = Decompose( ppt,
Vec(
Lit( "postproc"_sid ),
Val< ptr< void > >(),
SubTerm()
)
);
if( !result )
return nullopt;
auto&& [pPP, t] = *result;
return make_pair( t, static_pointer_cast< PostProcFunc >( pPP ) );
}
optional< Term > Postprocess( const Term& src, TypeCheckingContext& tcc )
{
if( auto optHole = HoleFromIRExpr( src ) )
{
const auto& hole = *optHole;
if( !hole.name.isNumerical() )
{
// If the name is not found, output it as is.
auto index = tcc.getLHSHoleIndex( hole.name );
if( index == TypeCheckingContext::InvalidIndex )
return src;
const auto& val = tcc.getValue( index );
if( !val )
return src;
return Postprocess( *val, tcc );
}
else
{
const auto& optVal = tcc.getValue( hole.name.id() );
if( !optVal )
return HOLE( "_"_sid );
return Postprocess( *optVal, tcc );
}
}
if( !holds_alternative< pvec >( src ) )
return src;
if( auto optPP = UnwrapPostprocFunc( src ) )
{
auto val = Postprocess( optPP->first, tcc );
if( !val )
return nullopt;
return ( *optPP->second )( *val, tcc );
}
const auto& vec = *get< pvec >( src );
auto outputTerms = make_shared< Vector >();
outputTerms->reserve( vec.terms().size() );
for( auto&& t : vec.terms() )
{
auto newT = Postprocess( t, tcc );
if( !newT )
return nullopt;
outputTerms->append( move( *newT ) );
}
return outputTerms;
}
}