1 ///////////////////////////////////////////////////////////////////////////////
3 /// Make any Proto expression a valid Fusion sequence
5 // Copyright 2008 Eric Niebler. Distributed under the Boost
6 // Software License, Version 1.0. (See accompanying file
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
10 #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
12 #include <boost/proto/detail/prefix.hpp>
13 #include <boost/config.hpp>
14 #include <boost/version.hpp>
15 #include <boost/type_traits/remove_reference.hpp>
16 #include <boost/mpl/if.hpp>
17 #include <boost/mpl/long.hpp>
18 #include <boost/mpl/sequence_tag_fwd.hpp>
19 #if BOOST_VERSION >= 103500
20 #include <boost/fusion/include/is_view.hpp>
21 #include <boost/fusion/include/tag_of_fwd.hpp>
22 #include <boost/fusion/include/category_of.hpp>
23 #include <boost/fusion/include/iterator_base.hpp>
24 #include <boost/fusion/include/intrinsic.hpp>
25 #include <boost/fusion/include/pop_front.hpp>
26 #include <boost/fusion/include/reverse.hpp>
27 #include <boost/fusion/include/single_view.hpp>
28 #include <boost/fusion/include/transform_view.hpp>
29 #include <boost/fusion/support/ext_/is_segmented.hpp>
30 #include <boost/fusion/sequence/intrinsic/ext_/segments.hpp>
31 #include <boost/fusion/sequence/intrinsic/ext_/size_s.hpp>
32 #include <boost/fusion/view/ext_/segmented_iterator.hpp>
34 #include <boost/spirit/fusion/sequence/is_sequence.hpp>
35 #include <boost/spirit/fusion/sequence/begin.hpp>
36 #include <boost/spirit/fusion/sequence/end.hpp>
37 #include <boost/spirit/fusion/sequence/at.hpp>
38 #include <boost/spirit/fusion/sequence/value_at.hpp>
39 #include <boost/spirit/fusion/sequence/single_view.hpp>
40 #include <boost/spirit/fusion/sequence/transform_view.hpp>
41 #include <boost/proto/detail/reverse.hpp>
42 #include <boost/proto/detail/pop_front.hpp>
44 #include <boost/proto/proto_fwd.hpp>
45 #include <boost/proto/traits.hpp>
46 #include <boost/proto/eval.hpp>
47 #include <boost/proto/detail/suffix.hpp>
51 #pragma warning(disable : 4510) // default constructor could not be generated
52 #pragma warning(disable : 4512) // assignment operator could not be generated
53 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
56 namespace boost
{ namespace proto
61 #define UNREF(x) typename boost::remove_reference<x>::type
66 template<typename Expr
, long Pos
>
68 : fusion::iterator_base
<expr_iterator
<Expr
, Pos
> >
70 typedef Expr expr_type
;
71 typedef typename
Expr::proto_tag proto_tag
;
72 BOOST_STATIC_CONSTANT(long, index
= Pos
);
73 BOOST_PROTO_FUSION_DEFINE_CATEGORY(fusion::random_access_traversal_tag
)
74 BOOST_PROTO_FUSION_DEFINE_TAG(tag::proto_expr_iterator
)
76 expr_iterator(Expr
const &e
)
83 template<typename Expr
>
86 typedef Expr expr_type
;
87 typedef typename
Expr::proto_tag proto_tag
;
88 BOOST_PROTO_FUSION_DEFINE_CATEGORY(fusion::forward_traversal_tag
)
89 BOOST_PROTO_FUSION_DEFINE_TAG(tag::proto_flat_view
)
91 explicit flat_view(Expr
&expr
)
98 template<typename Tag
>
101 template<typename Sig
>
104 template<typename This
, typename Expr
>
105 struct result
<This(Expr
)>
107 is_same
<Tag
, UNREF(Expr
)::proto_tag
>
108 , flat_view
<UNREF(Expr
) const>
109 , fusion::single_view
<UNREF(Expr
) const &>
113 template<typename Expr
>
114 typename result
<as_element(Expr
const &)>::type
115 operator ()(Expr
const &expr
) const
117 return typename result
<as_element(Expr
const &)>::type(expr
);
124 template<typename Expr
>
127 typedef detail::flat_view
<Expr
const> type
;
130 template<typename Expr
>
131 struct flatten
<Expr
&>
133 typedef detail::flat_view
<Expr
const> type
;
139 /// \brief A PolymorphicFunctionObject type that returns a "flattened"
140 /// view of a Proto expression tree.
142 /// A PolymorphicFunctionObject type that returns a "flattened"
143 /// view of a Proto expression tree. For a tree with a top-most node
144 /// tag of type \c T, the elements of the flattened sequence are
145 /// determined by recursing into each child node with the same
146 /// tag type and returning those nodes of different type. So for
147 /// instance, the Proto expression tree corresponding to the
148 /// expression <tt>a | b | c</tt> has a flattened view with elements
149 /// [a, b, c], even though the tree is grouped as
150 /// <tt>((a | b) | c)</tt>.
153 BOOST_PROTO_CALLABLE()
155 template<typename Sig
>
158 template<typename This
, typename Expr
>
159 struct result
<This(Expr
)>
161 typedef proto::detail::flat_view
<UNREF(Expr
) const> type
;
164 template<typename Expr
>
165 proto::detail::flat_view
<Expr
const>
166 operator ()(Expr
const &expr
) const
168 return proto::detail::flat_view
<Expr
const>(expr
);
172 /// \brief A PolymorphicFunctionObject type that invokes the
173 /// \c fusion::pop_front() algorithm on its argument.
175 /// A PolymorphicFunctionObject type that invokes the
176 /// \c fusion::pop_front() algorithm on its argument. This is
177 /// useful for defining a CallableTransform like \c pop_front(_)
178 /// which removes the first child from a Proto expression node.
179 /// Such a transform might be used as the first argument to the
180 /// \c proto::fold\<\> transform; that is, fold all but
184 BOOST_PROTO_CALLABLE()
186 template<typename Sig
>
189 template<typename This
, typename Expr
>
190 struct result
<This(Expr
)>
193 typename
fusion::BOOST_PROTO_FUSION_RESULT_OF::pop_front
<UNREF(Expr
) const>::type
197 template<typename Expr
>
198 typename
fusion::BOOST_PROTO_FUSION_RESULT_OF::pop_front
<Expr
const>::type
199 operator ()(Expr
const &expr
) const
201 return fusion::pop_front(expr
);
205 /// \brief A PolymorphicFunctionObject type that invokes the
206 /// \c fusion::reverse() algorithm on its argument.
208 /// A PolymorphicFunctionObject type that invokes the
209 /// \c fusion::reverse() algorithm on its argument. This is
210 /// useful for defining a CallableTransform like \c reverse(_)
211 /// which reverses the order of the children of a Proto
215 BOOST_PROTO_CALLABLE()
217 template<typename Sig
>
220 template<typename This
, typename Expr
>
221 struct result
<This(Expr
)>
224 typename
fusion::BOOST_PROTO_FUSION_RESULT_OF::reverse
<UNREF(Expr
) const>::type
228 template<typename Expr
>
229 typename
fusion::BOOST_PROTO_FUSION_RESULT_OF::reverse
<Expr
const>::type
230 operator ()(Expr
const &expr
) const
232 return fusion::reverse(expr
);
237 /// \brief A function that returns a "flattened"
238 /// view of a Proto expression tree.
240 /// For a tree with a top-most node
241 /// tag of type \c T, the elements of the flattened sequence are
242 /// determined by recursing into each child node with the same
243 /// tag type and returning those nodes of different type. So for
244 /// instance, the Proto expression tree corresponding to the
245 /// expression <tt>a | b | c</tt> has a flattened view with elements
246 /// [a, b, c], even though the tree is grouped as
247 /// <tt>((a | b) | c)</tt>.
248 template<typename Expr
>
249 proto::detail::flat_view
<Expr
const>
250 flatten(Expr
const &expr
)
252 return proto::detail::flat_view
<Expr
const>(expr
);
258 struct is_callable
<functional::flatten
>
265 struct is_callable
<functional::pop_front
>
272 struct is_callable
<functional::reverse
>
278 template<typename Context
>
281 explicit eval_fun(Context
&ctx
)
285 template<typename Sig
>
288 template<typename This
, typename Expr
>
289 struct result
<This(Expr
)>
292 typename
proto::result_of::eval
<UNREF(Expr
), Context
>::type
296 template<typename Expr
>
297 typename
proto::result_of::eval
<Expr
, Context
>::type
298 operator ()(Expr
&expr
) const
300 return proto::eval(expr
, this->ctx_
);
308 // Don't bother emitting all this into the Doxygen-generated
309 // reference section. It's enough to say that Proto expressions
310 // are valid Fusion sequence without showing all this gunk.
311 #ifndef BOOST_PROTO_BUILDING_DOCS
313 namespace boost
{ namespace fusion
315 #if BOOST_VERSION < 103500
316 template<typename Tag
, typename Args
, long Arity
>
317 struct is_sequence
<proto::expr
<Tag
, Args
, Arity
> >
321 template<typename Tag
, typename Args
, long Arity
>
322 struct is_sequence
<proto::expr
<Tag
, Args
, Arity
> const>
327 namespace BOOST_PROTO_FUSION_EXTENSION
330 template<typename Tag
>
334 struct is_view_impl
<proto::tag::proto_flat_view
>
336 template<typename Sequence
>
343 struct is_view_impl
<proto::tag::proto_expr
>
345 template<typename Sequence
>
351 template<typename Tag
>
352 struct value_of_impl
;
355 struct value_of_impl
<proto::tag::proto_expr_iterator
>
359 , long Arity
= proto::arity_of
<typename
Iterator::expr_type
>::value
364 typename
proto::result_of::child_c
<
365 typename
Iterator::expr_type
371 template<typename Iterator
>
372 struct apply
<Iterator
, 0>
375 typename
proto::result_of::value
<
376 typename
Iterator::expr_type
382 #if BOOST_VERSION < 103500
383 template<typename Tag
>
387 struct value_impl
<proto::tag::proto_expr_iterator
>
388 : value_of_impl
<proto::tag::proto_expr_iterator
>
392 template<typename Tag
>
396 struct deref_impl
<proto::tag::proto_expr_iterator
>
400 , long Arity
= proto::arity_of
<typename
Iterator::expr_type
>::value
405 typename
proto::result_of::child_c
<
406 typename
Iterator::expr_type
const &
411 static type
call(Iterator
const &iter
)
413 return proto::child_c
<Iterator::index
>(iter
.expr
);
417 template<typename Iterator
>
418 struct apply
<Iterator
, 0>
421 typename
proto::result_of::value
<
422 typename
Iterator::expr_type
const &
426 static type
call(Iterator
const &iter
)
428 return proto::value(iter
.expr
);
433 template<typename Tag
>
437 struct advance_impl
<proto::tag::proto_expr_iterator
>
439 template<typename Iterator
, typename N
>
443 typename
proto::detail::expr_iterator
<
444 typename
Iterator::expr_type
445 , Iterator::index
+ N::value
449 static type
call(Iterator
const &iter
)
451 return type(iter
.expr
);
456 template<typename Tag
>
457 struct distance_impl
;
460 struct distance_impl
<proto::tag::proto_expr_iterator
>
462 template<typename IteratorFrom
, typename IteratorTo
>
464 : mpl::long_
<IteratorTo::index
- IteratorFrom::index
>
468 template<typename Tag
>
472 struct next_impl
<proto::tag::proto_expr_iterator
>
474 template<typename Iterator
>
476 : advance_impl
<proto::tag::proto_expr_iterator
>::template apply
<Iterator
, mpl::long_
<1> >
480 template<typename Tag
>
484 struct prior_impl
<proto::tag::proto_expr_iterator
>
486 template<typename Iterator
>
488 : advance_impl
<proto::tag::proto_expr_iterator
>::template apply
<Iterator
, mpl::long_
<-1> >
492 #if BOOST_VERSION >= 103500
493 template<typename Tag
>
494 struct category_of_impl
;
497 struct category_of_impl
<proto::tag::proto_expr
>
499 template<typename Sequence
>
502 typedef random_access_traversal_tag type
;
507 template<typename Tag
>
511 struct size_impl
<proto::tag::proto_expr
>
513 template<typename Sequence
>
515 : mpl::long_
<0 == Sequence::proto_arity_c
? 1 : Sequence::proto_arity_c
>
519 template<typename Tag
>
523 struct begin_impl
<proto::tag::proto_expr
>
525 template<typename Sequence
>
528 typedef proto::detail::expr_iterator
<Sequence
, 0> type
;
530 static type
call(Sequence
const &seq
)
537 template<typename Tag
>
541 struct end_impl
<proto::tag::proto_expr
>
543 template<typename Sequence
>
547 proto::detail::expr_iterator
<
549 , 0 == Sequence::proto_arity_c
? 1 : Sequence::proto_arity_c
553 static type
call(Sequence
const &seq
)
560 template<typename Tag
>
561 struct value_at_impl
;
564 struct value_at_impl
<proto::tag::proto_expr
>
569 , long Arity
= proto::arity_of
<Sequence
>::value
574 typename
proto::result_of::child_c
<
581 template<typename Sequence
, typename Index
>
582 struct apply
<Sequence
, Index
, 0>
585 typename
proto::result_of::value
<
592 template<typename Tag
>
596 struct at_impl
<proto::tag::proto_expr
>
601 , long Arity
= proto::arity_of
<Sequence
>::value
606 typename
proto::result_of::child_c
<
612 static type
call(Sequence
&seq
)
614 return proto::child_c
<Index::value
>(seq
);
618 template<typename Sequence
, typename Index
>
619 struct apply
<Sequence
, Index
, 0>
622 typename
proto::result_of::value
<
627 static type
call(Sequence
&seq
)
629 return proto::value(seq
);
634 #if BOOST_VERSION >= 103500
635 template<typename Tag
>
636 struct is_segmented_impl
;
639 struct is_segmented_impl
<proto::tag::proto_flat_view
>
641 template<typename Iterator
>
647 template<typename Tag
>
648 struct segments_impl
;
651 struct segments_impl
<proto::tag::proto_flat_view
>
653 template<typename Sequence
>
656 typedef typename
Sequence::proto_tag proto_tag
;
658 typedef fusion::transform_view
<
659 typename
Sequence::expr_type
660 , proto::detail::as_element
<proto_tag
>
663 static type
call(Sequence
&sequence
)
665 return type(sequence
.expr_
, proto::detail::as_element
<proto_tag
>());
671 struct category_of_impl
<proto::tag::proto_flat_view
>
673 template<typename Sequence
>
676 typedef forward_traversal_tag type
;
681 struct begin_impl
<proto::tag::proto_flat_view
>
683 template<typename Sequence
>
685 : fusion::segmented_begin
<Sequence
>
690 struct end_impl
<proto::tag::proto_flat_view
>
692 template<typename Sequence
>
694 : fusion::segmented_end
<Sequence
>
699 struct size_impl
<proto::tag::proto_flat_view
>
701 template<typename Sequence
>
703 : fusion::segmented_size
<Sequence
>
712 namespace boost
{ namespace mpl
714 template<typename Tag
, typename Args
, long Arity
>
715 struct sequence_tag
< proto::expr
<Tag
, Args
, Arity
> >
717 typedef fusion::fusion_sequence_tag type
;
721 #endif // BOOST_PROTO_BUILDING_DOCS