Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2007-11-13 02:29:29


Author: eric_niebler
Date: 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
New Revision: 41053
URL: http://svn.boost.org/trac/boost/changeset/41053

Log:
add flatten() for a segmented proto tree iteration
Text files modified:
   branches/proto/v3/boost/xpressive/proto3/expr.hpp | 25 ++++++
   branches/proto/v3/boost/xpressive/proto3/fusion.hpp | 147 +++++++++++++++++++++++++++++++++++++++
   branches/proto/v3/boost/xpressive/proto3/proto_fwd.hpp | 3
   branches/proto/v3/boost/xpressive/proto3/tags.hpp | 1
   branches/proto/v3/libs/xpressive/proto3/test/Jamfile.v2 | 4
   branches/proto/v3/libs/xpressive/proto3/test/proto_fusion.cpp | 36 +++++----
   branches/proto/v3/libs/xpressive/proto3/test/proto_fusion_s.cpp | 72 ++++++++++---------
   7 files changed, 234 insertions(+), 54 deletions(-)

Modified: branches/proto/v3/boost/xpressive/proto3/expr.hpp
==============================================================================
--- branches/proto/v3/boost/xpressive/proto3/expr.hpp (original)
+++ branches/proto/v3/boost/xpressive/proto3/expr.hpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -12,6 +12,7 @@
 #include <cstddef>
 #include <boost/type_traits.hpp>
 #include <boost/utility/enable_if.hpp>
+#include <boost/utility/addressof.hpp>
 #include <boost/xpressive/proto3/proto_fwd.hpp>
 #include <boost/xpressive/proto3/tags.hpp>
 #include <boost/xpressive/proto3/traits.hpp>
@@ -23,6 +24,18 @@
     {
         namespace detail
         {
+ template<typename Tag, typename Arg>
+ struct address_of_hack
+ {
+ typedef address_of_hack type;
+ };
+
+ template<typename Expr>
+ struct address_of_hack<tag::address_of, Expr &>
+ {
+ typedef Expr *type;
+ };
+
             template<typename X, std::size_t N, typename Y>
             void checked_copy(X (&x)[N], Y (&y)[N])
             {
@@ -76,6 +89,7 @@
                 return that;
             }
 
+ // necessary for terminals that store arrays by value
             template<typename A, std::size_t N>
             static expr make(
                 A (&a)[N]
@@ -100,6 +114,17 @@
                 return *this;
             }
 
+ typedef
+ typename
+ exprns_::detail::address_of_hack<Tag, typename Args::cons_type::car_type>
+ ::type
+ address_of_hack_type_;
+
+ operator address_of_hack_type_() const
+ {
+ return boost::addressof(this->arg0.expr);
+ }
+
             template<typename A>
             expr<tag::assign, args<expr &, typename result_of::as_arg<A>::type> >
             operator=(A &&a)

Modified: branches/proto/v3/boost/xpressive/proto3/fusion.hpp
==============================================================================
--- branches/proto/v3/boost/xpressive/proto3/fusion.hpp (original)
+++ branches/proto/v3/boost/xpressive/proto3/fusion.hpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 /// \file fusion.hpp
-/// Make any Proto parse tree a valid Fusion sequence
+/// Make any Proto expression a valid Fusion sequence
 //
 // Copyright 2007 Eric Niebler. Distributed under the Boost
 // Software License, Version 1.0. (See accompanying file
@@ -9,15 +9,32 @@
 #ifndef BOOST_PROTO3_FUSION_HPP_EAN_11_04_2006
 #define BOOST_PROTO3_FUSION_HPP_EAN_11_04_2006
 
+#include <boost/type_traits.hpp>
 #include <boost/mpl/long.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/mpl.hpp>
 #include <boost/fusion/include/intrinsic.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/xpressive/proto3/proto_fwd.hpp>
 #include <boost/xpressive/proto3/traits.hpp>
 
+#define UNCV(x)\
+ typename remove_cv<x>::type
+
+#define UNREF(x)\
+ typename remove_reference<x>::type
+
+#define UNCVREF(x)\
+ UNCV(UNREF(x))
+
 namespace boost { namespace proto
 {
 
@@ -42,6 +59,26 @@
 
     }
 
+ 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 &expr)
+ : expr_(expr)
+ {}
+
+ Expr &expr_;
+ };
+
+ template<typename Expr>
+ flat_view<Expr const> flatten(Expr const &expr)
+ {
+ return flat_view<Expr const>(expr);
+ }
 }}
 
 namespace boost { namespace fusion
@@ -54,6 +91,15 @@
         struct is_view_impl;
 
         template<>
+ struct is_view_impl<proto::tag::proto_flat_view>
+ {
+ template<typename Iterator>
+ struct apply
+ : mpl::true_
+ {};
+ };
+
+ template<>
         struct is_view_impl<proto::tag::proto_expr>
         {
             template<typename Iterator>
@@ -225,8 +271,107 @@
             };
         };
 
