blob: 8683ab8f86ecf7818150538ae90b11817dfb4b91 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2007 Joel de Guzman
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef PHOENIX_STATEMENT_DETAIL_SWITCH_HPP
#define PHOENIX_STATEMENT_DETAIL_SWITCH_HPP
#include <boost/spirit/home/phoenix/core/nothing.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/push_back.hpp>
#include <boost/fusion/include/push_front.hpp>
#include <boost/fusion/include/begin.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/value_of.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
namespace boost { namespace phoenix
{
template <typename Actor, typename K, K Value>
struct switch_case;
template <typename Actor>
struct default_case;
namespace detail
{
template <typename T>
struct is_default_case : mpl::bool_<T::is_default> {};
template <typename A0, typename A1>
struct compose_case_a
{
// here, A0 and A1 are both switch cases
typedef typename
mpl::if_<
is_default_case<A1>
, fusion::vector<actor<A1>, actor<A0> >
, fusion::vector<actor<A0>, actor<A1> >
>::type
type;
static type
eval(A0 const& _0, A1 const& _1, mpl::false_)
{
return type(_0, _1);
}
static type
eval(A0 const& _0, A1 const& _1, mpl::true_)
{
return type(_1, _0);
}
static type
eval(A0 const& _0, A1 const& _1)
{
return eval(_0, _1, is_default_case<A1>());
}
};
template <typename Seq, typename Case>
struct compose_case_b
{
typedef typename fusion::result_of::as_vector<
typename mpl::eval_if<
is_default_case<Case>
, fusion::result_of::push_front<Seq const, actor<Case> >
, fusion::result_of::push_back<Seq const, actor<Case> >
>::type>::type
type;
static type
eval(Seq const& seq, Case const& case_, mpl::false_)
{
return fusion::as_vector(
fusion::push_back(seq, actor<Case>(case_)));
}
static type
eval(Seq const& seq, Case const& case_, mpl::true_)
{
return fusion::as_vector(
fusion::push_front(seq, actor<Case>(case_)));
}
static type
eval(Seq const& seq, Case const& case_)
{
return eval(seq, case_, is_default_case<Case>());
}
};
template <typename Cases>
struct ensure_default
{
typedef
is_default_case<
typename fusion::result_of::value_of<
typename fusion::result_of::begin<Cases>::type
>::type
>
is_default_case_;
typedef typename
mpl::eval_if<
is_default_case_
, mpl::identity<Cases>
, fusion::result_of::push_front<
Cases const, actor<default_case<actor<null_actor> > > >
>::type
type;
static type
eval(Cases const& cases, mpl::false_);
static type
eval(Cases const& cases, mpl::true_)
{
return cases;
}
static type
eval(Cases const& cases)
{
return eval(cases, is_default_case_());
}
};
template <typename Cond, typename Cases>
struct switch_composite
{
BOOST_STATIC_ASSERT(fusion::traits::is_sequence<Cases>::value);
typedef ensure_default<Cases> ensure_default_;
typedef typename
fusion::result_of::as_vector<
typename fusion::result_of::push_front<
typename ensure_default_::type, Cond>::type
>::type
tuple_type;
typedef
composite<
detail::switch_eval<fusion::result_of::size<tuple_type>::value-2>
, tuple_type>
type;
static type
eval(Cond const& cond, Cases const& cases)
{
return fusion::as_vector(
fusion::push_front(ensure_default_::eval(cases), cond));
}
};
template <typename Cond, typename Cases>
struct switch_composite_actor
{
typedef actor<typename switch_composite<Cond, Cases>::type> type;
};
}
}}
#endif