| /////////////////////////////////////////////////////////////////////////////// |
| /// \file fusion.hpp |
| /// Make any Proto expression a valid Fusion sequence |
| // |
| // Copyright 2008 Eric Niebler. 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 BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 |
| #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 |
| |
| #include <boost/config.hpp> |
| #include <boost/mpl/if.hpp> |
| #include <boost/mpl/long.hpp> |
| #include <boost/mpl/sequence_tag_fwd.hpp> |
| #include <boost/fusion/include/is_view.hpp> |
| #include <boost/fusion/include/tag_of_fwd.hpp> |
| #include <boost/fusion/include/category_of.hpp> |
| #include <boost/fusion/include/iterator_base.hpp> |
| #include <boost/fusion/include/intrinsic.hpp> |
| #include <boost/fusion/include/pop_front.hpp> |
| #include <boost/fusion/include/reverse.hpp> |
| #include <boost/fusion/include/single_view.hpp> |
| #include <boost/fusion/include/transform_view.hpp> |
| #include <boost/fusion/support/ext_/is_segmented.hpp> |
| #include <boost/fusion/sequence/intrinsic/ext_/segments.hpp> |
| #include <boost/fusion/sequence/intrinsic/ext_/size_s.hpp> |
| #include <boost/fusion/view/ext_/segmented_iterator.hpp> |
| #include <boost/proto/proto_fwd.hpp> |
| #include <boost/proto/traits.hpp> |
| #include <boost/proto/eval.hpp> |
| |
| #if BOOST_MSVC |
| #pragma warning(push) |
| #pragma warning(disable : 4510) // default constructor could not be generated |
| #pragma warning(disable : 4512) // assignment operator could not be generated |
| #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required |
| #endif |
| |
| namespace boost { namespace proto |
| { |
| |
| namespace detail |
| { |
| |
| template<typename Expr, long Pos> |
| struct expr_iterator |
| : fusion::iterator_base<expr_iterator<Expr, Pos> > |
| { |
| typedef Expr expr_type; |
| typedef typename Expr::proto_tag proto_tag; |
| BOOST_STATIC_CONSTANT(long, index = Pos); |
| typedef fusion::random_access_traversal_tag category; |
| typedef tag::proto_expr_iterator fusion_tag; |
| |
| expr_iterator(Expr &e) |
| : expr(e) |
| {} |
| |
| Expr &expr; |
| }; |
| |
| template<typename Expr> |
| struct flat_view |
| { |
| typedef Expr expr_type; |
| typedef typename Expr::proto_tag proto_tag; |
| typedef fusion::forward_traversal_tag category; |
| typedef tag::proto_flat_view fusion_tag; |
| |
| explicit flat_view(Expr &e) |
| : expr_(e) |
| {} |
| |
| Expr &expr_; |
| }; |
| |
| template<typename Tag> |
| struct as_element |
| { |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr)> |
| : result<This(Expr const &)> |
| {}; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr &)> |
| : mpl::if_c< |
| is_same<Tag, typename Expr::proto_tag>::value |
| , flat_view<Expr> |
| , fusion::single_view<Expr &> |
| > |
| {}; |
| |
| template<typename Expr> |
| typename result<as_element(Expr &)>::type const |
| operator ()(Expr &e) const |
| { |
| return typename result<as_element(Expr &)>::type(e); |
| } |
| |
| template<typename Expr> |
| typename result<as_element(Expr const &)>::type const |
| operator ()(Expr const &e) const |
| { |
| return typename result<as_element(Expr const &)>::type(e); |
| } |
| }; |
| } |
| |
| namespace result_of |
| { |
| template<typename Expr> |
| struct flatten |
| : flatten<Expr const &> |
| {}; |
| |
| template<typename Expr> |
| struct flatten<Expr &> |
| { |
| typedef detail::flat_view<Expr> type; |
| }; |
| } |
| |
| namespace functional |
| { |
| /// \brief A PolymorphicFunctionObject type that returns a "flattened" |
| /// view of a Proto expression tree. |
| /// |
| /// A PolymorphicFunctionObject type that returns a "flattened" |
| /// view of a Proto expression tree. For a tree with a top-most node |
| /// tag of type \c T, the elements of the flattened sequence are |
| /// determined by recursing into each child node with the same |
| /// tag type and returning those nodes of different type. So for |
| /// instance, the Proto expression tree corresponding to the |
| /// expression <tt>a | b | c</tt> has a flattened view with elements |
| /// [a, b, c], even though the tree is grouped as |
| /// <tt>((a | b) | c)</tt>. |
| struct flatten |
| { |
| BOOST_PROTO_CALLABLE() |
| |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr)> |
| : result<This(Expr const &)> |
| {}; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr &)> |
| { |
| typedef proto::detail::flat_view<Expr> type; |
| }; |
| |
| template<typename Expr> |
| proto::detail::flat_view<Expr> const |
| operator ()(Expr &e) const |
| { |
| return proto::detail::flat_view<Expr>(e); |
| } |
| |
| template<typename Expr> |
| proto::detail::flat_view<Expr const> const |
| operator ()(Expr const &e) const |
| { |
| return proto::detail::flat_view<Expr const>(e); |
| } |
| }; |
| |
| /// \brief A PolymorphicFunctionObject type that invokes the |
| /// \c fusion::pop_front() algorithm on its argument. |
| /// |
| /// A PolymorphicFunctionObject type that invokes the |
| /// \c fusion::pop_front() algorithm on its argument. This is |
| /// useful for defining a CallableTransform like \c pop_front(_) |
| /// which removes the first child from a Proto expression node. |
| /// Such a transform might be used as the first argument to the |
| /// \c proto::fold\<\> transform; that is, fold all but |
| /// the first child. |
| struct pop_front |
| { |
| BOOST_PROTO_CALLABLE() |
| |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr)> |
| : result<This(Expr const &)> |
| {}; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr &)> |
| : fusion::result_of::pop_front<Expr> |
| {}; |
| |
| template<typename Expr> |
| typename fusion::result_of::pop_front<Expr>::type |
| operator ()(Expr &e) const |
| { |
| // Work around a const-correctness issue in Fusion |
| typedef typename fusion::result_of::pop_front<Expr>::type result_type; |
| return result_type(fusion::next(fusion::begin(e)), fusion::end(e)); |
| } |
| |
| template<typename Expr> |
| typename fusion::result_of::pop_front<Expr const>::type |
| operator ()(Expr const &e) const |
| { |
| return fusion::pop_front(e); |
| } |
| }; |
| |
| /// \brief A PolymorphicFunctionObject type that invokes the |
| /// \c fusion::reverse() algorithm on its argument. |
| /// |
| /// A PolymorphicFunctionObject type that invokes the |
| /// \c fusion::reverse() algorithm on its argument. This is |
| /// useful for defining a CallableTransform like \c reverse(_) |
| /// which reverses the order of the children of a Proto |
| /// expression node. |
| struct reverse |
| { |
| BOOST_PROTO_CALLABLE() |
| |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr)> |
| : result<This(Expr const &)> |
| {}; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr &)> |
| : fusion::result_of::reverse<Expr> |
| {}; |
| |
| template<typename Expr> |
| typename fusion::result_of::reverse<Expr>::type |
| operator ()(Expr &e) const |
| { |
| // Work around a const-correctness issue in Fusion |
| typedef typename fusion::result_of::reverse<Expr>::type result_type; |
| return result_type(e); |
| } |
| |
| template<typename Expr> |
| typename fusion::result_of::reverse<Expr const>::type |
| operator ()(Expr const &e) const |
| { |
| return fusion::reverse(e); |
| } |
| }; |
| } |
| |
| /// \brief A function that returns a "flattened" |
| /// view of a Proto expression tree. |
| /// |
| /// For a tree with a top-most node |
| /// tag of type \c T, the elements of the flattened sequence are |
| /// determined by recursing into each child node with the same |
| /// tag type and returning those nodes of different type. So for |
| /// instance, the Proto expression tree corresponding to the |
| /// expression <tt>a | b | c</tt> has a flattened view with elements |
| /// [a, b, c], even though the tree is grouped as |
| /// <tt>((a | b) | c)</tt>. |
| template<typename Expr> |
| proto::detail::flat_view<Expr> const |
| flatten(Expr &e) |
| { |
| return proto::detail::flat_view<Expr>(e); |
| } |
| |
| /// \overload |
| /// |
| template<typename Expr> |
| proto::detail::flat_view<Expr const> const |
| flatten(Expr const &e) |
| { |
| return proto::detail::flat_view<Expr const>(e); |
| } |
| |
| /// INTERNAL ONLY |
| /// |
| template<> |
| struct is_callable<functional::flatten> |
| : mpl::true_ |
| {}; |
| |
| /// INTERNAL ONLY |
| /// |
| template<> |
| struct is_callable<functional::pop_front> |
| : mpl::true_ |
| {}; |
| |
| /// INTERNAL ONLY |
| /// |
| template<> |
| struct is_callable<functional::reverse> |
| : mpl::true_ |
| {}; |
| |
| /// INTERNAL ONLY |
| /// |
| template<typename Context> |
| struct eval_fun |
| { |
| explicit eval_fun(Context &ctx) |
| : ctx_(ctx) |
| {} |
| |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr)> |
| : result<This(Expr const &)> |
| {}; |
| |
| template<typename This, typename Expr> |
| struct result<This(Expr &)> |
| : proto::result_of::eval<Expr, Context> |
| {}; |
| |
| template<typename Expr> |
| typename proto::result_of::eval<Expr, Context>::type |
| operator ()(Expr &e) const |
| { |
| return proto::eval(e, this->ctx_); |
| } |
| |
| template<typename Expr> |
| typename proto::result_of::eval<Expr const, Context>::type |
| operator ()(Expr const &e) const |
| { |
| return proto::eval(e, this->ctx_); |
| } |
| |
| private: |
| Context &ctx_; |
| }; |
| }} |
| |
| namespace boost { namespace fusion |
| { |
| namespace extension |
| { |
| |
| template<typename Tag> |
| struct is_view_impl; |
| |
| template<> |
| struct is_view_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<> |
| struct is_view_impl<proto::tag::proto_expr> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::false_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct value_of_impl; |
| |
| template<> |
| struct value_of_impl<proto::tag::proto_expr_iterator> |
| { |
| template< |
| typename Iterator |
| , long Arity = proto::arity_of<typename Iterator::expr_type>::value |
| > |
| struct apply |
| { |
| typedef |
| typename proto::result_of::child_c< |
| typename Iterator::expr_type |
| , Iterator::index |
| >::value_type |
| type; |
| }; |
| |
| template<typename Iterator> |
| struct apply<Iterator, 0> |
| { |
| typedef |
| typename proto::result_of::value< |
| typename Iterator::expr_type |
| >::value_type |
| type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct deref_impl; |
| |
| template<> |
| struct deref_impl<proto::tag::proto_expr_iterator> |
| { |
| template< |
| typename Iterator |
| , long Arity = proto::arity_of<typename Iterator::expr_type>::value |
| > |
| struct apply |
| { |
| typedef |
| typename proto::result_of::child_c< |
| typename Iterator::expr_type & |
| , Iterator::index |
| >::type |
| type; |
| |
| static type call(Iterator const &iter) |
| { |
| return proto::child_c<Iterator::index>(iter.expr); |
| } |
| }; |
| |
| template<typename Iterator> |
| struct apply<Iterator, 0> |
| { |
| typedef |
| typename proto::result_of::value< |
| typename Iterator::expr_type & |
| >::type |
| type; |
| |
| static type call(Iterator const &iter) |
| { |
| return proto::value(iter.expr); |
| } |
| }; |
| }; |
| |
| template<typename Tag> |
| struct advance_impl; |
| |
| template<> |
| struct advance_impl<proto::tag::proto_expr_iterator> |
| { |
| template<typename Iterator, typename N> |
| struct apply |
| { |
| typedef |
| typename proto::detail::expr_iterator< |
| typename Iterator::expr_type |
| , Iterator::index + N::value |
| > |
| type; |
| |
| static type call(Iterator const &iter) |
| { |
| return type(iter.expr); |
| } |
| }; |
| }; |
| |
| template<typename Tag> |
| struct distance_impl; |
| |
| template<> |
| struct distance_impl<proto::tag::proto_expr_iterator> |
| { |
| template<typename IteratorFrom, typename IteratorTo> |
| struct apply |
| : mpl::long_<IteratorTo::index - IteratorFrom::index> |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct next_impl; |
| |
| template<> |
| struct next_impl<proto::tag::proto_expr_iterator> |
| { |
| template<typename Iterator> |
| struct apply |
| : advance_impl<proto::tag::proto_expr_iterator>::template apply<Iterator, mpl::long_<1> > |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct prior_impl; |
| |
| template<> |
| struct prior_impl<proto::tag::proto_expr_iterator> |
| { |
| template<typename Iterator> |
| struct apply |
| : advance_impl<proto::tag::proto_expr_iterator>::template apply<Iterator, mpl::long_<-1> > |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct category_of_impl; |
| |
| template<> |
| struct category_of_impl<proto::tag::proto_expr> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef random_access_traversal_tag type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct size_impl; |
| |
| template<> |
| struct size_impl<proto::tag::proto_expr> |
| { |
| template<typename Sequence> |
| struct apply |
| : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c> |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct begin_impl; |
| |
| template<> |
| struct begin_impl<proto::tag::proto_expr> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef proto::detail::expr_iterator<Sequence, 0> type; |
| |
| static type call(Sequence &seq) |
| { |
| return type(seq); |
| } |
| }; |
| }; |
| |
| template<typename Tag> |
| struct end_impl; |
| |
| template<> |
| struct end_impl<proto::tag::proto_expr> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef |
| proto::detail::expr_iterator< |
| Sequence |
| , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c |
| > |
| type; |
| |
| static type call(Sequence &seq) |
| { |
| return type(seq); |
| } |
| }; |
| }; |
| |
| template<typename Tag> |
| struct value_at_impl; |
| |
| template<> |
| struct value_at_impl<proto::tag::proto_expr> |
| { |
| template< |
| typename Sequence |
| , typename Index |
| , long Arity = proto::arity_of<Sequence>::value |
| > |
| struct apply |
| { |
| typedef |
| typename proto::result_of::child_c< |
| Sequence |
| , Index::value |
| >::value_type |
| type; |
| }; |
| |
| template<typename Sequence, typename Index> |
| struct apply<Sequence, Index, 0> |
| { |
| typedef |
| typename proto::result_of::value< |
| Sequence |
| >::value_type |
| type; |
| }; |
| }; |
| |
| template<typename Tag> |
| struct at_impl; |
| |
| template<> |
| struct at_impl<proto::tag::proto_expr> |
| { |
| template< |
| typename Sequence |
| , typename Index |
| , long Arity = proto::arity_of<Sequence>::value |
| > |
| struct apply |
| { |
| typedef |
| typename proto::result_of::child_c< |
| Sequence & |
| , Index::value |
| >::type |
| type; |
| |
| static type call(Sequence &seq) |
| { |
| return proto::child_c<Index::value>(seq); |
| } |
| }; |
| |
| template<typename Sequence, typename Index> |
| struct apply<Sequence, Index, 0> |
| { |
| typedef |
| typename proto::result_of::value< |
| Sequence & |
| >::type |
| type; |
| |
| static type call(Sequence &seq) |
| { |
| return proto::value(seq); |
| } |
| }; |
| }; |
| |
| template<typename Tag> |
| struct is_segmented_impl; |
| |
| template<> |
| struct is_segmented_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Iterator> |
| struct apply |
| : mpl::true_ |
| {}; |
| }; |
| |
| template<typename Tag> |
| struct segments_impl; |
| |
| template<> |
| struct segments_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef typename Sequence::proto_tag proto_tag; |
| |
| typedef fusion::transform_view< |
| typename Sequence::expr_type |
| , proto::detail::as_element<proto_tag> |
| > type; |
| |
| static type call(Sequence &sequence) |
| { |
| return type(sequence.expr_, proto::detail::as_element<proto_tag>()); |
| } |
| }; |
| }; |
| |
| template<> |
| struct category_of_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| { |
| typedef forward_traversal_tag type; |
| }; |
| }; |
| |
| template<> |
| struct begin_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| : fusion::segmented_begin<Sequence> |
| {}; |
| }; |
| |
| template<> |
| struct end_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| : fusion::segmented_end<Sequence> |
| {}; |
| }; |
| |
| template<> |
| struct size_impl<proto::tag::proto_flat_view> |
| { |
| template<typename Sequence> |
| struct apply |
| : fusion::segmented_size<Sequence> |
| {}; |
| }; |
| |
| } |
| |
| }} |
| |
| namespace boost { namespace mpl |
| { |
| template<typename Tag, typename Args, long Arity> |
| struct sequence_tag< proto::expr<Tag, Args, Arity> > |
| { |
| typedef fusion::fusion_sequence_tag type; |
| }; |
| |
| template<typename Tag, typename Args, long Arity> |
| struct sequence_tag< proto::basic_expr<Tag, Args, Arity> > |
| { |
| typedef fusion::fusion_sequence_tag type; |
| }; |
| }} |
| |
| #if BOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| |
| #endif |