+ 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 as_element
+ {
+ template<typename Sig>
+ struct result {};
+
+ template<typename This, typename Expr>
+ struct result<This(Expr)>
+ : mpl::if_<
+ is_same<Tag, UNREF(Expr)::proto_tag>
+ , proto::flat_view<UNREF(Expr) const>
+ , fusion::single_view<UNREF(Expr) const &>
+ >
+ {};
+
+ template<typename Expr>
+ typename result<as_element(Expr)>::type
+ operator()(Expr &expr) const
+ {
+ return typename result<as_element(Expr)>::type(expr);
+ }
+ };
+
+ 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
+ , as_element<proto_tag>
+ > type;
+
+ static type call(Sequence &sequence)
+ {
+ return type(sequence.expr_, 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>
+ {};
+ };
+
     }
 
 }}
 
+#undef UNCV
+#undef UNREF
+#undef UNCVREF
+
 #endif

Modified: branches/proto/v3/boost/xpressive/proto3/proto_fwd.hpp
==============================================================================
--- branches/proto/v3/boost/xpressive/proto3/proto_fwd.hpp (original)
+++ branches/proto/v3/boost/xpressive/proto3/proto_fwd.hpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -11,6 +11,8 @@
 
 #include <climits> // for INT_MAX
 #include <boost/type_traits.hpp>
+#include <boost/mpl/aux_/template_arity.hpp>
+#include <boost/mpl/aux_/lambda_arity_param.hpp>
 
 namespace boost { namespace proto
 {
@@ -138,6 +140,7 @@
 
         struct proto_expr;
         struct proto_expr_iterator;
+ struct proto_flat_view;
     }
 
     namespace utility

Modified: branches/proto/v3/boost/xpressive/proto3/tags.hpp
==============================================================================
--- branches/proto/v3/boost/xpressive/proto3/tags.hpp (original)
+++ branches/proto/v3/boost/xpressive/proto3/tags.hpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -66,6 +66,7 @@
         // For fusion
         struct proto_expr {};
         struct proto_expr_iterator {};
+ struct proto_flat_view {};
     }
 
 }}

Modified: branches/proto/v3/libs/xpressive/proto3/test/Jamfile.v2
==============================================================================
--- branches/proto/v3/libs/xpressive/proto3/test/Jamfile.v2 (original)
+++ branches/proto/v3/libs/xpressive/proto3/test/Jamfile.v2 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -18,8 +18,8 @@
 
 test-suite "proto"
     :
-# [ run proto_fusion.cpp : : : <toolset>gcc:<cxxflags>-ftemplate-depth-1024 ]
-# [ run proto_fusion_s.cpp ]
+ [ run proto_fusion.cpp : : : <toolset>gcc:<cxxflags>-ftemplate-depth-1024 ]
+ [ run proto_fusion_s.cpp ]
         [ run toy_spirit.cpp ]
         [ run calculator.cpp ]
         [ run lambda.cpp ]

