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/config.hpp>
13 #include <boost/mpl/if.hpp>
14 #include <boost/mpl/bool.hpp>
15 #include <boost/mpl/long.hpp>
16 #include <boost/mpl/sequence_tag_fwd.hpp>
17 #include <boost/utility/enable_if.hpp>
18 #include <boost/fusion/include/is_view.hpp>
19 #include <boost/fusion/include/tag_of_fwd.hpp>
20 #include <boost/fusion/include/category_of.hpp>
21 #include <boost/fusion/include/iterator_base.hpp>
22 #include <boost/fusion/include/intrinsic.hpp>
23 #include <boost/fusion/include/single_view.hpp>
24 #include <boost/fusion/include/transform.hpp>
25 #include <boost/fusion/include/as_list.hpp>
26 #include <boost/fusion/include/is_segmented.hpp>
27 #include <boost/fusion/sequence/comparison/enable_comparison.hpp>
28 #include <boost/proto/proto_fwd.hpp>
29 #include <boost/proto/traits.hpp>
30 #include <boost/proto/eval.hpp>
31 #include <boost/proto/make_expr.hpp>
35 #pragma warning(disable : 4510) // default constructor could not be generated
36 #pragma warning(disable : 4512) // assignment operator could not be generated
37 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
40 namespace boost { namespace proto
44 template<typename Expr, long Pos>
46 : fusion::iterator_base<expr_iterator<Expr, Pos> >
48 typedef Expr expr_type;
49 static const long index = Pos;
50 typedef fusion::random_access_traversal_tag category;
52 tag::proto_expr_iterator<
53 typename Expr::proto_tag
54 , typename Expr::proto_domain
58 explicit expr_iterator(Expr &e)
65 template<typename Tag>
68 template<typename Sig>
71 template<typename This, typename Expr>
72 struct result<This(Expr)>
73 : result<This(Expr const &)>
76 template<typename This, typename Expr>
77 struct result<This(Expr &)>
79 is_same<Tag, typename Expr::proto_tag>::value
81 , fusion::single_view<Expr &>
85 template<typename Expr>
86 typename result<as_element(Expr &)>::type const
87 operator ()(Expr &e) const
89 return typename result<as_element(Expr &)>::type(e);
92 template<typename Expr>
93 typename result<as_element(Expr const &)>::type const
94 operator ()(Expr const &e) const
96 return typename result<as_element(Expr const &)>::type(e);
100 template<typename Expr>
102 : fusion::sequence_base<flat_view<Expr> >
104 typedef fusion::forward_traversal_tag category;
106 tag::proto_flat_view<
107 typename Expr::proto_tag
108 , typename Expr::proto_domain
112 typename fusion::result_of::as_list<
113 typename fusion::result_of::transform<
115 , as_element<typename Expr::proto_tag>
120 explicit flat_view(Expr &e)
121 : segs_(fusion::as_list(fusion::transform(e, as_element<typename Expr::proto_tag>())))
130 template<typename Expr>
132 : flatten<Expr const &>
135 template<typename Expr>
136 struct flatten<Expr &>
138 typedef detail::flat_view<Expr> type;
144 /// \brief A PolymorphicFunctionObject type that returns a "flattened"
145 /// view of a Proto expression tree.
147 /// A PolymorphicFunctionObject type that returns a "flattened"
148 /// view of a Proto expression tree. For a tree with a top-most node
149 /// tag of type \c T, the elements of the flattened sequence are
150 /// determined by recursing into each child node with the same
151 /// tag type and returning those nodes of different type. So for
152 /// instance, the Proto expression tree corresponding to the
153 /// expression <tt>a | b | c</tt> has a flattened view with elements
154 /// [a, b, c], even though the tree is grouped as
155 /// <tt>((a | b) | c)</tt>.
158 BOOST_PROTO_CALLABLE()
160 template<typename Sig>
163 template<typename This, typename Expr>
164 struct result<This(Expr)>
165 : result<This(Expr const &)>
168 template<typename This, typename Expr>
169 struct result<This(Expr &)>
171 typedef proto::detail::flat_view<Expr> type;
174 template<typename Expr>
175 proto::detail::flat_view<Expr> const
176 operator ()(Expr &e) const
178 return proto::detail::flat_view<Expr>(e);
181 template<typename Expr>
182 proto::detail::flat_view<Expr const> const
183 operator ()(Expr const &e) const
185 return proto::detail::flat_view<Expr const>(e);
190 /// \brief A function that returns a "flattened"
191 /// view of a Proto expression tree.
193 /// For a tree with a top-most node
194 /// tag of type \c T, the elements of the flattened sequence are
195 /// determined by recursing into each child node with the same
196 /// tag type and returning those nodes of different type. So for
197 /// instance, the Proto expression tree corresponding to the
198 /// expression <tt>a | b | c</tt> has a flattened view with elements
199 /// [a, b, c], even though the tree is grouped as
200 /// <tt>((a | b) | c)</tt>.
201 template<typename Expr>
202 proto::detail::flat_view<Expr> const
205 return proto::detail::flat_view<Expr>(e);
210 template<typename Expr>
211 proto::detail::flat_view<Expr const> const
212 flatten(Expr const &e)
214 return proto::detail::flat_view<Expr const>(e);
219 template<typename Context>
223 explicit eval_fun(Context &ctx)
227 template<typename Sig>
230 template<typename This, typename Expr>
231 struct result<This(Expr)>
232 : result<This(Expr const &)>
235 template<typename This, typename Expr>
236 struct result<This(Expr &)>
237 : proto::result_of::eval<Expr, Context>
240 template<typename Expr>
241 typename proto::result_of::eval<Expr, Context>::type
242 operator ()(Expr &e) const
244 return proto::eval(e, this->ctx_);
247 template<typename Expr>
248 typename proto::result_of::eval<Expr const, Context>::type
249 operator ()(Expr const &e) const
251 return proto::eval(e, this->ctx_);
260 template<typename Context>
261 struct is_callable<eval_fun<Context> >
266 namespace boost { namespace fusion
270 template<typename Tag>
271 struct is_sequence_impl;
273 template<typename Tag, typename Domain>
274 struct is_sequence_impl<proto::tag::proto_flat_view<Tag, Domain> >
276 template<typename Sequence>
282 template<typename Tag, typename Domain>
283 struct is_sequence_impl<proto::tag::proto_expr<Tag, Domain> >
285 template<typename Sequence>
291 template<typename Tag>
294 template<typename Tag, typename Domain>
295 struct is_view_impl<proto::tag::proto_flat_view<Tag, Domain> >
297 template<typename Sequence>
303 template<typename Tag, typename Domain>
304 struct is_view_impl<proto::tag::proto_expr<Tag, Domain> >
306 template<typename Sequence>
312 template<typename Tag>
313 struct value_of_impl;
315 template<typename Tag, typename Domain>
316 struct value_of_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
320 , long Arity = proto::arity_of<typename Iterator::expr_type>::value
325 typename proto::result_of::child_c<
326 typename Iterator::expr_type
332 template<typename Iterator>
333 struct apply<Iterator, 0>
336 typename proto::result_of::value<
337 typename Iterator::expr_type
343 template<typename Tag>
346 template<typename Tag, typename Domain>
347 struct deref_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
351 , long Arity = proto::arity_of<typename Iterator::expr_type>::value
356 typename proto::result_of::child_c<
357 typename Iterator::expr_type &
362 static type call(Iterator const &iter)
364 return proto::child_c<Iterator::index>(iter.expr);
368 template<typename Iterator>
369 struct apply<Iterator, 0>
372 typename proto::result_of::value<
373 typename Iterator::expr_type &
377 static type call(Iterator const &iter)
379 return proto::value(iter.expr);
384 template<typename Tag>
387 template<typename Tag, typename Domain>
388 struct advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
390 template<typename Iterator, typename N>
394 proto::detail::expr_iterator<
395 typename Iterator::expr_type
396 , Iterator::index + N::value
400 static type call(Iterator const &iter)
402 return type(iter.expr);
407 template<typename Tag>
408 struct distance_impl;
410 template<typename Tag, typename Domain>
411 struct distance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
413 template<typename IteratorFrom, typename IteratorTo>
415 : mpl::long_<IteratorTo::index - IteratorFrom::index>
419 template<typename Tag>
422 template<typename Tag, typename Domain>
423 struct next_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
425 template<typename Iterator>
427 : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<1> >
431 template<typename Tag>
434 template<typename Tag, typename Domain>
435 struct prior_impl<proto::tag::proto_expr_iterator<Tag, Domain> >
437 template<typename Iterator>
439 : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<-1> >
443 template<typename Tag>
444 struct category_of_impl;
446 template<typename Tag, typename Domain>
447 struct category_of_impl<proto::tag::proto_expr<Tag, Domain> >
449 template<typename Sequence>
452 typedef random_access_traversal_tag type;
456 template<typename Tag>
459 template<typename Tag, typename Domain>
460 struct size_impl<proto::tag::proto_expr<Tag, Domain> >
462 template<typename Sequence>
464 : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c>
468 template<typename Tag>
471 template<typename Tag, typename Domain>
472 struct begin_impl<proto::tag::proto_expr<Tag, Domain> >
474 template<typename Sequence>
477 typedef proto::detail::expr_iterator<Sequence, 0> type;
479 static type call(Sequence &seq)
486 template<typename Tag>
489 template<typename Tag, typename Domain>
490 struct end_impl<proto::tag::proto_expr<Tag, Domain> >
492 template<typename Sequence>
496 proto::detail::expr_iterator<
498 , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c
502 static type call(Sequence &seq)
509 template<typename Tag>
510 struct value_at_impl;
512 template<typename Tag, typename Domain>
513 struct value_at_impl<proto::tag::proto_expr<Tag, Domain> >
518 , long Arity = proto::arity_of<Sequence>::value
523 typename proto::result_of::child_c<
530 template<typename Sequence, typename Index>
531 struct apply<Sequence, Index, 0>
534 typename proto::result_of::value<
541 template<typename Tag>
544 template<typename Tag, typename Domain>
545 struct at_impl<proto::tag::proto_expr<Tag, Domain> >
550 , long Arity = proto::arity_of<Sequence>::value
555 typename proto::result_of::child_c<
561 static type call(Sequence &seq)
563 return proto::child_c<Index::value>(seq);
567 template<typename Sequence, typename Index>
568 struct apply<Sequence, Index, 0>
571 typename proto::result_of::value<
576 static type call(Sequence &seq)
578 return proto::value(seq);
583 template<typename Tag>
586 template<typename Tag, typename Domain>
587 struct convert_impl<proto::tag::proto_expr<Tag, Domain> >
589 template<typename Sequence>
593 typename proto::result_of::unpack_expr<
600 static type call(Sequence& seq)
602 return proto::unpack_expr<Tag, Domain>(seq);
607 template<typename Tag, typename Domain>
608 struct convert_impl<proto::tag::proto_flat_view<Tag, Domain> >
610 template<typename Sequence>
614 typename proto::result_of::unpack_expr<
621 static type call(Sequence& seq)
623 return proto::unpack_expr<Tag, Domain>(seq);
628 template<typename Tag>
629 struct is_segmented_impl;
631 template<typename Tag, typename Domain>
632 struct is_segmented_impl<proto::tag::proto_flat_view<Tag, Domain> >
634 template<typename Iterator>
640 template<typename Tag>
641 struct segments_impl;
643 template<typename Tag, typename Domain>
644 struct segments_impl<proto::tag::proto_flat_view<Tag, Domain> >
646 template<typename Sequence>
649 typedef typename Sequence::segments_type const &type;
651 static type call(Sequence &sequence)
653 return sequence.segs_;
658 template<typename Tag, typename Domain>
659 struct category_of_impl<proto::tag::proto_flat_view<Tag, Domain> >
661 template<typename Sequence>
664 typedef forward_traversal_tag type;
671 template<typename Seq1, typename Seq2>
672 struct enable_equality<
675 , typename enable_if_c<
678 , proto::is_expr<Seq2>
685 template<typename Seq1, typename Seq2>
686 struct enable_comparison<
689 , typename enable_if_c<
692 , proto::is_expr<Seq2>
701 namespace boost { namespace mpl
703 template<typename Tag, typename Args, long Arity>
704 struct sequence_tag< proto::expr<Tag, Args, Arity> >
706 typedef fusion::fusion_sequence_tag type;
709 template<typename Tag, typename Args, long Arity>
710 struct sequence_tag< proto::basic_expr<Tag, Args, Arity> >
712 typedef fusion::fusion_sequence_tag type;