$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: eric_at_[hidden]
Date: 2008-03-13 13:46:10
Author: eric_niebler
Date: 2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
New Revision: 43593
URL: http://svn.boost.org/trac/boost/changeset/43593
Log:
add lambda example, fix doc errors and typos
Added:
   trunk/libs/xpressive/proto/example/lambda.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/xpressive/proto/doc/Jamfile.v2         |    21 +++++++++++----------                   
   trunk/libs/xpressive/proto/doc/construction.qbk   |    10 +++++++---                              
   trunk/libs/xpressive/proto/doc/examples.qbk       |    13 +++++++++++++                           
   trunk/libs/xpressive/proto/example/Jamfile.v2     |     5 +++++                                   
   trunk/libs/xpressive/proto/example/map_assign.cpp |     2 +-                                      
   trunk/libs/xpressive/proto/example/vector.cpp     |     2 +-                                      
   6 files changed, 38 insertions(+), 15 deletions(-)
Modified: trunk/libs/xpressive/proto/doc/Jamfile.v2
==============================================================================
--- trunk/libs/xpressive/proto/doc/Jamfile.v2	(original)
+++ trunk/libs/xpressive/proto/doc/Jamfile.v2	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -81,28 +81,29 @@
         # How far down we go with TOC's
         <xsl:param>generate.section.toc.level=10
         # Set the path to the boost-root so we find our graphics:
-        #<xsl:param>boost.root=../../../..
+        #<xsl:param>boost.root=$(BOOST_ROOT)
         # location of the main index file so our links work:
-        #<xsl:param>boost.libraries=../../../../libs/libraries.htm
+        #<xsl:param>boost.libraries=$(BOOST_ROOT)/libs/libraries.htm
 
         # PDF Options:
         # TOC Generation: this is needed for FOP-0.9 and later:
         # <xsl:param>fop1.extensions=1
-        <xsl:param>xep.extensions=1
+        <format>pdf:<xsl:param>fop1.extensions=0
+        <format>pdf:<xsl:param>xep.extensions=1
         # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
-        <xsl:param>fop.extensions=0
+        <format>pdf:<xsl:param>fop.extensions=0
         # No indent on body text:
-        <xsl:param>body.start.indent=0pt
+        <format>pdf:<xsl:param>body.start.indent=0pt
         # Margin size:
-        <xsl:param>page.margin.inner=0.5in
+        <format>pdf:<xsl:param>page.margin.inner=0.5in
         # Margin size:
-        <xsl:param>page.margin.outer=0.5in
+        <format>pdf:<xsl:param>page.margin.outer=0.5in
         # Yes, we want graphics for admonishments:
-        <xsl:param>admon.graphics=1
+        <format>pdf:<xsl:param>admon.graphics=1
         # Set this one for PDF generation *only*:
-        # default pnd graphics are awful in PDF form,
+        # default png graphics are awful in PDF form,
         # better use SVG's instead:
-        # <xsl:param>admon.graphics.extension=".svg"
+        # <format>pdf:<xsl:param>admon.graphics.extension=".svg"
 
         <dependency>protodoc
     ;
Modified: trunk/libs/xpressive/proto/doc/construction.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/construction.qbk	(original)
+++ trunk/libs/xpressive/proto/doc/construction.qbk	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -959,13 +959,13 @@
     // Define the construct() function template that
     // constructs an object lazily.
     template<typename T, typename A0, typename A1>
-    typename proto::make_expr<
+    typename proto::result_of::make_expr<
         proto::tag::function
       , construct_<T> const
       , A0 const &
       , A1 const &
     >::type const