Modified: branches/proto/v3/libs/xpressive/proto3/test/proto_fusion.cpp
==============================================================================
--- branches/proto/v3/libs/xpressive/proto3/test/proto_fusion.cpp (original)
+++ branches/proto/v3/libs/xpressive/proto3/test/proto_fusion.cpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -17,15 +17,15 @@
 #include <boost/utility/addressof.hpp>
 #include <sstream>
 
-boost::proto::terminal<char>::type a_ = {'a'};
-boost::proto::terminal<char>::type b_ = {'b'};
-boost::proto::terminal<char>::type c_ = {'c'};
-boost::proto::terminal<char>::type d_ = {'d'};
-boost::proto::terminal<char>::type e_ = {'e'};
-boost::proto::terminal<char>::type f_ = {'f'};
-boost::proto::terminal<char>::type g_ = {'g'};
-boost::proto::terminal<char>::type h_ = {'h'};
-boost::proto::terminal<char>::type i_ = {'i'};
+boost::proto::terminal<char>::type a_ = {{'a'}};
+boost::proto::terminal<char>::type b_ = {{'b'}};
+boost::proto::terminal<char>::type c_ = {{'c'}};
+boost::proto::terminal<char>::type d_ = {{'d'}};
+boost::proto::terminal<char>::type e_ = {{'e'}};
+boost::proto::terminal<char>::type f_ = {{'f'}};
+boost::proto::terminal<char>::type g_ = {{'g'}};
+boost::proto::terminal<char>::type h_ = {{'h'}};
+boost::proto::terminal<char>::type i_ = {{'i'}};
 
 std::ostream &operator <<(std::ostream &sout, boost::proto::tag::shift_right)
 {
@@ -75,41 +75,43 @@
 
 void test1()
 {
+ using boost::proto::flatten;
+
     std::stringstream sout;
 
     // Test for 1-way branching "tree"
     sout.str("");
- boost::fusion::for_each(!!!!(a_ >> b_), to_string(sout));
+ boost::fusion::for_each(flatten(!!!!(a_ >> b_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)", sout.str());
 
     // Tests for 2-way branching trees
     sout.str("");
- boost::fusion::for_each(a_ >> b_ >> c_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ >> b_ >> c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each(a_ | b_ | c_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ | b_ | c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each(a_ >> b_ | c_ >> d_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each(a_ | b_ >> c_ | d_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ | b_ >> c_ | d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str());
 
     sout.str("");
- boost::fusion::for_each(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_, to_string(sout));
+ boost::fusion::for_each(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str());
 
     // Test for n-way branching tree
     sout.str("");
- boost::fusion::for_each(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_), to_string(sout));
+ boost::fusion::for_each(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str());
 }
 

Modified: branches/proto/v3/libs/xpressive/proto3/test/proto_fusion_s.cpp
==============================================================================
--- branches/proto/v3/libs/xpressive/proto3/test/proto_fusion_s.cpp (original)
+++ branches/proto/v3/libs/xpressive/proto3/test/proto_fusion_s.cpp 2007-11-13 02:29:27 EST (Tue, 13 Nov 2007)
@@ -65,51 +65,53 @@
 
 void test1()
 {
- boost::proto::terminal<char>::type a_ = {'a'};
- boost::proto::terminal<char>::type b_ = {'b'};
- boost::proto::terminal<char>::type c_ = {'c'};
- boost::proto::terminal<char>::type d_ = {'d'};
- boost::proto::terminal<char>::type e_ = {'e'};
- boost::proto::terminal<char>::type f_ = {'f'};
- boost::proto::terminal<char>::type g_ = {'g'};
- boost::proto::terminal<char>::type h_ = {'h'};
- boost::proto::terminal<char>::type i_ = {'i'};
+ using boost::proto::flatten;
+
+ boost::proto::terminal<char>::type a_ = {{'a'}};
+ boost::proto::terminal<char>::type b_ = {{'b'}};
+ boost::proto::terminal<char>::type c_ = {{'c'}};
+ boost::proto::terminal<char>::type d_ = {{'d'}};
+ boost::proto::terminal<char>::type e_ = {{'e'}};
+ boost::proto::terminal<char>::type f_ = {{'f'}};
+ boost::proto::terminal<char>::type g_ = {{'g'}};
+ boost::proto::terminal<char>::type h_ = {{'h'}};
+ boost::proto::terminal<char>::type i_ = {{'i'}};
 
     std::stringstream sout;
 
     // Test for 1-way branching "tree"
     sout.str("");
- boost::fusion::for_each_s(!!!!(a_ >> b_), to_string(sout));
+ boost::fusion::for_each_s(flatten(!!!!(a_ >> b_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)", sout.str());
 
     // Tests for 2-way branching trees
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ >> c_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ >> c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ | b_ | c_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ | b_ | c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ | b_ >> c_ | d_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ | b_ >> c_ | d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str());
 
     // Test for n-way branching tree
     sout.str("");
- boost::fusion::for_each_s(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_), to_string(sout));
+ boost::fusion::for_each_s(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str());
 }
 
@@ -134,51 +136,53 @@
 
 void test2()
 {
- My<boost::proto::terminal<char>::type> a_ = {{'a'}};
- My<boost::proto::terminal<char>::type> b_ = {{'b'}};
- My<boost::proto::terminal<char>::type> c_ = {{'c'}};
- My<boost::proto::terminal<char>::type> d_ = {{'d'}};
- My<boost::proto::terminal<char>::type> e_ = {{'e'}};
- My<boost::proto::terminal<char>::type> f_ = {{'f'}};
- My<boost::proto::terminal<char>::type> g_ = {{'g'}};
- My<boost::proto::terminal<char>::type> h_ = {{'h'}};
- My<boost::proto::terminal<char>::type> i_ = {{'i'}};
+ using boost::proto::flatten;
+
+ My<boost::proto::terminal<char>::type> a_ = {{{'a'}}};
+ My<boost::proto::terminal<char>::type> b_ = {{{'b'}}};
+ My<boost::proto::terminal<char>::type> c_ = {{{'c'}}};
+ My<boost::proto::terminal<char>::type> d_ = {{{'d'}}};
+ My<boost::proto::terminal<char>::type> e_ = {{{'e'}}};
+ My<boost::proto::terminal<char>::type> f_ = {{{'f'}}};
+ My<boost::proto::terminal<char>::type> g_ = {{{'g'}}};
+ My<boost::proto::terminal<char>::type> h_ = {{{'h'}}};
+ My<boost::proto::terminal<char>::type> i_ = {{{'i'}}};
 
     std::stringstream sout;
 
     // Test for 1-way branching "tree"
     sout.str("");
- boost::fusion::for_each_s(!!!!(a_ >> b_), to_string(sout));
+ boost::fusion::for_each_s(flatten(!!!!(a_ >> b_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)", sout.str());
 
     // Tests for 2-way branching trees
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ >> c_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ >> c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ | b_ | c_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ | b_ | c_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ | b_ >> c_ | d_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ | b_ >> c_ | d_), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b>>c)(d)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_ | e_ >> f_ >> g_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f>>g)", sout.str());
 
     sout.str("");
- boost::fusion::for_each_s(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_, to_string(sout));
+ boost::fusion::for_each_s(flatten(a_ >> b_ | c_ >> d_ | e_ >> (f_ | g_) >> h_), to_string(sout));
     BOOST_CHECK_EQUAL("(a>>b)(c>>d)(e>>f|g>>h)", sout.str());
 
     // Test for n-way branching tree
     sout.str("");
- boost::fusion::for_each_s(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_), to_string(sout));
+ boost::fusion::for_each_s(flatten(a_(b_(c_ >> d_, e_ | f_), g_ >> h_)(i_)), to_string(sout));
     BOOST_CHECK_EQUAL("(a)(b)(c>>d)(e|f)(g>>h)(i)", sout.str());
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk