| /*============================================================================= |
| 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 |