summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/proto
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/proto')
-rw-r--r--src/boost/libs/proto/example/Jamfile.v287
-rw-r--r--src/boost/libs/proto/example/calc1.cpp68
-rw-r--r--src/boost/libs/proto/example/calc2.cpp103
-rw-r--r--src/boost/libs/proto/example/calc3.cpp154
-rw-r--r--src/boost/libs/proto/example/external_transforms.cpp128
-rw-r--r--src/boost/libs/proto/example/futures.cpp134
-rw-r--r--src/boost/libs/proto/example/hello.cpp28
-rw-r--r--src/boost/libs/proto/example/lambda.cpp17
-rw-r--r--src/boost/libs/proto/example/lambda.hpp1730
-rw-r--r--src/boost/libs/proto/example/lazy_vector.cpp142
-rw-r--r--src/boost/libs/proto/example/map_assign.cpp136
-rw-r--r--src/boost/libs/proto/example/mini_lambda.cpp263
-rw-r--r--src/boost/libs/proto/example/mixed.cpp375
-rw-r--r--src/boost/libs/proto/example/rgb.cpp102
-rw-r--r--src/boost/libs/proto/example/tarray.cpp222
-rw-r--r--src/boost/libs/proto/example/vec3.cpp184
-rw-r--r--src/boost/libs/proto/example/vector.cpp241
-rw-r--r--src/boost/libs/proto/example/virtual_member.cpp306
-rw-r--r--src/boost/libs/proto/index.html15
-rw-r--r--src/boost/libs/proto/meta/libraries.json14
-rw-r--r--src/boost/libs/proto/preprocess/Jamfile.v218
-rw-r--r--src/boost/libs/proto/preprocess/preprocess_proto.cpp10
-rw-r--r--src/boost/libs/proto/preprocess/wave.cfg27
-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
47 files changed, 9336 insertions, 0 deletions
diff --git a/src/boost/libs/proto/example/Jamfile.v2 b/src/boost/libs/proto/example/Jamfile.v2
new file mode 100644
index 00000000..7528f9ee
--- /dev/null
+++ b/src/boost/libs/proto/example/Jamfile.v2
@@ -0,0 +1,87 @@
+# (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)
+
+exe hello
+ :
+ hello.cpp
+ ;
+
+
+exe calc1
+ :
+ calc1.cpp
+ ;
+
+exe calc2
+ :
+ calc2.cpp
+ ;
+
+exe calc3
+ :
+ calc3.cpp
+ ;
+
+exe lazy_vector
+ :
+ lazy_vector.cpp
+ ;
+
+exe tarray
+ :
+ tarray.cpp
+ ;
+
+exe rgb
+ :
+ rgb.cpp
+ ;
+
+exe vec3
+ :
+ vec3.cpp
+ ;
+
+exe vector
+ :
+ vector.cpp
+ ;
+
+exe mixed
+ :
+ mixed.cpp
+ ;
+
+exe futures
+ :
+ futures.cpp
+ ;
+
+exe map_assign
+ :
+ map_assign.cpp
+ ;
+
+exe mini_lambda
+ :
+ mini_lambda.cpp
+ ;
+
+exe virtual_member
+ :
+ virtual_member.cpp
+ ;
+
+exe external_transforms
+ :
+ external_transforms.cpp
+ ;
+
+exe lambda
+ :
+ lambda.cpp
+ :
+ <include>.
+ <toolset>clang:<cxxflags>-Wno-unused-local-typedef
+ ;
diff --git a/src/boost/libs/proto/example/calc1.cpp b/src/boost/libs/proto/example/calc1.cpp
new file mode 100644
index 00000000..d3fefa62
--- /dev/null
+++ b/src/boost/libs/proto/example/calc1.cpp
@@ -0,0 +1,68 @@
+//[ Calc1
+// 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)
+//
+// This is a simple example of how to build an arithmetic expression
+// evaluator with placeholders.
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+template<int I> struct placeholder {};
+
+// Define some placeholders
+proto::terminal< placeholder< 1 > >::type const _1 = {{}};
+proto::terminal< placeholder< 2 > >::type const _2 = {{}};
+
+// Define a calculator context, for evaluating arithmetic expressions
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I - 1 ];
+ }
+};
+
+template<typename Expr>
+double evaluate( Expr const &expr, double d1 = 0., double d2 = 0. )
+{
+ // Create a calculator context with d1 and d2 substituted for _1 and _2
+ calculator_context const ctx(d1, d2);
+
+ // Evaluate the calculator expression with the calculator_context
+ return proto::eval(expr, ctx);
+}
+
+int main()
+{
+ // Displays "5"
+ std::cout << evaluate( _1 + 2.0, 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << evaluate( _1 * _2, 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << evaluate( (_1 - _2) / _2, 3.0, 2.0 ) << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/calc2.cpp b/src/boost/libs/proto/example/calc2.cpp
new file mode 100644
index 00000000..6fc490bf
--- /dev/null
+++ b/src/boost/libs/proto/example/calc2.cpp
@@ -0,0 +1,103 @@
+//[ Calc2
+// 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)
+//
+// This example enhances the simple arithmetic expression evaluator
+// in calc1.cpp by using proto::extends to make arithmetic
+// expressions immediately evaluable with operator (), a-la a
+// function object
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct calculator_expression;
+
+// Tell proto how to generate expressions in the calculator_domain
+struct calculator_domain
+ : proto::domain<proto::generator<calculator_expression> >
+{};
+
+// Will be used to define the placeholders _1 and _2
+template<int I> struct placeholder {};
+
+// Define a calculator context, for evaluating arithmetic expressions
+// (This is as before, in calc1.cpp)
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<int I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I - 1 ];
+ }
+};
+
+// Wrap all calculator expressions in this type, which defines
+// operator () to evaluate the expression.
+template<typename Expr>
+struct calculator_expression
+ : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+{
+ explicit calculator_expression(Expr const &expr = Expr())
+ : calculator_expression::proto_extends(expr)
+ {}
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
+
+ // Override operator () to evaluate the expression
+ double operator ()() const
+ {
+ calculator_context const ctx;
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1) const
+ {
+ calculator_context const ctx(d1);
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1, double d2) const
+ {
+ calculator_context const ctx(d1, d2);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some placeholders (notice they're wrapped in calculator_expression<>)
+calculator_expression<proto::terminal< placeholder< 1 > >::type> const _1;
+calculator_expression<proto::terminal< placeholder< 2 > >::type> const _2;
+
+// Now, our arithmetic expressions are immediately executable function objects:
+int main()
+{
+ // Displays "5"
+ std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/calc3.cpp b/src/boost/libs/proto/example/calc3.cpp
new file mode 100644
index 00000000..9ca97d65
--- /dev/null
+++ b/src/boost/libs/proto/example/calc3.cpp
@@ -0,0 +1,154 @@
+//[ Calc3
+// 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)
+//
+// This example enhances the arithmetic expression evaluator
+// in calc2.cpp by using a proto transform to calculate the
+// number of arguments an expression requires and using a
+// compile-time assert to guarantee that the right number of
+// arguments are actually specified.
+
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// Will be used to define the placeholders _1 and _2
+template<typename I> struct placeholder : I {};
+
+// This grammar basically says that a calculator expression is one of:
+// - A placeholder terminal
+// - Some other terminal
+// - Some non-terminal whose children are calculator expressions
+// In addition, it has transforms that say how to calculate the
+// expression arity for each of the three cases.
+struct CalculatorGrammar
+ : proto::or_<
+
+ // placeholders have a non-zero arity ...
+ proto::when< proto::terminal< placeholder<_> >, proto::_value >
+
+ // Any other terminals have arity 0 ...
+ , proto::when< proto::terminal<_>, mpl::int_<0>() >
+
+ // For any non-terminals, find the arity of the children and
+ // take the maximum. This is recursive.
+ , proto::when< proto::nary_expr<_, proto::vararg<_> >
+ , proto::fold<_, mpl::int_<0>(), mpl::max<CalculatorGrammar, proto::_state>() > >
+
+ >
+{};
+
+// Simple wrapper for calculating a calculator expression's arity.
+// It specifies mpl::int_<0> as the initial state. The data, which
+// is not used, is mpl::void_.
+template<typename Expr>
+struct calculator_arity
+ : boost::result_of<CalculatorGrammar(Expr)>
+{};
+
+template<typename Expr>
+struct calculator_expression;
+
+// Tell proto how to generate expressions in the calculator_domain
+struct calculator_domain
+ : proto::domain<proto::generator<calculator_expression> >
+{};
+
+// Define a calculator context, for evaluating arithmetic expressions
+// (This is as before, in calc1.cpp and calc2.cpp)
+struct calculator_context
+ : proto::callable_context< calculator_context const >
+{
+ // The values bound to the placeholders
+ double d[2];
+
+ // The result of evaluating arithmetic expressions
+ typedef double result_type;
+
+ explicit calculator_context(double d1 = 0., double d2 = 0.)
+ {
+ d[0] = d1;
+ d[1] = d2;
+ }
+
+ // Handle the evaluation of the placeholder terminals
+ template<typename I>
+ double operator ()(proto::tag::terminal, placeholder<I>) const
+ {
+ return d[ I() - 1 ];
+ }
+};
+
+// Wrap all calculator expressions in this type, which defines
+// operator () to evaluate the expression.
+template<typename Expr>
+struct calculator_expression
+ : proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+{
+ typedef
+ proto::extends<Expr, calculator_expression<Expr>, calculator_domain>
+ base_type;
+
+ explicit calculator_expression(Expr const &expr = Expr())
+ : base_type(expr)
+ {}
+
+ BOOST_PROTO_EXTENDS_USING_ASSIGN(calculator_expression<Expr>)
+
+ // Override operator () to evaluate the expression
+ double operator ()() const
+ {
+ // Assert that the expression has arity 0
+ BOOST_MPL_ASSERT_RELATION(0, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx;
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1) const
+ {
+ // Assert that the expression has arity 1
+ BOOST_MPL_ASSERT_RELATION(1, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx(d1);
+ return proto::eval(*this, ctx);
+ }
+
+ double operator ()(double d1, double d2) const
+ {
+ // Assert that the expression has arity 2
+ BOOST_MPL_ASSERT_RELATION(2, ==, calculator_arity<Expr>::type::value);
+ calculator_context const ctx(d1, d2);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some placeholders (notice they're wrapped in calculator_expression<>)
+calculator_expression<proto::terminal< placeholder< mpl::int_<1> > >::type> const _1;
+calculator_expression<proto::terminal< placeholder< mpl::int_<2> > >::type> const _2;
+
+// Now, our arithmetic expressions are immediately executable function objects:
+int main()
+{
+ // Displays "5"
+ std::cout << (_1 + 2.0)( 3.0 ) << std::endl;
+
+ // Displays "6"
+ std::cout << ( _1 * _2 )( 3.0, 2.0 ) << std::endl;
+
+ // Displays "0.5"
+ std::cout << ( (_1 - _2) / _2 )( 3.0, 2.0 ) << std::endl;
+
+ // This won't compile because the arity of the
+ // expression doesn't match the number of arguments
+ // ( (_1 - _2) / _2 )( 3.0 );
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/external_transforms.cpp b/src/boost/libs/proto/example/external_transforms.cpp
new file mode 100644
index 00000000..3667ebbd
--- /dev/null
+++ b/src/boost/libs/proto/example/external_transforms.cpp
@@ -0,0 +1,128 @@
+//[ CheckedCalc
+// 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/assert.hpp>
+#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>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+
+// 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::_> >
+ , 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))
+ >
+ >
+{};
+
+int main()
+{
+ non_checked_division non_checked;
+ int result2 = calc_grammar()(_1 / _2, fusion::make_vector(6, 2), non_checked);
+ BOOST_ASSERT(result2 == 3);
+
+ try
+ {
+ checked_division checked;
+ // This should throw
+ int result3 = calc_grammar()(_1 / _2, fusion::make_vector(6, 0), checked);
+ BOOST_ASSERT(false); // shouldn't get here!
+ }
+ catch(division_by_zero)
+ {
+ std::cout << "caught division by zero!\n";
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/futures.cpp b/src/boost/libs/proto/example/futures.cpp
new file mode 100644
index 00000000..29e77d6e
--- /dev/null
+++ b/src/boost/libs/proto/example/futures.cpp
@@ -0,0 +1,134 @@
+//[ FutureGroup
+// 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)
+//
+// This is an example of using Proto transforms to implement
+// Howard Hinnant's future group proposal.
+
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/as_vector.hpp>
+#include <boost/fusion/include/joint_view.hpp>
+#include <boost/fusion/include/single_view.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+template<class L,class R>
+struct pick_left
+{
+ BOOST_MPL_ASSERT((boost::is_same<L, R>));
+ typedef L type;
+};
+
+// Work-arounds for Microsoft Visual C++ 7.1
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define FutureGroup(x) proto::call<FutureGroup(x)>
+#endif
+
+// Define the grammar of future group expression, as well as a
+// transform to turn them into a Fusion sequence of the correct
+// type.
+struct FutureGroup
+ : proto::or_<
+ // terminals become a single-element Fusion sequence
+ proto::when<
+ proto::terminal<_>
+ , fusion::single_view<proto::_value>(proto::_value)
+ >
+ // (a && b) becomes a concatenation of the sequence
+ // from 'a' and the one from 'b':
+ , proto::when<
+ proto::logical_and<FutureGroup, FutureGroup>
+ , fusion::joint_view<
+ boost::add_const<FutureGroup(proto::_left) >
+ , boost::add_const<FutureGroup(proto::_right) >
+ >(FutureGroup(proto::_left), FutureGroup(proto::_right))
+ >
+ // (a || b) becomes the sequence for 'a', so long
+ // as it is the same as the sequence for 'b'.
+ , proto::when<
+ proto::logical_or<FutureGroup, FutureGroup>
+ , pick_left<
+ FutureGroup(proto::_left)
+ , FutureGroup(proto::_right)
+ >(FutureGroup(proto::_left))
+ >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef FutureGroup
+#endif
+
+template<class E>
+struct future_expr;
+
+struct future_dom
+ : proto::domain<proto::generator<future_expr>, FutureGroup>
+{};
+
+// Expressions in the future group domain have a .get()
+// member function that (ostensibly) blocks for the futures
+// to complete and returns the results in an appropriate
+// tuple.
+template<class E>
+struct future_expr
+ : proto::extends<E, future_expr<E>, future_dom>
+{
+ explicit future_expr(E const &e)
+ : future_expr::proto_extends(e)
+ {}
+
+ typename fusion::result_of::as_vector<
+ typename boost::result_of<FutureGroup(E)>::type
+ >::type
+ get() const
+ {
+ return fusion::as_vector(FutureGroup()(*this));
+ }
+};
+
+// The future<> type has an even simpler .get()
+// member function.
+template<class T>
+struct future
+ : future_expr<typename proto::terminal<T>::type>
+{
+ future(T const &t = T())
+ : future::proto_derived_expr(future::proto_base_expr::make(t))
+ {}
+
+ T get() const
+ {
+ return proto::value(*this);
+ }
+};
+
+// TEST CASES
+struct A {};
+struct B {};
+struct C {};
+
+int main()
+{
+ using fusion::vector;
+ future<A> a;
+ future<B> b;
+ future<C> c;
+ future<vector<A,B> > ab;
+
+ // Verify that various future groups have the
+ // correct return types.
+ A t0 = a.get();
+ vector<A, B, C> t1 = (a && b && c).get();
+ vector<A, C> t2 = ((a || a) && c).get();
+ vector<A, B, C> t3 = ((a && b || a && b) && c).get();
+ vector<vector<A, B>, C> t4 = ((ab || ab) && c).get();
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/hello.cpp b/src/boost/libs/proto/example/hello.cpp
new file mode 100644
index 00000000..4b9cd99b
--- /dev/null
+++ b/src/boost/libs/proto/example/hello.cpp
@@ -0,0 +1,28 @@
+//[ HelloWorld
+////////////////////////////////////////////////////////////////////
+// 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/core.hpp>
+#include <boost/proto/context.hpp>
+// This #include is only needed for compilers that use typeof emulation:
+#include <boost/typeof/std/ostream.hpp>
+namespace proto = boost::proto;
+
+proto::terminal< std::ostream & >::type cout_ = {std::cout};
+
+template< typename Expr >
+void evaluate( Expr const & expr )
+{
+ proto::default_context ctx;
+ proto::eval(expr, ctx);
+}
+
+int main()
+{
+ evaluate( cout_ << "hello" << ',' << " world" );
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/lambda.cpp b/src/boost/libs/proto/example/lambda.cpp
new file mode 100644
index 00000000..bb5c1f03
--- /dev/null
+++ b/src/boost/libs/proto/example/lambda.cpp
@@ -0,0 +1,17 @@
+//[ Lambda
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example builds a simple but functional lambda library using Proto.
+
+#include <iostream>
+#include "./lambda.hpp"
+
+int main()
+{
+ using namespace boost::lambda;
+ int i = (_1 + _1)(42);
+ std::cout << i << std::endl;
+}
diff --git a/src/boost/libs/proto/example/lambda.hpp b/src/boost/libs/proto/example/lambda.hpp
new file mode 100644
index 00000000..a08d9bf6
--- /dev/null
+++ b/src/boost/libs/proto/example/lambda.hpp
@@ -0,0 +1,1730 @@
+#ifndef BOOST_PP_IS_ITERATING
+ ///////////////////////////////////////////////////////////////////////////////
+ // 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)
+ //
+ // This example contains a full-featured reimplementation of the old,
+ // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It
+ // is necessarily complex to accomodate all the quirks and inconsistencies
+ // of that old library, but it is a good example of how to build a
+ // complete and full-featured EDLS using Proto.
+ #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008
+ #define BOOST_LAMBDA_HPP_EAN_04_19_2008
+
+ #include <iosfwd>
+ #include <typeinfo>
+ #include <algorithm>
+ #include <boost/ref.hpp>
+ #include <boost/assert.hpp>
+ #include <boost/mpl/or.hpp>
+ #include <boost/mpl/int.hpp>
+ #include <boost/mpl/void.hpp>
+ #include <boost/mpl/identity.hpp>
+ #include <boost/mpl/next_prior.hpp>
+ #include <boost/mpl/min_max.hpp>
+ #include <boost/mpl/assert.hpp>
+ #include <boost/preprocessor.hpp>
+ #include <boost/utility/enable_if.hpp>
+ #include <boost/utility/result_of.hpp>
+ #include <boost/fusion/include/vector.hpp>
+ #include <boost/type_traits/add_reference.hpp>
+ #include <boost/type_traits/remove_reference.hpp>
+ #include <boost/type_traits/remove_const.hpp>
+ #include <boost/type_traits/is_same.hpp>
+ #include <boost/proto/proto.hpp>
+
+ #ifndef BOOST_LAMBDA_MAX_ARITY
+ # define BOOST_LAMBDA_MAX_ARITY 3
+ #endif
+
+ #ifdef _MSC_VER
+ # pragma warning(push)
+ # pragma warning(disable: 4355) // 'this' : used in base member initializer list
+ # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
+ #endif
+
+ namespace boost { namespace lambda
+ {
+ namespace tag
+ {
+ struct if_ {};
+ struct if_else_ {};
+ struct for_ {};
+ struct while_ {};
+ struct do_while_ {};
+ struct protect {};
+ struct try_ {};
+ struct throw_ {};
+ struct rethrow_ {};
+ struct switch_ {};
+ struct default_ {};
+ template<int I> struct case_ { static const int value = I; };
+ template<typename E> struct catch_ { typedef E exception_type; };
+ struct catch_all_ { typedef catch_all_ exception_type; };
+ };
+
+ template<typename Int>
+ struct placeholder
+ {
+ typedef typename Int::tag tag;
+ typedef typename Int::value_type value_type;
+ typedef placeholder<Int> type;
+ typedef placeholder<typename Int::next> next;
+ typedef placeholder<typename Int::prior> prior;
+ static const value_type value = Int::value;
+
+ friend std::ostream &operator<<(std::ostream &sout, placeholder)
+ {
+ return sout << "boost::lambda::_" << (Int::value+1);
+ }
+ };
+
+ struct exception_placeholder
+ {};
+
+ struct no_exception_type {};
+ no_exception_type const no_exception = {};
+
+ // Calculate the arity of a lambda expression
+ struct Arity
+ : proto::or_<
+ proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()>
+ , proto::when<proto::terminal<proto::_>, mpl::int_<0>()>
+ , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> >
+ >
+ {};
+
+ // True when a lambda expression can be applied with no arguments and
+ // without an active exception object
+ struct IsNullary
+ : proto::or_<
+ proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()>
+ , proto::when<proto::terminal<exception_placeholder>, mpl::false_()>
+ , proto::when<proto::terminal<proto::_>, mpl::true_()>
+ , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> >
+ >
+ {};
+
+ struct Eval;
+
+ template<typename Expr, typename State, typename Data>
+ typename boost::result_of<Eval(Expr&, State&, Data&)>::type
+ eval_lambda(Expr& e, State& s, Data& d);
+
+ struct EvalWhile : proto::transform<EvalWhile>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ while(eval_lambda(proto::left(expr), state, data))
+ {
+ eval_lambda(proto::right(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalDoWhile : proto::transform<EvalDoWhile>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ do
+ {
+ eval_lambda(proto::child_c<0>(expr), state, data);
+ }
+ while(eval_lambda(proto::child_c<1>(expr), state, data));
+
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalFor : proto::transform<EvalFor>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ for(eval_lambda(proto::child_c<0>(expr), state, data)
+ ; eval_lambda(proto::child_c<1>(expr), state, data)
+ ; eval_lambda(proto::child_c<2>(expr), state, data))
+ {
+ eval_lambda(proto::child_c<3>(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalIf : proto::transform<EvalIf>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ if(eval_lambda(proto::left(expr), state, data))
+ {
+ eval_lambda(proto::right(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalIfElse : proto::transform<EvalIfElse>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef mpl::void_ result_type;
+
+ result_type operator()(
+ typename impl::expr_param expr
+ , typename impl::state_param state
+ , typename impl::data_param data
+ ) const
+ {
+ if(eval_lambda(proto::child_c<0>(expr), state, data))
+ {
+ eval_lambda(proto::child_c<1>(expr), state, data);
+ }
+ else
+ {
+ eval_lambda(proto::child_c<2>(expr), state, data);
+ }
+ return result_type();
+ }
+ };
+ };
+
+ struct EvalException : proto::transform<EvalException>
+ {
+ template<typename Expr, typename State, typename Data>
+ struct impl : proto::transform_impl<Expr, State, Data>
+ {
+ typedef typename remove_const<typename impl::state>::type result_type;
+ BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>));
+ BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>));
+
+ typename impl::state_param operator()(
+ typename impl::expr_param
+ , typename impl::state_param state
+ , typename impl::data_param
+ ) const
+ {
+ return state;
+ }
+ };
+ };
+
+ struct EvalSwitch : proto::transform<EvalSwitch>
+ {
+ template<typename Expr, typename State, typename Data, long Arity, typename BackTag>
+ struct impl2;
+
+ #define M0(Z, N, DATA) \
+ case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \
+ eval_lambda(proto::child_c<N>(expr), state, data); \
+ break; \
+ /**/
+
+ #define M1(Z, N, DATA) \
+ template<typename Expr, typename State, typename Data, typename BackTag> \
+ struct impl2<Expr, State, Data, N, BackTag> \
+ : proto::transform_impl<Expr, State, Data> \
+ { \
+ typedef void result_type; \
+ \
+ void operator()( \
+ typename impl2::expr_param expr \
+ , typename impl2::state_param state \
+ , typename impl2::data_param data \
+ ) const \
+ { \
+ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \
+ { \
+ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \
+ default: \
+ break; \
+ } \
+ } \
+ }; \
+ \
+ template<typename Expr, typename State, typename Data> \
+ struct impl2<Expr, State, Data, N, tag::default_> \
+ : proto::transform_impl<Expr, State, Data> \
+ { \
+ typedef void result_type; \
+ \
+ void operator()( \
+ typename impl2::expr_param expr \
+ , typename impl2::state_param state \
+ , typename impl2::data_param data \
+ ) const \
+ { \
+ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \
+ { \
+ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \
+ default:; \
+ eval_lambda(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \
+ break; \
+ } \
+ } \
+ }; \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~)
+ #undef M0
+ #undef M1
+
+ template<typename Expr, typename State, typename Data>
+ struct impl
+ : impl2<
+ Expr
+ , State
+ , Data
+ , proto::arity_of<Expr>::value
+ , typename proto::tag_of<
+ typename proto::result_of::child_c<
+ Expr
+ , proto::arity_of<Expr>::value-1
+ >::type
+ >::type
+ >
+ {};
+ };
+
+ struct throw_fun
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef void result_type;
+ template<typename Expr>
+ void operator()(Expr const &e) const
+ {
+ throw e;
+ }
+ };
+
+ struct unwrap_ref : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename T>
+ struct result<This(reference_wrapper<T>)>
+ {
+ typedef T &type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(T &)>
+ : result<This(T)>
+ {};
+
+ template<typename T>
+ T &operator()(reference_wrapper<T> const &ref) const
+ {
+ return ref;
+ }
+ };
+
+ struct anytype
+ {
+ template<typename T>
+ anytype(T &) { BOOST_ASSERT(false); }
+ template<typename T>
+ operator T &() const { BOOST_ASSERT(false); throw; }
+ private:
+ anytype();
+ };
+
+ struct rethrow_fun
+ {
+ BOOST_PROTO_CALLABLE()
+ typedef anytype result_type;
+ template<typename State>
+ anytype operator()(State const &) const
+ {
+ BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>));
+ throw;
+ }
+ };
+
+ struct Cases
+ {
+ template<typename Tag>
+ struct case_
+ : proto::otherwise<proto::_default<Eval> >
+ {};
+
+ template<typename E>
+ struct case_<tag::catch_<E> >
+ : proto::otherwise<Eval(proto::_child)>
+ {};
+
+ template<int I>
+ struct case_<tag::case_<I> >
+ : proto::otherwise<Eval(proto::_child)>
+ {};
+ };
+
+ template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {};
+ template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {};
+ template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {};
+ template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {};
+ template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {};
+ template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {};
+ template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {};
+ template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {};
+ template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {};
+
+ template<>
+ struct Cases::case_<proto::tag::terminal>
+ : proto::or_<
+ proto::when<
+ proto::terminal<placeholder<proto::_> >
+ , proto::functional::at(proto::_data, proto::_value)
+ >
+ , proto::when<
+ proto::terminal<exception_placeholder>
+ , EvalException
+ >
+ , proto::when<
+ proto::terminal<reference_wrapper<proto::_> >
+ , unwrap_ref(proto::_value)
+ >
+ , proto::otherwise<proto::_default<Eval> >
+ >
+ {};
+
+ template<>
+ struct Cases::case_<proto::tag::function>
+ : proto::or_<
+ proto::when<
+ proto::function<proto::terminal<rethrow_fun> >
+ , rethrow_fun(proto::_state)
+ >
+ , proto::otherwise<proto::_default<Eval> >
+ >
+ {};
+
+ struct Eval
+ : proto::switch_<Cases>
+ {};
+
+ template<typename Expr, typename State, typename Data>
+ typename boost::result_of<Eval(Expr&, State&, Data&)>::type
+ eval_lambda(Expr& e, State& s, Data& d)
+ {
+ return Eval()(e, s, d);
+ }
+
+ // Use a grammar to disable Proto's assignment operator overloads.
+ // We'll define our own because we want (x+=_1) to store x by
+ // reference. (In all other cases, variables are stored by value
+ // within lambda expressions.)
+ struct Grammar
+ : proto::switch_<struct AssignOps>
+ {};
+
+ struct AssignOps
+ {
+ template<typename Tag> struct case_ : proto::_ {};
+ };
+
+ template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {};
+ template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {};
+
+ template<typename Expr>
+ struct llexpr;
+
+ // Wrap expressions in lambda::llexpr<>.
+ struct Generator
+ : proto::pod_generator<llexpr>
+ {};
+
+ // The domain for the lambda library.
+ struct lldomain
+ : proto::domain<Generator, Grammar, proto::default_domain>
+ {
+ // Make all terminals and children held by value instead of by reference.
+ // Proto::domain<>::as_expr<> holds everything it can by value; the only
+ // exceptions are function types, abstract types, and iostreams.
+ template<typename T>
+ struct as_child
+ : proto_base_domain::as_expr<T>
+ {};
+
+ // The exception is arrays, which should still be held by reference
+ template<typename T, std::size_t N>
+ struct as_child<T[N]>
+ : proto_base_domain::as_child<T[N]>
+ {};
+ };
+
+ template<typename Sig>
+ struct llresult;
+
+ template<typename This>
+ struct llresult<This()>
+ : mpl::if_c<
+ result_of<IsNullary(This &)>::type::value
+ , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)>
+ , mpl::identity<void>
+ >::type
+ {};
+
+ #define M0(Z, N, DATA) \
+ template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
+ struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \
+ : result_of< \
+ Eval( \
+ This & \
+ , no_exception_type const & \
+ , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \
+ ) \
+ > \
+ {}; \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~)
+ #undef M0
+
+ template<typename Expr>
+ struct llexpr
+ {
+ BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ template<typename Sig>
+ struct result
+ : llresult<Sig>
+ {};
+
+ typename result<llexpr const()>::type
+ operator()() const
+ {
+ fusion::vector0<> args;
+ return eval_lambda(*this, no_exception, args);
+ }
+
+ #define M1(Z, N, _) ((0)(1))
+
+ #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT)
+
+ #define M3(R, SIZE, PRODUCT) \
+ template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \
+ typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \
+ operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \
+ { \
+ BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \
+ BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \
+ (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \
+ return eval_lambda(*this, no_exception, args); \
+ } \
+ /**/
+
+ #define M4(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \
+ /**/
+
+ #define M5(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \
+ /**/
+
+ #define M6(R, _, I, ELEM) \
+ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \
+ /**/
+
+ #define C0
+
+ #define C1 const
+
+ #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "lambda.hpp"))
+ #include BOOST_PP_ITERATE()
+
+ #undef C0
+ #undef C1
+ #undef M1
+ #undef M2
+ #undef M3
+ #undef M4
+ #undef M5
+ #undef M6
+ };
+
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type;
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type;
+ typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type;
+
+ placeholder1_type const _1 = {{{}}};
+ placeholder2_type const _2 = {{{}}};
+ placeholder3_type const _3 = {{{}}};
+
+ placeholder1_type const free1 = {{{}}};
+ placeholder2_type const free2 = {{{}}};
+ placeholder3_type const free3 = {{{}}};
+
+ typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type;
+ placeholderE_type const _e = {{{}}};
+
+ struct byref
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename T>
+ struct result<This(T &)>
+ {
+ typedef llexpr<typename proto::terminal<T &>::type> type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(llexpr<T> &)>
+ {
+ typedef boost::reference_wrapper<llexpr<T> > type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(llexpr<T> const &)>
+ {
+ typedef boost::reference_wrapper<llexpr<T> const> type;
+ };
+
+ template<typename T>
+ typename result<byref(T &)>::type operator()(T &t) const
+ {
+ typename result<byref(T &)>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ typename result<byref(T const &)>::type operator()(T const &t) const
+ {
+ typename result<byref(T const &)>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const
+ {
+ return boost::ref(t);
+ }
+
+ template<typename T>
+ boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const
+ {
+ return boost::ref(t);
+ }
+ };
+
+ namespace exprns_
+ {
+ // Ugh, the assign operators (and only the assign operators) store
+ // their left terminals by reference. That requires this special handling.
+ #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \
+ template<typename T, typename U> \
+ typename proto::result_of::make_expr< \
+ TAG \
+ , lldomain \
+ , typename boost::result_of<byref(T &)>::type \
+ , U & \
+ >::type const \
+ operator OP(T &t, U &u) \
+ { \
+ return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
+ } \
+ template<typename T, typename U> \
+ typename proto::result_of::make_expr< \
+ TAG \
+ , lldomain \
+ , typename boost::result_of<byref(T &)>::type \
+ , U const & \
+ >::type const \
+ operator OP(T &t, U const &u) \
+ { \
+ return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
+ } \
+ /**/
+
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign)
+ BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign)
+ }
+
+ template<typename T>
+ struct var_type
+ {
+ typedef llexpr<typename proto::terminal<T &>::type> type;
+ };
+
+ template<typename T>
+ llexpr<typename proto::terminal<T &>::type> const
+ var(T &t)
+ {
+ llexpr<typename proto::terminal<T &>::type> that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ struct constant_type
+ : proto::result_of::make_expr<
+ proto::tag::terminal
+ , lldomain
+ , T const &
+ >
+ {};
+
+ template<typename T>
+ typename constant_type<T>::type const
+ constant(T const &t)
+ {
+ typename constant_type<T>::type that = {{t}};
+ return that;
+ }
+
+ template<typename T>
+ struct constant_ref_type
+ {
+ typedef llexpr<typename proto::terminal<T const &>::type> type;
+ };
+
+ template<typename T>
+ llexpr<typename proto::terminal<T const &>::type> const
+ constant_ref(T const &t)
+ {
+ llexpr<typename proto::terminal<T const &>::type> that = {{t}};
+ return that;
+ }
+
+ template<typename Cond>
+ struct while_generator
+ {
+ explicit while_generator(Cond const &c)
+ : cond(c)
+ {}
+
+ template<typename Body>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(this->cond)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Cond const &cond;
+ };
+
+ template<typename Expr>
+ while_generator<Expr> while_(Expr const &expr)
+ {
+ return while_generator<Expr>(expr);
+ }
+
+ template<typename Expr>
+ struct else_generator
+ {
+ typedef typename proto::result_of::left<Expr const &>::type condition_type;
+ typedef typename proto::result_of::right<Expr const &>::type body1_type;
+
+ explicit else_generator(Expr const &expr)
+ : if_(expr)
+ {}
+
+ template<typename Body2>
+ typename proto::result_of::make_expr<
+ tag::if_else_
+ , lldomain
+ , condition_type
+ , body1_type
+ , Body2 const &
+ >::type const
+ operator[](Body2 const &body2) const
+ {
+ return proto::make_expr<tag::if_else_, lldomain>(
+ boost::ref(proto::left(this->if_))
+ , boost::ref(proto::right(this->if_))
+ , boost::ref(body2)
+ );
+ }
+
+ private:
+ Expr const &if_;
+ };
+
+ template<typename Expr>
+ struct with_else : Expr
+ {
+ template<typename T>
+ with_else(T const &expr)
+ : Expr(expr)
+ , else_(*this)
+ {}
+
+ else_generator<Expr> else_;
+ };
+
+ template<typename Cond>
+ struct if_generator
+ {
+ explicit if_generator(Cond const &c)
+ : cond(c)
+ {}
+
+ template<typename Body>
+ with_else<
+ typename proto::result_of::make_expr<
+ tag::if_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type
+ > const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::if_, lldomain>(
+ boost::ref(this->cond)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Cond const &cond;
+ };
+
+ template<typename Expr>
+ if_generator<Expr> if_(Expr const &expr)
+ {
+ return if_generator<Expr>(expr);
+ }
+
+ template<typename Init, typename Cond, typename Oper>
+ struct for_generator
+ {
+ explicit for_generator(Init const &i, Cond const &c, Oper const &o)
+ : init(i)
+ , cond(c)
+ , oper(o)
+ {}
+
+ template<typename Body>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , Body const &
+ >::type const
+ operator[](Body const &body) const
+ {
+ return proto::make_expr<tag::for_, lldomain>(
+ boost::ref(this->init)
+ , boost::ref(this->cond)
+ , boost::ref(this->oper)
+ , boost::ref(body)
+ );
+ }
+
+ private:
+ Init const &init;
+ Cond const &cond;
+ Oper const &oper;
+ };
+
+ template<typename Init, typename Cond, typename Oper>
+ for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o)
+ {
+ return for_generator<Init, Cond, Oper>(i, c, o);
+ }
+
+ template<typename Body>
+ struct do_while_generator
+ {
+ explicit do_while_generator(Body const &b)
+ : body(b)
+ {}
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , Body const &
+ , Cond const &
+ >::type const
+ operator()(Cond const &cond) const
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(this->body)
+ , boost::ref(cond)
+ );
+ }
+
+ private:
+ Body const &body;
+ };
+
+ template<typename Body>
+ struct do_body
+ {
+ explicit do_body(Body const &body)
+ : while_(body)
+ {}
+
+ do_while_generator<Body> while_;
+ };
+
+ struct do_generator
+ {
+ template<typename Body>
+ do_body<Body> operator[](Body const &body) const
+ {
+ return do_body<Body>(body);
+ }
+ };
+
+ do_generator const do_ = {};
+
+ struct noop_fun
+ {
+ typedef void result_type;
+ void operator()() const {}
+ };
+
+ typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type;
+ noop_type const noop = {{{{{}}}}};
+
+ template<typename Init, typename Cond, typename Oper>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , noop_type const &
+ >::type const
+ for_loop(Init const &init, Cond const &cond, Oper const &oper)
+ {
+ return proto::make_expr<tag::for_, lldomain>(
+ boost::ref(init)
+ , boost::ref(cond)
+ , boost::ref(oper)
+ , boost::ref(noop)
+ );
+ }
+
+ template<typename Init, typename Cond, typename Oper, typename Body>
+ typename proto::result_of::make_expr<
+ tag::for_
+ , lldomain
+ , Init const &
+ , Cond const &
+ , Oper const &
+ , Body const &
+ >::type const
+ for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body)
+ {
+ return proto::make_expr<tag::for_>(
+ boost::ref(init)
+ , boost::ref(cond)
+ , boost::ref(oper)
+ , boost::ref(body)
+ );
+ }
+
+ template<typename Cond, typename Body>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , Body const &
+ >::type const
+ while_loop(Cond const &cond, Body const &body)
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body)
+ );
+ }
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::while_
+ , lldomain
+ , Cond const &
+ , noop_type const &
+ >::type const
+ while_loop(Cond const &cond)
+ {
+ return proto::make_expr<tag::while_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(noop)
+ );
+ }
+
+ template<typename Cond, typename Body>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , Body const &
+ , Cond const &
+ >::type const
+ do_while_loop(Cond const &cond, Body const &body)
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(body)
+ , boost::ref(cond)
+ );
+ }
+
+ template<typename Cond>
+ typename proto::result_of::make_expr<
+ tag::do_while_
+ , lldomain
+ , noop_type const &
+ , Cond const &
+ >::type const
+ do_while_loop(Cond const &cond)
+ {
+ return proto::make_expr<tag::do_while_, lldomain>(
+ boost::ref(noop)
+ , boost::ref(cond)
+ );
+ }
+
+ template<typename Cond, typename Body1>
+ typename proto::result_of::make_expr<
+ tag::if_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ >::type const
+ if_then(Cond const &cond, Body1 const &body1)
+ {
+ return proto::make_expr<tag::if_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ );
+ }
+
+ template<typename Cond, typename Body1, typename Body2>
+ typename proto::result_of::make_expr<
+ tag::if_else_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ , Body2 const &
+ >::type const
+ if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2)
+ {
+ return proto::make_expr<tag::if_else_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ , boost::ref(body2)
+ );
+ }
+
+ template<typename Cond, typename Body1, typename Body2>
+ typename proto::result_of::make_expr<
+ proto::tag::if_else_
+ , lldomain
+ , Cond const &
+ , Body1 const &
+ , Body2 const &
+ >::type const
+ if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2)
+ {
+ return proto::make_expr<proto::tag::if_else_, lldomain>(
+ boost::ref(cond)
+ , boost::ref(body1)
+ , boost::ref(body2)
+ );
+ }
+
+ template<typename T>
+ T const &make_const(T const &t)
+ {
+ return t;
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ bind(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
+ } \
+ \
+ template<typename Ret, typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ bind(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<typename Ret, typename Expr>
+ Expr const &ret(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Expr>
+ Expr const &const_parameters(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Expr>
+ Expr const &break_const(Expr const &expr)
+ {
+ return expr;
+ }
+
+ template<typename Lambda>
+ proto::unexpr<Lambda> const
+ unlambda(Lambda const &lambda)
+ {
+ return proto::unexpr<Lambda>(lambda);
+ }
+
+ template<typename Lambda>
+ typename proto::result_of::make_expr<
+ tag::protect
+ , lldomain
+ , Lambda const &
+ >::type const
+ protect(Lambda const &lambda)
+ {
+ return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda));
+ }
+
+ template<typename T>
+ T const std_functor(T const &t)
+ {
+ return t;
+ }
+
+ template<typename T>
+ struct ll_static_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return static_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return static_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_static_cast_fun<T>
+ , U const &
+ >::type
+ ll_static_cast(U const &u)
+ {
+ ll_static_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_const_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return const_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return const_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_const_cast_fun<T>
+ , U const &
+ >::type
+ ll_const_cast(U const &u)
+ {
+ ll_const_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_dynamic_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return dynamic_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return dynamic_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_dynamic_cast_fun<T>
+ , U const &
+ >::type
+ ll_dynamic_cast(U const &u)
+ {
+ ll_dynamic_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct ll_reinterpret_cast_fun
+ {
+ typedef T result_type;
+
+ template<typename U>
+ T operator()(U &u) const
+ {
+ return reinterpret_cast<T>(u);
+ }
+
+ template<typename U>
+ T operator()(U const &u) const
+ {
+ return reinterpret_cast<T>(u);
+ }
+ };
+
+ template<typename T, typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_reinterpret_cast_fun<T>
+ , U const &
+ >::type
+ ll_reinterpret_cast(U const &u)
+ {
+ ll_reinterpret_cast_fun<T> fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ struct ll_sizeof_fun
+ {
+ typedef std::size_t result_type;
+
+ template<typename U>
+ std::size_t operator()(U const &) const
+ {
+ return sizeof(U);
+ }
+ };
+
+ template<typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_sizeof_fun
+ , U const &
+ >::type
+ ll_sizeof(U const &u)
+ {
+ ll_sizeof_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ struct ll_typeid_fun
+ {
+ typedef std::type_info const &result_type;
+
+ template<typename U>
+ std::type_info const &operator()(U const &) const
+ {
+ return typeid(U);
+ }
+ };
+
+ template<typename U>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , ll_typeid_fun
+ , U const &
+ >::type
+ ll_typeid(U const &u)
+ {
+ ll_typeid_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
+ }
+
+ template<typename T>
+ struct constructor
+ {
+ typedef T result_type;
+
+ T operator()() const
+ {
+ return T();
+ }
+
+ #define M0(Z, N, DATA) \
+ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
+ T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
+ { \
+ return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
+ } \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
+ #undef M0
+ };
+
+ template<typename T>
+ struct new_ptr
+ {
+ typedef T *result_type;
+
+ T *operator()() const
+ {
+ return new T();
+ }
+
+ #define M0(Z, N, DATA) \
+ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
+ T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
+ { \
+ return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
+ } \
+ /**/
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
+ #undef M0
+ };
+
+ struct destructor
+ {
+ typedef void result_type;
+
+ template<typename T>
+ void operator()(T const &t) const
+ {
+ t.~T();
+ }
+
+ template<typename T>
+ void operator()(T *const &t) const
+ {
+ (*t).~T();
+ }
+ };
+
+ struct delete_ptr
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T *t) const
+ {
+ delete t;
+ }
+ };
+
+ template<typename T>
+ struct new_array
+ {
+ typedef T *result_type;
+ T *operator()(std::size_t n) const
+ {
+ return new T[n];
+ }
+ };
+
+ struct delete_array
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T *t) const
+ {
+ delete[] t;
+ }
+ };
+
+ template<typename T>
+ struct type2type {};
+
+ struct try_catch_nil {};
+
+ template<typename Head, typename Tail>
+ struct try_catch_cons : Tail
+ {
+ typedef typename Head::proto_tag::exception_type exception_type;
+
+ try_catch_cons(Head const &head, Tail const &tail)
+ : Tail(tail)
+ , head(head)
+ {}
+
+ template<typename State, typename Data>
+ typename result_of<Tail const(State const &, Data &)>::type
+ operator()(State const &state, Data &data) const
+ {
+ return this->invoke(state, data, type2type<exception_type>());
+ }
+
+ private:
+ // catch(Exception const &)
+ template<typename State, typename Data, typename Exception>
+ typename result_of<Tail const(State const &, Data &)>::type
+ invoke(State const &state, Data &data, type2type<Exception>) const
+ {
+ typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
+ try
+ {
+ return static_cast<result_type>(this->Tail::operator()(state, data));
+ }
+ catch(Exception const &e)
+ {
+ return static_cast<result_type>(eval_lambda(this->head, e, data));
+ }
+ }
+
+ // catch(...)
+ template<typename State, typename Data>
+ typename result_of<Tail const(State const &, Data &)>::type
+ invoke(State const &state, Data &data, type2type<tag::catch_all_>) const
+ {
+ typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
+ try
+ {
+ return static_cast<result_type>(this->Tail::operator()(state, data));
+ }
+ catch(...)
+ {
+ return static_cast<result_type>(eval_lambda(this->head, tag::catch_all_(), data));
+ }
+ }
+
+ Head const &head;
+ };
+
+ template<typename Head>
+ struct try_catch_cons<Head, try_catch_nil> : proto::callable
+ {
+ try_catch_cons(Head const &head, try_catch_nil const &)
+ : head(head)
+ {}
+
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename State, typename Data>
+ struct result<This(State, Data)>
+ : result_of<Eval(Head const &, State, Data)>
+ {};
+
+ template<typename State, typename Data>
+ typename result_of<Eval(Head const &, State, Data)>::type
+ operator()(State const &state, Data &data) const
+ {
+ return eval_lambda(this->head, state, data);
+ }
+
+ private:
+ Head const &head;
+ };
+
+ struct try_catch_fun : proto::callable
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Fun, typename State, typename Data>
+ struct result<This(Fun, State, Data)>
+ : result_of<Fun(State, Data)>
+ {};
+
+ template<typename Fun, typename State, typename Data>
+ typename result_of<Fun(State const &, Data &)>::type
+ operator()(Fun const &fun, State const &state, Data &data) const
+ {
+ return fun(state, data);
+ }
+ };
+
+ template<>
+ struct Cases::case_<tag::try_>
+ : proto::otherwise<
+ try_catch_fun(
+ proto::fold<
+ proto::_
+ , try_catch_nil()
+ , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state)
+ >
+ , proto::_state
+ , proto::_data
+ )
+ >
+ {};
+
+ template<typename E, typename Expr>
+ typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const
+ catch_exception(Expr const &expr)
+ {
+ return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr));
+ }
+
+ template<typename E>
+ typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const
+ catch_exception()
+ {
+ return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop));
+ }
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ tag::catch_all_
+ , lldomain
+ , Expr const &
+ >::type const
+ catch_all(Expr const &expr)
+ {
+ return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const
+ catch_all()
+ {
+ return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop));
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ tag::try_ \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ try_catch(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<tag::try_, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , throw_fun
+ , Expr const &
+ >::type const
+ throw_exception(Expr const &expr)
+ {
+ throw_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const
+ rethrow()
+ {
+ return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun());
+ }
+
+ struct make_void_fun
+ {
+ typedef void result_type;
+ template<typename T>
+ void operator()(T const &) const
+ {}
+ };
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , lldomain
+ , make_void_fun
+ , Expr const &
+ >::type const
+ make_void(Expr const &expr)
+ {
+ make_void_fun fun;
+ return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
+ }
+
+ #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+ template<typename_A(N)> \
+ typename proto::result_of::make_expr< \
+ tag::switch_ \
+ , lldomain \
+ , A_const_ref(N) \
+ >::type const \
+ switch_statement(A_const_ref_a(N)) \
+ { \
+ return proto::make_expr<tag::switch_, lldomain>(ref_a(N)); \
+ } \
+ /**/
+ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
+ #undef M1
+
+ template<int I, typename Expr>
+ typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const
+ case_statement(Expr const &expr)
+ {
+ return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr));
+ }
+
+ template<int I>
+ typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const
+ case_statement()
+ {
+ return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop));
+ }
+
+ template<typename Expr>
+ typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const
+ default_statement(Expr const &expr)
+ {
+ return proto::make_expr<tag::default_, lldomain>(boost::ref(expr));
+ }
+
+ inline
+ proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const
+ default_statement()
+ {
+ return proto::make_expr<tag::default_, lldomain>(boost::ref(noop));
+ }
+
+ namespace ll
+ {
+ struct for_each
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Begin, typename End, typename Fun>
+ struct result<This(Begin, End, Fun)>
+ : remove_const<typename remove_reference<Fun>::type>
+ {};
+
+ template<typename InIter, typename Fun>
+ Fun operator()(InIter begin, InIter end, Fun fun) const
+ {
+ return std::for_each(begin, end, fun);
+ }
+ };
+ }
+
+ }}
+
+ namespace boost
+ {
+ template<typename Expr>
+ struct result_of<lambda::llexpr<Expr>()>
+ : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()>
+ {};
+
+ template<typename Expr>
+ struct result_of<lambda::llexpr<Expr> const()>
+ : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()>
+ {};
+ }
+
+ #ifdef _MSC_VER
+ # pragma warning(pop)
+ #endif
+
+ #endif
+
+#else
+
+ BOOST_PP_SEQ_FOR_EACH_PRODUCT(
+ M2,
+ BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~)
+ )
+
+#endif
diff --git a/src/boost/libs/proto/example/lazy_vector.cpp b/src/boost/libs/proto/example/lazy_vector.cpp
new file mode 100644
index 00000000..2fc7755c
--- /dev/null
+++ b/src/boost/libs/proto/example/lazy_vector.cpp
@@ -0,0 +1,142 @@
+//[ LazyVector
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example constructs a mini-library for linear algebra, using
+// expression templates to eliminate the need for temporaries when
+// adding vectors of numbers.
+//
+// This example uses a domain with a grammar to prune the set
+// of overloaded operators. Only those operators that produce
+// valid lazy vector expressions are allowed.
+
+#include <vector>
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct lazy_vector_expr;
+
+// This grammar describes which lazy vector expressions
+// are allowed; namely, vector terminals and addition
+// and subtraction of lazy vector expressions.
+struct LazyVectorGrammar
+ : proto::or_<
+ proto::terminal< std::vector<_> >
+ , proto::plus< LazyVectorGrammar, LazyVectorGrammar >
+ , proto::minus< LazyVectorGrammar, LazyVectorGrammar >
+ >
+{};
+
+// Tell proto that in the lazy_vector_domain, all
+// expressions should be wrapped in laxy_vector_expr<>
+// and must conform to the lazy vector grammar.
+struct lazy_vector_domain
+ : proto::domain<proto::generator<lazy_vector_expr>, LazyVectorGrammar>
+{};
+
+// Here is an evaluation context that indexes into a lazy vector
+// expression, and combines the result.
+template<typename Size = std::size_t>
+struct lazy_subscript_context
+{
+ lazy_subscript_context(Size subscript)
+ : subscript_(subscript)
+ {}
+
+ // Use default_eval for all the operations ...
+ template<typename Expr, typename Tag = typename Expr::proto_tag>
+ struct eval
+ : proto::default_eval<Expr, lazy_subscript_context>
+ {};
+
+ // ... except for terminals, which we index with our subscript
+ template<typename Expr>
+ struct eval<Expr, proto::tag::terminal>
+ {
+ typedef typename proto::result_of::value<Expr>::type::value_type result_type;
+
+ result_type operator ()( Expr const & expr, lazy_subscript_context & ctx ) const
+ {
+ return proto::value( expr )[ ctx.subscript_ ];
+ }
+ };
+
+ Size subscript_;
+};
+
+// Here is the domain-specific expression wrapper, which overrides
+// operator [] to evaluate the expression using the lazy_subscript_context.
+template<typename Expr>
+struct lazy_vector_expr
+ : proto::extends<Expr, lazy_vector_expr<Expr>, lazy_vector_domain>
+{
+ lazy_vector_expr( Expr const & expr = Expr() )
+ : lazy_vector_expr::proto_extends( expr )
+ {}
+
+ // Use the lazy_subscript_context<> to implement subscripting
+ // of a lazy vector expression tree.
+ template< typename Size >
+ typename proto::result_of::eval< Expr, lazy_subscript_context<Size> >::type
+ operator []( Size subscript ) const
+ {
+ lazy_subscript_context<Size> ctx(subscript);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Here is our lazy_vector terminal, implemented in terms of lazy_vector_expr
+template< typename T >
+struct lazy_vector
+ : lazy_vector_expr< typename proto::terminal< std::vector<T> >::type >
+{
+ typedef typename proto::terminal< std::vector<T> >::type expr_type;
+
+ lazy_vector( std::size_t size = 0, T const & value = T() )
+ : lazy_vector_expr<expr_type>( expr_type::make( std::vector<T>( size, value ) ) )
+ {}
+
+ // Here we define a += operator for lazy vector terminals that
+ // takes a lazy vector expression and indexes it. expr[i] here
+ // uses lazy_subscript_context<> under the covers.
+ template< typename Expr >
+ lazy_vector &operator += (Expr const & expr)
+ {
+ std::size_t size = proto::value(*this).size();
+ for(std::size_t i = 0; i < size; ++i)
+ {
+ proto::value(*this)[i] += expr[i];
+ }
+ return *this;
+ }
+};
+
+int main()
+{
+ // lazy_vectors with 4 elements each.
+ lazy_vector< double > v1( 4, 1.0 ), v2( 4, 2.0 ), v3( 4, 3.0 );
+
+ // Add two vectors lazily and get the 2nd element.
+ double d1 = ( v2 + v3 )[ 2 ]; // Look ma, no temporaries!
+ std::cout << d1 << std::endl;
+
+ // Subtract two vectors and add the result to a third vector.
+ v1 += v2 - v3; // Still no temporaries!
+ std::cout << '{' << v1[0] << ',' << v1[1]
+ << ',' << v1[2] << ',' << v1[3] << '}' << std::endl;
+
+ // This expression is disallowed because it does not conform
+ // to the LazyVectorGrammar
+ //(v2 + v3) += v1;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/map_assign.cpp b/src/boost/libs/proto/example/map_assign.cpp
new file mode 100644
index 00000000..93911059
--- /dev/null
+++ b/src/boost/libs/proto/example/map_assign.cpp
@@ -0,0 +1,136 @@
+//[ MapAssign
+// 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)
+//
+// This is a port of map_list_of() from the Boost.Assign library.
+// It has the advantage of being more efficient at runtime by not
+// building any temporary container that requires dynamic allocation.
+
+#include <map>
+#include <string>
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/type_traits/add_reference.hpp>
+namespace proto = boost::proto;
+using proto::_;
+
+struct map_list_of_tag
+{};
+
+// A simple callable function object that inserts a
+// (key,value) pair into a map.
+struct insert
+ : proto::callable
+{
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Map, typename Key, typename Value>
+ struct result<This(Map, Key, Value)>
+ : boost::add_reference<Map>
+ {};
+
+ template<typename Map, typename Key, typename Value>
+ Map &operator()(Map &map, Key const &key, Value const &value) const
+ {
+ map.insert(typename Map::value_type(key, value));
+ return map;
+ }
+};
+
+// Work-arounds for Microsoft Visual C++ 7.1
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define MapListOf(x) proto::call<MapListOf(x)>
+#define _value(x) call<proto::_value(x)>
+#endif
+
+// The grammar for valid map-list expressions, and a
+// transform that populates the map.
+struct MapListOf
+ : proto::or_<
+ proto::when<
+ // map_list_of(a,b)
+ proto::function<
+ proto::terminal<map_list_of_tag>
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ , insert(
+ proto::_data
+ , proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+ , proto::when<
+ // map_list_of(a,b)(c,d)...
+ proto::function<
+ MapListOf
+ , proto::terminal<_>
+ , proto::terminal<_>
+ >
+ , insert(
+ MapListOf(proto::_child0)
+ , proto::_value(proto::_child1)
+ , proto::_value(proto::_child2)
+ )
+ >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef MapListOf
+#undef _value
+#endif
+
+template<typename Expr>
+struct map_list_of_expr;
+
+struct map_list_of_dom
+ : proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf>
+{};
+
+// An expression wrapper that provides a conversion to a
+// map that uses the MapListOf
+template<typename Expr>
+struct map_list_of_expr
+{
+ BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom)
+ BOOST_PROTO_EXTENDS_FUNCTION()
+
+ template<typename Key, typename Value, typename Cmp, typename Al>
+ operator std::map<Key, Value, Cmp, Al> () const
+ {
+ BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>));
+ std::map<Key, Value, Cmp, Al> map;
+ return MapListOf()(*this, 0, map);
+ }
+};
+
+map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}};
+
+int main()
+{
+ // Initialize a map:
+ std::map<std::string, int> op =
+ map_list_of
+ ("<", 1)
+ ("<=",2)
+ (">", 3)
+ (">=",4)
+ ("=", 5)
+ ("<>",6)
+ ;
+
+ std::cout << "\"<\" --> " << op["<"] << std::endl;
+ std::cout << "\"<=\" --> " << op["<="] << std::endl;
+ std::cout << "\">\" --> " << op[">"] << std::endl;
+ std::cout << "\">=\" --> " << op[">="] << std::endl;
+ std::cout << "\"=\" --> " << op["="] << std::endl;
+ std::cout << "\"<>\" --> " << op["<>"] << std::endl;
+
+ return 0;
+}
+//]
+
diff --git a/src/boost/libs/proto/example/mini_lambda.cpp b/src/boost/libs/proto/example/mini_lambda.cpp
new file mode 100644
index 00000000..0f3d52c6
--- /dev/null
+++ b/src/boost/libs/proto/example/mini_lambda.cpp
@@ -0,0 +1,263 @@
+//[ Lambda
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example builds a simple but functional lambda library using Proto.
+
+#include <iostream>
+#include <algorithm>
+#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/ostream.hpp>
+#include <boost/typeof/std/iostream.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+// 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;
+};
+
+// The lambda grammar, with the transforms for calculating the max arity
+struct lambda_arity
+ : proto::or_<
+ proto::when<
+ proto::terminal< placeholder<_> >
+ , mpl::next<placeholder_arity<proto::_value> >()
+ >
+ , proto::when< proto::terminal<_>
+ , mpl::int_<0>()
+ >
+ , proto::when<
+ proto::nary_expr<_, proto::vararg<_> >
+ , proto::fold<_, mpl::int_<0>(), mpl::max<lambda_arity, proto::_state>()>
+ >
+ >
+{};
+
+// 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()
+
+ // Calculate the arity of this lambda expression
+ static int const arity = boost::result_of<lambda_arity(T)>::type::value;
+
+ template<typename Sig>
+ struct result;
+
+ // Define nested result<> specializations to calculate the return
+ // type of this lambda expression. But be careful not to evaluate
+ // the return type of the nullary function unless we have a nullary
+ // lambda!
+ template<typename This>
+ struct result<This()>
+ : mpl::eval_if_c<
+ 0 == arity
+ , proto::result_of::eval<T const, lambda_context<fusion::tuple<> > >
+ , mpl::identity<void>
+ >
+ {};
+
+ template<typename This, typename A0>
+ struct result<This(A0)>
+ : proto::result_of::eval<T const, lambda_context<fusion::tuple<A0> > >
+ {};
+
+ template<typename This, typename A0, typename A1>
+ struct result<This(A0, A1)>
+ : proto::result_of::eval<T const, lambda_context<fusion::tuple<A0, A1> > >
+ {};
+
+ // Define our operator () that evaluates the lambda expression.
+ typename result<lambda()>::type
+ operator ()() const
+ {
+ fusion::tuple<> args;
+ lambda_context<fusion::tuple<> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+
+ template<typename A0>
+ typename result<lambda(A0 const &)>::type
+ operator ()(A0 const &a0) const
+ {
+ fusion::tuple<A0 const &> args(a0);
+ lambda_context<fusion::tuple<A0 const &> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+
+ template<typename A0, typename A1>
+ typename result<lambda(A0 const &, A1 const &)>::type
+ operator ()(A0 const &a0, A1 const &a1) const
+ {
+ fusion::tuple<A0 const &, A1 const &> args(a0, a1);
+ lambda_context<fusion::tuple<A0 const &, A1 const &> > ctx(args);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define some lambda placeholders
+lambda<proto::terminal<placeholder<mpl::int_<0> > >::type> const _1 = {{}};
+lambda<proto::terminal<placeholder<mpl::int_<1> > >::type> const _2 = {{}};
+
+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;
+}
+
+template<typename T>
+struct construct_helper
+{
+ typedef T result_type; // for TR1 result_of
+
+ T operator()() const
+ { return T(); }
+
+ // Generate BOOST_PROTO_MAX_ARITY overloads of the
+ // following function call operator.
+#define BOOST_PROTO_LOCAL_MACRO(N, typename_A, A_const_ref, A_const_ref_a, a)\
+ template<typename_A(N)> \
+ T operator()(A_const_ref_a(N)) const \
+ { return T(a(N)); }
+#define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
+#include BOOST_PROTO_LOCAL_ITERATE()
+};
+
+// Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
+// following construct() function template.
+#define M0(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
+template<typename T, typename_A(N)> \
+typename proto::result_of::make_expr< \
+ proto::tag::function \
+ , lambda_domain \
+ , construct_helper<T> \
+ , A_const_ref(N) \
+>::type const \
+construct(A_const_ref_a(N)) \
+{ \
+ return proto::make_expr< \
+ proto::tag::function \
+ , lambda_domain \
+ >( \
+ construct_helper<T>() \
+ , ref_a(N) \
+ ); \
+}
+BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0)
+#undef M0
+
+struct S
+{
+ S() {}
+ S(int i, char c)
+ {
+ std::cout << "S(" << i << "," << c << ")\n";
+ }
+};
+
+int main()
+{
+ // Create some lambda objects and immediately
+ // invoke them by applying their operator():
+ int i = ( (_1 + 2) / 4 )(42);
+ std::cout << i << std::endl; // prints 11
+
+ int j = ( (-(_1 + 2)) / 4 )(42);
+ std::cout << j << std::endl; // prints -11
+
+ double d = ( (4 - _2) * 3 )(42, 3.14);
+ std::cout << d << std::endl; // prints 2.58
+
+ // check non-const ref terminals
+ (std::cout << _1 << " -- " << _2 << '\n')(42, "Life, the Universe and Everything!");
+ // prints "42 -- Life, the Universe and Everything!"
+
+ // "Nullary" lambdas work too
+ int k = (val(1) + val(2))();
+ std::cout << k << std::endl; // prints 3
+
+ // check array indexing for kicks
+ int integers[5] = {0};
+ (var(integers)[2] = 2)();
+ (var(integers)[_1] = _1)(3);
+ std::cout << integers[2] << std::endl; // prints 2
+ std::cout << integers[3] << std::endl; // prints 3
+
+ // Now use a lambda with an STL algorithm!
+ int rgi[4] = {1,2,3,4};
+ char rgc[4] = {'a','b','c','d'};
+ S rgs[4];
+
+ std::transform(rgi, rgi+4, rgc, rgs, construct<S>(_1, _2));
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/mixed.cpp b/src/boost/libs/proto/example/mixed.cpp
new file mode 100644
index 00000000..d48e21dc
--- /dev/null
+++ b/src/boost/libs/proto/example/mixed.cpp
@@ -0,0 +1,375 @@
+//[ Mixed
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
+// expressions using std::vector<> and std::list, non-proto types. It is a port
+// of the Mixed example from PETE.
+// (http://www.codesourcery.com/pooma/download.html).
+
+#include <list>
+#include <cmath>
+#include <vector>
+#include <complex>
+#include <iostream>
+#include <stdexcept>
+#include <boost/proto/core.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/transform.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/typeof/std/list.hpp>
+#include <boost/typeof/std/vector.hpp>
+#include <boost/typeof/std/complex.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+namespace proto = boost::proto;
+namespace mpl = boost::mpl;
+using proto::_;
+
+template<typename Expr>
+struct MixedExpr;
+
+template<typename Iter>
+struct iterator_wrapper
+{
+ typedef Iter iterator;
+
+ explicit iterator_wrapper(Iter iter)
+ : it(iter)
+ {}
+
+ mutable Iter it;
+};
+
+struct begin : proto::callable
+{
+ template<class Sig>
+ struct result;
+
+ template<class This, class Cont>
+ struct result<This(Cont)>
+ : proto::result_of::as_expr<
+ iterator_wrapper<typename boost::remove_reference<Cont>::type::const_iterator>
+ >
+ {};
+
+ template<typename Cont>
+ typename result<begin(Cont const &)>::type
+ operator ()(Cont const &cont) const
+ {
+ iterator_wrapper<typename Cont::const_iterator> it(cont.begin());
+ return proto::as_expr(it);
+ }
+};
+
+// Here is a grammar that replaces vector and list terminals with their
+// begin iterators
+struct Begin
+ : proto::or_<
+ proto::when< proto::terminal< std::vector<_, _> >, begin(proto::_value) >
+ , proto::when< proto::terminal< std::list<_, _> >, begin(proto::_value) >
+ , proto::when< proto::terminal<_> >
+ , proto::when< proto::nary_expr<_, proto::vararg<Begin> > >
+ >
+{};
+
+// Here is an evaluation context that dereferences iterator
+// terminals.
+struct DereferenceCtx
+{
+ // Unless this is an iterator terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::default_eval<Expr, DereferenceCtx const>
+ {};
+
+ // Dereference iterator terminals.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
+ >::type
+ >
+ {
+ typedef typename proto::result_of::value<Expr>::type IteratorWrapper;
+ typedef typename IteratorWrapper::iterator iterator;
+ typedef typename std::iterator_traits<iterator>::reference result_type;
+
+ result_type operator ()(Expr &expr, DereferenceCtx const &) const
+ {
+ return *proto::value(expr).it;
+ }
+ };
+};
+
+// Here is an evaluation context that increments iterator
+// terminals.
+struct IncrementCtx
+{
+ // Unless this is an iterator terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::null_eval<Expr, IncrementCtx const>
+ {};
+
+ // advance iterator terminals.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<iterator_wrapper<_> > >
+ >::type
+ >
+ {
+ typedef void result_type;
+
+ result_type operator ()(Expr &expr, IncrementCtx const &) const
+ {
+ ++proto::value(expr).it;
+ }
+ };
+};
+
+// A grammar which matches all the assignment operators,
+// so we can easily disable them.
+struct AssignOps
+ : proto::switch_<struct AssignOpsCases>
+{};
+
+// Here are the cases used by the switch_ above.
+struct AssignOpsCases
+{
+ template<typename Tag, int D = 0> struct case_ : proto::not_<_> {};
+
+ template<int D> struct case_< proto::tag::plus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::minus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::multiplies_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::divides_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::modulus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_left_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_right_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_and_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_or_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_xor_assign, D > : _ {};
+};
+
+// An expression conforms to the MixedGrammar if it is a terminal or some
+// op that is not an assignment op. (Assignment will be handled specially.)
+struct MixedGrammar
+ : proto::or_<
+ proto::terminal<_>
+ , proto::and_<
+ proto::nary_expr<_, proto::vararg<MixedGrammar> >
+ , proto::not_<AssignOps>
+ >
+ >
+{};
+
+// Expressions in the MixedDomain will be wrapped in MixedExpr<>
+// and must conform to the MixedGrammar
+struct MixedDomain
+ : proto::domain<proto::generator<MixedExpr>, MixedGrammar>
+{};
+
+// Here is MixedExpr, a wrapper for expression types in the MixedDomain.
+template<typename Expr>
+struct MixedExpr
+ : proto::extends<Expr, MixedExpr<Expr>, MixedDomain>
+{
+ explicit MixedExpr(Expr const &expr)
+ : MixedExpr::proto_extends(expr)
+ {}
+private:
+ // hide this:
+ using proto::extends<Expr, MixedExpr<Expr>, MixedDomain>::operator [];
+};
+
+// Define a trait type for detecting vector and list terminals, to
+// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
+template<typename T>
+struct IsMixed
+ : mpl::false_
+{};
+
+template<typename T, typename A>
+struct IsMixed<std::list<T, A> >
+ : mpl::true_
+{};
+
+template<typename T, typename A>
+struct IsMixed<std::vector<T, A> >
+ : mpl::true_
+{};
+
+namespace MixedOps
+{
+ // This defines all the overloads to make expressions involving
+ // std::vector to build expression templates.
+ BOOST_PROTO_DEFINE_OPERATORS(IsMixed, MixedDomain)
+
+ struct assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t = u;
+ }
+ };
+
+ struct plus_assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t += u;
+ }
+ };
+
+ struct minus_assign_op
+ {
+ template<typename T, typename U>
+ void operator ()(T &t, U const &u) const
+ {
+ t -= u;
+ }
+ };
+
+ struct sin_
+ {
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Arg>
+ struct result<This(Arg)>
+ : boost::remove_const<typename boost::remove_reference<Arg>::type>
+ {};
+
+ template<typename Arg>
+ Arg operator ()(Arg const &a) const
+ {
+ return std::sin(a);
+ }
+ };
+
+ template<typename A>
+ typename proto::result_of::make_expr<
+ proto::tag::function
+ , MixedDomain
+ , sin_ const
+ , A const &
+ >::type sin(A const &a)
+ {
+ return proto::make_expr<proto::tag::function, MixedDomain>(sin_(), boost::ref(a));
+ }
+
+ template<typename FwdIter, typename Expr, typename Op>
+ void evaluate(FwdIter begin, FwdIter end, Expr const &expr, Op op)
+ {
+ IncrementCtx const inc = {};
+ DereferenceCtx const deref = {};
+ typename boost::result_of<Begin(Expr const &)>::type expr2 = Begin()(expr);
+ for(; begin != end; ++begin)
+ {
+ op(*begin, proto::eval(expr2, deref));
+ proto::eval(expr2, inc);
+ }
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
+ return arr;
+ }
+
+ // Add-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &assign(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), assign_op());
+ return arr;
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
+ return arr;
+ }
+
+ // Add-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &operator +=(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), plus_assign_op());
+ return arr;
+ }
+
+ // Minus-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator -=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
+ return arr;
+ }
+
+ // Minus-assign to a list from some expression.
+ template<typename T, typename A, typename Expr>
+ std::list<T, A> &operator -=(std::list<T, A> &arr, Expr const &expr)
+ {
+ evaluate(arr.begin(), arr.end(), proto::as_expr<MixedDomain>(expr), minus_assign_op());
+ return arr;
+ }
+}
+
+int main()
+{
+ using namespace MixedOps;
+
+ int n = 10;
+ std::vector<int> a,b,c,d;
+ std::list<double> e;
+ std::list<std::complex<double> > f;
+
+ int i;
+ for(i = 0;i < n; ++i)
+ {
+ a.push_back(i);
+ b.push_back(2*i);
+ c.push_back(3*i);
+ d.push_back(i);
+ e.push_back(0.0);
+ f.push_back(std::complex<double>(1.0, 1.0));
+ }
+
+ MixedOps::assign(b, 2);
+ MixedOps::assign(d, a + b * c);
+ a += if_else(d < 30, b, c);
+
+ MixedOps::assign(e, c);
+ e += e - 4 / (c + 1);
+
+ f -= sin(0.1 * e * std::complex<double>(0.2, 1.2));
+
+ std::list<double>::const_iterator ei = e.begin();
+ std::list<std::complex<double> >::const_iterator fi = f.begin();
+ for (i = 0; i < n; ++i)
+ {
+ std::cout
+ << "a(" << i << ") = " << a[i]
+ << " b(" << i << ") = " << b[i]
+ << " c(" << i << ") = " << c[i]
+ << " d(" << i << ") = " << d[i]
+ << " e(" << i << ") = " << *ei++
+ << " f(" << i << ") = " << *fi++
+ << std::endl;
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/rgb.cpp b/src/boost/libs/proto/example/rgb.cpp
new file mode 100644
index 00000000..51b0f459
--- /dev/null
+++ b/src/boost/libs/proto/example/rgb.cpp
@@ -0,0 +1,102 @@
+//[ RGB
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is a simple example of doing arbitrary type manipulations with proto
+// transforms. It takes some expression involving primary colors and combines
+// the colors according to arbitrary rules. It is a port of the RGB example
+// from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <iostream>
+#include <boost/proto/core.hpp>
+#include <boost/proto/transform.hpp>
+namespace proto = boost::proto;
+
+struct RedTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, RedTag)
+ {
+ return sout << "This expression is red.";
+ }
+};
+
+struct BlueTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, BlueTag)
+ {
+ return sout << "This expression is blue.";
+ }
+};
+
+struct GreenTag
+{
+ friend std::ostream &operator <<(std::ostream &sout, GreenTag)
+ {
+ return sout << "This expression is green.";
+ }
+};
+
+typedef proto::terminal<RedTag>::type RedT;
+typedef proto::terminal<BlueTag>::type BlueT;
+typedef proto::terminal<GreenTag>::type GreenT;
+
+struct Red;
+struct Blue;
+struct Green;
+
+///////////////////////////////////////////////////////////////////////////////
+// A transform that produces new colors according to some arbitrary rules:
+// red & green give blue, red & blue give green, blue and green give red.
+struct Red
+ : proto::or_<
+ proto::plus<Green, Blue>
+ , proto::plus<Blue, Green>
+ , proto::plus<Red, Red>
+ , proto::terminal<RedTag>
+ >
+{};
+
+struct Green
+ : proto::or_<
+ proto::plus<Red, Blue>
+ , proto::plus<Blue, Red>
+ , proto::plus<Green, Green>
+ , proto::terminal<GreenTag>
+ >
+{};
+
+struct Blue
+ : proto::or_<
+ proto::plus<Red, Green>
+ , proto::plus<Green, Red>
+ , proto::plus<Blue, Blue>
+ , proto::terminal<BlueTag>
+ >
+{};
+
+struct RGB
+ : proto::or_<
+ proto::when< Red, RedTag() >
+ , proto::when< Blue, BlueTag() >
+ , proto::when< Green, GreenTag() >
+ >
+{};
+
+template<typename Expr>
+void printColor(Expr const & expr)
+{
+ int i = 0; // dummy state and data parameter, not used
+ std::cout << RGB()(expr, i, i) << std::endl;
+}
+
+int main()
+{
+ printColor(RedT() + GreenT());
+ printColor(RedT() + GreenT() + BlueT());
+ printColor(RedT() + (GreenT() + BlueT()));
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/tarray.cpp b/src/boost/libs/proto/example/tarray.cpp
new file mode 100644
index 00000000..338f69b1
--- /dev/null
+++ b/src/boost/libs/proto/example/tarray.cpp
@@ -0,0 +1,222 @@
+//[ TArray
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This example constructs a mini-library for linear algebra, using
+// expression templates to eliminate the need for temporaries when
+// adding arrays of numbers. It duplicates the TArray example from
+// PETE (http://www.codesourcery.com/pooma/download.html)
+
+#include <iostream>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// This grammar describes which TArray expressions
+// are allowed; namely, int and array terminals
+// plus, minus, multiplies and divides of TArray expressions.
+struct TArrayGrammar
+ : proto::or_<
+ proto::terminal< int >
+ , proto::terminal< int[3] >
+ , proto::plus< TArrayGrammar, TArrayGrammar >
+ , proto::minus< TArrayGrammar, TArrayGrammar >
+ , proto::multiplies< TArrayGrammar, TArrayGrammar >
+ , proto::divides< TArrayGrammar, TArrayGrammar >
+ >
+{};
+
+template<typename Expr>
+struct TArrayExpr;
+
+// Tell proto that in the TArrayDomain, all
+// expressions should be wrapped in TArrayExpr<> and
+// must conform to the TArrayGrammar
+struct TArrayDomain
+ : proto::domain<proto::generator<TArrayExpr>, TArrayGrammar>
+{};
+
+// Here is an evaluation context that indexes into a TArray
+// expression, and combines the result.
+struct TArraySubscriptCtx
+ : proto::callable_context< TArraySubscriptCtx const >
+{
+ typedef int result_type;
+
+ TArraySubscriptCtx(std::ptrdiff_t i)
+ : i_(i)
+ {}
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ int operator ()(proto::tag::terminal, int const (&data)[3]) const
+ {
+ return data[this->i_];
+ }
+
+ std::ptrdiff_t i_;
+};
+
+// Here is an evaluation context that prints a TArray expression.
+struct TArrayPrintCtx
+ : proto::callable_context< TArrayPrintCtx const >
+{
+ typedef std::ostream &result_type;
+
+ TArrayPrintCtx() {}
+
+ std::ostream &operator ()(proto::tag::terminal, int i) const
+ {
+ return std::cout << i;
+ }
+
+ std::ostream &operator ()(proto::tag::terminal, int const (&arr)[3]) const
+ {
+ return std::cout << '{' << arr[0] << ", " << arr[1] << ", " << arr[2] << '}';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::plus, L const &l, R const &r) const
+ {
+ return std::cout << '(' << l << " + " << r << ')';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::minus, L const &l, R const &r) const
+ {
+ return std::cout << '(' << l << " - " << r << ')';
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::multiplies, L const &l, R const &r) const
+ {
+ return std::cout << l << " * " << r;
+ }
+
+ template<typename L, typename R>
+ std::ostream &operator ()(proto::tag::divides, L const &l, R const &r) const
+ {
+ return std::cout << l << " / " << r;
+ }
+};
+
+// Here is the domain-specific expression wrapper, which overrides
+// operator [] to evaluate the expression using the TArraySubscriptCtx.
+template<typename Expr>
+struct TArrayExpr
+ : proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain>
+{
+ typedef proto::extends<Expr, TArrayExpr<Expr>, TArrayDomain> base_type;
+
+ TArrayExpr( Expr const & expr = Expr() )
+ : base_type( expr )
+ {}
+
+ // Use the TArraySubscriptCtx to implement subscripting
+ // of a TArray expression tree.
+ int operator []( std::ptrdiff_t i ) const
+ {
+ TArraySubscriptCtx const ctx(i);
+ return proto::eval(*this, ctx);
+ }
+
+ // Use the TArrayPrintCtx to display a TArray expression tree.
+ friend std::ostream &operator <<(std::ostream &sout, TArrayExpr<Expr> const &expr)
+ {
+ TArrayPrintCtx const ctx;
+ return proto::eval(expr, ctx);
+ }
+};
+
+// Here is our TArray terminal, implemented in terms of TArrayExpr
+// It is basically just an array of 3 integers.
+struct TArray
+ : TArrayExpr< proto::terminal< int[3] >::type >
+{
+ explicit TArray( int i = 0, int j = 0, int k = 0 )
+ {
+ (*this)[0] = i;
+ (*this)[1] = j;
+ (*this)[2] = k;
+ }
+
+ // Here we override operator [] to give read/write access to
+ // the elements of the array. (We could use the TArrayExpr
+ // operator [] if we made the subscript context smarter about
+ // returning non-const reference when appropriate.)
+ int &operator [](std::ptrdiff_t i)
+ {
+ return proto::value(*this)[i];
+ }
+
+ int const &operator [](std::ptrdiff_t i) const
+ {
+ return proto::value(*this)[i];
+ }
+
+ // Here we define a operator = for TArray terminals that
+ // takes a TArray expression.
+ template< typename Expr >
+ TArray &operator =(Expr const & expr)
+ {
+ // proto::as_expr<TArrayDomain>(expr) is the same as
+ // expr unless expr is an integer, in which case it
+ // is made into a TArrayExpr terminal first.
+ return this->assign(proto::as_expr<TArrayDomain>(expr));
+ }
+
+ template< typename Expr >
+ TArray &printAssign(Expr const & expr)
+ {
+ *this = expr;
+ std::cout << *this << " = " << expr << std::endl;
+ return *this;
+ }
+
+private:
+ template< typename Expr >
+ TArray &assign(Expr const & expr)
+ {
+ // expr[i] here uses TArraySubscriptCtx under the covers.
+ (*this)[0] = expr[0];
+ (*this)[1] = expr[1];
+ (*this)[2] = expr[2];
+ return *this;
+ }
+};
+
+int main()
+{
+ TArray a(3,1,2);
+
+ TArray b;
+
+ std::cout << a << std::endl;
+ std::cout << b << std::endl;
+
+ b[0] = 7; b[1] = 33; b[2] = -99;
+
+ TArray c(a);
+
+ std::cout << c << std::endl;
+
+ a = 0;
+
+ std::cout << a << std::endl;
+ std::cout << b << std::endl;
+ std::cout << c << std::endl;
+
+ a = b + c;
+
+ std::cout << a << std::endl;
+
+ a.printAssign(b+c*(b + 3*c));
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/vec3.cpp b/src/boost/libs/proto/example/vec3.cpp
new file mode 100644
index 00000000..2da94872
--- /dev/null
+++ b/src/boost/libs/proto/example/vec3.cpp
@@ -0,0 +1,184 @@
+//[ Vec3
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is a simple example using proto::extends to extend a terminal type with
+// additional behaviors, and using custom contexts and proto::eval for
+// evaluating expressions. It is a port of the Vec3 example
+// from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <iostream>
+#include <functional>
+#include <boost/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/proto/proto_typeof.hpp>
+#include <boost/proto/transform.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+// Here is an evaluation context that indexes into a Vec3
+// expression, and combines the result.
+struct Vec3SubscriptCtx
+ : proto::callable_context< Vec3SubscriptCtx const >
+{
+ typedef int result_type;
+
+ Vec3SubscriptCtx(int i)
+ : i_(i)
+ {}
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ int operator ()(proto::tag::terminal, int const (&arr)[3]) const
+ {
+ return arr[this->i_];
+ }
+
+ int i_;
+};
+
+// Here is an evaluation context that counts the number
+// of Vec3 terminals in an expression.
+struct CountLeavesCtx
+ : proto::callable_context< CountLeavesCtx, proto::null_context >
+{
+ CountLeavesCtx()
+ : count(0)
+ {}
+
+ typedef void result_type;
+
+ void operator ()(proto::tag::terminal, int const(&)[3])
+ {
+ ++this->count;
+ }
+
+ int count;
+};
+
+struct iplus : std::plus<int>, proto::callable {};
+
+// Here is a transform that does the same thing as the above context.
+// It demonstrates the use of the std::plus<> function object
+// with the fold transform. With minor modifications, this
+// transform could be used to calculate the leaf count at compile
+// time, rather than at runtime.
+struct CountLeaves
+ : proto::or_<
+ // match a Vec3 terminal, return 1
+ proto::when<proto::terminal<int[3]>, mpl::int_<1>() >
+ // match a terminal, return int() (which is 0)
+ , proto::when<proto::terminal<_>, int() >
+ // fold everything else, using std::plus<> to add
+ // the leaf count of each child to the accumulated state.
+ , proto::otherwise< proto::fold<_, int(), iplus(CountLeaves, proto::_state) > >
+ >
+{};
+
+// Here is the Vec3 struct, which is a vector of 3 integers.
+struct Vec3
+ : proto::extends<proto::terminal<int[3]>::type, Vec3>
+{
+ explicit Vec3(int i=0, int j=0, int k=0)
+ {
+ (*this)[0] = i;
+ (*this)[1] = j;
+ (*this)[2] = k;
+ }
+
+ int &operator [](int i)
+ {
+ return proto::value(*this)[i];
+ }
+
+ int const &operator [](int i) const
+ {
+ return proto::value(*this)[i];
+ }
+
+ // Here we define a operator = for Vec3 terminals that
+ // takes a Vec3 expression.
+ template< typename Expr >
+ Vec3 &operator =(Expr const & expr)
+ {
+ typedef Vec3SubscriptCtx const CVec3SubscriptCtx;
+ (*this)[0] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(0));
+ (*this)[1] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(1));
+ (*this)[2] = proto::eval(proto::as_expr(expr), CVec3SubscriptCtx(2));
+ return *this;
+ }
+
+ // This copy-assign is needed because a template is never
+ // considered for copy assignment.
+ Vec3 &operator=(Vec3 const &that)
+ {
+ (*this)[0] = that[0];
+ (*this)[1] = that[1];
+ (*this)[2] = that[2];
+ return *this;
+ }
+
+ void print() const
+ {
+ std::cout << '{' << (*this)[0]
+ << ", " << (*this)[1]
+ << ", " << (*this)[2]
+ << '}' << std::endl;
+ }
+};
+
+// The count_leaves() function uses the CountLeaves transform and
+// to count the number of leaves in an expression.
+template<typename Expr>
+int count_leaves(Expr const &expr)
+{
+ // Count the number of Vec3 terminals using the
+ // CountLeavesCtx evaluation context.
+ CountLeavesCtx ctx;
+ proto::eval(expr, ctx);
+
+ // This is another way to count the leaves using a transform.
+ int i = 0;
+ BOOST_ASSERT( CountLeaves()(expr, i, i) == ctx.count );
+
+ return ctx.count;
+}
+
+int main()
+{
+ Vec3 a, b, c;
+
+ c = 4;
+
+ b[0] = -1;
+ b[1] = -2;
+ b[2] = -3;
+
+ a = b + c;
+
+ a.print();
+
+ Vec3 d;
+ BOOST_PROTO_AUTO(expr1, b + c);
+ d = expr1;
+ d.print();
+
+ int num = count_leaves(expr1);
+ std::cout << num << std::endl;
+
+ BOOST_PROTO_AUTO(expr2, b + 3 * c);
+ num = count_leaves(expr2);
+ std::cout << num << std::endl;
+
+ BOOST_PROTO_AUTO(expr3, b + c * d);
+ num = count_leaves(expr3);
+ std::cout << num << std::endl;
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/example/vector.cpp b/src/boost/libs/proto/example/vector.cpp
new file mode 100644
index 00000000..a2b80fe8
--- /dev/null
+++ b/src/boost/libs/proto/example/vector.cpp
@@ -0,0 +1,241 @@
+//[ Vector
+///////////////////////////////////////////////////////////////////////////////
+// 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)
+//
+// This is an example of using BOOST_PROTO_DEFINE_OPERATORS to Protofy
+// expressions using std::vector<>, a non-proto type. It is a port of the
+// Vector example from PETE (http://www.codesourcery.com/pooma/download.html).
+
+#include <vector>
+#include <iostream>
+#include <stdexcept>
+#include <boost/mpl/bool.hpp>
+#include <boost/proto/core.hpp>
+#include <boost/proto/debug.hpp>
+#include <boost/proto/context.hpp>
+#include <boost/utility/enable_if.hpp>
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+using proto::_;
+
+template<typename Expr>
+struct VectorExpr;
+
+// Here is an evaluation context that indexes into a std::vector
+// expression and combines the result.
+struct VectorSubscriptCtx
+{
+ VectorSubscriptCtx(std::size_t i)
+ : i_(i)
+ {}
+
+ // Unless this is a vector terminal, use the
+ // default evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::default_eval<Expr, VectorSubscriptCtx const>
+ {};
+
+ // Index vector terminals with our subscript.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<std::vector<_, _> > >
+ >::type
+ >
+ {
+ typedef typename proto::result_of::value<Expr>::type::value_type result_type;
+
+ result_type operator ()(Expr &expr, VectorSubscriptCtx const &ctx) const
+ {
+ return proto::value(expr)[ctx.i_];
+ }
+ };
+
+ std::size_t i_;
+};
+
+// Here is an evaluation context that verifies that all the
+// vectors in an expression have the same size.
+struct VectorSizeCtx
+{
+ VectorSizeCtx(std::size_t size)
+ : size_(size)
+ {}
+
+ // Unless this is a vector terminal, use the
+ // null evaluation context
+ template<typename Expr, typename EnableIf = void>
+ struct eval
+ : proto::null_eval<Expr, VectorSizeCtx const>
+ {};
+
+ // Index array terminals with our subscript. Everything
+ // else will be handled by the default evaluation context.
+ template<typename Expr>
+ struct eval<
+ Expr
+ , typename boost::enable_if<
+ proto::matches<Expr, proto::terminal<std::vector<_, _> > >
+ >::type
+ >
+ {
+ typedef void result_type;
+
+ result_type operator ()(Expr &expr, VectorSizeCtx const &ctx) const
+ {
+ if(ctx.size_ != proto::value(expr).size())
+ {
+ throw std::runtime_error("LHS and RHS are not compatible");
+ }
+ }
+ };
+
+ std::size_t size_;
+};
+
+// A grammar which matches all the assignment operators,
+// so we can easily disable them.
+struct AssignOps
+ : proto::switch_<struct AssignOpsCases>
+{};
+
+// Here are the cases used by the switch_ above.
+struct AssignOpsCases
+{
+ template<typename Tag, int D = 0> struct case_ : proto::not_<_> {};
+
+ template<int D> struct case_< proto::tag::plus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::minus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::multiplies_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::divides_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::modulus_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_left_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::shift_right_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_and_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_or_assign, D > : _ {};
+ template<int D> struct case_< proto::tag::bitwise_xor_assign, D > : _ {};
+};
+
+// A vector grammar is a terminal or some op that is not an
+// assignment op. (Assignment will be handled specially.)
+struct VectorGrammar
+ : proto::or_<
+ proto::terminal<_>
+ , proto::and_<proto::nary_expr<_, proto::vararg<VectorGrammar> >, proto::not_<AssignOps> >
+ >
+{};
+
+// Expressions in the vector domain will be wrapped in VectorExpr<>
+// and must conform to the VectorGrammar
+struct VectorDomain
+ : proto::domain<proto::generator<VectorExpr>, VectorGrammar>
+{};
+
+// Here is VectorExpr, which extends a proto expr type by
+// giving it an operator [] which uses the VectorSubscriptCtx
+// to evaluate an expression with a given index.
+template<typename Expr>
+struct VectorExpr
+ : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>
+{
+ explicit VectorExpr(Expr const &expr)
+ : proto::extends<Expr, VectorExpr<Expr>, VectorDomain>(expr)
+ {}
+
+ // Use the VectorSubscriptCtx to implement subscripting
+ // of a Vector expression tree.
+ typename proto::result_of::eval<Expr const, VectorSubscriptCtx const>::type
+ operator []( std::size_t i ) const
+ {
+ VectorSubscriptCtx const ctx(i);
+ return proto::eval(*this, ctx);
+ }
+};
+
+// Define a trait type for detecting vector terminals, to
+// be used by the BOOST_PROTO_DEFINE_OPERATORS macro below.
+template<typename T>
+struct IsVector
+ : mpl::false_
+{};
+
+template<typename T, typename A>
+struct IsVector<std::vector<T, A> >
+ : mpl::true_
+{};
+
+namespace VectorOps
+{
+ // This defines all the overloads to make expressions involving
+ // std::vector to build expression templates.
+ BOOST_PROTO_DEFINE_OPERATORS(IsVector, VectorDomain)
+
+ typedef VectorSubscriptCtx const CVectorSubscriptCtx;
+
+ // Assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &assign(std::vector<T, A> &arr, Expr const &expr)
+ {
+ VectorSizeCtx const size(arr.size());
+ proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match
+ for(std::size_t i = 0; i < arr.size(); ++i)
+ {
+ arr[i] = proto::as_expr<VectorDomain>(expr)[i];
+ }
+ return arr;
+ }
+
+ // Add-assign to a vector from some expression.
+ template<typename T, typename A, typename Expr>
+ std::vector<T, A> &operator +=(std::vector<T, A> &arr, Expr const &expr)
+ {
+ VectorSizeCtx const size(arr.size());
+ proto::eval(proto::as_expr<VectorDomain>(expr), size); // will throw if the sizes don't match
+ for(std::size_t i = 0; i < arr.size(); ++i)
+ {
+ arr[i] += proto::as_expr<VectorDomain>(expr)[i];
+ }
+ return arr;
+ }
+}
+
+int main()
+{
+ using namespace VectorOps;
+
+ int i;
+ const int n = 10;
+ std::vector<int> a,b,c,d;
+ std::vector<double> e(n);
+
+ for (i = 0; i < n; ++i)
+ {
+ a.push_back(i);
+ b.push_back(2*i);
+ c.push_back(3*i);
+ d.push_back(i);
+ }
+
+ VectorOps::assign(b, 2);
+ VectorOps::assign(d, a + b * c);
+ a += if_else(d < 30, b, c);
+
+ VectorOps::assign(e, c);
+ e += e - 4 / (c + 1);
+
+ for (i = 0; i < n; ++i)
+ {
+ std::cout
+ << " a(" << i << ") = " << a[i]
+ << " b(" << i << ") = " << b[i]
+ << " c(" << i << ") = " << c[i]
+ << " d(" << i << ") = " << d[i]
+ << " e(" << i << ") = " << e[i]
+ << std::endl;
+ }
+}
+//]
diff --git a/src/boost/libs/proto/example/virtual_member.cpp b/src/boost/libs/proto/example/virtual_member.cpp
new file mode 100644
index 00000000..46183bae
--- /dev/null
+++ b/src/boost/libs/proto/example/virtual_member.cpp
@@ -0,0 +1,306 @@
+//[ VirtualMember
+// 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)
+//
+// This example demonstrates how to use BOOST_PROTO_EXTENDS_MEMBERS()
+// to add "virtual" data members to expressions within a domain. For
+// instance, with Phoenix you can create a lambda expression such as
+//
+// if_(_1 > 0)[ std::cout << _2 ].else_[ std::cout << _3 ]
+//
+// In the above expression, "else_" is a so-called virtual data member
+// of the expression "if_(_1 > 0)[ std::cout << _2 ]". This example
+// shows how to implement the ".else_" syntax with Proto.
+//
+// ****WARNING****WARNING****WARNING****WARNING****WARNING****WARNING****
+// * The virtual data member feature is experimental and can change at *
+// * any time. Use it at your own risk. *
+// **********************************************************************
+
+#if defined(_MSC_VER) && _MSC_VER == 1310
+#error "Sorry, this example doesn\'t work with MSVC 7.1"
+#endif
+
+#include <iostream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/typeof/std/ostream.hpp>
+#include <boost/proto/proto.hpp>
+
+namespace mpl = boost::mpl;
+namespace proto = boost::proto;
+namespace fusion = boost::fusion;
+using proto::_;
+
+namespace mini_lambda
+{
+ // A callable PolymorphicFunctionObject that wraps
+ // fusion::at()
+ struct at : proto::callable
+ {
+ template<class Sig>
+ struct result;
+
+ template<class This, class Vector, class N>
+ struct result<This(Vector, N)>
+ : fusion::result_of::at<
+ typename boost::remove_reference<Vector>::type
+ , typename boost::remove_reference<N>::type
+ >
+ {};
+
+ template<class Vector, class N>
+ typename fusion::result_of::at<Vector const, N>::type
+ operator()(Vector const &vector, N) const
+ {
+ return fusion::at<N>(vector);
+ }
+ };
+
+ // An MPL IntegralConstant
+ template<class N>
+ struct placeholder
+ {
+ typedef N type;
+ typedef typename N::tag tag;
+ typedef typename N::next next;
+ typedef typename N::prior prior;
+ typedef typename N::value_type value_type;
+ static const value_type value = N::value;
+ };
+
+ // Some keyword types for our lambda EDSL
+ namespace keyword
+ {
+ struct if_ {};
+ struct else_ {};
+ struct do_ {};
+ struct while_ {};
+ struct try_ {};
+ struct catch_ {};
+ }
+
+ // Forward declaration for the mini-lambda grammar
+ struct eval_if_else;
+
+ // Forward declaration for the mini-lambda expression wrapper
+ template<class E>
+ struct expression;
+
+ // The grammar for mini-lambda expressions with transforms for
+ // evaluating the lambda expression.
+ struct grammar
+ : proto::or_<
+ // When evaluating a placeholder, use the placeholder
+ // to index into the "data" parameter, which is a fusion
+ // vector containing the arguments to the lambda expression.
+ proto::when<
+ proto::terminal<placeholder<_> >
+ , at(proto::_data, proto::_value)
+ >
+ // When evaluating if/then/else expressions of the form
+ // "if_( E0 )[ E1 ].else_[ E2 ]", pass E0, E1 and E2 to
+ // eval_if_else along with the "data" parameter. Note the
+ // use of proto::member<> to match binary expressions like
+ // "X.Y" where "Y" is a virtual data member.
+ , proto::when<
+ proto::subscript<
+ proto::member<
+ proto::subscript<
+ proto::function<
+ proto::terminal<keyword::if_>
+ , grammar
+ >
+ , grammar
+ >
+ , proto::terminal<keyword::else_>
+ >
+ , grammar
+ >
+ , eval_if_else(
+ proto::_right(proto::_left(proto::_left(proto::_left)))
+ , proto::_right(proto::_left(proto::_left))
+ , proto::_right
+ , proto::_data
+ )
+ >
+ , proto::otherwise<
+ proto::_default<grammar>
+ >
+ >
+ {};
+
+ // A callable PolymorphicFunctionObject that evaluates
+ // if/then/else expressions.
+ struct eval_if_else : proto::callable
+ {
+ typedef void result_type;
+
+ template<typename If, typename Then, typename Else, typename Args>
+ void operator()(If const &if_, Then const &then_, Else const &else_, Args const &args) const
+ {
+ if(grammar()(if_, 0, args))
+ {
+ grammar()(then_, 0, args);
+ }
+ else
+ {
+ grammar()(else_, 0, args);
+ }
+ }
+ };
+
+ // Define the mini-lambda domain, in which all expressions are
+ // wrapped in mini_lambda::expression.
+ struct domain
+ : proto::domain<proto::pod_generator<expression> >
+ {};
+
+ // A simple transform for computing the arity of
+ // a lambda expression.
+ struct arity_of
+ : proto::or_<
+ proto::when<
+ proto::terminal< placeholder<_> >
+ , mpl::next<proto::_value>()
+ >
+ , proto::when<
+ proto::terminal<_>
+ , mpl::int_<0>()
+ >
+ , proto::otherwise<
+ proto::fold<
+ _
+ , mpl::int_<0>()
+ , mpl::max<arity_of, proto::_state>()
+ >
+ >
+ >
+ {};
+
+ // Here is the mini-lambda expression wrapper. It serves two purposes:
+ // 1) To define operator() overloads that evaluate the lambda expression, and
+ // 2) To define virtual data members like "else_" so that we can write
+ // expressions like "if_(X)[Y].else_[Z]".
+ template<class E>
+ struct expression
+ {
+ BOOST_PROTO_BASIC_EXTENDS(E, expression<E>, domain)
+ BOOST_PROTO_EXTENDS_ASSIGN()
+ BOOST_PROTO_EXTENDS_SUBSCRIPT()
+
+ // Use BOOST_PROTO_EXTENDS_MEMBERS() to define "virtual"
+ // data members that all expressions in the mini-lambda
+ // domain will have. They can be used to create expressions
+ // like "if_(x)[y].else_[z]" and "do_[y].while_(z)".
+ BOOST_PROTO_EXTENDS_MEMBERS(
+ ((keyword::else_, else_))
+ ((keyword::while_, while_))
+ ((keyword::catch_, catch_))
+ )
+
+ // Calculate the arity of this lambda expression
+ static int const arity = boost::result_of<arity_of(E)>::type::value;
+
+ // Define overloads of operator() that evaluate the lambda
+ // expression for up to 3 arguments.
+
+ // Don't try to compute the return type of the lambda if
+ // it isn't nullary.
+ typename mpl::eval_if_c<
+ 0 != arity
+ , mpl::identity<void>
+ , boost::result_of<grammar(
+ E const &
+ , int const &
+ , fusion::vector<> &
+ )>
+ >::type
+ operator()() const
+ {
+ BOOST_MPL_ASSERT_RELATION(arity, ==, 0);
+ fusion::vector<> args;
+ return grammar()(proto_base(), 0, args);
+ }
+
+ #define BOOST_PROTO_LOCAL_MACRO( \
+ N, typename_A, A_const_ref, A_const_ref_a, a \
+ ) \
+ template<typename_A(N)> \
+ typename boost::result_of<grammar( \
+ E const & \
+ , int const & \
+ , fusion::vector<A_const_ref(N)> & \
+ )>::type \
+ operator ()(A_const_ref_a(N)) const \
+ { \
+ BOOST_MPL_ASSERT_RELATION(arity, <=, N); \
+ fusion::vector<A_const_ref(N)> args(a(N)); \
+ return grammar()(proto_base(), 0, args); \
+ }
+ // Repeats BOOST_PROTO_LOCAL_MACRO macro for N=1 to 3
+ // inclusive (because there are only 3 placeholders)
+ #define BOOST_PROTO_LOCAL_a BOOST_PROTO_a
+ #define BOOST_PROTO_LOCAL_LIMITS (1, 3)
+ #include BOOST_PROTO_LOCAL_ITERATE()
+ };
+
+ namespace placeholders
+ {
+ typedef placeholder<mpl::int_<0> > _1_t;
+ typedef placeholder<mpl::int_<1> > _2_t;
+ typedef placeholder<mpl::int_<2> > _3_t;
+
+ // Define some placeholders
+ expression<proto::terminal<_1_t>::type> const _1 = {{{}}};
+ expression<proto::terminal<_2_t>::type> const _2 = {{{}}};
+ expression<proto::terminal<_3_t>::type> const _3 = {{{}}};
+
+ // Define the if_() statement
+ template<typename E>
+ typename proto::result_of::make_expr<proto::tag::function, domain
+ , keyword::if_
+ , E const &
+ >::type const
+ if_(E const &e)
+ {
+ return proto::make_expr<proto::tag::function, domain>(
+ keyword::if_()
+ , boost::ref(e)
+ );
+ }
+ }
+
+ using placeholders::if_;
+}
+
+int main()
+{
+ using namespace mini_lambda::placeholders;
+
+ // OK, we can create if/then/else lambda expressions
+ // and evaluate them.
+ if_(_1 > 0)
+ [
+ std::cout << _2 << '\n'
+ ]
+ .else_
+ [
+ std::cout << _3 << '\n'
+ ]
+ (-42, "positive", "non-positive");
+
+ // Even though all expressions in the mini-lambda
+ // domain have members named else_, while_, and catch_,
+ // they all occupy the same byte in the expression.
+ BOOST_MPL_ASSERT_RELATION(sizeof(_1), ==, 2);
+
+ return 0;
+}
+//]
diff --git a/src/boost/libs/proto/index.html b/src/boost/libs/proto/index.html
new file mode 100644
index 00000000..2629a3c3
--- /dev/null
+++ b/src/boost/libs/proto/index.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=../../doc/html/proto.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="../../doc/html/proto.html">../../doc/html/proto.html</a>
+<p>Copyright&nbsp;Eric Niebler 2006</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying file
+<a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at
+<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>).
+</p>
+</body>
+</html>
+
diff --git a/src/boost/libs/proto/meta/libraries.json b/src/boost/libs/proto/meta/libraries.json
new file mode 100644
index 00000000..11ccc12d
--- /dev/null
+++ b/src/boost/libs/proto/meta/libraries.json
@@ -0,0 +1,14 @@
+{
+ "key": "proto",
+ "name": "Proto",
+ "authors": [
+ "Eric Niebler"
+ ],
+ "description": "Expression template library and compiler construction toolkit for domain-specific embedded languages.",
+ "category": [
+ "Metaprogramming"
+ ],
+ "maintainers": [
+ "Eric Niebler <eric -at- boostpro.com>"
+ ]
+}
diff --git a/src/boost/libs/proto/preprocess/Jamfile.v2 b/src/boost/libs/proto/preprocess/Jamfile.v2
new file mode 100644
index 00000000..04b7cce0
--- /dev/null
+++ b/src/boost/libs/proto/preprocess/Jamfile.v2
@@ -0,0 +1,18 @@
+# (C) 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)
+
+# Generates preprocessed files with wave.
+
+project : requirements <link>static <variant>release ;
+
+actions wave
+{
+ $(>[2]) -o- -DBOOST_PROTO_MAX_ARITY=10 --config-file wave.cfg $(>[1])
+}
+
+W = /boost/libs/wave/tool//wave ;
+
+make preprocess_proto
+ : preprocess_proto.cpp $(W) : wave : <dependency>wave.cfg
+ ;
diff --git a/src/boost/libs/proto/preprocess/preprocess_proto.cpp b/src/boost/libs/proto/preprocess/preprocess_proto.cpp
new file mode 100644
index 00000000..b1023f0d
--- /dev/null
+++ b/src/boost/libs/proto/preprocess/preprocess_proto.cpp
@@ -0,0 +1,10 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 "../include/boost/proto/core.hpp"
+#include "../include/boost/proto/debug.hpp"
+#include "../include/boost/proto/context.hpp"
+#include "../include/boost/proto/transform.hpp"
+#include "../include/boost/proto/functional.hpp"
diff --git a/src/boost/libs/proto/preprocess/wave.cfg b/src/boost/libs/proto/preprocess/wave.cfg
new file mode 100644
index 00000000..b0059003
--- /dev/null
+++ b/src/boost/libs/proto/preprocess/wave.cfg
@@ -0,0 +1,27 @@
+# (C) 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)
+
+# NOTE: Some of the paths in this file may need to be changed for your system.
+
+-DBOOST_PROTO_DONT_USE_PREPROCESSED_FILES
+-DBOOST_PROTO_CREATE_PREPROCESSED_FILES
+-D_WIN32
+-NBOOST_STATIC_ASSERT
+-NBOOST_PROTO_TEMPLATE_ARITY_PARAM
+-NBOOST_PROTO_RESULT_OF
+-NBOOST_PROTO_DISABLE_IF_IS_CONST
+-NBOOST_PROTO_DISABLE_IF_IS_FUNCTION
+-NBOOST_PROTO_USE_GET_POINTER
+-NBOOST_PROTO_GET_POINTER
+-NBOOST_PROTO_ASSERT_VALID_DOMAIN
+-NBOOST_PROTO_RETURN_TYPE_STRICT_LOOSE
+-NBOOST_FORCEINLINE
+-NBOOST_MPL_ASSERT
+-NBOOST_MPL_ASSERT_MSG
+-NBOOST_MPL_ASSERT_RELATION
+-S../include
+-S../../..
+-S"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include"
+-S.
+--variadics
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;
+}