#ifndef EMPATHY_IR_ENUMERATE_INL
#define EMPATHY_IR_ENUMERATE_INL
namespace empathy::ir
{
//--------------------------------------------------------------------------------------------
// Primitive types
//--------------------------------------------------------------------------------------------
template< typename T, typename U >
static Generator< pair< Term, const U& > > Enumerate( const ValueTrieNode< T, U >& trie )
{
for( auto&& [k,v] : trie.m_branches )
co_yield { TERM( k ), v };
}
//--------------------------------------------------------------------------------------------
// Containers
//--------------------------------------------------------------------------------------------
template< typename U >
static Generator< pair< Term, const U& > > Enumerate( Vector&& vec, const TrieContainerBranch_t& contBranch )
{
if( contBranch.index() == 0 )
{
for( auto&& [t, payload] : Enumerate( get< 0 >( contBranch )->m_trie ) )
{
auto newVec = Vector::MakeAppend( vec, t );
co_yield Enumerate< U >( move( newVec ), payload );
}
}
else
co_yield { TERM( make_shared< Vector >( move( vec ) ) ), *any_cast< U >( &get< 1 >( contBranch ) ) };
}
template< typename U >
static Generator< pair< Term, const U& > > Enumerate( const TrieNode< pvec, U >& trie )
{
for( auto&& [k, branch] : trie.m_fixedLengthBranches )
co_yield Enumerate< U >( Vector(), branch );
using rpt_node = ptr< TrieContainerRepetitionNode< U > >;
for( auto&& [k, branch] : trie.m_variableLengthBranches )
{
for( auto&& [vecTerm, pRptNode] : Enumerate< rpt_node >( Vector(), branch ) )
{
for( auto&& [repetitionTerm, payload] : Enumerate< U >( pRptNode->m_repetition ) )
{
auto pNewVec = make_shared< Vector >( *get< pvec >( vecTerm.content() ) );
pNewVec->setRepetitionTerm( move( repetitionTerm ) );
co_yield { TERM( move( pNewVec ) ), payload };
}
}
}
}
//--------------------------------------------------------------------------------------------
// Terms
//--------------------------------------------------------------------------------------------
template< size_t I, typename U >
static Generator< pair< Term, const U& > > Enumerate( const Trie< U >& trie )
{
if( const auto& ptr = get< I >( trie.branches() ) )
co_yield Enumerate( *ptr );
if constexpr( ( I + 1 ) < tuple_size_v< typename Trie< U >::BranchesTuple > )
co_yield Enumerate< I + 1 >( trie );
}
template< typename U >
static Generator< pair< Term, const U& > > Enumerate( const Trie< U >& trie )
{
return Enumerate< 0 >( trie );
}
}
#endif