-    construct(A0 const &a0, A0 const &a1)
+    construct(A0 const &a0, A1 const &a1)
     {
         return proto::make_expr<proto::tag::function>(
             construct_<T>()
@@ -977,7 +977,7 @@
 Now users can say `construct<S>(_1, _2)` and get the lazy object
 construction they want. (Making it work with `std::transform()`
 takes a little more effort, but that's covered in the 
-[link boost_proto.users_guide.examples.calc2 Calc2] example.)
+[link boost_proto.users_guide.examples.lambda Lambda] example.)
 Now we need /N/ overloads to handle up to /N/ arguments. That's a lot
 of boiler plate, so we can use the `BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()`
 macro to simplify our job.
@@ -997,6 +997,10 @@
 The fourth argument to the macro is actually a PP sequence of PP 
 sequences. Each sequence describes one implicit argument.
 
+To see `BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE()` and `construct()` in
+action, please check out the
+[link boost_proto.users_guide.examples.lambda Lambda] example.
+
 [blurb [*Ugly Macros]
 
 You may find this use of the preprocessor distasteful and decide to
Modified: trunk/libs/xpressive/proto/doc/examples.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/examples.qbk	(original)
+++ trunk/libs/xpressive/proto/doc/examples.qbk	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -17,6 +17,7 @@
 [import ../example/vector.cpp]
 [import ../example/map_assign.cpp]
 [import ../example/futures.cpp]
+[import ../example/lambda.cpp]
 
 [/===============]
 [section Examples]
@@ -176,4 +177,16 @@
 
 [endsect]
 
+[/========================================================]
+[section:lambda Lambda: A Simple Lambda Library with Proto]
+[/========================================================]
+
+This is an advanced example that shows how to implement a simple
+lambda DSEL with Proto, like the Boost.Lambda_library. It uses
+contexts, transforms and expression extension.
+
+[Lambda]
+
+[endsect]
+
 [endsect]
Modified: trunk/libs/xpressive/proto/example/Jamfile.v2
==============================================================================
--- trunk/libs/xpressive/proto/example/Jamfile.v2	(original)
+++ trunk/libs/xpressive/proto/example/Jamfile.v2	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -63,3 +63,8 @@
         map_assign.cpp
     ;
 
+exe lambda
+    :
+        lambda.cpp
+    ;
+
Added: trunk/libs/xpressive/proto/example/lambda.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/xpressive/proto/example/lambda.cpp	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -0,0 +1,228 @@
+//[ 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/xpressive/proto/proto.hpp>
+#include <boost/xpressive/proto/context.hpp>
+#include <boost/xpressive/proto/transform.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;
+    using namespace transform;
+
+    // The lambda grammar, with the transforms for calculating the max arity
+    struct Lambda
+      : or_<
+            when< terminal< placeholder<_> >,  mpl::next<placeholder_arity<_arg> >() >
+          , 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_EXTENDS(T, lambda<T>, lambda_domain)
+    BOOST_PROTO_EXTENDS_ASSIGN(T, lambda<T>, lambda_domain)
+    BOOST_PROTO_EXTENDS_SUBSCRIPT(T, lambda<T>, lambda_domain)
+
+    // 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);
+    }
+
+    template<typename A0>
+    typename proto::result_of::eval<T const, lambda_context<fusion::tuple<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 proto::result_of::eval<T const, lambda_context<fusion::tuple<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(); }
+    
+    template<typename A0>
+    T operator()(A0 const &a0) const
+    { return T(a0); }
+    
+    template<typename A0, typename A1>
+    T operator()(A0 const &a0, A1 const &a1) const
+    { return T(a0, a1); }
+};
+
+// Generate BOOST_PROTO_MAX_ARITY-1 overloads of the
+// construct function template like the one defined above.
+BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE(            \
+    construct                                           \
+  , lambda_domain                                       \
+  , (proto::tag::function)                              \
+  , ((construct_helper)(typename))                      \
+)
+
+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)(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;
+}
+//]
Modified: trunk/libs/xpressive/proto/example/map_assign.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/map_assign.cpp	(original)
+++ trunk/libs/xpressive/proto/example/map_assign.cpp	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -3,7 +3,7 @@
 //  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_assign from the Boost.Assign library.
+// 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.
 
Modified: trunk/libs/xpressive/proto/example/vector.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/vector.cpp	(original)
+++ trunk/libs/xpressive/proto/example/vector.cpp	2008-03-13 13:46:09 EDT (Thu, 13 Mar 2008)
@@ -109,7 +109,7 @@
 };
 
 // A vector grammar is a terminal or some op that is not an
-// assignment op. (Assignment will be handles specially.)
+// assignment op. (Assignment will be handled specially.)
 struct VectorGrammar
   : proto::or_<
         proto::terminal<_>