Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/iris/x4/operator/alternative.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace iris::x4 {
template<class Left, class Right>
struct alternative : binary_parser<Left, Right, alternative<Left, Right>>
{
using attribute_type = traits::attribute_of_binary<iris::rvariant, alternative, Left, Right>::type;
using attribute_type = traits::attribute_of_binary<iris::rvariant, Left, Right>::type;

using binary_parser<Left, Right, alternative>::binary_parser;

Expand Down
2 changes: 1 addition & 1 deletion include/iris/x4/operator/sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace iris::x4 {
template<class Left, class Right>
struct sequence : binary_parser<Left, Right, sequence<Left, Right>>
{
using attribute_type = traits::attribute_of_binary<alloy::tuple, x4::sequence, Left, Right>::type;
using attribute_type = traits::attribute_of_binary<alloy::tuple, Left, Right>::type;

static constexpr std::size_t sequence_size =
parser_traits<Left>::sequence_size + parser_traits<Right>::sequence_size;
Expand Down
107 changes: 64 additions & 43 deletions include/iris/x4/traits/attribute_of_binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,81 +16,102 @@
#include <iris/x4/core/unused.hpp>
#include <iris/x4/core/parser_traits.hpp>

#include <iris/type_traits.hpp> // TODO: move iris::type_list to separate header

#include <type_traits>

namespace iris::x4::traits {

namespace detail {

template<class... Ts>
struct type_sequence
{
using type = type_sequence;

static constexpr std::size_t size = sizeof...(Ts);

template<class... Us>
using prepend = type_sequence<Us..., Ts...>;
template<class TypeList, class... Us>
struct append_to_type_list {};

template<class U>
using extend = U::template prepend<Ts...>;
template<class TypeList, class... Us>
using append_to_type_list_t = append_to_type_list<TypeList, Us...>::type;

template<template<class...> class U>
using transfer_to = U<Ts...>;
template<class... Ts>
struct append_to_type_list<type_list<Ts...>>
{
using type = type_list<Ts...>;
};

template<X4Attribute Attr>
struct types_of_binary_init : type_sequence<Attr>
template<class... Ts, class... Us>
struct append_to_type_list<type_list<Ts...>, unused_type, Us...>
: append_to_type_list<type_list<Ts...>, Us...>
{};

template<>
struct types_of_binary_init<unused_type> : type_sequence<>
template<class... Ts, class U, class... Us>
struct append_to_type_list<type_list<Ts...>, U, Us...>
: append_to_type_list<type_list<Ts..., U>, Us...>
{};

template<>
struct types_of_binary_init<unused_type const> : type_sequence<>
template<class... Ts, class... Us, class... Vs>
struct append_to_type_list<type_list<Ts...>, type_list<Us...>, Vs...>
: append_to_type_list<append_to_type_list_t<type_list<Ts...>, Us...>, Vs...>
{};

template<template<class, class> class BinaryParserTT, class ParserT>
struct get_types_of_binary
: types_of_binary_init<typename parser_traits<ParserT>::attribute_type> // TODO: unwrap
{};
template<template<class...> class TupleTT, class T>
struct tuple_to_type_list;

template<template<class, class> class BinaryParserTT, class Left, class Right>
struct get_types_of_binary<BinaryParserTT, BinaryParserTT<Left, Right>>
: get_types_of_binary<BinaryParserTT, Left>::template extend<get_types_of_binary<BinaryParserTT, Right>>
{};
template<template<class...> class TupleTT, class T>
using tuple_to_type_list_t = tuple_to_type_list<TupleTT, T>::type;

template<template<class...> class AttrTT, class T, std::size_t = T::size>
struct type_sequence_to_attribute
template<template<class...> class TupleTT, class T>
struct tuple_to_type_list
{
using type = typename T::template transfer_to<AttrTT>;
using type = T;
};

template<template<class...> class AttrTT, class T>
struct type_sequence_to_attribute<AttrTT, T, 1>
: T::template transfer_to<std::type_identity>
{};
template<template<class...> class TupleTT, class... Ts>
struct tuple_to_type_list<TupleTT, TupleTT<Ts...>>
{
using type = type_list<tuple_to_type_list_t<TupleTT, Ts>...>;
};

template<template<class...> class TupleTT, class T>
using tuple_to_type_list_t = tuple_to_type_list<TupleTT, T>::type;

template<template<class...> class TupleTT, class TypeList>
struct type_list_to_tuple {};

template<template<class...> class AttrTT, class T>
struct type_sequence_to_attribute<AttrTT, T, 0>
template<template<class...> class TupleTT>
struct type_list_to_tuple<TupleTT, type_list<>>
{
using type = unused_type;
};

template<template<class...> class TupleTT, class T>
struct type_list_to_tuple<TupleTT, type_list<T>>
{
using type = T;
};

template<template<class...> class TupleTT, class T0, class T1, class... Ts>
struct type_list_to_tuple<TupleTT, type_list<T0, T1, Ts...>>
{
using type = TupleTT<T0, T1, Ts...>;
};

template<template<class...> class TupleTT, class TypeList>
using type_list_to_tuple_t = type_list_to_tuple<TupleTT, TypeList>::type;

} // detail

template<
template<class...> class AttrTT,
template<class, class> class BinaryParserTT,
class Left, class Right
template<class...> class TupleTT,
class LeftParser, class RightParser
>
struct attribute_of_binary
{
using type = detail::type_sequence_to_attribute<
AttrTT,
typename detail::get_types_of_binary<BinaryParserTT, BinaryParserTT<Left, Right>>::type
>::type;
using type = detail::type_list_to_tuple_t<
TupleTT,
detail::append_to_type_list_t<
type_list<>,
detail::tuple_to_type_list_t<TupleTT, typename parser_traits<LeftParser>::attribute_type>,
detail::tuple_to_type_list_t<TupleTT, typename parser_traits<RightParser>::attribute_type>
>
>;
};

} // iris::x4::traits
Expand Down