#ifndef EMPATHY_IR_DECOMPOSE_H
#define EMPATHY_IR_DECOMPOSE_H
namespace empathy::ir
{
template< typename T >
struct LiteralSpec
{
using type = T;
template< typename TT >
LiteralSpec( TT&& val ) : m_val( forward< TT >( val ) )
{}
T m_val;
};
template< typename T >
auto Lit( T&& val );
template< typename T >
struct Val
{
using type = T;
};
template< typename T >
struct IsLiteralSpec : public false_type
{};
template< typename T >
struct IsLiteralSpec< LiteralSpec< T > > : public true_type
{};
template< typename... T >
struct VecDecompositionReturnTypeBuilder
{};
template< typename... TU >
struct VecDecompositionReturnTypeBuilder< tuple< TU... > >
{
using type = tuple< TU... >;
};
template< typename... TU, typename HS, typename... TS >
struct VecDecompositionReturnTypeBuilder< tuple< TU... >, HS, TS... >
{
using type = conditional_t< IsLiteralSpec< HS >::value,
typename VecDecompositionReturnTypeBuilder< tuple< TU... >, TS... >::type,
typename VecDecompositionReturnTypeBuilder< tuple< TU..., typename HS::type >, TS... >::type
>;
};
template< typename... S >
struct VectorSpec
{
using type = typename VecDecompositionReturnTypeBuilder< tuple<>, S... >::type;
template< typename... T >
VectorSpec( T&&... specs ) :
m_specs( forward< T >( specs )... )
{}
tuple< S... > m_specs;
};
template< typename... S >
auto Vec( S&&... specs );
template< typename T >
bool Decompose( const Term& t, const LiteralSpec< T >& spec );
template< typename T >
optional< reference_wrapper< const T > > Decompose( const Term& t, const Val< T >& spec );
template< typename... S >
optional< typename VectorSpec< S... >::type > Decompose( const Term& t, const VectorSpec< S... >& spec );
}
#endif