Sprout/sprout/breed/transform/when.hpp
2012-05-22 01:06:13 +09:00

126 lines
3.5 KiB
C++

#ifndef SPROUT_BREED_TRANSFORM_WHEN_HPP
#define SPROUT_BREED_TRANSFORM_WHEN_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type/type_tuple.hpp>
#include <sprout/type/iterator/deref.hpp>
#include <sprout/type/seq/algorithm/find_if.hpp>
#include <sprout/breed/breed_fwd.hpp>
#include <sprout/breed/traits.hpp>
#include <sprout/breed/transform/call.hpp>
#include <sprout/breed/transform/make.hpp>
#include <sprout/breed/transform/impl.hpp>
namespace sprout {
namespace breed {
//
// when
//
template<typename Grammar, typename PrimitiveTransform>
struct when
: public PrimitiveTransform
{
public:
typedef Grammar first;
typedef PrimitiveTransform second;
typedef typename Grammar::breed_grammar breed_grammar;
};
template<typename Grammar, typename Fun>
struct when<Grammar, Fun*>
: public sprout::breed::when<Grammar, Fun>
{};
template<typename Grammar>
struct when<Grammar, sprout::breed::external_transform>
: public sprout::breed::transform<when<Grammar, sprout::breed::external_transform> >
{
public:
typedef Grammar first;
typedef external_transform second;
typedef typename Grammar::breed_grammar breed_grammar;
public:
template<typename Expr, typename State, typename Data>
struct impl
: public Data::template when<Grammar>::template impl<Expr, State, Data>
{};
template<typename Expr, typename State, typename Data>
struct impl<Expr, State, Data&>
: public Data::template when<Grammar>::template impl<Expr, State, Data&>
{};
};
template<typename Grammar, typename R, typename... Args>
struct when<Grammar, R(Args...)>
: public sprout::breed::transform<when<Grammar, R(Args...)> >
{
public:
typedef Grammar first;
typedef R second(Args...);
typedef typename Grammar::breed_grammar breed_grammar;
public:
template<typename Expr, typename State, typename Data>
struct impl
: public sprout::breed::transform_impl<Expr, State, Data>
{
public:
typedef typename std::conditional<
sprout::breed::is_callable<R>::value,
sprout::breed::call<R(Args...)>,
sprout::breed::make<R(Args...)>
>::type which;
typedef typename which::template impl<Expr, State, Data>::result_type result_type;
public:
SPROUT_CONSTEXPR result_type operator()(
typename impl::expr_param e,
typename impl::state_param s,
typename impl::data_param d
) const
{
return typename which::template impl<Expr, State, Data>()(e, s, d);
}
};
};
//
// is_callable
//
template<typename Grammar, typename Transform>
struct is_callable<sprout::breed::when<Grammar, Transform> >
: public std::true_type
{};
//
// otherwise
//
template<typename Fun>
struct otherwise
: public sprout::breed::when<sprout::breed::_, Fun>
{};
//
// external_transforms
//
template<typename... Args>
struct external_transforms {
public:
typedef sprout::types::type_tuple<Args...> map_type;
private:
template<typename Rule>
struct map_pred {
public:
template<typename T>
struct apply
: public std::is_same<Rule, typename T::first>
{};
};
public:
template<typename Rule>
struct when
: public sprout::breed::when<
sprout::breed::_,
sprout::types::deref<
typename sprout::types::find_if<map_type, map_pred<Rule> >::type
>::type
>
{};
};
} // namespace breed
} // namespace sprout
#endif // #ifndef SPROUT_BREED_TRANSFORM_WHEN_HPP