Boost logo

Boost-Commit :

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<_>


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