summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/proto/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/proto/test
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/proto/test')
-rw-r--r--src/boost/libs/proto/test/Jamfile.v250
-rw-r--r--src/boost/libs/proto/test/bug2407.cpp51
-rw-r--r--src/boost/libs/proto/test/calculator.cpp109
-rw-r--r--src/boost/libs/proto/test/constrained_ops.cpp131
-rw-r--r--src/boost/libs/proto/test/cpp-next_bug.cpp80
-rw-r--r--src/boost/libs/proto/test/deduce_domain.cpp142
-rw-r--r--src/boost/libs/proto/test/deep_copy.cpp56
-rw-r--r--src/boost/libs/proto/test/display_expr.cpp68
-rw-r--r--src/boost/libs/proto/test/env_var.cpp297
-rw-r--r--src/boost/libs/proto/test/examples.cpp498
-rw-r--r--src/boost/libs/proto/test/external_transforms.cpp185
-rw-r--r--src/boost/libs/proto/test/flatten.cpp211
-rw-r--r--src/boost/libs/proto/test/lambda.cpp188
-rw-r--r--src/boost/libs/proto/test/make.cpp98
-rw-r--r--src/boost/libs/proto/test/make_expr.cpp407
-rw-r--r--src/boost/libs/proto/test/matches.cpp319
-rw-r--r--src/boost/libs/proto/test/mem_ptr.cpp303
-rw-r--r--src/boost/libs/proto/test/mpl.cpp67
-rw-r--r--src/boost/libs/proto/test/noinvoke.cpp116
-rw-r--r--src/boost/libs/proto/test/pack_expansion.cpp124
-rw-r--r--src/boost/libs/proto/test/protect.cpp106
-rw-r--r--src/boost/libs/proto/test/switch.cpp95
-rw-r--r--src/boost/libs/proto/test/toy_spirit.cpp665
-rw-r--r--src/boost/libs/proto/test/toy_spirit2.cpp466
24 files changed, 4832 insertions, 0 deletions
diff --git a/src/boost/libs/proto/test/Jamfile.v2 b/src/boost/libs/proto/test/Jamfile.v2
new file mode 100644
index 00000000..d765eae9
--- /dev/null
+++ b/src/boost/libs/proto/test/Jamfile.v2
@@ -0,0 +1,50 @@
+# (C) Copyright 2004: 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)
+
+# bring in rules for testing
+import testing ;
+
+project
+ : requirements
+ <toolset>intel:<debug-symbols>off
+ <toolset>msvc-7.1:<debug-symbols>off
+ <toolset>msvc-8.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-8.0:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc-9.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-10.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-11.0:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>msvc-11.0:<define>_SCL_SECURE_NO_WARNINGS
+ <toolset>gcc:<cxxflags>-ftemplate-depth-1024
+ <library>/boost/test//boost_unit_test_framework
+ <link>static
+# <define>BOOST_PROTO_DONT_USE_PREPROCESSED_FILES
+ ;
+
+test-suite "proto"
+ :
+ [ run calculator.cpp ]
+ [ run constrained_ops.cpp ]
+ [ run cpp-next_bug.cpp ]
+ [ run deep_copy.cpp ]
+ [ run display_expr.cpp ]
+ [ run deduce_domain.cpp ]
+ [ run env_var.cpp ]
+ [ run examples.cpp ]
+ [ run external_transforms.cpp ]
+ [ run lambda.cpp ]
+ [ run make_expr.cpp ]
+ [ run matches.cpp ]
+ [ run flatten.cpp ]
+ [ run switch.cpp ]
+ [ run toy_spirit.cpp ]
+ [ run toy_spirit2.cpp ]
+ [ run make.cpp ]
+ [ run mem_ptr.cpp : : : <toolset>msvc:<cxxflags>/wd4355 ]
+ [ run mpl.cpp ]
+ [ run noinvoke.cpp ]
+ [ run pack_expansion.cpp ]
+ [ run protect.cpp ]
+ [ compile bug2407.cpp ]
+ ;
+
diff --git a/src/boost/libs/proto/test/bug2407.cpp b/src/boost/libs/proto/test/bug2407.cpp
new file mode 100644
index 00000000..c67bd55c
--- /dev/null
+++ b/src/boost/libs/proto/test/bug2407.cpp
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+// bug2407.hpp
+//
+// 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)
+
+#include <iostream>
+#include <boost/proto/proto.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<class E>
+struct e;
+
+struct g
+ : proto::or_<
+ proto::terminal<int>
+ , proto::plus<g,g>
+ >
+{};
+
+struct d
+ : proto::domain<proto::generator<e>, g>
+{};
+
+template<class E>
+struct e
+ : proto::extends<E, e<E>, d>
+{
+ BOOST_MPL_ASSERT((proto::matches<E, g>));
+
+ e(E const &x = E())
+ : proto::extends<E, e<E>, d>(x)
+ {}
+};
+
+e<proto::terminal<int>::type> i;
+
+template<class E>
+std::ostream &operator<<(std::ostream &sout, e<E> const &x)
+{
+ return sout;
+}
+
+int main()
+{
+ std::cout << (i+i);
+}
diff --git a/src/boost/libs/proto/test/calculator.cpp b/src/boost/libs/proto/test/calculator.cpp
new file mode 100644
index 00000000..ceea6c72
--- /dev/null
+++ b/src/boost/libs/proto/test/calculator.cpp
@@ -0,0 +1,109 @@
+///////////////////////////////////////////////////////////////////////////////
+// calculator.hpp
+//
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost;
+
+struct placeholder {};
+proto::terminal<placeholder>::type const _1 = {{}};
+
+struct calculator : proto::callable_context<calculator const>
+{
+ typedef int result_type;
+
+ calculator(int i)
+ : i_(i)
+ {}
+
+ int operator ()(proto::tag::terminal, placeholder) const
+ {
+ return this->i_;
+ }
+
+ int operator ()(proto::tag::terminal, int j) const
+ {
+ return j;
+ }
+
+ template<typename Left, typename Right>
+ int operator ()(proto::tag::plus, Left const &left, Right const &right) const
+ {
+ return proto::eval(left, *this) + proto::eval(right, *this);
+ }
+
+ template<typename Left, typename Right>
+ int operator ()(proto::tag::minus, Left const &left, Right const &right) const
+ {
+ return proto::eval(left, *this) - proto::eval(right, *this);
+ }
+
+ template<typename Left, typename Right>
+ int operator ()(proto::tag::multiplies, Left const &left, Right const &right) const
+ {
+ return proto::eval(left, *this) * proto::eval(right, *this);
+ }
+
+ template<typename Left, typename Right>
+ int operator ()(proto::tag::divides, Left const &left, Right const &right) const
+ {
+ return proto::eval(left, *this) / proto::eval(right, *this);
+ }
+
+private:
+ int i_;
+};
+
+template<typename Fun, typename Expr>
+struct functional
+{
+ typedef typename proto::result_of::eval<Expr, Fun>::type result_type;
+
+ functional(Expr const &expr)
+ : expr_(expr)
+ {}
+
+ template<typename T>
+ result_type operator ()(T const &t) const
+ {
+ Fun fun(t);
+ return proto::eval(this->expr_, fun);
+ }
+
+private:
+ Expr const &expr_;
+};
+
+template<typename Fun, typename Expr>
+functional<Fun, Expr> as(Expr const &expr)
+{
+ return functional<Fun, Expr>(expr);
+}
+
+void test_calculator()
+{
+ BOOST_CHECK_EQUAL(10, proto::eval(((_1 + 42)-3)/4, calculator(1)));
+ BOOST_CHECK_EQUAL(11, proto::eval(((_1 + 42)-3)/4, calculator(5)));
+
+ BOOST_CHECK_EQUAL(10, as<calculator>(((_1 + 42)-3)/4)(1));
+ BOOST_CHECK_EQUAL(11, as<calculator>(((_1 + 42)-3)/4)(5));
+}
+
+using namespace unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test immediate evaluation of proto parse trees");
+
+ test->add(BOOST_TEST_CASE(&test_calculator));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/constrained_ops.cpp b/src/boost/libs/proto/test/constrained_ops.cpp
new file mode 100644
index 00000000..c638ddc3
--- /dev/null
+++ b/src/boost/libs/proto/test/constrained_ops.cpp
@@ -0,0 +1,131 @@
+///////////////////////////////////////////////////////////////////////////////
+// constrained_ops.cpp
+//
+// Copyright 2010 Thomas Heller
+// Copyright 2011 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)
+
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost;
+
+typedef proto::terminal<int>::type term;
+
+struct equation;
+
+struct addition:
+ proto::or_
+ <
+ proto::terminal<proto::_>,
+ proto::plus<addition, addition>
+ >
+{};
+
+struct equation:
+ proto::or_
+ <
+ proto::equal_to<addition, addition>
+ >
+{};
+
+template<class Expr>
+struct extension;
+
+struct my_domain:
+ proto::domain
+ <
+ proto::pod_generator<extension>,
+ equation,
+ proto::default_domain
+ >
+{};
+
+template<class Expr>
+struct lhs_extension;
+
+struct my_lhs_domain:
+ proto::domain
+ <
+ proto::pod_generator<lhs_extension>,
+ addition,
+ my_domain
+ >
+{};
+
+template<class Expr>
+struct rhs_extension;
+
+struct my_rhs_domain:
+ proto::domain
+ <
+ proto::pod_generator<rhs_extension>,
+ addition,
+ my_domain
+ >
+{};
+
+template<class Expr>
+struct extension
+{
+ BOOST_PROTO_BASIC_EXTENDS(
+ Expr
+ , extension<Expr>
+ , my_domain
+ )
+
+ void test() const
+ {}
+};
+
+template<class Expr>
+struct lhs_extension
+{
+ BOOST_PROTO_BASIC_EXTENDS(
+ Expr
+ , lhs_extension<Expr>
+ , my_lhs_domain
+ )
+};
+
+template<class Expr>
+struct rhs_extension
+{
+ BOOST_PROTO_BASIC_EXTENDS(
+ Expr
+ , rhs_extension<Expr>
+ , my_rhs_domain
+ )
+};
+
+void test_constrained_ops()
+{
+ lhs_extension<term> const i = {};
+ rhs_extension<term> const j = {};
+
+ proto::assert_matches_not<equation>(i); // false
+ proto::assert_matches_not<equation>(j); // false
+ proto::assert_matches_not<equation>(i + i); // false
+ proto::assert_matches_not<equation>(j + j); // false
+#if 0
+ proto::assert_matches_not<equation>(i + j); // compile error (by design)
+ proto::assert_matches_not<equation>(j + i); // compile error (by design)
+#endif
+ proto::assert_matches<equation>(i == j); // true
+ proto::assert_matches<equation>(i == j + j); // true
+ proto::assert_matches<equation>(i + i == j); // true
+ proto::assert_matches<equation>(i + i == j + j); // true
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test constrained EDSLs");
+ test->add(BOOST_TEST_CASE(&test_constrained_ops));
+ return test;
+}
diff --git a/src/boost/libs/proto/test/cpp-next_bug.cpp b/src/boost/libs/proto/test/cpp-next_bug.cpp
new file mode 100644
index 00000000..2f4b8b47
--- /dev/null
+++ b/src/boost/libs/proto/test/cpp-next_bug.cpp
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+// cpp-next_bug.hpp
+//
+// Copyright 2012 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)
+
+#include <vector>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+namespace linear_algebra
+{
+ // A trait that returns true only for std::vector
+ template<typename T>
+ struct is_std_vector
+ : mpl::false_
+ {};
+
+ template<typename T, typename A>
+ struct is_std_vector<std::vector<T, A> >
+ : mpl::true_
+ {};
+
+ // A type used as a domain for linear algebra expressions
+ struct linear_algebra_domain
+ : proto::domain<>
+ {};
+
+ // Define all the operator overloads for combining std::vectors
+ BOOST_PROTO_DEFINE_OPERATORS(is_std_vector, linear_algebra_domain)
+
+ // Take any expression and turn each node
+ // into a subscript expression, using the
+ // state as the RHS.
+ struct Distribute
+ : proto::or_<
+ proto::when<proto::terminal<_>, proto::_make_subscript(_, proto::_state)>
+ , proto::plus<Distribute, Distribute>
+ >
+ {};
+
+ struct Optimize
+ : proto::or_<
+ proto::when<
+ proto::subscript<Distribute, proto::terminal<_> >,
+ Distribute(proto::_left, proto::_right)
+ >
+ , proto::plus<Optimize, Optimize>
+ , proto::terminal<_>
+ >
+ {};
+}
+
+static const int celems = 4;
+static int const value[celems] = {1,2,3,4};
+std::vector<int> A(value, value+celems), B(A);
+
+void test1()
+{
+ using namespace linear_algebra;
+ proto::_default<> eval;
+ BOOST_CHECK_EQUAL(8, eval(Optimize()((A + B)[3])));
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for a problem reported on the cpp-next.com blog");
+
+ test->add(BOOST_TEST_CASE(&test1));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/deduce_domain.cpp b/src/boost/libs/proto/test/deduce_domain.cpp
new file mode 100644
index 00000000..47215fdc
--- /dev/null
+++ b/src/boost/libs/proto/test/deduce_domain.cpp
@@ -0,0 +1,142 @@
+///////////////////////////////////////////////////////////////////////////////
+// deduce_domain.hpp
+//
+// 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)
+
+// Avoid a compile-time check inside the deduce_domain code.
+#define BOOST_PROTO_ASSERT_VALID_DOMAIN(DOM) typedef DOM DOM ## _
+
+#include <boost/proto/core.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace proto = boost::proto;
+using proto::_;
+
+struct D0 : proto::domain<>
+{
+};
+
+struct D1 : proto::domain<proto::default_generator, _, D0>
+{
+};
+
+struct D2 : proto::domain<proto::default_generator, _, D0>
+{
+};
+
+struct D3 : proto::domain<>
+{
+};
+
+struct DD0 : proto::domain<proto::default_generator, _, proto::default_domain>
+{
+};
+
+struct DD1 : proto::domain<proto::default_generator, _, proto::default_domain>
+{
+};
+
+struct DD2 : proto::domain<proto::default_generator, _, proto::default_domain>
+{
+};
+
+struct DD3 : proto::domain<proto::default_generator, _, DD2>
+{
+};
+
+struct DD4 : proto::domain<proto::default_generator, _, DD2>
+{
+};
+
+void test1()
+{
+ using boost::is_same;
+
+ //*
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, D0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, proto::default_domain, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D0, proto::default_domain>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, proto::default_domain, proto::default_domain>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, D0, proto::default_domain>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, proto::default_domain, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, proto::default_domain, proto::default_domain>::type, proto::default_domain>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, D0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, DD0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D0, DD0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, DD0, DD0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, D0, DD0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, DD0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, DD0, DD0>::type, DD0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, proto::default_domain, DD0>::type, DD0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, DD0, proto::default_domain>::type, DD0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, proto::default_domain, DD0>::type, DD0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<proto::default_domain, DD0, proto::default_domain>::type, DD0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, DD0, proto::default_domain>::type, DD0>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D0, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D1, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D1, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D0, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D0, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D1, D0>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D1, D1>::type, D1>));
+
+ // Very tricky to get right
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D2, D2, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D2, D1, D2>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D2, D1, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D2, D2>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D2, D1>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D1, D2>::type, D0>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D1, D1>::type, D1>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D3, D0, D0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D3, D0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D0, D3>::type, proto::detail::not_a_domain>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D3, D1, D0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D3, D0, D1>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D3, D0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D3, D1>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D0, D1, D3>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D0, D3>::type, proto::detail::not_a_domain>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D3, D1, D2>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D3, D2, D1>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D3, D2>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D2, D3, D1>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D2, D1, D3>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<D1, D2, D3>::type, proto::detail::not_a_domain>));
+
+ // These should be ambiguous.
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD1, DD0, DD0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, DD1, DD0>::type, proto::detail::not_a_domain>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD0, DD0, DD1>::type, proto::detail::not_a_domain>));
+
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD3, DD2, DD2>::type, DD2>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD2, DD3, DD2>::type, DD2>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD2, DD2, DD3>::type, DD2>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD3, DD4, DD4>::type, DD2>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD4, DD3, DD4>::type, DD2>));
+ BOOST_MPL_ASSERT((is_same<proto::detail::common_domain3<DD4, DD4, DD3>::type, DD2>));
+ //*/
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test deducing domains from sub-domains");
+
+ test->add(BOOST_TEST_CASE(&test1));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/deep_copy.cpp b/src/boost/libs/proto/test/deep_copy.cpp
new file mode 100644
index 00000000..42d75282
--- /dev/null
+++ b/src/boost/libs/proto/test/deep_copy.cpp
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+// deep_copy.hpp
+//
+// 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)
+
+#include <iostream>
+#include <boost/utility/addressof.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost;
+
+void foo() {}
+
+void test1()
+{
+ using namespace proto;
+
+ int i = 42;
+ terminal<int &>::type t1 = {i};
+ terminal<int>::type r1 = deep_copy(t1);
+ BOOST_CHECK_EQUAL(42, value(r1));
+
+ plus<terminal<int>::type, terminal<int>::type>::type r2 = deep_copy(t1 + 24);
+ BOOST_CHECK_EQUAL(42, value(left(r2)));
+ BOOST_CHECK_EQUAL(24, value(right(r2)));
+
+ char buf[16] = {'\0'};
+ terminal<char (&)[16]>::type t3 = {buf};
+ terminal<char[16]>::type r3 = deep_copy(t3);
+
+ terminal<void(&)()>::type t4 = {foo};
+ plus<terminal<void(&)()>::type, terminal<int>::type>::type r4 = deep_copy(t4 + t1);
+ BOOST_CHECK_EQUAL(42, value(right(r4)));
+ BOOST_CHECK_EQUAL(&foo, &value(left(r4)));
+
+ terminal<std::ostream &>::type cout_ = {std::cout};
+ shift_left<terminal<std::ostream &>::type, terminal<int>::type>::type r5 = deep_copy(cout_ << t1);
+ BOOST_CHECK_EQUAL(42, value(right(r5)));
+ BOOST_CHECK_EQUAL(boost::addressof(std::cout), boost::addressof(value(left(r5))));
+}
+
+using namespace unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test deep_copy of proto parse trees");
+
+ test->add(BOOST_TEST_CASE(&test1));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/display_expr.cpp b/src/boost/libs/proto/test/display_expr.cpp
new file mode 100644
index 00000000..05c47ff5
--- /dev/null
+++ b/src/boost/libs/proto/test/display_expr.cpp
@@ -0,0 +1,68 @@
+///////////////////////////////////////////////////////////////////////////////
+// display_expr.cpp
+//
+// Copyright 2010 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)
+
+#include <sstream>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+struct A {};
+struct B : A {};
+std::ostream& operator<<( std::ostream& out, const A& ) { return out << "this is A!"; }
+
+struct C {};
+
+void test_display_expr()
+{
+ // https://svn.boost.org/trac/boost/ticket/4910
+ proto::terminal<int>::type i = {0};
+
+ {
+ std::stringstream sout;
+ proto::display_expr(i + A(), sout);
+ BOOST_CHECK_EQUAL(sout.str(), std::string(
+ "plus(\n"
+ " terminal(0)\n"
+ " , terminal(this is A!)\n"
+ ")\n"));
+ }
+
+ {
+ std::stringstream sout;
+ proto::display_expr(i + B(), sout);
+ BOOST_CHECK_EQUAL(sout.str(), std::string(
+ "plus(\n"
+ " terminal(0)\n"
+ " , terminal(this is A!)\n"
+ ")\n"));
+ }
+
+ {
+ std::stringstream sout;
+ char const * Cname = BOOST_CORE_TYPEID(C).name();
+ proto::display_expr(i + C(), sout);
+ BOOST_CHECK_EQUAL(sout.str(), std::string(
+ "plus(\n"
+ " terminal(0)\n"
+ " , terminal(") + Cname + std::string(")\n"
+ ")\n"));
+ }
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test display_expr() function");
+ test->add(BOOST_TEST_CASE(&test_display_expr));
+ return test;
+}
diff --git a/src/boost/libs/proto/test/env_var.cpp b/src/boost/libs/proto/test/env_var.cpp
new file mode 100644
index 00000000..14ce8be9
--- /dev/null
+++ b/src/boost/libs/proto/test/env_var.cpp
@@ -0,0 +1,297 @@
+///////////////////////////////////////////////////////////////////////////////
+// env_var.cpp
+//
+// Copyright 2012 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)
+
+#include <cstring>
+#include <sstream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace proto = boost::proto;
+
+BOOST_PROTO_DEFINE_ENV_VAR(tag0_type, tag0);
+
+struct abstract
+{
+ virtual ~abstract() = 0;
+};
+
+abstract::~abstract() {}
+
+struct concrete : abstract
+{
+ ~concrete() {}
+};
+
+template<typename Tag, typename Env>
+void assert_has_env_var(Env const &)
+{
+ BOOST_MPL_ASSERT((proto::result_of::has_env_var<Env, Tag>));
+}
+
+template<typename Tag, typename Env>
+void assert_has_env_var_not(Env const &)
+{
+ BOOST_MPL_ASSERT_NOT((proto::result_of::has_env_var<Env, Tag>));
+}
+
+void test_is_env()
+{
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int &>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<int const &>));
+
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract &>));
+ BOOST_MPL_ASSERT_NOT((proto::is_env<abstract const &>));
+
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env &>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::empty_env const &>));
+
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> >));
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> &>));
+ BOOST_MPL_ASSERT((proto::is_env<proto::env<tag0_type, int> const &>));
+}
+
+void test_as_env()
+{
+ proto::env<proto::data_type, int> e0 = proto::as_env(2);
+ BOOST_CHECK_EQUAL(e0[proto::data], 2);
+ assert_has_env_var<proto::data_type>(e0);
+ assert_has_env_var_not<tag0_type>(e0);
+
+ int i = 39;
+ proto::env<proto::data_type, int &> e1 = proto::as_env(boost::ref(i));
+ assert_has_env_var<proto::data_type>(i);
+ assert_has_env_var_not<tag0_type>(i);
+ BOOST_CHECK_EQUAL(e1[proto::data], 39);
+ BOOST_CHECK_EQUAL(&e1[proto::data], &i);
+
+ proto::empty_env e2 = proto::as_env(proto::empty_env());
+ proto::env<proto::data_type, int &> e3 = proto::as_env(e1);
+ proto::env<proto::data_type, int &> & e4 = proto::as_env(boost::ref(e1));
+ BOOST_CHECK_EQUAL(&e4, &e1);
+
+ concrete c;
+ abstract &a = c;
+ std::stringstream sout;
+ int rgi[2] = {};
+ proto::env<proto::data_type, abstract &> e5 = proto::as_env(a);
+ proto::env<proto::data_type, std::stringstream &> e6 = proto::as_env(sout);
+ BOOST_CHECK_EQUAL(&e6[proto::data], &sout);
+ proto::env<proto::data_type, int(&)[2]> e7 = proto::as_env(rgi);
+ BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]);
+ proto::env<proto::data_type, void(&)()> e8 = proto::as_env(test_as_env);
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+}
+
+void test_comma()
+{
+ proto::env<proto::data_type, int> e0 = (proto::data = 1);
+ BOOST_CHECK_EQUAL(e0[proto::data], 1);
+
+ int i = 39;
+ proto::env<proto::data_type, int &> e1 = (proto::data = boost::ref(i));
+ BOOST_CHECK_EQUAL(e1[proto::data], 39);
+ BOOST_CHECK_EQUAL(&e1[proto::data], &i);
+
+ concrete c;
+ abstract &a = c;
+ std::stringstream sout;
+ int rgi[2] = {};
+ proto::env<proto::data_type, abstract &> e5 = (proto::data = a);
+ proto::env<proto::data_type, std::stringstream &> e6 = (proto::data = sout);
+ BOOST_CHECK_EQUAL(&e6[proto::data], &sout);
+ proto::env<proto::data_type, int(&)[2]> e7 = (proto::data = rgi);
+ BOOST_CHECK_EQUAL(&e7[proto::data][0], &rgi[0]);
+ // The test below fails on msvc due to a compiler bug
+ // note: <https://connect.microsoft.com/VisualStudio/feedback/details/754684/premature-decay-of-function-types-in-overloaded-assignment-operator>
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ proto::env<proto::data_type, void(&)()> e8 = (proto::data = boost::ref(test_as_env));
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+#else
+ proto::env<proto::data_type, void(&)()> e8 = (proto::data = test_as_env);
+ BOOST_CHECK_EQUAL(&e8[proto::data], &test_as_env);
+#endif
+
+ proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, int>
+ > e9 = (proto::data = 1, tag0 = "hello");
+ BOOST_CHECK_EQUAL(e9[proto::data], 1);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e9[tag0], "hello"));
+
+ proto::env<
+ tag0_type
+ , int
+ , proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, int>
+ >
+ > e10 = (proto::data = 1, tag0 = "hello", tag0 = 42);
+ BOOST_CHECK_EQUAL(e10[proto::data], 1);
+ BOOST_CHECK_EQUAL(e10[tag0], 42);
+
+ proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, abstract &>
+ > e11 = (a, tag0 = "hello");
+ BOOST_CHECK_EQUAL(&e11[proto::data], &a);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e11[tag0], "hello"));
+
+ proto::env<
+ tag0_type
+ , int
+ , proto::env<
+ tag0_type
+ , char const (&)[6]
+ , proto::env<proto::data_type, abstract &>
+ >
+ > e12 = (a, tag0 = "hello", tag0 = 42);
+ BOOST_CHECK_EQUAL(&e12[proto::data], &a);
+ BOOST_CHECK_EQUAL(e12[tag0], 42);
+
+ proto::env<tag0_type, int> e13 = (proto::empty_env(), tag0 = 42);
+ BOOST_CHECK_EQUAL(e13[tag0], 42);
+ assert_has_env_var<tag0_type>(e13);
+ assert_has_env_var_not<proto::data_type>(e13);
+
+ proto::empty_env empty;
+ proto::env<tag0_type, int> e14 = (boost::ref(empty), tag0 = 42);
+ BOOST_CHECK_EQUAL(e14[tag0], 42);
+
+ proto::env<
+ proto::data_type
+ , char const (&)[6]
+ , proto::env<tag0_type, int>
+ > e15 = (boost::ref(e14), proto::data = "hello");
+ BOOST_CHECK_EQUAL(e15[tag0], 42);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e15[proto::data], "hello"));
+
+ proto::env<
+ proto::data_type
+ , char const (&)[6]
+ , proto::env<tag0_type, int>
+ > e16 = (proto::as_env(boost::ref(e14)), proto::data = "hello");
+ BOOST_CHECK_EQUAL(e16[tag0], 42);
+ BOOST_CHECK_EQUAL(0, std::strcmp(e16[proto::data], "hello"));
+}
+
+void test_result_of_env_var()
+{
+ typedef proto::empty_env env0_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type, proto::data_type>::type, proto::key_not_found>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type &, proto::data_type>::type, proto::key_not_found>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env0_type const &, proto::data_type>::type, proto::key_not_found>));
+
+ typedef proto::env<proto::data_type, int> env1_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type, proto::data_type>::type, int>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type &, proto::data_type>::type, int>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env1_type const &, proto::data_type>::type, int>));
+
+ typedef proto::env<proto::data_type, int &> env2_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type, proto::data_type>::type, int &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type &, proto::data_type>::type, int &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env2_type const &, proto::data_type>::type, int &>));
+
+ typedef proto::env<proto::data_type, double, proto::env<tag0_type, abstract &> > env3_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type, tag0_type>::type, abstract &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type &, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type &, tag0_type>::type, abstract &>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type const &, proto::data_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env3_type const &, tag0_type>::type, abstract &>));
+
+ typedef proto::env<tag0_type, double, proto::env<tag0_type, abstract &> > env4_type;
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type, tag0_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type &, tag0_type>::type, double>));
+ BOOST_MPL_ASSERT((boost::is_same<proto::result_of::env_var<env4_type const &, tag0_type>::type, double>));
+}
+
+void test_env_var()
+{
+ proto::key_not_found x0 = proto::env_var<proto::data_type>(proto::empty_env());
+ proto::key_not_found x1 = proto::env_var<proto::data_type>(tag0 = 42);
+ int x2 = proto::env_var<tag0_type>(tag0 = 42);
+ BOOST_CHECK_EQUAL(x2, 42);
+ int x3 = proto::functional::env_var<tag0_type>()(tag0 = 42);
+ BOOST_CHECK_EQUAL(x3, 42);
+
+ int i = 43;
+ int & x4 = proto::env_var<tag0_type>(tag0 = boost::ref(i));
+ BOOST_CHECK_EQUAL(&x4, &i);
+ int & x5 = proto::functional::env_var<tag0_type>()(tag0 = boost::ref(i));
+ BOOST_CHECK_EQUAL(&x5, &i);
+
+ concrete c;
+ abstract &a = c;
+ abstract &x6 = proto::env_var<tag0_type>(tag0 = a);
+ BOOST_CHECK_EQUAL(&x6, &a);
+ abstract &x7 = proto::functional::env_var<tag0_type>()(tag0 = a);
+ BOOST_CHECK_EQUAL(&x7, &a);
+
+ abstract &x8 = proto::env_var<tag0_type>((42, tag0 = a));
+ BOOST_CHECK_EQUAL(&x8, &a);
+ abstract &x9 = proto::functional::env_var<tag0_type>()((42, tag0 = a));
+ BOOST_CHECK_EQUAL(&x9, &a);
+}
+
+void test_env_var_tfx()
+{
+ typedef proto::terminal<int>::type int_;
+ int_ i = {42};
+
+ // tests for _env
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &)>::type, proto::empty_env>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int)>::type, proto::empty_env>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float &)>::type, float &>));
+
+ // Bummer, is there any way around this?
+#ifdef BOOST_RESULT_OF_USE_DECLTYPE
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float)>::type, float const &>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::tr1_result_of<proto::_env(int_ &, int &, float)>::type, float>));
+#else
+ BOOST_MPL_ASSERT((boost::is_same<boost::result_of<proto::_env(int_ &, int &, float)>::type, float>));
+ BOOST_MPL_ASSERT((boost::is_same<boost::tr1_result_of<proto::_env(int_ &, int &, float)>::type, float>));
+#endif
+
+ double d = 3.14;
+ double & rd = proto::_env()(i, 0, d);
+ BOOST_CHECK_EQUAL(&d, &rd);
+
+ proto::env<proto::data_type, int> e0 = proto::_env()(i, 0, proto::as_env(42));
+ BOOST_CHECK_EQUAL(e0[proto::data], 42);
+
+ proto::env<proto::data_type, int> e1 = proto::_env()(i, 0, proto::functional::as_env()(42));
+ BOOST_CHECK_EQUAL(e1[proto::data], 42);
+
+ proto::env<proto::data_type, int> e2 = proto::_env()(i, 0, (proto::data = 42));
+ BOOST_CHECK_EQUAL(e2[proto::data], 42);
+
+ proto::env<proto::data_type, int, proto::env<proto::data_type, int> > e3 = proto::_env()(i, 0, (42, proto::data = 43));
+ BOOST_CHECK_EQUAL(e3[proto::data], 43);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for environment variables");
+ test->add(BOOST_TEST_CASE(&test_as_env));
+ test->add(BOOST_TEST_CASE(&test_comma));
+ test->add(BOOST_TEST_CASE(&test_result_of_env_var));
+ test->add(BOOST_TEST_CASE(&test_env_var));
+ test->add(BOOST_TEST_CASE(&test_env_var_tfx));
+ return test;
+}
diff --git a/src/boost/libs/proto/test/examples.cpp b/src/boost/libs/proto/test/examples.cpp
new file mode 100644
index 00000000..35769bca
--- /dev/null
+++ b/src/boost/libs/proto/test/examples.cpp
@@ -0,0 +1,498 @@
+///////////////////////////////////////////////////////////////////////////////
+// examples.hpp
+//
+// 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)
+
+#include <iostream>
+#include <boost/config.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/proto/functional/fusion.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/fusion/include/cons.hpp>
+#include <boost/fusion/include/tuple.hpp>
+#include <boost/fusion/include/pop_front.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+template<int I>
+struct placeholder
+{};
+
+namespace test1
+{
+//[ CalcGrammar
+ // This is the grammar for calculator expressions,
+ // to which we will attach transforms for computing
+ // the expressions' arity.
+ /*<< A Calculator expression is ... >>*/
+ struct CalcArity
+ : proto::or_<
+ /*<< _1, or ... >>*/
+ proto::terminal< placeholder<0> >
+ /*<< _2, or ... >>*/
+ , proto::terminal< placeholder<1> >
+ /*<< some other terminal, or ... >>*/
+ , proto::terminal< _ >
+ /*<< a unary expression where the operand is a calculator expression, or ... >>*/
+ , proto::unary_expr< _, CalcArity >
+ /*<< a binary expression where the operands are calculator expressions >>*/
+ , proto::binary_expr< _, CalcArity, CalcArity >
+ >
+ {};
+//]
+}
+
+//[ binary_arity
+/*<< The `CalculatorArity` is a transform for calculating
+the arity of a calculator expression. It will be define in
+terms of `binary_arity`, which is defined in terms of
+`CalculatorArity`; hence, the definition is recursive.>>*/
+struct CalculatorArity;
+
+// A custom transform that returns the arity of a unary
+// calculator expression by finding the arity of the
+// child expression.
+struct unary_arity
+ /*<< Custom transforms should inherit from
+ transform<>. In some cases, (e.g., when the transform
+ is a template), it is also necessary to specialize
+ the proto::is_callable<> trait. >>*/
+ : proto::transform<unary_arity>
+{
+ template<typename Expr, typename State, typename Data>
+ /*<< Transforms have a nested `impl<>` that is
+ a valid TR1 function object. >>*/
+ struct impl
+ : proto::transform_impl<Expr, State, Data>
+ {
+ /*<< Get the child. >>*/
+ typedef typename proto::result_of::child<Expr>::type child_expr;
+
+ /*<< Apply `CalculatorArity` to find the arity of the child. >>*/
+ typedef typename boost::result_of<CalculatorArity(child_expr, State, Data)>::type result_type;
+
+ /*<< The `unary_arity` transform doesn't have an interesting
+ runtime counterpart, so just return a default-constructed object
+ of the correct type. >>*/
+ result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const
+ {
+ return result_type();
+ }
+ };
+};
+
+// A custom transform that returns the arity of a binary
+// calculator expression by finding the maximum of the
+// arities of the mpl::int_<2> child expressions.
+struct binary_arity
+ /*<< All custom transforms should inherit from
+ transform. In some cases, (e.g., when the transform
+ is a template), it is also necessary to specialize
+ the proto::is_callable<> trait. >>*/
+ : proto::transform<binary_arity>
+{
+ template<typename Expr, typename State, typename Data>
+ /*<< Transforms have a nested `impl<>` that is
+ a valid TR1 function object. >>*/
+ struct impl
+ : proto::transform_impl<Expr, State, Data>
+ {
+ /*<< Get the left and right children. >>*/
+ typedef typename proto::result_of::left<Expr>::type left_expr;
+ typedef typename proto::result_of::right<Expr>::type right_expr;
+
+ /*<< Apply `CalculatorArity` to find the arity of the left and right children. >>*/
+ typedef typename boost::result_of<CalculatorArity(left_expr, State, Data)>::type left_arity;
+ typedef typename boost::result_of<CalculatorArity(right_expr, State, Data)>::type right_arity;
+
+ /*<< The return type is the maximum of the children's arities. >>*/
+ typedef typename mpl::max<left_arity, right_arity>::type result_type;
+
+ /*<< The `unary_arity` transform doesn't have an interesting
+ runtime counterpart, so just return a default-constructed object
+ of the correct type. >>*/
+ result_type operator ()(proto::ignore, proto::ignore, proto::ignore) const
+ {
+ return result_type();
+ }
+ };
+};
+//]
+
+proto::terminal< placeholder<0> >::type const _1 = {};
+proto::terminal< placeholder<1> >::type const _2 = {};
+
+//[ CalculatorArityGrammar
+struct CalculatorArity
+ : proto::or_<
+ proto::when< proto::terminal< placeholder<0> >, mpl::int_<1>() >
+ , proto::when< proto::terminal< placeholder<1> >, mpl::int_<2>() >
+ , proto::when< proto::terminal<_>, mpl::int_<0>() >
+ , proto::when< proto::unary_expr<_, _>, unary_arity >
+ , proto::when< proto::binary_expr<_, _, _>, binary_arity >
+ >
+{};
+//]
+
+//[ CalcArity
+struct CalcArity
+ : proto::or_<
+ proto::when< proto::terminal< placeholder<0> >,
+ mpl::int_<1>()
+ >
+ , proto::when< proto::terminal< placeholder<1> >,
+ mpl::int_<2>()
+ >
+ , proto::when< proto::terminal<_>,
+ mpl::int_<0>()
+ >
+ , proto::when< proto::unary_expr<_, CalcArity>,
+ CalcArity(proto::_child)
+ >
+ , proto::when< proto::binary_expr<_, CalcArity, CalcArity>,
+ mpl::max<CalcArity(proto::_left),
+ CalcArity(proto::_right)>()
+ >
+ >
+{};
+//]
+
+// BUGBUG find workaround for this
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define _pop_front(x) call<proto::_pop_front(x)>
+#define _value(x) call<proto::_value(x)>
+#endif
+
+//[ AsArgList
+// This transform matches function invocations such as foo(1,'a',"b")
+// and transforms them into Fusion cons lists of their arguments. In this
+// case, the result would be cons(1, cons('a', cons("b", nil()))).
+struct ArgsAsList
+ : proto::when<
+ proto::function<proto::terminal<_>, proto::vararg<proto::terminal<_> > >
+ /*<< Use a `fold<>` transform to iterate over the children of this
+ node in forward order, building a fusion list from front to back. >>*/
+ , proto::fold<
+ /*<< The first child expression of a `function<>` node is the
+ function being invoked. We don't want that in our list, so use
+ `pop_front()` to remove it. >>*/
+ proto::_pop_front(_)
+ /*<< `nil` is the initial state used by the `fold<>` transform. >>*/
+ , fusion::nil()
+ /*<< Put the rest of the function arguments in a fusion cons
+ list. >>*/
+ , proto::functional::push_back(proto::_state, proto::_value)
+ >
+ >
+{};
+//]
+
+//[ FoldTreeToList
+// This transform matches expressions of the form (_1=1,'a',"b")
+// (note the use of the comma operator) and transforms it into a
+// Fusion cons list of their arguments. In this case, the result
+// would be cons(1, cons('a', cons("b", nil()))).
+struct FoldTreeToList
+ : proto::or_<
+ // This grammar describes what counts as the terminals in expressions
+ // of the form (_1=1,'a',"b"), which will be flattened using
+ // reverse_fold_tree<> below.
+ proto::when< proto::assign<_, proto::terminal<_> >
+ , proto::_value(proto::_right)
+ >
+ , proto::when< proto::terminal<_>
+ , proto::_value
+ >
+ , proto::when<
+ proto::comma<FoldTreeToList, FoldTreeToList>
+ /*<< Fold all terminals that are separated by commas into a Fusion cons list. >>*/
+ , proto::reverse_fold_tree<
+ _
+ , fusion::nil()
+ , fusion::cons<FoldTreeToList, proto::_state>(FoldTreeToList, proto::_state)
+ >
+ >
+ >
+{};
+//]
+
+//[ Promote
+// This transform finds all float terminals in an expression and promotes
+// them to doubles.
+struct Promote
+ : proto::or_<
+ /*<< Match a `terminal<float>`, then construct a
+ `terminal<double>::type` with the `float`. >>*/
+ proto::when<proto::terminal<float>, proto::terminal<double>::type(proto::_value) >
+ , proto::when<proto::terminal<_> >
+ /*<< `nary_expr<>` has a pass-through transform which
+ will transform each child sub-expression using the
+ `Promote` transform. >>*/
+ , proto::when<proto::nary_expr<_, proto::vararg<Promote> > >
+ >
+{};
+//]
+
+//[ LazyMakePair
+struct make_pair_tag {};
+proto::terminal<make_pair_tag>::type const make_pair_ = {{}};
+
+// This transform matches lazy function invocations like
+// `make_pair_(1, 3.14)` and actually builds a `std::pair<>`
+// from the arguments.
+struct MakePair
+ : proto::when<
+ /*<< Match expressions like `make_pair_(1, 3.14)` >>*/
+ proto::function<
+ proto::terminal<make_pair_tag>
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ /*<< Return `std::pair<F,S>(f,s)` where `f` and `s` are the
+ first and second arguments to the lazy `make_pair_()` function.
+ (This uses `proto::make<>` under the covers to evaluate the
+ transform.)>>*/
+ , std::pair<
+ proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ >(
+ proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+{};
+//]
+
+namespace lazy_make_pair2
+{
+ //[ LazyMakePair2
+ struct make_pair_tag {};
+ proto::terminal<make_pair_tag>::type const make_pair_ = {{}};
+
+ // Like std::make_pair(), only as a function object.
+ /*<<Inheriting from `proto::callable` lets Proto know
+ that this is a callable transform, so we can use it
+ without having to wrap it in `proto::call<>`.>>*/
+ struct make_pair : proto::callable
+ {
+ template<typename Sig> struct result;
+
+ template<typename This, typename First, typename Second>
+ struct result<This(First, Second)>
+ {
+ typedef
+ std::pair<
+ BOOST_PROTO_UNCVREF(First)
+ , BOOST_PROTO_UNCVREF(Second)
+ >
+ type;
+ };
+
+ template<typename First, typename Second>
+ std::pair<First, Second>
+ operator()(First const &first, Second const &second) const
+ {
+ return std::make_pair(first, second);
+ }
+ };
+
+ // This transform matches lazy function invocations like
+ // `make_pair_(1, 3.14)` and actually builds a `std::pair<>`
+ // from the arguments.
+ struct MakePair
+ : proto::when<
+ /*<< Match expressions like `make_pair_(1, 3.14)` >>*/
+ proto::function<
+ proto::terminal<make_pair_tag>
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ /*<< Return `make_pair()(f,s)` where `f` and `s` are the
+ first and second arguments to the lazy `make_pair_()` function.
+ (This uses `proto::call<>` under the covers to evaluate the
+ transform.)>>*/
+ , make_pair(
+ proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+ {};
+ //]
+}
+
+
+//[ NegateInt
+struct NegateInt
+ : proto::when<proto::terminal<int>, proto::negate<_>(_)>
+{};
+//]
+
+#ifndef BOOST_MSVC
+//[ SquareAndPromoteInt
+struct SquareAndPromoteInt
+ : proto::when<
+ proto::terminal<int>
+ , proto::_make_multiplies(
+ proto::terminal<long>::type(proto::_value)
+ , proto::terminal<long>::type(proto::_value)
+ )
+ >
+{};
+//]
+#endif
+
+namespace lambda_transform
+{
+ //[LambdaTransform
+ template<typename N>
+ struct placeholder : N {};
+
+ // A function object that calls fusion::at()
+ struct at : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Cont, typename Index>
+ struct result<This(Cont, Index)>
+ : fusion::result_of::at<
+ typename boost::remove_reference<Cont>::type
+ , typename boost::remove_reference<Index>::type
+ >
+ {};
+
+ template<typename Cont, typename Index>
+ typename fusion::result_of::at<Cont, Index>::type
+ operator ()(Cont &cont, Index const &) const
+ {
+ return fusion::at<Index>(cont);
+ }
+ };
+
+ // A transform that evaluates a lambda expression.
+ struct LambdaEval
+ : proto::or_<
+ /*<<When you match a placeholder ...>>*/
+ proto::when<
+ proto::terminal<placeholder<_> >
+ /*<<... call at() with the data parameter, which
+ is a tuple, and the placeholder, which is an MPL
+ Integral Constant.>>*/
+ , at(proto::_data, proto::_value)
+ >
+ /*<<Otherwise, use the _default<> transform, which
+ gives the operators their usual C++ meanings.>>*/
+ , proto::otherwise< proto::_default<LambdaEval> >
+ >
+ {};
+
+ // Define the lambda placeholders
+ proto::terminal<placeholder<mpl::int_<0> > >::type const _1 = {};
+ proto::terminal<placeholder<mpl::int_<1> > >::type const _2 = {};
+
+ void test_lambda()
+ {
+ // a tuple that contains the values
+ // of _1 and _2
+ fusion::tuple<int, int> tup(2,3);
+
+ // Use LambdaEval to evaluate a lambda expression
+ int j = LambdaEval()( _2 - _1, 0, tup );
+ BOOST_CHECK_EQUAL(j, 1);
+
+ // You can mutate leaves in an expression tree
+ proto::literal<int> k(42);
+ int &l = LambdaEval()( k += 4, 0, tup );
+ BOOST_CHECK_EQUAL(k.get(), 46);
+ BOOST_CHECK_EQUAL(&l, &k.get());
+
+ // You can mutate the values in the tuple, too.
+ LambdaEval()( _1 += 4, 0, tup );
+ BOOST_CHECK_EQUAL(6, fusion::at_c<0>(tup));
+ }
+ //]
+}
+
+void test_examples()
+{
+ //[ CalculatorArityTest
+ int i = 0; // not used, dummy state and data parameter
+
+ std::cout << CalculatorArity()( proto::lit(100) * 200, i, i) << '\n';
+ std::cout << CalculatorArity()( (_1 - _1) / _1 * 100, i, i) << '\n';
+ std::cout << CalculatorArity()( (_2 - _1) / _2 * 100, i, i) << '\n';
+ //]
+
+ BOOST_CHECK_EQUAL(0, CalculatorArity()( proto::lit(100) * 200, i, i));
+ BOOST_CHECK_EQUAL(1, CalculatorArity()( (_1 - _1) / _1 * 100, i, i));
+ BOOST_CHECK_EQUAL(2, CalculatorArity()( (_2 - _1) / _2 * 100, i, i));
+
+ BOOST_CHECK_EQUAL(0, CalcArity()( proto::lit(100) * 200, i, i));
+ BOOST_CHECK_EQUAL(1, CalcArity()( (_1 - _1) / _1 * 100, i, i));
+ BOOST_CHECK_EQUAL(2, CalcArity()( (_2 - _1) / _2 * 100, i, i));
+
+ using boost::fusion::cons;
+ using boost::fusion::nil;
+ cons<int, cons<char, cons<std::string> > > args(ArgsAsList()( _1(1, 'a', std::string("b")), i, i ));
+ BOOST_CHECK_EQUAL(args.car, 1);
+ BOOST_CHECK_EQUAL(args.cdr.car, 'a');
+ BOOST_CHECK_EQUAL(args.cdr.cdr.car, std::string("b"));
+
+ cons<int, cons<char, cons<std::string> > > lst(FoldTreeToList()( (_1 = 1, 'a', std::string("b")), i, i ));
+ BOOST_CHECK_EQUAL(lst.car, 1);
+ BOOST_CHECK_EQUAL(lst.cdr.car, 'a');
+ BOOST_CHECK_EQUAL(lst.cdr.cdr.car, std::string("b"));
+
+ proto::plus<
+ proto::terminal<double>::type
+ , proto::terminal<double>::type
+ >::type p = Promote()( proto::lit(1.f) + 2.f, i, i );
+
+ //[ LazyMakePairTest
+ int j = 0; // not used, dummy state and data parameter
+
+ std::pair<int, double> p2 = MakePair()( make_pair_(1, 3.14), j, j );
+
+ std::cout << p2.first << std::endl;
+ std::cout << p2.second << std::endl;
+ //]
+
+ BOOST_CHECK_EQUAL(p2.first, 1);
+ BOOST_CHECK_EQUAL(p2.second, 3.14);
+
+ std::pair<int, double> p3 = lazy_make_pair2::MakePair()( lazy_make_pair2::make_pair_(1, 3.14), j, j );
+
+ std::cout << p3.first << std::endl;
+ std::cout << p3.second << std::endl;
+
+ BOOST_CHECK_EQUAL(p3.first, 1);
+ BOOST_CHECK_EQUAL(p3.second, 3.14);
+
+ NegateInt()(proto::lit(1), i, i);
+ #ifndef BOOST_MSVC
+ SquareAndPromoteInt()(proto::lit(1), i, i);
+ #endif
+
+ lambda_transform::test_lambda();
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test examples from the documentation");
+
+ test->add(BOOST_TEST_CASE(&test_examples));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/external_transforms.cpp b/src/boost/libs/proto/test/external_transforms.cpp
new file mode 100644
index 00000000..f72e9458
--- /dev/null
+++ b/src/boost/libs/proto/test/external_transforms.cpp
@@ -0,0 +1,185 @@
+// Copyright 2011 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)
+//
+// This is an example of how to specify a transform externally so
+// that a single grammar can be used to drive multiple differnt
+// calculations. In particular, it defines a calculator grammar
+// that computes the result of an expression with either checked
+// or non-checked division.
+
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/fusion/container/vector.hpp>
+#include <boost/fusion/container/generation/make_vector.hpp>
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+// The argument placeholder type
+template<typename I> struct placeholder : I {};
+
+// Give each rule in the grammar a "name". This is so that we
+// can easily dispatch on it later.
+struct calc_grammar;
+struct divides_rule : proto::divides<calc_grammar, calc_grammar> {};
+
+// Use external transforms in calc_gramar
+struct calc_grammar
+ : proto::or_<
+ proto::when<
+ proto::terminal<placeholder<_> >
+ , proto::functional::at(proto::_state, proto::_value)
+ >
+ , proto::when<
+ proto::terminal<proto::convertible_to<double> >
+ , proto::_value
+ >
+ , proto::when<
+ proto::plus<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ , proto::when<
+ proto::minus<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ , proto::when<
+ proto::multiplies<calc_grammar, calc_grammar>
+ , proto::_default<calc_grammar>
+ >
+ // Note that we don't specify how division nodes are
+ // handled here. Proto::external_transform is a placeholder
+ // for an actual transform.
+ , proto::when<
+ divides_rule
+ , proto::external_transform
+ >
+ >
+{};
+
+template<typename E> struct calc_expr;
+struct calc_domain : proto::domain<proto::generator<calc_expr> > {};
+
+template<typename E>
+struct calc_expr
+ : proto::extends<E, calc_expr<E>, calc_domain>
+{
+ calc_expr(E const &e = E()) : calc_expr::proto_extends(e) {}
+};
+
+calc_expr<proto::terminal<placeholder<mpl::int_<0> > >::type> _1;
+calc_expr<proto::terminal<placeholder<mpl::int_<1> > >::type> _2;
+
+// Use proto::external_transforms to map from named grammar rules to
+// transforms.
+struct non_checked_division
+ : proto::external_transforms<
+ proto::when< divides_rule, proto::_default<calc_grammar> >
+ >
+{};
+
+struct division_by_zero : std::exception {};
+
+struct do_checked_divide
+ : proto::callable
+{
+ typedef int result_type;
+ int operator()(int left, int right) const
+ {
+ if (right == 0) throw division_by_zero();
+ return left / right;
+ }
+};
+
+// Use proto::external_transforms again, this time to map the divides_rule
+// to a transforms that performs checked division.
+struct checked_division
+ : proto::external_transforms<
+ proto::when<
+ divides_rule
+ , do_checked_divide(calc_grammar(proto::_left), calc_grammar(proto::_right))
+ >
+ >
+{};
+
+BOOST_PROTO_DEFINE_ENV_VAR(mydata_tag, mydata);
+
+void test_external_transforms()
+{
+ non_checked_division non_checked;
+ int result1 = calc_grammar()(_1 / _2, fusion::make_vector(6, 2), non_checked);
+ BOOST_CHECK_EQUAL(result1, 3);
+
+ // check that additional data slots are ignored
+ int result2 = calc_grammar()(_1 / _2, fusion::make_vector(8, 2), (non_checked, mydata = "foo"));
+ BOOST_CHECK_EQUAL(result2, 4);
+
+ // check that we can use the dedicated slot for this purpose
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(8, 2), (42, proto::transforms = non_checked, mydata = "foo"));
+ BOOST_CHECK_EQUAL(result2, 4);
+
+ checked_division checked;
+ try
+ {
+ // This should throw
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), checked);
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+
+ try
+ {
+ // This should throw
+ int result4 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), (checked, mydata = test_external_transforms));
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+
+ try
+ {
+ // This should throw
+ int result5 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), (42, proto::transforms = checked, mydata = test_external_transforms));
+ BOOST_CHECK(!"Didn't throw an exception"); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ ; // OK
+ }
+ catch(...)
+ {
+ BOOST_CHECK(!"Unexpected exception"); // shouldn't get here!
+ }
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test for external transforms");
+
+ test->add(BOOST_TEST_CASE(&test_external_transforms));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/flatten.cpp b/src/boost/libs/proto/test/flatten.cpp
new file mode 100644
index 00000000..fd19474b
--- /dev/null
+++ b/src/boost/libs/proto/test/flatten.cpp
@@ -0,0 +1,211 @@
+///////////////////////////////////////////////////////////////////////////////
+// proto_fusion_s.cpp
+//
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/fusion.hpp>
+#include <boost/fusion/include/for_each.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility/addressof.hpp>
+#include <sstream>
+
+std::ostream &operator <<(std::ostream &sout, boost::proto::tag::shift_right)
+{
+ return sout << ">>";
+}
+
+std::ostream &operator <<(std::ostream &sout, boost::proto::tag::bitwise_or)
+{
+ return sout << "|";
+}
+
+template<typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::expr<boost::proto::tag::terminal, Args, 0> const *op)
+{
+ return sout << boost::proto::value(*op);
+}
+
+template<typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<boost::proto::tag::terminal, Args, 0> const *op)
+{
+ return sout << boost::proto::value(*op);
+}
+
+template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 1> const *op)
+{
+ return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base());
+}
+
+template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 1> const *op)
+{
+ return sout << Tag() << boost::addressof(boost::proto::child(*op).proto_base());
+}
+
+template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::expr<Tag, Args, 2> const *op)
+{
+ return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
+}
+
+template<typename Tag, typename Args>
+std::ostream &operator <<(std::ostream &sout, boost::proto::basic_expr<Tag, Args, 2> const *op)
+{
+ return sout << boost::addressof(boost::proto::left(*op).proto_base()) << Tag() << boost::addressof(boost::proto::right(*op).proto_base());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// to_string
+//
+struct to_string
+{
+ to_string(std::ostream &sout)
+ : sout_(sout)
+ {}
+
+ template<typename Op>
+ void operator ()(Op const &op) const
+ {
+ this->sout_ << '(' << boost::addressof(op.proto_base()) << ')';
+ }
+private:
+ std::ostream &sout_;
+};
+
+void test1()
+{
+ 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(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(flatten(a_ >> b_ >> c_), to_string(sout));
+ BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
+
+ sout.str("");
+ 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(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
+ BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
+
+ sout.str("");
+ 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(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(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(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());
+}
+
+////////////////////////////////////////////////////////////////////////
+// Test that EXTENDS expression wrappers are also valid fusion sequences
+
+template<typename Expr>
+struct My;
+
+struct MyDomain
+ : boost::proto::domain<boost::proto::pod_generator<My> >
+{};
+
+template<typename Expr>
+struct My
+{
+ BOOST_PROTO_EXTENDS(Expr, My<Expr>, MyDomain)
+};
+
+void test2()
+{
+ 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(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(flatten(a_ >> b_ >> c_), to_string(sout));
+ BOOST_CHECK_EQUAL("(a)(b)(c)", sout.str());
+
+ sout.str("");
+ 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(flatten(a_ >> b_ | c_ >> d_), to_string(sout));
+ BOOST_CHECK_EQUAL("(a>>b)(c>>d)", sout.str());
+
+ sout.str("");
+ 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(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(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(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());
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto and segmented fusion integration");
+
+ test->add(BOOST_TEST_CASE(&test1));
+ test->add(BOOST_TEST_CASE(&test2));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/lambda.cpp b/src/boost/libs/proto/test/lambda.cpp
new file mode 100644
index 00000000..807f7cdb
--- /dev/null
+++ b/src/boost/libs/proto/test/lambda.cpp
@@ -0,0 +1,188 @@
+///////////////////////////////////////////////////////////////////////////////
+// lambda.hpp
+//
+// 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)
+
+#include <sstream>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/fusion/tuple.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <boost/typeof/std/sstream.hpp>
+#include <boost/typeof/std/ostream.hpp>
+#include <boost/typeof/std/iostream.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
+using namespace boost;
+
+// Forward declaration of the lambda expression wrapper
+template<typename T>
+struct lambda;
+
+struct lambda_domain
+ : proto::domain<proto::pod_generator<lambda> >
+{};
+
+template<typename I>
+struct placeholder
+{
+ typedef I arity;
+};
+
+template<typename T>
+struct placeholder_arity
+{
+ typedef typename T::arity type;
+};
+
+namespace grammar
+{
+ using namespace proto;
+
+ // The lambda grammar, with the transforms for calculating the max arity
+ struct Lambda
+ : or_<
+ when< terminal< placeholder<_> >, mpl::next<placeholder_arity<_value> >() >
+ , when< terminal<_>, mpl::int_<0>() >
+ , when< nary_expr<_, vararg<_> >, fold<_, mpl::int_<0>(), mpl::max<Lambda,_state>()> >
+ >
+ {};
+}
+
+// simple wrapper for calculating a lambda expression's arity.
+template<typename Expr>
+struct lambda_arity
+ : boost::result_of<grammar::Lambda(Expr, mpl::void_, mpl::void_)>
+{};
+
+// The lambda context is the same as the default context
+// with the addition of special handling for lambda placeholders
+template<typename Tuple>
+struct lambda_context
+ : proto::callable_context<lambda_context<Tuple> const>
+{
+ lambda_context(Tuple const &args)
+ : args_(args)
+ {}
+
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename I>
+ struct result<This(proto::tag::terminal, placeholder<I> const &)>
+ : fusion::result_of::at<Tuple, I>
+ {};
+
+ template<typename I>
+ typename fusion::result_of::at<Tuple, I>::type
+ operator ()(proto::tag::terminal, placeholder<I> const &) const
+ {
+ return fusion::at<I>(this->args_);
+ }
+
+ Tuple args_;
+};
+
+// The lambda<> expression wrapper makes expressions polymorphic
+// function objects
+template<typename T>
+struct lambda
+{
+ BOOST_PROTO_BASIC_EXTENDS(T, lambda<T>, lambda_domain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ // Careful not to evaluate the return type of the nullary function
+ // unless we have a nullary lambda!
+ typedef typename mpl::eval_if<
+ typename lambda_arity<T>::type
+ , mpl::identity<void>
+ , proto::result_of::eval<T const, lambda_context<fusion::tuple<> > >
+ >::type nullary_type;
+
+ // Define our operator () that evaluates the lambda expression.
+ nullary_type operator ()() const
+ {
+ fusion::tuple<> args;
+ lambda_context<fusion::tuple<> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+
+ #define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::eval<T const, lambda_context<fusion::tuple<A_const_ref(N)> > >::type \
+ operator ()(A_const_ref_a(N)) const \
+ { \
+ fusion::tuple<A_const_ref(N)> args(ref_a(N)); \
+ lambda_context<fusion::tuple<A_const_ref(N)> > ctx(args); \
+ return proto::eval(*this, ctx); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(1, 4, M0)
+ #undef M0
+};
+
+// Define some lambda placeholders
+lambda<proto::terminal<placeholder<mpl::int_<0> > >::type> const _1 = {{}};
+lambda<proto::terminal<placeholder<mpl::int_<1> > >::type> const _2 = {{}};
+lambda<proto::terminal<placeholder<mpl::int_<3> > >::type> const _3 = {{}};
+
+template<typename T>
+lambda<typename proto::terminal<T>::type> const val(T const &t)
+{
+ lambda<typename proto::terminal<T>::type> that = {{t}};
+ return that;
+}
+
+template<typename T>
+lambda<typename proto::terminal<T &>::type> const var(T &t)
+{
+ lambda<typename proto::terminal<T &>::type> that = {{t}};
+ return that;
+}
+
+void test_lambda()
+{
+ BOOST_CHECK_EQUAL(11, ( (_1 + 2) / 4 )(42));
+ BOOST_CHECK_EQUAL(-11, ( (-(_1 + 2)) / 4 )(42));
+ BOOST_CHECK_CLOSE(2.58, ( (4 - _2) * 3 )(42, 3.14), 0.1);
+
+ // check non-const ref terminals
+ std::stringstream sout;
+ (sout << _1 << " -- " << _2)(42, "Life, the Universe and Everything!");
+ BOOST_CHECK_EQUAL("42 -- Life, the Universe and Everything!", sout.str());
+
+ // check nullary lambdas
+ BOOST_CHECK_EQUAL(3, (val(1) + val(2))());
+
+ // check array indexing for kicks
+ int integers[5] = {0};
+ (var(integers)[2] = 2)();
+ (var(integers)[_1] = _1)(3);
+ BOOST_CHECK_EQUAL(2, integers[2]);
+ BOOST_CHECK_EQUAL(3, integers[3]);
+}
+
+using namespace unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test expression template domains");
+
+ test->add(BOOST_TEST_CASE(&test_lambda));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/make.cpp b/src/boost/libs/proto/test/make.cpp
new file mode 100644
index 00000000..17675aa2
--- /dev/null
+++ b/src/boost/libs/proto/test/make.cpp
@@ -0,0 +1,98 @@
+///////////////////////////////////////////////////////////////////////////////
+// make.hpp
+//
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/arg.hpp>
+#include <boost/proto/transform/make.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename T>
+struct type2type {};
+
+template<typename T>
+struct wrapper
+{
+ T t_;
+ explicit wrapper(T const & t = T()) : t_(t) {}
+};
+
+template<typename T>
+struct careful
+{
+ typedef typename T::not_there not_there;
+};
+
+// Test that when no substitution is done, we don't instantiate templates
+struct MakeTest1
+ : proto::make< type2type< careful<int> > >
+{};
+
+void make_test1()
+{
+ proto::terminal<int>::type i = {42};
+ type2type< careful<int> > res = MakeTest1()(i);
+}
+
+// Test that when substitution is done, and there is no nested ::type
+// typedef, the result is the wrapper
+struct MakeTest2
+ : proto::make< wrapper< proto::_value > >
+{};
+
+void make_test2()
+{
+ proto::terminal<int>::type i = {42};
+ wrapper<int> res = MakeTest2()(i);
+ BOOST_CHECK_EQUAL(res.t_, 0);
+}
+
+// Test that when substitution is done, and there is no nested ::type
+// typedef, the result is the wrapper
+struct MakeTest3
+ : proto::make< wrapper< proto::_value >(proto::_value) >
+{};
+
+void make_test3()
+{
+ proto::terminal<int>::type i = {42};
+ wrapper<int> res = MakeTest3()(i);
+ BOOST_CHECK_EQUAL(res.t_, 42);
+}
+
+// Test that when substitution is done, and there is no nested ::type
+// typedef, the result is the wrapper
+struct MakeTest4
+ : proto::make< mpl::identity< proto::_value >(proto::_value) >
+{};
+
+void make_test4()
+{
+ proto::terminal<int>::type i = {42};
+ int res = MakeTest4()(i);
+ BOOST_CHECK_EQUAL(res, 42);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test the make transform");
+
+ test->add(BOOST_TEST_CASE(&make_test1));
+ test->add(BOOST_TEST_CASE(&make_test2));
+ test->add(BOOST_TEST_CASE(&make_test3));
+ test->add(BOOST_TEST_CASE(&make_test4));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/make_expr.cpp b/src/boost/libs/proto/test/make_expr.cpp
new file mode 100644
index 00000000..d59f7574
--- /dev/null
+++ b/src/boost/libs/proto/test/make_expr.cpp
@@ -0,0 +1,407 @@
+///////////////////////////////////////////////////////////////////////////////
+// proto::make_expr.hpp
+//
+// 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)
+
+#include <sstream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/fusion/tuple.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace fusion = boost::fusion;
+namespace proto = boost::proto;
+
+template<typename E> struct ewrap;
+
+struct mydomain
+ : proto::domain<proto::generator<ewrap> >
+{};
+
+template<typename E> struct ewrap
+ : proto::extends<E, ewrap<E>, mydomain>
+{
+ explicit ewrap(E const &e = E())
+ : proto::extends<E, ewrap<E>, mydomain>(e)
+ {}
+};
+
+void test_make_expr()
+{
+ int i = 42;
+ proto::terminal<int>::type t1 = proto::make_expr<proto::tag::terminal>(1);
+ proto::terminal<int>::type t2 = proto::make_expr<proto::tag::terminal>(i);
+ proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(1);
+ proto::unary_plus<proto::terminal<int>::type>::type p2 = proto::make_expr<proto::tag::unary_plus>(i);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::make_expr<proto::tag::unary_plus, mydomain>(i);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::make_expr<proto::tag::plus>(p3, 0);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+}
+
+void test_make_expr_ref()
+{
+ int i = 42;
+ int const ci = 84;
+ proto::terminal<int const &>::type t1 = proto::make_expr<proto::tag::terminal>(boost::cref(ci));
+ proto::terminal<int &>::type t2 = proto::make_expr<proto::tag::terminal>(boost::ref(i));
+ BOOST_CHECK_EQUAL(&i, &proto::value(t2));
+ proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::make_expr<proto::tag::unary_plus>(boost::cref(ci));
+ proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::make_expr<proto::tag::unary_plus>(boost::ref(i));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::make_expr<proto::tag::unary_plus, mydomain>(boost::ref(i));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type &
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::make_expr<proto::tag::plus>(boost::ref(p3), 0);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+}
+
+void test_make_expr_functional()
+{
+ int i = 42;
+ proto::terminal<int>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(1);
+ proto::terminal<int>::type t2 = proto::functional::make_expr<proto::tag::terminal>()(i);
+ proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(1);
+ proto::unary_plus<proto::terminal<int>::type>::type p2 = proto::functional::make_expr<proto::tag::unary_plus>()(i);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::functional::make_expr<proto::tag::unary_plus, mydomain>()(i);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::functional::make_expr<proto::tag::plus>()(p3, 0);
+}
+
+void test_make_expr_functional_ref()
+{
+ int i = 42;
+ int const ci = 84;
+ proto::terminal<int const &>::type t1 = proto::functional::make_expr<proto::tag::terminal>()(boost::cref(ci));
+ proto::terminal<int &>::type t2 = proto::functional::make_expr<proto::tag::terminal>()(boost::ref(i));
+ BOOST_CHECK_EQUAL(&i, &proto::value(t2));
+ proto::unary_plus<proto::terminal<int const &>::type>::type p1 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::cref(ci));
+ proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::functional::make_expr<proto::tag::unary_plus>()(boost::ref(i));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::functional::make_expr<proto::tag::unary_plus, mydomain>()(boost::ref(i));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type &
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::functional::make_expr<proto::tag::plus>()(boost::ref(p3), 0);
+ BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+}
+
+void test_unpack_expr()
+{
+ int i = 42;
+ proto::terminal<int>::type t1 = proto::unpack_expr<proto::tag::terminal>(fusion::make_tuple(1));
+ proto::terminal<int &>::type t2 = proto::unpack_expr<proto::tag::terminal>(fusion::make_tuple(boost::ref(i)));
+ proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::unpack_expr<proto::tag::unary_plus>(fusion::make_tuple(1));
+ proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::unpack_expr<proto::tag::unary_plus>(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::unpack_expr<proto::tag::unary_plus, mydomain>(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type &
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::unpack_expr<proto::tag::plus>(fusion::make_tuple(boost::ref(p3), 0));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+}
+
+void test_unpack_expr_functional()
+{
+ int i = 42;
+ proto::terminal<int>::type t1 = proto::functional::unpack_expr<proto::tag::terminal>()(fusion::make_tuple(1));
+ proto::terminal<int &>::type t2 = proto::functional::unpack_expr<proto::tag::terminal>()(fusion::make_tuple(boost::ref(i)));
+ proto::unary_plus<proto::terminal<int>::type>::type p1 = proto::functional::unpack_expr<proto::tag::unary_plus>()(fusion::make_tuple(1));
+ proto::unary_plus<proto::terminal<int &>::type>::type p2 = proto::functional::unpack_expr<proto::tag::unary_plus>()(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p2)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::unary_plus
+ , proto::list1<
+ ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int &> > >
+ >
+ >
+ >
+ p3_type;
+ p3_type p3 = proto::functional::unpack_expr<proto::tag::unary_plus, mydomain>()(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(p3)), 42);
+
+ typedef
+ ewrap<
+ proto::basic_expr<
+ proto::tag::plus
+ , proto::list2<
+ p3_type &
+ , ewrap<proto::basic_expr<proto::tag::terminal, proto::term<int> > >
+ >
+ >
+ >
+ p4_type;
+ p4_type p4 = proto::functional::unpack_expr<proto::tag::plus>()(fusion::make_tuple(boost::ref(p3), 0));
+ BOOST_CHECK_EQUAL(proto::value(proto::child(proto::left(p4))), 42);
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define _byref(x) call<proto::_byref(x)>
+#define _byval(x) call<proto::_byval(x)>
+#define Minus(x) proto::call<Minus(x)>
+#endif
+
+// Turn all terminals held by reference into ones held by value
+struct ByVal
+ : proto::or_<
+ proto::when<proto::terminal<proto::_>, proto::_make_terminal(proto::_byval(proto::_value))>
+ , proto::when<proto::nary_expr<proto::_, proto::vararg<ByVal> > >
+ >
+{};
+
+// Turn all terminals held by value into ones held by reference (not safe in general)
+struct ByRef
+ : proto::or_<
+ proto::when<proto::terminal<proto::_>, proto::_make_terminal(proto::_byref(proto::_value))>
+ , proto::when<proto::nary_expr<proto::_, proto::vararg<ByRef> > >
+ >
+{};
+
+// turn all proto::plus nodes to minus nodes:
+struct Minus
+ : proto::or_<
+ proto::when<proto::terminal<proto::_> >
+ , proto::when<proto::plus<Minus, Minus>, proto::_make_minus(Minus(proto::_left), Minus(proto::_right)) >
+ >
+{};
+
+struct Square
+ : proto::or_<
+ // Not creating new proto::terminal nodes here,
+ // so hold the existing terminals by reference:
+ proto::when<proto::terminal<proto::_>, proto::_make_multiplies(proto::_, proto::_)>
+ , proto::when<proto::plus<Square, Square> >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef _byref
+#undef _byval
+#undef Minus
+#endif
+
+void test_make_expr_transform()
+{
+ proto::plus<
+ proto::terminal<int>::type
+ , proto::terminal<int>::type
+ >::type t1 = ByVal()(proto::as_expr(1) + 1);
+
+ proto::plus<
+ proto::terminal<int const &>::type
+ , proto::terminal<int const &>::type
+ >::type t2 = ByRef()(proto::as_expr(1) + 1);
+
+ proto::minus<
+ proto::terminal<int>::type const &
+ , proto::terminal<int const &>::type const &
+ >::type t3 = Minus()(proto::as_expr(1) + 1);
+
+ proto::plus<
+ proto::multiplies<proto::terminal<int>::type const &, proto::terminal<int>::type const &>::type
+ , proto::multiplies<proto::terminal<int const &>::type const &, proto::terminal<int const &>::type const &>::type
+ >::type t4 = Square()(proto::as_expr(1) + 1);
+}
+
+
+struct length_impl {};
+struct dot_impl {};
+
+proto::terminal<length_impl>::type const length = {{}};
+proto::terminal<dot_impl>::type const dot = {{}};
+
+// work around msvc bugs...
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
+#define _byref(a) call<proto::_byref(a)>
+#define _byval(a) call<proto::_byval(a)>
+#define _child1(a) call<proto::_child1(a)>
+#define _make_terminal(a) call<proto::_make_terminal(a)>
+#define _make_function(a,b,c) call<proto::_make_function(a,b,c)>
+#define dot_impl() proto::make<dot_impl()>
+#endif
+
+// convert length(a) < length(b) to dot(a,a) < dot(b,b)
+struct Convert
+ : proto::when<
+ proto::less<
+ proto::function<proto::terminal<length_impl>, proto::_>
+ , proto::function<proto::terminal<length_impl>, proto::_>
+ >
+ , proto::_make_less(
+ proto::_make_function(
+ proto::_make_terminal(dot_impl())
+ , proto::_child1(proto::_child0)
+ , proto::_child1(proto::_child0)
+ )
+ , proto::_make_function(
+ proto::_make_terminal(dot_impl())
+ , proto::_child1(proto::_child1)
+ , proto::_child1(proto::_child1)
+ )
+ )
+ >
+{};
+
+template<typename Expr>
+void test_make_expr_transform2_test(Expr const &expr)
+{
+ void const *addr1 = boost::addressof(proto::child_c<1>(proto::child_c<0>(expr)));
+ void const *addr2 = boost::addressof(proto::child_c<1>(proto::child_c<0>(Convert()(expr))));
+ BOOST_CHECK_EQUAL(addr1, addr2);
+
+ BOOST_CHECK_EQUAL(1, proto::value(proto::child_c<1>(proto::child_c<0>(expr))));
+ BOOST_CHECK_EQUAL(1, proto::value(proto::child_c<1>(proto::child_c<0>(Convert()(expr)))));
+}
+
+void test_make_expr_transform2()
+{
+ test_make_expr_transform2_test(length(1) < length(2));
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
+#undef _byref
+#undef _byval
+#undef _child1
+#undef _make_terminal
+#undef _make_function
+#undef dot_impl
+#endif
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::make_expr, proto::unpack_expr and friends");
+
+ test->add(BOOST_TEST_CASE(&test_make_expr));
+ test->add(BOOST_TEST_CASE(&test_make_expr_ref));
+ test->add(BOOST_TEST_CASE(&test_make_expr_functional));
+ test->add(BOOST_TEST_CASE(&test_make_expr_functional_ref));
+ test->add(BOOST_TEST_CASE(&test_unpack_expr));
+ test->add(BOOST_TEST_CASE(&test_unpack_expr_functional));
+ test->add(BOOST_TEST_CASE(&test_make_expr_transform));
+ test->add(BOOST_TEST_CASE(&test_make_expr_transform2));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/matches.cpp b/src/boost/libs/proto/test/matches.cpp
new file mode 100644
index 00000000..60b8f725
--- /dev/null
+++ b/src/boost/libs/proto/test/matches.cpp
@@ -0,0 +1,319 @@
+///////////////////////////////////////////////////////////////////////////////
+// matches.hpp
+//
+// 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)
+
+#include <string>
+#include <iostream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/proto/transform/arg.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+
+struct int_convertible
+{
+ int_convertible() {}
+ operator int() const { return 0; }
+};
+
+struct Input
+ : proto::or_<
+ proto::shift_right< proto::terminal< std::istream & >, proto::_ >
+ , proto::shift_right< Input, proto::_ >
+ >
+{};
+
+struct Output
+ : proto::or_<
+ proto::shift_left< proto::terminal< std::ostream & >, proto::_ >
+ , proto::shift_left< Output, proto::_ >
+ >
+{};
+
+proto::terminal< std::istream & >::type const cin_ = {std::cin};
+proto::terminal< std::ostream & >::type const cout_ = {std::cout};
+
+struct Anything
+ : proto::or_<
+ proto::terminal<proto::_>
+ , proto::nary_expr<proto::_, proto::vararg<Anything> >
+ >
+{};
+
+void a_function() {}
+
+struct MyCases
+{
+ template<typename Tag>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+template<>
+struct MyCases::case_<proto::tag::shift_right>
+ : proto::_
+{};
+
+template<>
+struct MyCases::case_<proto::tag::plus>
+ : proto::_
+{};
+
+enum binary_representation_enum
+{
+ magnitude
+ , two_complement
+};
+
+typedef
+ mpl::integral_c<binary_representation_enum, magnitude>
+magnitude_c;
+
+typedef
+ mpl::integral_c<binary_representation_enum, two_complement>
+two_complement_c;
+
+template<typename Type, typename Representation>
+struct number
+{};
+
+struct NumberGrammar
+ : proto::or_ <
+ proto::terminal<number<proto::_, two_complement_c> >
+ , proto::terminal<number<proto::_, magnitude_c> >
+ >
+{};
+
+struct my_terminal
+{};
+
+template<typename T>
+struct a_template
+{};
+
+template<typename Expr>
+struct my_expr;
+
+struct my_domain
+ : proto::domain<proto::pod_generator<my_expr> >
+{};
+
+template<typename Expr>
+struct my_expr
+{
+ BOOST_PROTO_BASIC_EXTENDS(Expr, my_expr, my_domain)
+};
+
+void test_matches()
+{
+ proto::assert_matches< proto::_ >( proto::lit(1) );
+ proto::assert_matches< proto::_ >( proto::as_child(1) );
+ proto::assert_matches< proto::_ >( proto::as_expr(1) );
+
+ proto::assert_matches< proto::terminal<int> >( proto::lit(1) );
+ proto::assert_matches< proto::terminal<int> >( proto::as_child(1) );
+ proto::assert_matches< proto::terminal<int> >( proto::as_expr(1) );
+
+ proto::assert_matches_not< proto::terminal<int> >( proto::lit('a') );
+ proto::assert_matches_not< proto::terminal<int> >( proto::as_child('a') );
+ proto::assert_matches_not< proto::terminal<int> >( proto::as_expr('a') );
+
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::lit('a') );
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_child('a') );
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_expr('a') );
+
+ proto::assert_matches_not< proto::terminal<int> >( proto::lit((int_convertible())) );
+ proto::assert_matches_not< proto::terminal<int> >( proto::as_child((int_convertible())) );
+ proto::assert_matches_not< proto::terminal<int> >( proto::as_expr((int_convertible())) );
+
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::lit((int_convertible())) );
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_child((int_convertible())) );
+ proto::assert_matches< proto::terminal<proto::convertible_to<int> > >( proto::as_expr((int_convertible())) );
+
+ proto::assert_matches< proto::if_<boost::is_same<proto::_value, int>() > >( proto::lit(1) );
+ proto::assert_matches_not< proto::if_<boost::is_same<proto::_value, int>() > >( proto::lit('a') );
+
+ proto::assert_matches<
+ proto::and_<
+ proto::terminal<proto::_>
+ , proto::if_<boost::is_same<proto::_value, int>() >
+ >
+ >( proto::lit(1) );
+
+ proto::assert_matches_not<
+ proto::and_<
+ proto::terminal<proto::_>
+ , proto::if_<boost::is_same<proto::_value, int>() >
+ >
+ >( proto::lit('a') );
+
+ proto::assert_matches< proto::terminal<char const *> >( proto::lit("hello") );
+ proto::assert_matches< proto::terminal<char const *> >( proto::as_child("hello") );
+ proto::assert_matches< proto::terminal<char const *> >( proto::as_expr("hello") );
+
+ proto::assert_matches< proto::terminal<char const[6]> >( proto::lit("hello") );
+ proto::assert_matches< proto::terminal<char const (&)[6]> >( proto::as_child("hello") );
+ proto::assert_matches< proto::terminal<char const[6]> >( proto::as_expr("hello") );
+
+ proto::assert_matches< proto::terminal<char [6]> >( proto::lit("hello") );
+ proto::assert_matches< proto::terminal<char [6]> >( proto::as_child("hello") );
+ proto::assert_matches< proto::terminal<char [6]> >( proto::as_expr("hello") );
+
+ proto::assert_matches< proto::terminal<char const[proto::N]> >( proto::lit("hello") );
+ proto::assert_matches< proto::terminal<char const (&)[proto::N]> >( proto::as_child("hello") );
+ proto::assert_matches< proto::terminal<char const[proto::N]> >( proto::as_expr("hello") );
+
+ proto::assert_matches< proto::terminal<char [proto::N]> >( proto::lit("hello") );
+ proto::assert_matches< proto::terminal<char [proto::N]> >( proto::as_child("hello") );
+ proto::assert_matches< proto::terminal<char [proto::N]> >( proto::as_expr("hello") );
+
+ proto::assert_matches< proto::terminal<wchar_t const[proto::N]> >( proto::lit(L"hello") );
+ proto::assert_matches< proto::terminal<wchar_t const (&)[proto::N]> >( proto::as_child(L"hello") );
+ proto::assert_matches< proto::terminal<wchar_t const[proto::N]> >( proto::as_expr(L"hello") );
+
+ proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::lit(L"hello") );
+ proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::as_child(L"hello") );
+ proto::assert_matches< proto::terminal<wchar_t [proto::N]> >( proto::as_expr(L"hello") );
+
+ proto::assert_matches_not< proto::if_<boost::is_same<proto::_value, int>()> >( proto::lit("hello") );
+
+ proto::assert_matches< proto::terminal<std::string> >( proto::lit(std::string("hello")) );
+ proto::assert_matches< proto::terminal<std::string> >( proto::as_child(std::string("hello")) );
+ proto::assert_matches< proto::terminal<std::string> >( proto::as_expr(std::string("hello")) );
+
+ proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::lit(std::string("hello")) );
+ proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::as_child(std::string("hello")) );
+ proto::assert_matches< proto::terminal<std::basic_string<proto::_> > >( proto::as_expr(std::string("hello")) );
+
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::lit(1) );
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::as_child(1) );
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> > >( proto::as_expr(1) );
+
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::lit(1) );
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::as_child(1) );
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_,proto::_,proto::_> > >( proto::as_expr(1) );
+
+ #if BOOST_WORKAROUND(__HP_aCC, BOOST_TESTED_AT(61700))
+ typedef std::string const const_string;
+ #else
+ typedef std::string const_string;
+ #endif
+
+ proto::assert_matches< proto::terminal<std::basic_string<proto::_> const & > >( proto::lit(const_string("hello")) );
+ proto::assert_matches< proto::terminal<std::basic_string<proto::_> const & > >( proto::as_child(const_string("hello")) );
+ proto::assert_matches_not< proto::terminal<std::basic_string<proto::_> const & > >( proto::as_expr(const_string("hello")) );
+
+ proto::assert_matches< proto::terminal< void(&)() > >( proto::lit(a_function) );
+ proto::assert_matches< proto::terminal< void(&)() > >( proto::as_child(a_function) );
+ proto::assert_matches< proto::terminal< void(&)() > >( proto::as_expr(a_function) );
+
+ proto::assert_matches_not< proto::terminal< void(*)() > >( proto::lit(a_function) );
+ proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_child(a_function) );
+ proto::assert_matches_not< proto::terminal< void(*)() > >( proto::as_expr(a_function) );
+
+ proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::lit(a_function) );
+ proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::as_child(a_function) );
+ proto::assert_matches< proto::terminal< proto::convertible_to<void(*)()> > >( proto::as_expr(a_function) );
+
+ proto::assert_matches< proto::terminal< void(*)() > >( proto::lit(&a_function) );
+ proto::assert_matches< proto::terminal< void(*)() > >( proto::as_child(&a_function) );
+ proto::assert_matches< proto::terminal< void(*)() > >( proto::as_expr(&a_function) );
+
+ proto::assert_matches< proto::terminal< void(* const &)() > >( proto::lit(&a_function) );
+ proto::assert_matches< proto::terminal< void(* const &)() > >( proto::as_child(&a_function) );
+ proto::assert_matches_not< proto::terminal< void(* const &)() > >( proto::as_expr(&a_function) );
+
+ proto::assert_matches<
+ proto::or_<
+ proto::if_<boost::is_same<proto::_value, char>() >
+ , proto::if_<boost::is_same<proto::_value, int>() >
+ >
+ >( proto::lit(1) );
+
+ proto::assert_matches_not<
+ proto::or_<
+ proto::if_<boost::is_same<proto::_value, char>() >
+ , proto::if_<boost::is_same<proto::_value, int>() >
+ >
+ >( proto::lit(1u) );
+
+ proto::assert_matches< Input >( cin_ >> 1 >> 2 >> 3 );
+ proto::assert_matches_not< Output >( cin_ >> 1 >> 2 >> 3 );
+
+ proto::assert_matches< Output >( cout_ << 1 << 2 << 3 );
+ proto::assert_matches_not< Input >( cout_ << 1 << 2 << 3 );
+
+ proto::assert_matches< proto::function< proto::terminal<int>, proto::vararg< proto::terminal<char> > > >( proto::lit(1)('a','b','c','d') );
+ proto::assert_matches_not< proto::function< proto::terminal<int>, proto::vararg< proto::terminal<char> > > >( proto::lit(1)('a','b','c',"d") );
+
+ proto::assert_matches< Anything >( cout_ << 1 << +proto::lit('a') << proto::lit(1)('a','b','c',"d") );
+
+ proto::assert_matches< proto::switch_<MyCases> >( proto::lit(1) >> 'a' );
+ proto::assert_matches< proto::switch_<MyCases> >( proto::lit(1) + 'a' );
+ proto::assert_matches_not< proto::switch_<MyCases> >( proto::lit(1) << 'a' );
+
+ number<int, two_complement_c> num;
+ proto::assert_matches<NumberGrammar>(proto::as_expr(num));
+
+ // check custom terminal types
+ {
+ proto::nullary_expr<my_terminal, int>::type i = {0};
+
+ proto::assert_matches<proto::nullary_expr<my_terminal, proto::_> >( i );
+ proto::assert_matches_not<proto::terminal<proto::_> >( i );
+
+ proto::terminal<int>::type j = {0};
+ proto::assert_matches<proto::terminal<proto::_> >( j );
+ proto::assert_matches_not<proto::nullary_expr<my_terminal, proto::_> >( j );
+
+ proto::assert_matches<proto::nullary_expr<proto::_, proto::_> >( i );
+ }
+
+ // check 0 and 1 arg forms or or_ and and_
+ {
+ proto::assert_matches< proto::and_<> >( proto::lit(1) );
+ proto::assert_matches_not< proto::or_<> >( proto::lit(1) );
+
+ proto::assert_matches< proto::and_<proto::terminal<int> > >( proto::lit(1) );
+ proto::assert_matches< proto::or_<proto::terminal<int> > >( proto::lit(1) );
+ }
+
+ // Test lambda matches with arrays, a corner case that had
+ // a bug that was reported by Antoine de Maricourt on boost@lists.boost.org
+ {
+ a_template<int[3]> a;
+ proto::assert_matches< proto::terminal< a_template<proto::_> > >( proto::lit(a) );
+ }
+
+ // Test that the actual derived expression type makes it through to proto::if_
+ {
+ my_expr<proto::terminal<int>::type> e = {{1}};
+ proto::assert_matches< proto::if_<boost::is_same<proto::domain_of<proto::_>, my_domain>()> >( e );
+ }
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::matches<>");
+
+ test->add(BOOST_TEST_CASE(&test_matches));
+
+ return test;
+}
+
diff --git a/src/boost/libs/proto/test/mem_ptr.cpp b/src/boost/libs/proto/test/mem_ptr.cpp
new file mode 100644
index 00000000..5326c665
--- /dev/null
+++ b/src/boost/libs/proto/test/mem_ptr.cpp
@@ -0,0 +1,303 @@
+///////////////////////////////////////////////////////////////////////////////
+// mem_ptr.hpp
+//
+// Copyright 2009 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)
+
+#include <boost/mpl/print.hpp>
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/proto/proto.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace proto = boost::proto;
+using proto::_;
+
+struct evaluator
+ : proto::when<_, proto::_default<evaluator> >
+{};
+
+template<typename Ret, typename Expr>
+void assert_result_type(Expr &)
+{
+ // check that the return type as calculated by the _default transform
+ // is correct.
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ Ret
+ , typename boost::result_of<evaluator(Expr &)>::type
+ >
+ ));
+
+ // check that the return type as calculated by the default_context
+ // is correct.
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ Ret
+ , typename boost::result_of<proto::functional::eval(Expr &, proto::default_context &)>::type
+ >
+ ));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct S
+{
+ S() : x(-42) {}
+ int x;
+};
+
+// like a normal terminal except with an operator() that can
+// accept non-const lvalues (Proto's only accepts const lvalues)
+template<typename T, typename Dummy = proto::is_proto_expr>
+struct my_terminal
+{
+ typedef typename proto::terminal<T>::type my_terminal_base;
+ BOOST_PROTO_BASIC_EXTENDS(my_terminal_base, my_terminal, proto::default_domain)
+
+ template<typename A0>
+ typename proto::result_of::make_expr<proto::tag::function, my_terminal const &, A0 &>::type const
+ operator()(A0 &a0) const
+ {
+ return proto::make_expr<proto::tag::function>(boost::ref(*this), boost::ref(a0));
+ }
+
+ template<typename A0>
+ typename proto::result_of::make_expr<proto::tag::function, my_terminal const &, A0 const &>::type const
+ operator()(A0 const &a0) const
+ {
+ return proto::make_expr<proto::tag::function>(boost::ref(*this), boost::ref(a0));
+ }
+};
+
+my_terminal<int S::*> test1 = {{ &S::x }};
+
+// Some tests with the default transform
+void test_refs_transform()
+{
+ S s;
+ BOOST_REQUIRE_EQUAL(s.x, -42);
+
+ // Check that evaluating a memptr invocation with a
+ // non-const lvalue argument yields the member as a
+ // non-const lvalue
+ assert_result_type<int &>(test1(s));
+ evaluator()(test1(s)) = 0;
+ BOOST_CHECK_EQUAL(s.x, 0);
+
+ // Ditto for reference_wrappers
+ assert_result_type<int &>(test1(boost::ref(s)));
+ evaluator()(test1(boost::ref(s))) = 42;
+ BOOST_CHECK_EQUAL(s.x, 42);
+
+ // Check that evaluating a memptr invocation with a
+ // const lvalue argument yields the member as a
+ // const lvalue
+ S const &rcs = s;
+ assert_result_type<int const &>(test1(rcs));
+ int const &s_x = evaluator()(test1(rcs));
+ BOOST_CHECK_EQUAL(&s.x, &s_x);
+}
+
+// Some tests with the default context
+void test_refs_context()
+{
+ proto::default_context ctx;
+ S s;
+ BOOST_REQUIRE_EQUAL(s.x, -42);
+
+ // Check that evaluating a memptr invocation with a
+ // non-const lvalue argument yields the member as a
+ // non-const lvalue
+ assert_result_type<int &>(test1(s));
+ proto::eval(test1(s), ctx) = 0;
+ BOOST_CHECK_EQUAL(s.x, 0);
+
+ // Ditto for reference_wrappers
+ assert_result_type<int &>(test1(boost::ref(s)));
+ proto::eval(test1(boost::ref(s)), ctx) = 42;
+ BOOST_CHECK_EQUAL(s.x, 42);
+
+ // Check that evaluating a memptr invocation with a
+ // const lvalue argument yields the member as a
+ // const lvalue
+ S const &rcs = s;
+ assert_result_type<int const &>(test1(rcs));
+ int const &s_x = proto::eval(test1(rcs), ctx);
+ BOOST_CHECK_EQUAL(&s.x, &s_x);
+}
+
+void test_ptrs_transform()
+{
+ S s;
+ BOOST_REQUIRE_EQUAL(s.x, -42);
+
+ // Check that evaluating a memptr invocation with a
+ // pointer to a non-const argument yields the member as a
+ // non-const lvalue
+ assert_result_type<int &>(test1(&s));
+ evaluator()(test1(&s)) = 0;
+ BOOST_CHECK_EQUAL(s.x, 0);
+
+ S* ps = &s;
+ assert_result_type<int &>(test1(ps));
+ evaluator()(test1(ps)) = 42;
+ BOOST_CHECK_EQUAL(s.x, 42);
+
+ boost::shared_ptr<S> const sp(new S);
+ BOOST_REQUIRE_EQUAL(sp->x, -42);
+
+ // Ditto for shared_ptr (which hook the get_pointer()
+ // customization point)
+ assert_result_type<int &>(test1(sp));
+ evaluator()(test1(sp)) = 0;
+ BOOST_CHECK_EQUAL(sp->x, 0);
+
+ // Check that evaluating a memptr invocation with a
+ // const lvalue argument yields the member as a
+ // const lvalue
+ S const &rcs = s;
+ assert_result_type<int const &>(test1(&rcs));
+ int const &s_x0 = evaluator()(test1(&rcs));
+ BOOST_CHECK_EQUAL(&s.x, &s_x0);
+
+ S const *pcs = &s;
+ assert_result_type<int const &>(test1(pcs));
+ int const &s_x1 = evaluator()(test1(pcs));
+ BOOST_CHECK_EQUAL(&s.x, &s_x1);
+
+ boost::shared_ptr<S const> spc(new S);
+ BOOST_REQUIRE_EQUAL(spc->x, -42);
+
+ assert_result_type<int const &>(test1(spc));
+ int const &s_x2 = evaluator()(test1(spc));
+ BOOST_CHECK_EQUAL(&spc->x, &s_x2);
+}
+
+void test_ptrs_context()
+{
+ proto::default_context ctx;
+ S s;
+ BOOST_REQUIRE_EQUAL(s.x, -42);
+
+ // Check that evaluating a memptr invocation with a
+ // pointer to a non-const argument yields the member as a
+ // non-const lvalue
+ assert_result_type<int &>(test1(&s));
+ proto::eval(test1(&s), ctx) = 0;
+ BOOST_CHECK_EQUAL(s.x, 0);
+
+ S* ps = &s;
+ assert_result_type<int &>(test1(ps));
+ proto::eval(test1(ps), ctx) = 42;
+ BOOST_CHECK_EQUAL(s.x, 42);
+
+ boost::shared_ptr<S> const sp(new S);
+ BOOST_REQUIRE_EQUAL(sp->x, -42);
+
+ // Ditto for shared_ptr (which hook the get_pointer()
+ // customization point)
+ assert_result_type<int &>(test1(sp));
+ proto::eval(test1(sp), ctx) = 0;
+ BOOST_CHECK_EQUAL(sp->x, 0);
+
+ // Check that evaluating a memptr invocation with a
+ // const lvalue argument yields the member as a
+ // const lvalue
+ S const &rcs = s;
+ assert_result_type<int const &>(test1(&rcs));
+ int const &s_x0 = proto::eval(test1(&rcs), ctx);
+ BOOST_CHECK_EQUAL(&s.x, &s_x0);
+
+ S const *pcs = &s;
+ assert_result_type<int const &>(test1(pcs));
+ int const &s_x1 = proto::eval(test1(pcs), ctx);
+ BOOST_CHECK_EQUAL(&s.x, &s_x1);
+
+ boost::shared_ptr<S const> spc(new S);
+ BOOST_REQUIRE_EQUAL(spc->x, -42);
+
+ assert_result_type<int const &>(test1(spc));
+ int const &s_x2 = proto::eval(test1(spc), ctx);
+ BOOST_CHECK_EQUAL(&spc->x, &s_x2);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct T
+{
+ int x;
+};
+
+proto::terminal<int T::*>::type test2 = { &T::x };
+
+int const *get_pointer(T const &t)
+{
+ return &t.x;
+}
+
+void with_get_pointer_transform()
+{
+ T t;
+ evaluator()(test2(t));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template<typename T>
+struct dumb_ptr
+{
+ dumb_ptr(T *p_) : p(p_) {}
+
+ friend T const *get_pointer(dumb_ptr const &p)
+ {
+ return p.p;
+ }
+
+ T *p;
+};
+
+struct U : dumb_ptr<U>
+{
+ U() : dumb_ptr<U>(this), x(42) {}
+ int x;
+};
+
+my_terminal<U *dumb_ptr<U>::*> U_p = {{&U::p}};
+my_terminal<int U::*> U_x = {{&U::x}};
+
+void potentially_ambiguous_transform()
+{
+ U u;
+
+ // This should yield a non-const reference to a pointer-to-const
+ U *&up = evaluator()(U_p(u));
+ BOOST_CHECK_EQUAL(&up, &u.p);
+
+ // This should yield a non-const reference to a pointer-to-const
+ int &ux = evaluator()(U_x(u));
+ BOOST_CHECK_EQUAL(&ux, &u.x);
+}
+
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test handling of member pointers by the default transform and default contexts");
+
+ test->add(BOOST_TEST_CASE(&test_refs_transform));
+ test->add(BOOST_TEST_CASE(&test_refs_context));
+
+ test->add(BOOST_TEST_CASE(&test_ptrs_transform));
+ test->add(BOOST_TEST_CASE(&test_ptrs_context));
+
+ test->add(BOOST_TEST_CASE(&with_get_pointer_transform));
+
+ test->add(BOOST_TEST_CASE(&potentially_ambiguous_transform));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/mpl.cpp b/src/boost/libs/proto/test/mpl.cpp
new file mode 100644
index 00000000..292e582b
--- /dev/null
+++ b/src/boost/libs/proto/test/mpl.cpp
@@ -0,0 +1,67 @@
+///////////////////////////////////////////////////////////////////////////////
+// mpl.hpp
+//
+// Copyright 2012 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)
+
+#include <boost/proto/proto.hpp>
+#include <boost/fusion/mpl.hpp>
+#include <boost/mpl/pop_back.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/test/unit_test.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+template<class E>
+struct my_expr;
+
+struct my_domain
+ : proto::domain<proto::generator<my_expr> >
+{};
+
+template<class E>
+struct my_expr
+ : proto::extends<E, my_expr<E>, my_domain>
+{
+ my_expr(E const &e = E())
+ : proto::extends<E, my_expr<E>, my_domain>(e)
+ {}
+
+ typedef fusion::fusion_sequence_tag tag;
+};
+
+template<typename T>
+void test_impl(T const &)
+{
+ typedef typename mpl::pop_back<T>::type result_type;
+ BOOST_STATIC_ASSERT(
+ (boost::is_same<
+ result_type
+ , my_expr<proto::basic_expr<proto::tag::plus, proto::list1<my_expr<proto::terminal<int>::type>&> > >
+ >::value)
+ );
+}
+
+// Test that we can call mpl algorithms on proto expression types, and get proto expression types back
+void test_mpl()
+{
+ my_expr<proto::terminal<int>::type> i;
+ test_impl(i + i);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto mpl integration via fusion");
+
+ test->add(BOOST_TEST_CASE(&test_mpl));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/noinvoke.cpp b/src/boost/libs/proto/test/noinvoke.cpp
new file mode 100644
index 00000000..05e738a1
--- /dev/null
+++ b/src/boost/libs/proto/test/noinvoke.cpp
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////////////////////
+// noinvoke.hpp
+//
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/make.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/test/unit_test.hpp>
+namespace proto=boost::proto;
+using proto::_;
+
+struct Test
+ : proto::when<
+ _
+ , proto::noinvoke<
+ // This remove_pointer invocation is bloked by noinvoke
+ boost::remove_pointer<
+ // This add_pointer invocation is *not* blocked by noinvoke
+ boost::add_pointer<_>
+ >
+ >()
+ >
+{};
+
+struct Test2
+ : proto::when<
+ _
+ // This add_pointer gets invoked because a substitution takes place
+ // within it.
+ , boost::add_pointer<
+ proto::noinvoke<
+ // This remove_pointer invocation is bloked by noinvoke
+ boost::remove_pointer<
+ // This add_pointer invocation is *not* blocked by noinvoke
+ boost::add_pointer<_>
+ >
+ >
+ >()
+ >
+{};
+
+template<typename T, typename U>
+struct select2nd
+{
+ typedef U type;
+};
+
+struct Test3
+ : proto::when<
+ _
+ // This add_pointer gets invoked because a substitution takes place
+ // within it.
+ , select2nd<
+ void
+ , proto::noinvoke<
+ // This remove_pointer invocation is bloked by noinvoke
+ select2nd<
+ void
+ // This add_pointer invocation is *not* blocked by noinvoke
+ , boost::add_pointer<_>
+ >
+ >
+ >()
+ >
+{};
+
+
+void test_noinvoke()
+{
+ typedef proto::terminal<int>::type Int;
+ Int i = {42};
+
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ boost::result_of<Test(Int)>::type
+ , boost::remove_pointer<Int *>
+ >
+ ));
+
+ boost::remove_pointer<Int *> t = Test()(i);
+
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ boost::result_of<Test2(Int)>::type
+ , boost::remove_pointer<Int *> *
+ >
+ ));
+
+ boost::remove_pointer<Int *> * t2 = Test2()(i);
+
+ BOOST_MPL_ASSERT((
+ boost::is_same<
+ boost::result_of<Test3(Int)>::type
+ , select2nd<void, Int *>
+ >
+ ));
+
+ select2nd<void, Int *> t3 = Test3()(i);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::noinvoke");
+
+ test->add(BOOST_TEST_CASE(&test_noinvoke));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/pack_expansion.cpp b/src/boost/libs/proto/test/pack_expansion.cpp
new file mode 100644
index 00000000..7aacb32f
--- /dev/null
+++ b/src/boost/libs/proto/test/pack_expansion.cpp
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+// pack_expansion.hpp
+//
+// 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)
+
+#include <boost/proto/proto.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/typeof/typeof.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename T> T declval();
+
+struct eval_ : proto::callable
+{
+ template<typename Sig>
+ struct result;
+
+#define UNARY_OP(TAG, OP) \
+ template<typename This, typename Arg> \
+ struct result<This(proto::tag::TAG, Arg)> \
+ { \
+ BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (OP declval<Arg>())) \
+ typedef typename nested::type type; \
+ }; \
+ \
+ template<typename Arg> \
+ typename result<eval_(proto::tag::TAG, Arg)>::type \
+ operator()(proto::tag::TAG, Arg arg) const \
+ { \
+ return OP arg; \
+ } \
+ /**/
+
+#define BINARY_OP(TAG, OP) \
+ template<typename This, typename Left, typename Right> \
+ struct result<This(proto::tag::TAG, Left, Right)> \
+ { \
+ BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (declval<Left>() OP declval<Right>())) \
+ typedef typename nested::type type; \
+ }; \
+ \
+ template<typename Left, typename Right> \
+ typename result<eval_(proto::tag::TAG, Left, Right)>::type \
+ operator()(proto::tag::TAG, Left left, Right right) const \
+ { \
+ return left OP right; \
+ } \
+ /**/
+
+ UNARY_OP(negate, -)
+ BINARY_OP(plus, +)
+ BINARY_OP(minus, -)
+ BINARY_OP(multiplies, *)
+ BINARY_OP(divides, /)
+ /*... others ...*/
+};
+
+struct eval1
+ : proto::or_<
+ proto::when<proto::terminal<_>, proto::_value>
+ , proto::otherwise<eval_(proto::tag_of<_>(), eval1(proto::pack(_))...)>
+ >
+{};
+
+struct eval2
+ : proto::or_<
+ proto::when<proto::terminal<_>, proto::_value>
+ , proto::otherwise<proto::call<eval_(proto::tag_of<_>(), eval2(proto::pack(_))...)> >
+ >
+{};
+
+void test_call_pack()
+{
+ proto::terminal<int>::type i = {42};
+ int res = eval1()(i);
+ BOOST_CHECK_EQUAL(res, 42);
+ res = eval1()(i + 2);
+ BOOST_CHECK_EQUAL(res, 44);
+ res = eval1()(i * 2);
+ BOOST_CHECK_EQUAL(res, 84);
+ res = eval1()(i * 2 + 4);
+ BOOST_CHECK_EQUAL(res, 88);
+
+ res = eval2()(i + 2);
+ BOOST_CHECK_EQUAL(res, 44);
+ res = eval2()(i * 2);
+ BOOST_CHECK_EQUAL(res, 84);
+ res = eval2()(i * 2 + 4);
+ BOOST_CHECK_EQUAL(res, 88);
+}
+
+struct make_pair
+ : proto::when<
+ proto::binary_expr<_, proto::terminal<int>, proto::terminal<int> >
+ , std::pair<int, int>(proto::_value(proto::pack(_))...)
+ >
+{};
+
+void test_make_pack()
+{
+ proto::terminal<int>::type i = {42};
+ std::pair<int, int> p = make_pair()(i + 43);
+ BOOST_CHECK_EQUAL(p.first, 42);
+ BOOST_CHECK_EQUAL(p.second, 43);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test immediate evaluation of proto parse trees");
+
+ test->add(BOOST_TEST_CASE(&test_call_pack));
+ test->add(BOOST_TEST_CASE(&test_make_pack));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/protect.cpp b/src/boost/libs/proto/test/protect.cpp
new file mode 100644
index 00000000..33b05519
--- /dev/null
+++ b/src/boost/libs/proto/test/protect.cpp
@@ -0,0 +1,106 @@
+///////////////////////////////////////////////////////////////////////////////
+// protect.hpp
+//
+// Copyright 2012 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform/make.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/test/unit_test.hpp>
+namespace proto=boost::proto;
+using proto::_;
+
+template<typename T>
+struct identity
+{
+ typedef T type;
+};
+
+struct TestWithMake
+ : proto::make< proto::protect<_> >
+{};
+
+struct TestWithMake1
+ : proto::make< identity<proto::protect<_> > >
+{};
+
+struct TestWithMake2
+ : proto::make< identity<proto::protect<int> > >
+{};
+
+struct TestWithMake3
+ : proto::make< identity<proto::protect<identity<_> > > >
+{};
+
+struct TestWithMake4
+ : proto::make< identity<proto::protect<identity<int> > > >
+{};
+
+struct TestWithMake5
+ : proto::make< identity<proto::protect<identity<identity<int> > > > >
+{};
+
+void test_protect_with_make()
+{
+ proto::terminal<int>::type i = {42};
+
+ _ t = TestWithMake()(i);
+ _ t1 = TestWithMake1()(i);
+ int t2 = TestWithMake2()(i);
+ identity<_> t3 = TestWithMake3()(i);
+ identity<int> t4 = TestWithMake4()(i);
+ identity<identity<int> > t5 = TestWithMake5()(i);
+}
+
+//struct TestWithWhen
+// : proto::when<_, proto::protect<_>() >
+//{};
+
+struct TestWithWhen1
+ : proto::when<_, identity<proto::protect<_> >() >
+{};
+
+struct TestWithWhen2
+ : proto::when<_, identity<proto::protect<int> >() >
+{};
+
+struct TestWithWhen3
+ : proto::when<_, identity<proto::protect<identity<_> > >() >
+{};
+
+struct TestWithWhen4
+ : proto::when<_, identity<proto::protect<identity<int> > >() >
+{};
+
+struct TestWithWhen5
+ : proto::when<_, identity<proto::protect<identity<identity<int> > > >() >
+{};
+
+void test_protect_with_when()
+{
+ proto::terminal<int>::type i = {42};
+
+ //_ t = TestWithWhen()(i);
+ _ t1 = TestWithWhen1()(i);
+ int t2 = TestWithWhen2()(i);
+ identity<_> t3 = TestWithWhen3()(i);
+ identity<int> t4 = TestWithWhen4()(i);
+ identity<identity<int> > t5 = TestWithWhen5()(i);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::protect");
+
+ test->add(BOOST_TEST_CASE(&test_protect_with_make));
+ test->add(BOOST_TEST_CASE(&test_protect_with_when));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/switch.cpp b/src/boost/libs/proto/test/switch.cpp
new file mode 100644
index 00000000..be5881f5
--- /dev/null
+++ b/src/boost/libs/proto/test/switch.cpp
@@ -0,0 +1,95 @@
+///////////////////////////////////////////////////////////////////////////////
+// new_switch.cpp
+//
+// Copyright 2011 Eric Niebler
+// Copyright Pierre Esterie & Joel Falcou.
+// 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)
+
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace proto = boost::proto;
+
+struct MyCases
+{
+ template<typename Tag>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+template<>
+struct MyCases::case_<proto::tag::shift_right>
+ : proto::_
+{};
+
+template<>
+struct MyCases::case_<proto::tag::plus>
+ : proto::_
+{};
+
+struct ArityOf;
+
+struct ArityOfCases
+{
+ template<typename ArityOf>
+ struct case_
+ : proto::not_<proto::_>
+ {};
+};
+
+
+template<>
+struct ArityOfCases::case_<boost::mpl::long_<1> >
+ : boost::proto::when<boost::proto::_, boost::mpl::false_()>
+{};
+
+template<>
+struct ArityOfCases::case_<boost::mpl::long_<2> >
+ : boost::proto::when<boost::proto::_, boost::mpl::true_()>
+{};
+
+struct ArityOf
+ : boost::proto::switch_<
+ ArityOfCases
+ , proto::arity_of<proto::_>()
+ >
+{};
+
+void test_switch()
+{
+ // Tests for backward compatibility
+ proto::assert_matches<proto::switch_<MyCases> >(proto::lit(1) >> 'a');
+ proto::assert_matches<proto::switch_<MyCases> >(proto::lit(1) + 'a');
+ proto::assert_matches_not<proto::switch_<MyCases> >(proto::lit(1) << 'a');
+
+ //Test new matching on the Transform result type
+ ArityOf ar;
+
+ proto::assert_matches_not<ArityOf>(proto::lit(1));
+ proto::assert_matches<ArityOf>(proto::lit(1) + 2);
+ proto::assert_matches<ArityOf>(!proto::lit(1));
+ BOOST_CHECK_EQUAL(ar(!proto::lit(1)), false);
+ BOOST_CHECK_EQUAL(ar(proto::lit(1) + 2), true);
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite(int argc, char* argv[])
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto::switch_<>");
+
+ test->add(BOOST_TEST_CASE(&test_switch));
+
+ return test;
+}
+
diff --git a/src/boost/libs/proto/test/toy_spirit.cpp b/src/boost/libs/proto/test/toy_spirit.cpp
new file mode 100644
index 00000000..6d2fcad9
--- /dev/null
+++ b/src/boost/libs/proto/test/toy_spirit.cpp
@@ -0,0 +1,665 @@
+///////////////////////////////////////////////////////////////////////////////
+// toy_spirit.hpp
+//
+// 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)
+
+#include <cctype>
+#include <string>
+#include <cstring>
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace boost
+{
+ // global tags
+ struct char_tag {};
+ struct ichar_tag {};
+ struct istring_tag {};
+ struct ichar_range_tag {};
+ struct never_tag {};
+ struct always_tag {};
+ struct space_tag {};
+
+ // global primitives
+ proto::terminal<char_tag>::type const char_ = {{}};
+ proto::terminal<space_tag>::type const space = {{}};
+
+ using proto::lit;
+ using proto::literal;
+}
+
+namespace boost { namespace spirit2
+{
+
+ // handy typedefs
+ typedef proto::terminal<char_tag>::type anychar_p;
+ typedef proto::terminal<ichar_tag>::type ianychar_p;
+ typedef proto::terminal<istring_tag>::type ianystr_p;
+ typedef proto::terminal<ichar_range_tag>::type ianychar_range_p;
+ typedef proto::terminal<never_tag>::type never_p;
+ typedef proto::terminal<space_tag>::type space_p;
+
+ struct SpiritGrammar;
+ struct SkipperGrammar;
+ struct SpiritPrimitives;
+ template<typename Grammar>
+ struct SpiritComposites;
+
+ struct CharLiteral
+ : proto::terminal<char>
+ {};
+
+ struct NTBSLiteral
+ : proto::terminal<char const *>
+ {};
+
+ struct StdStringLiteral
+ : proto::terminal<std::string>
+ {};
+
+ struct CharParser
+ : proto::function<anychar_p, CharLiteral>
+ {};
+
+ struct ICharParser
+ : proto::function<ianychar_p, CharLiteral, CharLiteral>
+ {};
+
+ struct CharRangeParser
+ : proto::function<anychar_p, CharLiteral, CharLiteral>
+ {};
+
+ struct IStrParser
+ : proto::function<ianystr_p, StdStringLiteral>
+ {};
+
+ struct ICharRangeParser
+ : proto::function<ianychar_range_p, CharLiteral, CharLiteral>
+ {};
+
+ ianychar_p const ichar_ = {{}};
+ ianystr_p const istr_ = {{}};
+ ianychar_range_p const ichar_range_ = {{}};
+
+ namespace utility
+ {
+ inline bool char_icmp(char ch, char lo, char hi)
+ {
+ return ch == lo || ch == hi;
+ }
+
+ template<typename FwdIter>
+ inline bool string_cmp(char const *sz, FwdIter &begin, FwdIter end)
+ {
+ FwdIter tmp = begin;
+ for(; *sz; ++tmp, ++sz)
+ if(tmp == end || *tmp != *sz)
+ return false;
+ begin = tmp;
+ return true;
+ }
+
+ template<typename FwdIter>
+ inline bool string_icmp(std::string const &str, FwdIter &begin, FwdIter end)
+ {
+ BOOST_ASSERT(0 == str.size() % 2);
+ FwdIter tmp = begin;
+ std::string::const_iterator istr = str.begin(), estr = str.end();
+ for(; istr != estr; ++tmp, istr += 2)
+ if(tmp == end || (*tmp != *istr && *tmp != *(istr+1)))
+ return false;
+ begin = tmp;
+ return true;
+ }
+
+ inline bool in_range(char ch, char lo, char hi)
+ {
+ return ch >= lo && ch <= hi;
+ }
+
+ inline bool in_irange(char ch, char lo, char hi)
+ {
+ return in_range(ch, lo, hi)
+ || in_range(std::tolower(ch), lo, hi)
+ || in_range(std::toupper(ch), lo, hi);
+ }
+
+ inline std::string to_istr(char const *sz)
+ {
+ std::string res;
+ res.reserve(std::strlen(sz) * 2);
+ for(; *sz; ++sz)
+ {
+ res.push_back(std::tolower(*sz));
+ res.push_back(std::toupper(*sz));
+ }
+ return res;
+ }
+ } // namespace utility
+
+ template<typename FwdIter, typename Skipper = never_p>
+ struct spirit_context
+ : std::pair<FwdIter, FwdIter>
+ , proto::callable_context<spirit_context<FwdIter, Skipper> >
+ {
+ typedef bool result_type;
+ typedef FwdIter iterator;
+
+ spirit_context(FwdIter first, FwdIter second, Skipper const &skip = Skipper())
+ : std::pair<FwdIter, FwdIter>(first, second)
+ , skip_(skip)
+ , in_skip_(false)
+ {}
+
+ // parse function for anychar_p
+ bool operator()(proto::tag::terminal, char_tag)
+ {
+ this->skip();
+ if(this->first == this->second)
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // parse function for char_('a')
+ template<typename Expr>
+ bool operator()(proto::tag::function, anychar_p, Expr const &expr)
+ {
+ this->skip();
+ return proto::eval(expr, *this);
+ }
+
+ // parse function for space_p
+ bool operator()(proto::tag::terminal, space_tag)
+ {
+ this->skip();
+ if(this->first == this->second || !std::isspace(*this->first))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // parse function for bare character literals
+ bool operator()(proto::tag::terminal, char ch)
+ {
+ this->skip();
+ if(this->first == this->second || *this->first != ch)
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // case-insensitive character parser
+ template<typename Arg1, typename Arg2>
+ bool operator()(proto::tag::function, ianychar_p, Arg1 const &arg1, Arg2 const &arg2)
+ {
+ this->skip();
+ if(this->first == this->second
+ || !utility::char_icmp(*this->first, proto::value(arg1), proto::value(arg2)))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // parse function for NTBS literals
+ bool operator()(proto::tag::terminal, char const *sz)
+ {
+ this->skip();
+ return utility::string_cmp(sz, this->first, this->second);
+ }
+
+ // parse function for istr_("hello")
+ template<typename Expr>
+ bool operator()(proto::tag::function, ianystr_p, Expr const &expr)
+ {
+ this->skip();
+ return utility::string_icmp(proto::value(expr), this->first, this->second);
+ }
+
+ // parse function for char_('a','z')
+ template<typename Arg1, typename Arg2>
+ bool operator()(proto::tag::function, anychar_p, Arg1 const &arg1, Arg2 const &arg2)
+ {
+ BOOST_ASSERT(proto::value(arg1) <= proto::value(arg2));
+ this->skip();
+ if(this->first == this->second
+ || !utility::in_range(*this->first, proto::value(arg1), proto::value(arg2)))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // parse function for ichar_range_('a','z')
+ template<typename Arg1, typename Arg2>
+ bool operator()(proto::tag::function, ianychar_range_p, Arg1 const &arg1, Arg2 const &arg2)
+ {
+ BOOST_ASSERT(proto::value(arg1) <= proto::value(arg2));
+ this->skip();
+ if(this->first == this->second
+ || !utility::in_irange(*this->first, proto::value(arg1), proto::value(arg2)))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ // parse function for complemented thingies (where thingies are assumed
+ // to be 1 character wide).
+ template<typename Expr>
+ bool operator()(proto::tag::complement, Expr const &expr)
+ {
+ this->skip();
+ iterator where = this->first;
+ if(proto::eval(expr, *this))
+ return this->first = where, false;
+ this->first = ++where;
+ return true;
+ }
+
+ // never_p parse function always returns false.
+ bool operator()(proto::tag::terminal, never_tag)
+ {
+ return false;
+ }
+
+ // for A >> B, succeeds if A and B matches.
+ template<typename Left, typename Right>
+ bool operator()(proto::tag::shift_right, Left const &left, Right const &right)
+ {
+ return proto::eval(left, *this) && proto::eval(right, *this);
+ }
+
+ // for A | B, succeeds if either A or B matches at this point.
+ template<typename Left, typename Right>
+ bool operator()(proto::tag::bitwise_or, Left const &left, Right const &right)
+ {
+ iterator where = this->first;
+ return proto::eval(left, *this) || proto::eval(right, this->reset(where));
+ }
+
+ // for *A, greedily match A as many times as possible.
+ template<typename Expr>
+ bool operator()(proto::tag::dereference, Expr const &expr)
+ {
+ iterator where = this->first;
+ while(proto::eval(expr, *this))
+ where = this->first;
+ // make sure that when we return true, the iterator is at the correct position!
+ this->first = where;
+ return true;
+ }
+
+ // for +A, greedily match A one or more times.
+ template<typename Expr>
+ bool operator()(proto::tag::unary_plus, Expr const &expr)
+ {
+ return proto::eval(expr, *this) && proto::eval(*expr, *this);
+ }
+
+ // for !A, optionally match A.
+ template<typename Expr>
+ bool operator()(proto::tag::logical_not, Expr const &expr)
+ {
+ iterator where = this->first;
+ if(!proto::eval(expr, *this))
+ this->first = where;
+ return true;
+ }
+
+ // for (A - B), matches when A but not B matches.
+ template<typename Left, typename Right>
+ bool operator()(proto::tag::minus, Left const &left, Right const &right)
+ {
+ iterator where = this->first;
+ return !proto::eval(right, *this) && proto::eval(left, this->reset(where));
+ }
+ private:
+ spirit_context &reset(iterator where)
+ {
+ this->first = where;
+ return *this;
+ }
+
+ void skip()
+ {
+ if(!this->in_skip_)
+ {
+ this->in_skip_ = true;
+ while(proto::eval(this->skip_, *this))
+ {}
+ this->in_skip_ = false;
+ }
+ }
+
+ Skipper skip_;
+ bool in_skip_;
+ };
+
+ struct as_ichar_parser : proto::callable
+ {
+ typedef proto::function<
+ ianychar_p
+ , proto::terminal<char>::type
+ , proto::terminal<char>::type
+ >::type result_type;
+
+ template<typename Expr>
+ result_type operator()(Expr const &expr) const
+ {
+ char lo = std::tolower(proto::value(proto::child_c<1>(expr)));
+ char hi = std::toupper(proto::value(proto::child_c<1>(expr)));
+ result_type that = {ichar_, {lo}, {hi}};
+ return that;
+ }
+ };
+
+ struct as_ichar_range_parser : proto::callable
+ {
+ typedef proto::function<
+ ianychar_range_p
+ , proto::terminal<char>::type
+ , proto::terminal<char>::type
+ >::type result_type;
+
+ template<typename Expr>
+ result_type operator()(Expr const &expr) const
+ {
+ char lo = proto::value(proto::child_c<1>(expr));
+ char hi = proto::value(proto::child_c<2>(expr));
+ result_type that = {ichar_range_, {lo}, {hi}};
+ return that;
+ }
+ };
+
+ struct as_ichar_literal : proto::callable
+ {
+ typedef proto::function<
+ ianychar_p
+ , proto::terminal<char>::type
+ , proto::terminal<char>::type
+ >::type result_type;
+
+ template<typename Expr>
+ result_type operator()(Expr const &expr) const
+ {
+ char lo = std::tolower(proto::value(expr));
+ char hi = std::toupper(proto::value(expr));
+ result_type that = {ichar_, {lo}, {hi}};
+ return that;
+ }
+ };
+
+ struct as_intbs_literal : proto::callable
+ {
+ typedef proto::function<
+ ianystr_p
+ , proto::terminal<std::string>::type
+ >::type result_type;
+
+ template<typename Expr>
+ result_type operator()(Expr const &expr) const
+ {
+ result_type that = {istr_, {utility::to_istr(proto::value(expr))}};
+ return that;
+ }
+ };
+
+ struct as_istdstring_literal : proto::callable
+ {
+ typedef proto::function<
+ ianystr_p
+ , proto::terminal<std::string>::type
+ >::type result_type;
+
+ template<typename Expr>
+ result_type operator()(Expr const &expr) const
+ {
+ result_type that = {istr_, {utility::to_istr(proto::value(expr).c_str())}};
+ return that;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Transforms
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct skip_primitives : proto::transform<skip_primitives>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef
+ typename proto::shift_right<
+ typename proto::dereference<State>::type
+ , Expr
+ >::type
+ result_type;
+
+ result_type operator ()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ result_type that = {{state}, expr};
+ return that;
+ }
+ };
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Grammar
+ ///////////////////////////////////////////////////////////////////////////
+ using proto::_;
+
+ struct SpiritGrammar;
+
+ struct SpiritCaseSensitivePrimitives
+ : proto::or_<
+ proto::when<CharParser, as_ichar_parser(_)>
+ , proto::when<CharLiteral, as_ichar_literal(_)>
+ , proto::when<NTBSLiteral, as_intbs_literal(_)>
+ , proto::when<CharRangeParser, as_ichar_range_parser(_)>
+ , proto::when<StdStringLiteral, as_istdstring_literal(_)>
+ >
+ {};
+
+ struct SpiritCaseInsensitivePrimitives
+ : proto::or_<
+ anychar_p
+ , IStrParser
+ , ICharParser
+ , ICharRangeParser
+ , proto::complement<SpiritPrimitives>
+ >
+ {};
+
+ struct SpiritPrimitives
+ : proto::or_<
+ SpiritCaseSensitivePrimitives
+ , SpiritCaseInsensitivePrimitives
+ >
+ {};
+
+ template<typename Grammar>
+ struct SpiritComposites
+ : proto::or_<
+ proto::bitwise_or< Grammar, Grammar >
+ , proto::shift_right< Grammar, Grammar >
+ , proto::minus< Grammar, Grammar >
+ , proto::dereference< Grammar >
+ , proto::unary_plus< Grammar >
+ , proto::logical_not< Grammar >
+ >
+ {};
+
+ // Regular Spirit grammar, has no-case transforms
+ struct SpiritGrammar
+ : proto::or_<
+ SpiritComposites<SpiritGrammar>
+ , SpiritPrimitives
+ >
+ {};
+
+ // Spirit grammar with the skipper transform
+ struct SkipperGrammar
+ : proto::or_<
+ SpiritComposites<SkipperGrammar>
+ , proto::when<SpiritPrimitives, skip_primitives>
+ >
+ {};
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Directives
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct no_case_directive
+ {
+ template<typename Expr>
+ typename boost::result_of<SpiritGrammar(Expr const &)>::type const
+ operator [](Expr const &expr) const
+ {
+ return SpiritGrammar()(expr);
+ }
+ };
+
+ // no_case
+ no_case_directive const no_case = {};
+
+ template<typename Skipper>
+ struct skip_directive
+ {
+ skip_directive(Skipper const &skip)
+ : skip_(skip)
+ {}
+
+ template<typename Expr>
+ typename boost::result_of<SkipperGrammar(Expr const &, Skipper const &)>::type const
+ operator [](Expr const &expr) const
+ {
+ return SkipperGrammar()(expr, this->skip_);
+ }
+ private:
+ Skipper skip_;
+ };
+
+ // skip
+ template<typename Skipper>
+ skip_directive<Skipper> skip(Skipper const &skip)
+ {
+ return skip_directive<Skipper>(skip);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // parse
+ ///////////////////////////////////////////////////////////////////////////
+
+ template<typename FwdIter, typename Rule>
+ bool parse(FwdIter begin, FwdIter end, Rule const &rule)
+ {
+ // make sure the rule corresponds to the Spirit grammar:
+ BOOST_MPL_ASSERT((proto::matches<Rule, SpiritGrammar>));
+
+ spirit_context<FwdIter> ctx(begin, end);
+ return proto::eval(rule, ctx);
+ }
+
+ // parse with a skip parser can be implemented in one of two ways:
+ // Method 1)
+ // The skip parser is passed to all the parsers which invoke it
+ // before they invoke themselves. This is how Spirit-1 does it,
+ // and it is the cause of the Scanner Business. However, it has
+ // the advantage of not needing a parser transformation phase.
+ // Method 2)
+ // Transform the expression template to insert the skip parser
+ // in between all sequenced parsers. That is, transform (A >> B)
+ // to (*skip >> A >> *skip >> B). This has the advantage of making
+ // it unnecessary to pass the scanner to all the parsers, which
+ // means its type doesn't show up in function signatures, avoiding
+ // the Scanner Business.
+ // Recommendation:
+ // Both methods should be supported. Method 1 should be preferred
+ // when calling parse with parsers defined inline. Method 2 should
+ // be preferred when a parser expression is assigned to a rule<>,
+ // thereby making the type of the rule<> independent of the skip
+ // parser used. I imagine a syntax like:
+ // rule<> r = skip(space)[A >> B >> C]
+ template<typename FwdIter, typename Rule, typename Skipper>
+ bool parse(FwdIter begin, FwdIter end, Rule const &rule, Skipper const &skipper)
+ {
+ // make sure the rule corresponds to the Spirit grammar:
+ BOOST_MPL_ASSERT((proto::matches<Rule, SpiritGrammar>));
+
+ //// Method 1: pass skip parser in the context structure.
+ //spirit_context<FwdIter, Skipper> ctx(begin, end, skipper);
+ //return proto::eval(rule, ctx);
+
+ // Method 2: Embed skip parser via tree transformation.
+ spirit_context<FwdIter> ctx(begin, end);
+ return proto::eval(spirit2::skip(skipper)[rule], ctx);
+ }
+
+}}
+
+using namespace boost;
+using namespace spirit2;
+
+void test_toy_spirit()
+{
+ std::string str("abcd");
+
+ // This will fail:
+ BOOST_CHECK(!spirit2::parse(str.begin(), str.end()
+ , char_ >> char_('a')));
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , char_ >> char_('b') >> char_ >> 'd'));
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , 'a' >> ('c' >> char_ | 'b' >> char_('d') | 'b' >> char_('c')) >> 'd'));
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , *(char_ - 'd')));
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , no_case[char_('A') >> 'B' >> "CD"]));
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , no_case[*char_('A','Z')]));
+
+ literal<char> a = lit('a');
+ literal<char const *> bcd = lit("bcd");
+
+ // This will succeed:
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , +~~a >> no_case[bcd]));
+
+ // Scanner Business: R.I.P. :-)
+ str = "a b cd";
+ BOOST_CHECK(spirit2::parse(str.begin(), str.end()
+ , char_('a') >> 'b' >> 'c' >> 'd', space >> space));
+
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto and and toy spirit-2");
+
+ test->add(BOOST_TEST_CASE(&test_toy_spirit));
+
+ return test;
+}
diff --git a/src/boost/libs/proto/test/toy_spirit2.cpp b/src/boost/libs/proto/test/toy_spirit2.cpp
new file mode 100644
index 00000000..a0f246f3
--- /dev/null
+++ b/src/boost/libs/proto/test/toy_spirit2.cpp
@@ -0,0 +1,466 @@
+///////////////////////////////////////////////////////////////////////////////
+// toy_spirit3.cpp
+//
+// 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)
+
+#include <cctype>
+#include <string>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <boost/assert.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/fusion/include/for_each.hpp>
+#include <boost/fusion/include/fold.hpp>
+#include <boost/fusion/include/cons.hpp>
+#include <boost/fusion/include/any.hpp>
+#include <boost/test/unit_test.hpp>
+
+namespace boost
+{
+ // global tags
+ struct char_tag {};
+ struct space_tag {};
+
+ // global primitives
+ proto::terminal<char_tag>::type const char_ = {{}};
+ proto::terminal<space_tag>::type const space = {{}};
+
+ using proto::lit;
+ using proto::literal;
+}
+
+namespace boost { namespace spirit2
+{
+ namespace utility
+ {
+ inline bool char_icmp(char ch, char lo, char hi)
+ {
+ return ch == lo || ch == hi;
+ }
+
+ template<typename FwdIter>
+ inline bool string_cmp(char const *sz, FwdIter &begin, FwdIter end)
+ {
+ FwdIter tmp = begin;
+ for(; *sz; ++tmp, ++sz)
+ if(tmp == end || *tmp != *sz)
+ return false;
+ begin = tmp;
+ return true;
+ }
+
+ template<typename FwdIter>
+ inline bool string_icmp(std::string const &str, FwdIter &begin, FwdIter end)
+ {
+ BOOST_ASSERT(0 == str.size() % 2);
+ FwdIter tmp = begin;
+ std::string::const_iterator istr = str.begin(), estr = str.end();
+ for(; istr != estr; ++tmp, istr += 2)
+ if(tmp == end || (*tmp != *istr && *tmp != *(istr+1)))
+ return false;
+ begin = tmp;
+ return true;
+ }
+
+ inline bool in_range(char ch, char lo, char hi)
+ {
+ return ch >= lo && ch <= hi;
+ }
+
+ inline bool in_irange(char ch, char lo, char hi)
+ {
+ return in_range(ch, lo, hi)
+ || in_range(std::tolower(ch), lo, hi)
+ || in_range(std::toupper(ch), lo, hi);
+ }
+
+ inline std::string to_istr(char const *sz)
+ {
+ std::string res;
+ res.reserve(std::strlen(sz) * 2);
+ for(; *sz; ++sz)
+ {
+ res.push_back(std::tolower(*sz));
+ res.push_back(std::toupper(*sz));
+ }
+ return res;
+ }
+ } // namespace utility
+
+ template<typename List>
+ struct alternate
+ {
+ explicit alternate(List const &list)
+ : elems(list)
+ {}
+ List elems;
+ };
+
+ template<typename List>
+ struct sequence
+ {
+ explicit sequence(List const &list)
+ : elems(list)
+ {}
+ List elems;
+ };
+
+ struct char_range
+ : std::pair<char, char>
+ {
+ char_range(char from, char to)
+ : std::pair<char, char>(from, to)
+ {}
+ };
+
+ struct ichar
+ {
+ ichar(char ch)
+ : lo_(std::tolower(ch))
+ , hi_(std::toupper(ch))
+ {}
+
+ char lo_, hi_;
+ };
+
+ struct istr
+ {
+ istr(char const *sz)
+ : str_(utility::to_istr(sz))
+ {}
+
+ std::string str_;
+ };
+
+ struct ichar_range
+ : std::pair<char, char>
+ {
+ ichar_range(char from, char to)
+ : std::pair<char, char>(from, to)
+ {}
+ };
+
+ // The no-case directive
+ struct no_case_tag {};
+
+ struct True : mpl::true_ {};
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// Begin Spirit grammar here
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace grammar
+ {
+ using namespace proto;
+ using namespace fusion;
+
+ struct SpiritExpr;
+
+ struct AnyChar
+ : terminal<char_tag>
+ {};
+
+ struct CharLiteral
+ : terminal<char>
+ {};
+
+ struct NTBSLiteral
+ : terminal<char const *>
+ {};
+
+ struct CharParser
+ : proto::function<AnyChar, CharLiteral>
+ {};
+
+ struct CharRangeParser
+ : proto::function<AnyChar, CharLiteral, CharLiteral>
+ {};
+
+ struct NoCase
+ : terminal<no_case_tag>
+ {};
+
+ // The data determines the case-sensitivity of the terminals
+ typedef _data _icase;
+
+ // Ugh, would be nice to find a work-around for this:
+ #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ #define _value(x) call<_value(x)>
+ #define True() make<True()>
+ #endif
+
+ // Extract the child from terminals
+ struct SpiritTerminal
+ : or_<
+ when< AnyChar, _value >
+ , when< CharLiteral, if_<_icase, ichar(_value), _value> >
+ , when< CharParser, if_<_icase, ichar(_value(_child1)), _value(_child1)> > // char_('a')
+ , when< NTBSLiteral, if_<_icase, istr(_value), char const*(_value)> >
+ , when< CharRangeParser, if_<_icase
+ , ichar_range(_value(_child1), _value(_child2))
+ , char_range(_value(_child1), _value(_child2))> > // char_('a','z')
+ >
+ {};
+
+ struct FoldToList
+ : reverse_fold_tree<_, nil(), cons<SpiritExpr, _state>(SpiritExpr, _state)>
+ {};
+
+ // sequence rule folds all >>'s together into a list
+ // and wraps the result in a sequence<> wrapper
+ struct SpiritSequence
+ : when< shift_right<SpiritExpr, SpiritExpr>, sequence<FoldToList>(FoldToList) >
+ {};
+
+ // alternate rule folds all |'s together into a list
+ // and wraps the result in a alternate<> wrapper
+ struct SpiritAlternate
+ : when< bitwise_or<SpiritExpr, SpiritExpr>, alternate<FoldToList>(FoldToList) >
+ {};
+
+ // Directives such as no_case are handled here
+ struct SpiritDirective
+ : when< subscript<NoCase, SpiritExpr>, SpiritExpr(_right, _state, True()) >
+ {};
+
+ // A SpiritExpr is an alternate, a sequence, a directive or a terminal
+ struct SpiritExpr
+ : or_<
+ SpiritSequence
+ , SpiritAlternate
+ , SpiritDirective
+ , SpiritTerminal
+ >
+ {};
+
+ } // namespace grammar
+
+ using grammar::SpiritExpr;
+ using grammar::NoCase;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /// End SpiritExpr
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // Globals
+ NoCase::type const no_case = {{}};
+
+ template<typename Iterator>
+ struct parser;
+
+ template<typename Iterator>
+ struct fold_alternate
+ {
+ parser<Iterator> const &parse;
+
+ explicit fold_alternate(parser<Iterator> const &p)
+ : parse(p)
+ {}
+
+ template<typename T>
+ bool operator ()(T const &t) const
+ {
+ Iterator tmp = this->parse.first;
+ if(this->parse(t))
+ return true;
+ this->parse.first = tmp;
+ return false;
+ }
+ };
+
+ template<typename Iterator>
+ struct fold_sequence
+ {
+ parser<Iterator> const &parse;
+
+ explicit fold_sequence(parser<Iterator> const &p)
+ : parse(p)
+ {}
+
+ typedef bool result_type;
+
+ template<typename T>
+ bool operator ()(bool success, T const &t) const
+ {
+ return success && this->parse(t);
+ }
+ };
+
+ template<typename Iterator>
+ struct parser
+ {
+ mutable Iterator first;
+ Iterator second;
+
+ parser(Iterator begin, Iterator end)
+ : first(begin)
+ , second(end)
+ {}
+
+ bool done() const
+ {
+ return this->first == this->second;
+ }
+
+ template<typename List>
+ bool operator ()(alternate<List> const &alternates) const
+ {
+ return fusion::any(alternates.elems, fold_alternate<Iterator>(*this));
+ }
+
+ template<typename List>
+ bool operator ()(sequence<List> const &sequence) const
+ {
+ return fusion::fold(sequence.elems, true, fold_sequence<Iterator>(*this));
+ }
+
+ bool operator ()(char_tag ch) const
+ {
+ if(this->done())
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ bool operator ()(char ch) const
+ {
+ if(this->done() || ch != *this->first)
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ bool operator ()(ichar ich) const
+ {
+ if(this->done() || !utility::char_icmp(*this->first, ich.lo_, ich.hi_))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ bool operator ()(char const *sz) const
+ {
+ return utility::string_cmp(sz, this->first, this->second);
+ }
+
+ bool operator ()(istr const &s) const
+ {
+ return utility::string_icmp(s.str_, this->first, this->second);
+ }
+
+ bool operator ()(char_range rng) const
+ {
+ if(this->done() || !utility::in_range(*this->first, rng.first, rng.second))
+ return false;
+ ++this->first;
+ return true;
+ }
+
+ bool operator ()(ichar_range rng) const
+ {
+ if(this->done() || !utility::in_irange(*this->first, rng.first, rng.second))
+ return false;
+ ++this->first;
+ return true;
+ }
+ };
+
+ template<typename Rule, typename Iterator>
+ typename enable_if<proto::matches< Rule, SpiritExpr >, bool >::type
+ parse_impl(Rule const &rule, Iterator begin, Iterator end)
+ {
+ mpl::false_ is_case_sensitive;
+ parser<Iterator> parse_fun(begin, end);
+ return parse_fun(SpiritExpr()(rule, proto::ignore(), is_case_sensitive));
+ }
+
+ // 2nd overload provides a short error message for invalid rules
+ template<typename Rule, typename Iterator>
+ typename disable_if<proto::matches< Rule, SpiritExpr >, bool >::type
+ parse_impl(Rule const &rule, Iterator begin, Iterator end)
+ {
+ BOOST_MPL_ASSERT((proto::matches<Rule, SpiritExpr>));
+ return false;
+ }
+
+ // parse() converts rule literals to proto expressions if necessary
+ // and dispatches to parse_impl
+ template<typename Rule, typename Iterator>
+ bool parse(Rule const &rule, Iterator begin, Iterator end)
+ {
+ return parse_impl(proto::as_expr(rule), begin, end);
+ }
+
+}}
+
+void test_toy_spirit3()
+{
+ using boost::spirit2::no_case;
+ using boost::char_;
+ std::string hello("abcd");
+
+ BOOST_CHECK(
+ boost::spirit2::parse(
+ "abcd"
+ , hello.begin()
+ , hello.end()
+ )
+ );
+
+ BOOST_CHECK(
+ boost::spirit2::parse(
+ char_ >> char_('b') >> 'c' >> char_
+ , hello.begin()
+ , hello.end()
+ )
+ );
+
+ BOOST_CHECK(
+ !boost::spirit2::parse(
+ char_ >> char_('b') >> 'c' >> 'D'
+ , hello.begin()
+ , hello.end()
+ )
+ );
+
+ BOOST_CHECK(
+ boost::spirit2::parse(
+ char_ >> char_('b') >> 'c' >> 'e'
+ | char_ >> no_case[char_('B') >> "C" >> char_('D','Z')]
+ , hello.begin()
+ , hello.end()
+ )
+ );
+
+ std::string nest_alt_input("abd");
+ BOOST_CHECK(
+ boost::spirit2::parse(
+ char_('a')
+ >> ( char_('b')
+ | char_('c')
+ )
+ >> char_('d')
+ , nest_alt_input.begin()
+ , nest_alt_input.end()
+ )
+ );
+}
+
+using namespace boost::unit_test;
+///////////////////////////////////////////////////////////////////////////////
+// init_unit_test_suite
+//
+test_suite* init_unit_test_suite( int argc, char* argv[] )
+{
+ test_suite *test = BOOST_TEST_SUITE("test proto, grammars and tree transforms");
+
+ test->add(BOOST_TEST_CASE(&test_toy_spirit3));
+
+ return test;
+}