blob: 111b79b93888a99268a476746d86d97e67e77253 [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_SWITCH_HPP
#define PHOENIX_STATEMENT_SWITCH_HPP
#include <boost/spirit/home/phoenix/core/composite.hpp>
#include <boost/spirit/home/phoenix/core/compose.hpp>
#include <boost/spirit/home/phoenix/core/nothing.hpp>
#include <boost/spirit/home/phoenix/statement/detail/switch_eval.hpp>
#include <boost/spirit/home/phoenix/statement/detail/switch.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/not.hpp>
namespace boost { namespace phoenix
{
template <typename Derived, typename Actor>
struct switch_case_base
{
typedef Derived derived_t;
typedef Actor actor_t;
typedef typename Actor::no_nullary no_nullary;
template <typename Env>
struct result
{
typedef typename Actor::eval_type::template result<Env>::type type;
};
switch_case_base(Actor const& actor)
: actor(actor) {}
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return actor.eval(env);
}
Actor actor;
};
template <typename Actor, typename K, K Value>
struct switch_case : switch_case_base<switch_case<Actor, K, Value>, Actor>
{
typedef switch_case_base<switch_case<Actor, K, Value>, Actor> base_t;
static K const value = Value;
static bool const is_default = false;
switch_case(Actor const& actor)
: base_t(actor) {}
};
template <typename Actor>
struct default_case : switch_case_base<default_case<Actor>, Actor>
{
typedef switch_case_base<default_case<Actor>, Actor> base_t;
static bool const is_default = true;
default_case(Actor const& actor)
: base_t(actor) {}
};
template <typename Cond>
struct switch_gen
{
switch_gen(Cond const& cond)
: cond(cond) {}
template <typename Cases>
typename lazy_enable_if<
fusion::traits::is_sequence<Cases>
, detail::switch_composite_actor<Cond, Cases>
>::type
operator[](Cases const& cases) const
{
typedef typename
detail::switch_composite<Cond, Cases>
switch_composite;
return switch_composite::eval(cond, cases);
}
template <typename D, typename A>
actor<typename detail::
switch_composite<Cond, fusion::vector<actor<D> > >::type>
operator[](switch_case_base<D, A> const& case_) const
{
typedef typename
detail::switch_composite<Cond, fusion::vector<actor<D> > >
switch_composite;
return switch_composite::eval(cond,
fusion::vector<actor<D> >(static_cast<D const&>(case_)));
}
Cond cond;
};
template <typename Cond>
inline switch_gen<typename as_actor<Cond>::type>
switch_(Cond const& cond)
{
return switch_gen<typename as_actor<Cond>::type>(
as_actor<Cond>::convert(cond));
}
template <int N, typename A0>
switch_case<typename as_actor<A0>::type, int, N>
case_(A0 const& _0)
{
return switch_case<typename as_actor<A0>::type, int, N>
(as_actor<A0>::convert(_0));
}
template <typename A0>
default_case<typename as_actor<A0>::type>
default_(A0 const& _0)
{
return default_case<typename as_actor<A0>::type>
(as_actor<A0>::convert(_0));
}
template <typename D0, typename A0, typename D1, typename A1>
inline typename detail::compose_case_a<D0, D1>::type
operator,(
switch_case_base<D0, A0> const& _0
, switch_case_base<D1, A1> const& _1
)
{
return detail::compose_case_a<D0, D1>::eval(
static_cast<D0 const&>(_0)
, static_cast<D1 const&>(_1)
);
}
template <typename Seq, typename D, typename A>
inline typename
lazy_enable_if<
fusion::traits::is_sequence<Seq>
, detail::compose_case_b<Seq, D>
>::type
operator,(Seq const& seq, switch_case_base<D, A> const& case_)
{
return detail::compose_case_b<Seq, D>::eval(
seq, static_cast<D const&>(case_));
}
// Implementation of routines in detail/switch.hpp that depend on
// the completeness of default_case.
namespace detail {
template <typename Cases>
typename ensure_default<Cases>::type
ensure_default<Cases>::eval(Cases const& cases, mpl::false_)
{
actor<default_case<actor<null_actor> > > default_
= default_case<actor<null_actor> >(nothing);
return fusion::push_front(cases, default_);
}
}
}}
#endif