#ifndef EMPATHY_SEMA_UTRIE_UNI_INL
#define EMPATHY_SEMA_UTRIE_UNI_INL
namespace empathy::sema
{
template< typename U > typename UTrie< U >::template UniGen< U >
UTrie< U >::UnifyRepetition( VecGenerator vgen, const Vector& solutionVec, const RepetitionNode& rptNode, UnificationContext& c )
{
if( vgen.finished() )
co_yield { solutionVec, rptNode.m_next, c };
else
{
const auto& vt = vgen();
for( auto&& rt : Enumerate( rptNode.m_repetition ) )
{
auto localC = c;
for( auto&& [s,c] : sema::Unify( rt, vt, localC ) )
co_yield UnifyRepetition( vgen, Vector::MakeAppend( solutionVec, move( s ) ), rptNode, c );
}
}
}
template< typename U > template< typename T > Generator< tuple< Vector, const T&, UnificationContext, VecGenerator > >
UTrie< U >::Unify( VecGenerator vgen, const Vector& solutionVec, const branch_t& branch, UnificationContext& c )
{
if( branch.index() == 0 )
{
const auto& vt = vgen();
for( auto&& [t, payload] : Enumerate( get< 0 >( branch )->m_trie ) )
{
auto localC = c;
for( auto&& [s, c] : sema::Unify( t, vt, localC ) )
co_yield Unify< T >( vgen, Vector::MakeAppend( solutionVec, move( s ) ), payload, c );
}
}
else
co_yield { solutionVec, any_cast< T >( get< 1 >( branch ) ), c, vgen };
}
template< typename U >
typename UTrie< U >::template UniGen< U > UTrie< U >::unify( const Vector& rhs, UnificationContext& c ) const
{
auto exprLen = rhs.length();
c.incComplexity( 2 );
auto it = m_fixedLengthBranches.find( exprLen.minLength() );
if( it != m_fixedLengthBranches.end() )
{
VecGenerator vgen( rhs );
Vector sol;
for( auto&& [s, content, c, g] : Unify< U >( vgen, sol, it->second, c ) )
co_yield { s, content, c };
}
using rpt_node = ptr< RepetitionNode >;
it = m_variableLengthBranches.begin();
auto end = m_variableLengthBranches.upper_bound( exprLen.minLength() );
while( it != end )
{
VecGenerator vgen( rhs );
Vector sol;
for( auto&& [s, pRptNode, c, g] : Unify< rpt_node >( vgen, sol, it->second, c ) )
co_yield UnifyRepetition( g, sol, *pRptNode, c );
++it;
}
}
template< typename U > template< typename T > typename UTrie< U >::template UniGen< T >
UTrie< U >::HalfUnify( const Vector& solutionVec, const branch_t& branch, UnificationContext& c )
{
if( branch.index() == 0 )
{
for( auto&& [t, payload] : Enumerate( get< 0 >( branch )->m_trie ) )
{
auto localC = c;
for( auto&& [s, c] : sema::HalfUnify( t, localC ) )
co_yield HalfUnify< T >( Vector::MakeAppend( solutionVec, move( s ) ), payload, c );
}
}
else
co_yield { solutionVec, any_cast< T >( get< 1 >( branch ) ), c };
}
template< typename U >
typename UTrie< U >::template UniGen< U > UTrie< U >::halfUnify( UnificationContext& c ) const
{
c.incComplexity();
for( auto&& [len, branch] : m_fixedLengthBranches )
{
Vector sol;
for( auto&& [s, content, c] : HalfUnify< U >( sol, branch, c ) )
co_yield { s, content, c };
}
using rpt_node = ptr< TrieContainerRepetitionNode< U > >;
for( auto&& [minLen, branch] : m_variableLengthBranches )
{
Vector sol;
for( auto&& [s, pRptNode, c] : HalfUnify< rpt_node >( sol, branch, c ) )
{
for( auto&& [rt, payload] : Enumerate( pRptNode->m_repetition ) )
{
for( auto&& [s, c] : sema::HalfUnify( rt, c ) )
{
auto localSol = sol;
localSol.setRepetitionTerm( move( s ) );
co_yield { localSol, payload, c };
}
}
}
}
}
}
#endif