]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file fusion.hpp | |
3 | /// Make any Proto expression a valid Fusion sequence | |
4 | // | |
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) | |
8 | ||
9 | #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 | |
10 | #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 | |
11 | ||
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> | |
32 | ||
33 | #ifdef BOOST_MSVC | |
34 | #pragma warning(push) | |
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 | |
38 | #endif | |
39 | ||
40 | namespace boost { namespace proto | |
41 | { | |
42 | namespace detail | |
43 | { | |
44 | template<typename Expr, long Pos> | |
45 | struct expr_iterator | |
46 | : fusion::iterator_base<expr_iterator<Expr, Pos> > | |
47 | { | |
48 | typedef Expr expr_type; | |
49 | static const long index = Pos; | |
50 | typedef fusion::random_access_traversal_tag category; | |
51 | typedef | |
52 | tag::proto_expr_iterator< | |
53 | typename Expr::proto_tag | |
54 | , typename Expr::proto_domain | |
55 | > | |
56 | fusion_tag; | |
57 | ||
58 | explicit expr_iterator(Expr &e) | |
59 | : expr(e) | |
60 | {} | |
61 | ||
62 | Expr &expr; | |
63 | }; | |
64 | ||
65 | template<typename Tag> | |
66 | struct as_element | |
67 | { | |
68 | template<typename Sig> | |
69 | struct result; | |
70 | ||
71 | template<typename This, typename Expr> | |
72 | struct result<This(Expr)> | |
73 | : result<This(Expr const &)> | |
74 | {}; | |
75 | ||
76 | template<typename This, typename Expr> | |
77 | struct result<This(Expr &)> | |
78 | : mpl::if_c< | |
79 | is_same<Tag, typename Expr::proto_tag>::value | |
80 | , flat_view<Expr> | |
81 | , fusion::single_view<Expr &> | |
82 | > | |
83 | {}; | |
84 | ||
85 | template<typename Expr> | |
86 | typename result<as_element(Expr &)>::type const | |
87 | operator ()(Expr &e) const | |
88 | { | |
89 | return typename result<as_element(Expr &)>::type(e); | |
90 | } | |
91 | ||
92 | template<typename Expr> | |
93 | typename result<as_element(Expr const &)>::type const | |
94 | operator ()(Expr const &e) const | |
95 | { | |
96 | return typename result<as_element(Expr const &)>::type(e); | |
97 | } | |
98 | }; | |
99 | ||
100 | template<typename Expr> | |
101 | struct flat_view | |
102 | : fusion::sequence_base<flat_view<Expr> > | |
103 | { | |
104 | typedef fusion::forward_traversal_tag category; | |
105 | typedef | |
106 | tag::proto_flat_view< | |
107 | typename Expr::proto_tag | |
108 | , typename Expr::proto_domain | |
109 | > | |
110 | fusion_tag; | |
111 | typedef | |
112 | typename fusion::result_of::as_list< | |
113 | typename fusion::result_of::transform< | |
114 | Expr | |
115 | , as_element<typename Expr::proto_tag> | |
116 | >::type | |
117 | >::type | |
118 | segments_type; | |
119 | ||
120 | explicit flat_view(Expr &e) | |
121 | : segs_(fusion::as_list(fusion::transform(e, as_element<typename Expr::proto_tag>()))) | |
122 | {} | |
123 | ||
124 | segments_type segs_; | |
125 | }; | |
126 | } | |
127 | ||
128 | namespace result_of | |
129 | { | |
130 | template<typename Expr> | |
131 | struct flatten | |
132 | : flatten<Expr const &> | |
133 | {}; | |
134 | ||
135 | template<typename Expr> | |
136 | struct flatten<Expr &> | |
137 | { | |
138 | typedef detail::flat_view<Expr> type; | |
139 | }; | |
140 | } | |
141 | ||
142 | namespace functional | |
143 | { | |
144 | /// \brief A PolymorphicFunctionObject type that returns a "flattened" | |
145 | /// view of a Proto expression tree. | |
146 | /// | |
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>. | |
156 | struct flatten | |
157 | { | |
158 | BOOST_PROTO_CALLABLE() | |
159 | ||
160 | template<typename Sig> | |
161 | struct result; | |
162 | ||
163 | template<typename This, typename Expr> | |
164 | struct result<This(Expr)> | |
165 | : result<This(Expr const &)> | |
166 | {}; | |
167 | ||
168 | template<typename This, typename Expr> | |
169 | struct result<This(Expr &)> | |
170 | { | |
171 | typedef proto::detail::flat_view<Expr> type; | |
172 | }; | |
173 | ||
174 | template<typename Expr> | |
175 | proto::detail::flat_view<Expr> const | |
176 | operator ()(Expr &e) const | |
177 | { | |
178 | return proto::detail::flat_view<Expr>(e); | |
179 | } | |
180 | ||
181 | template<typename Expr> | |
182 | proto::detail::flat_view<Expr const> const | |
183 | operator ()(Expr const &e) const | |
184 | { | |
185 | return proto::detail::flat_view<Expr const>(e); | |
186 | } | |
187 | }; | |
188 | } | |
189 | ||
190 | /// \brief A function that returns a "flattened" | |
191 | /// view of a Proto expression tree. | |
192 | /// | |
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 | |
203 | flatten(Expr &e) | |
204 | { | |
205 | return proto::detail::flat_view<Expr>(e); | |
206 | } | |
207 | ||
208 | /// \overload | |
209 | /// | |
210 | template<typename Expr> | |
211 | proto::detail::flat_view<Expr const> const | |
212 | flatten(Expr const &e) | |
213 | { | |
214 | return proto::detail::flat_view<Expr const>(e); | |
215 | } | |
216 | ||
217 | /// INTERNAL ONLY | |
218 | /// | |
219 | template<typename Context> | |
220 | struct eval_fun | |
221 | : proto::callable | |
222 | { | |
223 | explicit eval_fun(Context &ctx) | |
224 | : ctx_(ctx) | |
225 | {} | |
226 | ||
227 | template<typename Sig> | |
228 | struct result; | |
229 | ||
230 | template<typename This, typename Expr> | |
231 | struct result<This(Expr)> | |
232 | : result<This(Expr const &)> | |
233 | {}; | |
234 | ||
235 | template<typename This, typename Expr> | |
236 | struct result<This(Expr &)> | |
237 | : proto::result_of::eval<Expr, Context> | |
238 | {}; | |
239 | ||
240 | template<typename Expr> | |
241 | typename proto::result_of::eval<Expr, Context>::type | |
242 | operator ()(Expr &e) const | |
243 | { | |
244 | return proto::eval(e, this->ctx_); | |
245 | } | |
246 | ||
247 | template<typename Expr> | |
248 | typename proto::result_of::eval<Expr const, Context>::type | |
249 | operator ()(Expr const &e) const | |
250 | { | |
251 | return proto::eval(e, this->ctx_); | |
252 | } | |
253 | ||
254 | private: | |
255 | Context &ctx_; | |
256 | }; | |
257 | ||
258 | /// INTERNAL ONLY | |
259 | /// | |
260 | template<typename Context> | |
261 | struct is_callable<eval_fun<Context> > | |
262 | : mpl::true_ | |
263 | {}; | |
264 | }} | |
265 | ||
266 | namespace boost { namespace fusion | |
267 | { | |
268 | namespace extension | |
269 | { | |
270 | template<typename Tag> | |
271 | struct is_sequence_impl; | |
272 | ||
273 | template<typename Tag, typename Domain> | |
274 | struct is_sequence_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
275 | { | |
276 | template<typename Sequence> | |
277 | struct apply | |
278 | : mpl::true_ | |
279 | {}; | |
280 | }; | |
281 | ||
282 | template<typename Tag, typename Domain> | |
283 | struct is_sequence_impl<proto::tag::proto_expr<Tag, Domain> > | |
284 | { | |
285 | template<typename Sequence> | |
286 | struct apply | |
287 | : mpl::true_ | |
288 | {}; | |
289 | }; | |
290 | ||
291 | template<typename Tag> | |
292 | struct is_view_impl; | |
293 | ||
294 | template<typename Tag, typename Domain> | |
295 | struct is_view_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
296 | { | |
297 | template<typename Sequence> | |
298 | struct apply | |
299 | : mpl::true_ | |
300 | {}; | |
301 | }; | |
302 | ||
303 | template<typename Tag, typename Domain> | |
304 | struct is_view_impl<proto::tag::proto_expr<Tag, Domain> > | |
305 | { | |
306 | template<typename Sequence> | |
307 | struct apply | |
308 | : mpl::false_ | |
309 | {}; | |
310 | }; | |
311 | ||
312 | template<typename Tag> | |
313 | struct value_of_impl; | |
314 | ||
315 | template<typename Tag, typename Domain> | |
316 | struct value_of_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
317 | { | |
318 | template< | |
319 | typename Iterator | |
320 | , long Arity = proto::arity_of<typename Iterator::expr_type>::value | |
321 | > | |
322 | struct apply | |
323 | { | |
324 | typedef | |
325 | typename proto::result_of::child_c< | |
326 | typename Iterator::expr_type | |
327 | , Iterator::index | |
328 | >::value_type | |
329 | type; | |
330 | }; | |
331 | ||
332 | template<typename Iterator> | |
333 | struct apply<Iterator, 0> | |
334 | { | |
335 | typedef | |
336 | typename proto::result_of::value< | |
337 | typename Iterator::expr_type | |
338 | >::value_type | |
339 | type; | |
340 | }; | |
341 | }; | |
342 | ||
343 | template<typename Tag> | |
344 | struct deref_impl; | |
345 | ||
346 | template<typename Tag, typename Domain> | |
347 | struct deref_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
348 | { | |
349 | template< | |
350 | typename Iterator | |
351 | , long Arity = proto::arity_of<typename Iterator::expr_type>::value | |
352 | > | |
353 | struct apply | |
354 | { | |
355 | typedef | |
356 | typename proto::result_of::child_c< | |
357 | typename Iterator::expr_type & | |
358 | , Iterator::index | |
359 | >::type | |
360 | type; | |
361 | ||
362 | static type call(Iterator const &iter) | |
363 | { | |
364 | return proto::child_c<Iterator::index>(iter.expr); | |
365 | } | |
366 | }; | |
367 | ||
368 | template<typename Iterator> | |
369 | struct apply<Iterator, 0> | |
370 | { | |
371 | typedef | |
372 | typename proto::result_of::value< | |
373 | typename Iterator::expr_type & | |
374 | >::type | |
375 | type; | |
376 | ||
377 | static type call(Iterator const &iter) | |
378 | { | |
379 | return proto::value(iter.expr); | |
380 | } | |
381 | }; | |
382 | }; | |
383 | ||
384 | template<typename Tag> | |
385 | struct advance_impl; | |
386 | ||
387 | template<typename Tag, typename Domain> | |
388 | struct advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
389 | { | |
390 | template<typename Iterator, typename N> | |
391 | struct apply | |
392 | { | |
393 | typedef | |
394 | proto::detail::expr_iterator< | |
395 | typename Iterator::expr_type | |
396 | , Iterator::index + N::value | |
397 | > | |
398 | type; | |
399 | ||
400 | static type call(Iterator const &iter) | |
401 | { | |
402 | return type(iter.expr); | |
403 | } | |
404 | }; | |
405 | }; | |
406 | ||
407 | template<typename Tag> | |
408 | struct distance_impl; | |
409 | ||
410 | template<typename Tag, typename Domain> | |
411 | struct distance_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
412 | { | |
413 | template<typename IteratorFrom, typename IteratorTo> | |
414 | struct apply | |
415 | : mpl::long_<IteratorTo::index - IteratorFrom::index> | |
416 | {}; | |
417 | }; | |
418 | ||
419 | template<typename Tag> | |
420 | struct next_impl; | |
421 | ||
422 | template<typename Tag, typename Domain> | |
423 | struct next_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
424 | { | |
425 | template<typename Iterator> | |
426 | struct apply | |
427 | : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<1> > | |
428 | {}; | |
429 | }; | |
430 | ||
431 | template<typename Tag> | |
432 | struct prior_impl; | |
433 | ||
434 | template<typename Tag, typename Domain> | |
435 | struct prior_impl<proto::tag::proto_expr_iterator<Tag, Domain> > | |
436 | { | |
437 | template<typename Iterator> | |
438 | struct apply | |
439 | : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<-1> > | |
440 | {}; | |
441 | }; | |
442 | ||
443 | template<typename Tag> | |
444 | struct category_of_impl; | |
445 | ||
446 | template<typename Tag, typename Domain> | |
447 | struct category_of_impl<proto::tag::proto_expr<Tag, Domain> > | |
448 | { | |
449 | template<typename Sequence> | |
450 | struct apply | |
451 | { | |
452 | typedef random_access_traversal_tag type; | |
453 | }; | |
454 | }; | |
455 | ||
456 | template<typename Tag> | |
457 | struct size_impl; | |
458 | ||
459 | template<typename Tag, typename Domain> | |
460 | struct size_impl<proto::tag::proto_expr<Tag, Domain> > | |
461 | { | |
462 | template<typename Sequence> | |
463 | struct apply | |
464 | : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c> | |
465 | {}; | |
466 | }; | |
467 | ||
468 | template<typename Tag> | |
469 | struct begin_impl; | |
470 | ||
471 | template<typename Tag, typename Domain> | |
472 | struct begin_impl<proto::tag::proto_expr<Tag, Domain> > | |
473 | { | |
474 | template<typename Sequence> | |
475 | struct apply | |
476 | { | |
477 | typedef proto::detail::expr_iterator<Sequence, 0> type; | |
478 | ||
479 | static type call(Sequence &seq) | |
480 | { | |
481 | return type(seq); | |
482 | } | |
483 | }; | |
484 | }; | |
485 | ||
486 | template<typename Tag> | |
487 | struct end_impl; | |
488 | ||
489 | template<typename Tag, typename Domain> | |
490 | struct end_impl<proto::tag::proto_expr<Tag, Domain> > | |
491 | { | |
492 | template<typename Sequence> | |
493 | struct apply | |
494 | { | |
495 | typedef | |
496 | proto::detail::expr_iterator< | |
497 | Sequence | |
498 | , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c | |
499 | > | |
500 | type; | |
501 | ||
502 | static type call(Sequence &seq) | |
503 | { | |
504 | return type(seq); | |
505 | } | |
506 | }; | |
507 | }; | |
508 | ||
509 | template<typename Tag> | |
510 | struct value_at_impl; | |
511 | ||
512 | template<typename Tag, typename Domain> | |
513 | struct value_at_impl<proto::tag::proto_expr<Tag, Domain> > | |
514 | { | |
515 | template< | |
516 | typename Sequence | |
517 | , typename Index | |
518 | , long Arity = proto::arity_of<Sequence>::value | |
519 | > | |
520 | struct apply | |
521 | { | |
522 | typedef | |
523 | typename proto::result_of::child_c< | |
524 | Sequence | |
525 | , Index::value | |
526 | >::value_type | |
527 | type; | |
528 | }; | |
529 | ||
530 | template<typename Sequence, typename Index> | |
531 | struct apply<Sequence, Index, 0> | |
532 | { | |
533 | typedef | |
534 | typename proto::result_of::value< | |
535 | Sequence | |
536 | >::value_type | |
537 | type; | |
538 | }; | |
539 | }; | |
540 | ||
541 | template<typename Tag> | |
542 | struct at_impl; | |
543 | ||
544 | template<typename Tag, typename Domain> | |
545 | struct at_impl<proto::tag::proto_expr<Tag, Domain> > | |
546 | { | |
547 | template< | |
548 | typename Sequence | |
549 | , typename Index | |
550 | , long Arity = proto::arity_of<Sequence>::value | |
551 | > | |
552 | struct apply | |
553 | { | |
554 | typedef | |
555 | typename proto::result_of::child_c< | |
556 | Sequence & | |
557 | , Index::value | |
558 | >::type | |
559 | type; | |
560 | ||
561 | static type call(Sequence &seq) | |
562 | { | |
563 | return proto::child_c<Index::value>(seq); | |
564 | } | |
565 | }; | |
566 | ||
567 | template<typename Sequence, typename Index> | |
568 | struct apply<Sequence, Index, 0> | |
569 | { | |
570 | typedef | |
571 | typename proto::result_of::value< | |
572 | Sequence & | |
573 | >::type | |
574 | type; | |
575 | ||
576 | static type call(Sequence &seq) | |
577 | { | |
578 | return proto::value(seq); | |
579 | } | |
580 | }; | |
581 | }; | |
582 | ||
583 | template<typename Tag> | |
584 | struct convert_impl; | |
585 | ||
586 | template<typename Tag, typename Domain> | |
587 | struct convert_impl<proto::tag::proto_expr<Tag, Domain> > | |
588 | { | |
589 | template<typename Sequence> | |
590 | struct apply | |
591 | { | |
592 | typedef | |
593 | typename proto::result_of::unpack_expr< | |
594 | Tag | |
595 | , Domain | |
596 | , Sequence | |
597 | >::type | |
598 | type; | |
599 | ||
600 | static type call(Sequence& seq) | |
601 | { | |
602 | return proto::unpack_expr<Tag, Domain>(seq); | |
603 | } | |
604 | }; | |
605 | }; | |
606 | ||
607 | template<typename Tag, typename Domain> | |
608 | struct convert_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
609 | { | |
610 | template<typename Sequence> | |
611 | struct apply | |
612 | { | |
613 | typedef | |
614 | typename proto::result_of::unpack_expr< | |
615 | Tag | |
616 | , Domain | |
617 | , Sequence | |
618 | >::type | |
619 | type; | |
620 | ||
621 | static type call(Sequence& seq) | |
622 | { | |
623 | return proto::unpack_expr<Tag, Domain>(seq); | |
624 | } | |
625 | }; | |
626 | }; | |
627 | ||
628 | template<typename Tag> | |
629 | struct is_segmented_impl; | |
630 | ||
631 | template<typename Tag, typename Domain> | |
632 | struct is_segmented_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
633 | { | |
634 | template<typename Iterator> | |
635 | struct apply | |
636 | : mpl::true_ | |
637 | {}; | |
638 | }; | |
639 | ||
640 | template<typename Tag> | |
641 | struct segments_impl; | |
642 | ||
643 | template<typename Tag, typename Domain> | |
644 | struct segments_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
645 | { | |
646 | template<typename Sequence> | |
647 | struct apply | |
648 | { | |
649 | typedef typename Sequence::segments_type const &type; | |
650 | ||
651 | static type call(Sequence &sequence) | |
652 | { | |
653 | return sequence.segs_; | |
654 | } | |
655 | }; | |
656 | }; | |
657 | ||
658 | template<typename Tag, typename Domain> | |
659 | struct category_of_impl<proto::tag::proto_flat_view<Tag, Domain> > | |
660 | { | |
661 | template<typename Sequence> | |
662 | struct apply | |
663 | { | |
664 | typedef forward_traversal_tag type; | |
665 | }; | |
666 | }; | |
667 | } | |
668 | ||
669 | namespace traits | |
670 | { | |
671 | template<typename Seq1, typename Seq2> | |
672 | struct enable_equality< | |
673 | Seq1 | |
674 | , Seq2 | |
675 | , typename enable_if_c< | |
676 | mpl::or_< | |
677 | proto::is_expr<Seq1> | |
678 | , proto::is_expr<Seq2> | |
679 | >::value | |
680 | >::type | |
681 | > | |
682 | : mpl::false_ | |
683 | {}; | |
684 | ||
685 | template<typename Seq1, typename Seq2> | |
686 | struct enable_comparison< | |
687 | Seq1 | |
688 | , Seq2 | |
689 | , typename enable_if_c< | |
690 | mpl::or_< | |
691 | proto::is_expr<Seq1> | |
692 | , proto::is_expr<Seq2> | |
693 | >::value | |
694 | >::type | |
695 | > | |
696 | : mpl::false_ | |
697 | {}; | |
698 | } | |
699 | }} | |
700 | ||
701 | namespace boost { namespace mpl | |
702 | { | |
703 | template<typename Tag, typename Args, long Arity> | |
704 | struct sequence_tag< proto::expr<Tag, Args, Arity> > | |
705 | { | |
706 | typedef fusion::fusion_sequence_tag type; | |
707 | }; | |
708 | ||
709 | template<typename Tag, typename Args, long Arity> | |
710 | struct sequence_tag< proto::basic_expr<Tag, Args, Arity> > | |
711 | { | |
712 | typedef fusion::fusion_sequence_tag type; | |
713 | }; | |
714 | }} | |
715 | ||
716 | #ifdef BOOST_MSVC | |
717 | #pragma warning(pop) | |
718 | #endif | |
719 | ||
720 | #endif |