Re: [proto] : Proto transform with state

2011-01-29 Thread Eric Niebler
On 11/18/2010 4:56 AM, Eric Niebler wrote:
 I think Proto transforms need a let statement for storing intermediate
 results. Maybe something like this:
 
   struct RenumberFun
 : proto::fold
   _
 , make_pair(fusion::vector0(), proto::_state)
 , let
   _a( Renumber(_, second(proto::_state)) )
 , make_pair(
   push_back(
   first(proto::_state)
 , first(_a)
   )
 , second(_a)
   )
   
   
   {};
 
 I haven't a clue how this would be implemented.
 
 It's fun to think about this stuff, but I wish it actually payed the bills.

Bills be damned. I just committed to trunk an implementation of
proto::let, along with tests and reference docs. End-user docs are still
todo.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2011-01-29 Thread Eric Niebler
On 1/29/2011 7:49 PM, Eric Niebler wrote:
 Bills be damned. I just committed to trunk an implementation of
 proto::let, along with tests and reference docs. End-user docs are still
 todo.

sigh As often happens, I woke up this morning knowing this code was
broken, so I pulled it. I think I finally know how to fix it, though.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com



signature.asc
Description: OpenPGP digital signature
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-12-07 Thread Eric Niebler
On 12/6/2010 4:50 PM, Thomas Heller wrote:
 Eric Niebler wrote:
 I played with the let transform idea over the weekend. It *may* be
 possible to accomplish without the two problems I described above. See
 the attached let transform (needs latest Proto trunk). I'm also
 attaching the Renumber example, reworked to use let.
snip
 
 Without having looked at it too much ... this looks a lot like the 
 environment in phoenix. Maybe this helps in cleaning it out a bit.

I tend to doubt it would help clean up the implementation of Phoenix
environments. These features exist on different meta-levels: one
(proto::let) is a feature for compiler-construction (Proto), the other
(phoenix::let) is a language feature (Phoenix). The have roughly the
same purpose within their purview, but as their purviews are separated
by one great, big Meta, it's not clear that they have anything to do
with each other.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-12-07 Thread Thomas Heller
Eric Niebler wrote:

 On 12/6/2010 4:50 PM, Thomas Heller wrote:
 Eric Niebler wrote:
 I played with the let transform idea over the weekend. It *may* be
 possible to accomplish without the two problems I described above. See
 the attached let transform (needs latest Proto trunk). I'm also
 attaching the Renumber example, reworked to use let.
 snip
 
 Without having looked at it too much ... this looks a lot like the
 environment in phoenix. Maybe this helps in cleaning it out a bit.
 
 I tend to doubt it would help clean up the implementation of Phoenix
 environments. These features exist on different meta-levels: one
 (proto::let) is a feature for compiler-construction (Proto), the other
 (phoenix::let) is a language feature (Phoenix). The have roughly the
 same purpose within their purview, but as their purviews are separated
 by one great, big Meta, it's not clear that they have anything to do
 with each other.

*Dough* misunderstanding here. I didn't mean to clean up the phoenix scope 
expressions with the help of proto::let. I was thinking, maybe proto::let 
can borrow something from phoenix scopes on a conceptual level. 
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-12-07 Thread Thomas Heller
Eric Niebler wrote:

 On 12/7/2010 3:13 PM, Thomas Heller wrote:
 Eric Niebler wrote:
 Now they do: T()(e,s,d). Inside T::impl, D had better be the type of d.
 Nowhere does the _data transform appear in this code, so changing _data
 to be smart about environments and scopes won't save you if you've
 monkeyed with the data parameter.
 
 Very true. Something like proto::transform_env_impl could help. Introduce
 a new type of primitive transform which is aware of this environment. The
 usual transform_impl can still be used.
 By calling T()(e,s,d) you just create a 2-tuple. The first parameter is
 the state, second data.
 Just thinking out loud here ...
 
 So transform_impl strips the data parameter of the let scope stuff, and
 the local variables like _a don't use transform_impl and see the scope
 with the locals?
 
 Well, it's not that simple Consider:
 
   make int(_a) 
 
 If make::impl uses transform_impl, it strips the let scope before _a
 gets to see the local variables. If this is to work, most of Proto's
 transforms must be special and pass the let scope through. That means
 proto::call, proto::make, proto::lazy and proto::when, at least. But ...
 it just might work. Good thinking!
 
 time passes...
 
 No, wait a minute. Look again:
 
 struct T : transformT {
 
   templateclass E, class S, class D
   struct impl : transform_implE, S, D {
 
 // do something with D
 
   };
 
 };
 
 T::impl gets passed D *before* transform_impl has a change to fix it up.
 Any existing transform that actually uses D and assumes it's what they
 passed in is going to be totally hosed. In order to make existing
 transforms let-friendly, they would all need to be changed. That's no
 good.
 
 Bummer, I was excited for a minute there. :-/

Yes ... this would basically mean a complete rewrite ... no good.
-- Proto V5, you might save the thought for the C++0x rewrite :)
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-12-06 Thread Eric Niebler
On 11/18/2010 3:31 PM, Eric Niebler wrote:
 On 11/18/2010 1:45 PM, Thomas Heller wrote:
 Eric Niebler e...@... writes:
 It's REALLY hard. The let context needs to be bundled with the Expr,
 State, or Data parameters somehow, but in a way that's transparent. I
 don't actually know if it's possible.

 Very hard ... yeah. I am thinking that we can maybe save these variables in 
 the 
 transform?
 
 I'm thinking we just stuff it into the Data parameter. We have a
 let_scope template that is effectively a pair containing:
 
 1. The user's original Data, and
 2. A Fusion map from local variables (_a) to values.
 
 The let transform evaluates the bindings and stores the result in the
 let_scope's Fusion map alongside the user's Data. We pass the let_scope
 as the new Data parameter. _a is itself a transform that looks up the
 value in Data's Fusion map. The proto::_data transform is changed to be
 aware of let_scope and return only the original user's Data. This can
 work. We also need to be sure not to break the new
 proto::external_transform.
 
 The problems with this approach as I see it:
 
 1. It's not completely transparent. Custom primitive transforms will see
 that the Data parameter has been monkeyed with.
 
 2. Local variables like _a are not lexically scoped. They are, in fact,
 dynamically scoped. That is, you can access _a outside of a let
 clause, as long as you've been called from within a let clause.
 
 Might be worth it. But as there's no pressing need, I'm content to let
 this simmer. Maybe we can think of something better.

I played with the let transform idea over the weekend. It *may* be
possible to accomplish without the two problems I described above. See
the attached let transform (needs latest Proto trunk). I'm also
attaching the Renumber example, reworked to use let.

This code is NOT ready for prime time. I'm not convinced it behaves
sensibly in all cases. I'm only posting it as a curiosity. You're insane
if you use this in production code. Etc, etc.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
#ifndef BOOST_PP_IS_ITERATING

///
/// \file let.hpp
/// Contains definition of the let transform.
//
//  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)

#ifndef BOOST_PROTO_TRANSFORM_LET_HPP_EAN_12_04_2010
#define BOOST_PROTO_TRANSFORM_LET_HPP_EAN_12_04_2010

#include boost/preprocessor/cat.hpp
#include boost/preprocessor/facilities/intercept.hpp
#include boost/preprocessor/repetition/repeat.hpp
#include boost/preprocessor/repetition/enum.hpp
#include boost/preprocessor/repetition/enum_trailing.hpp
#include boost/preprocessor/repetition/enum_params.hpp
#include boost/preprocessor/repetition/enum_binary_params.hpp
#include boost/preprocessor/repetition/enum_trailing_params.hpp
#include boost/preprocessor/repetition/enum_params_with_a_default.hpp
#include boost/preprocessor/repetition/enum_trailing_binary_params.hpp
#include boost/preprocessor/facilities/intercept.hpp
#include boost/preprocessor/iteration/iterate.hpp
#include boost/mpl/if.hpp
#include boost/mpl/eval_if.hpp
//#include boost/mpl/print.hpp
#include boost/mpl/identity.hpp
#include boost/mpl/aux_/template_arity.hpp
#include boost/mpl/aux_/lambda_arity_param.hpp
#include boost/fusion/include/map.hpp
#include boost/fusion/include/at_key.hpp
#include boost/proto/proto_fwd.hpp
#include boost/proto/traits.hpp
#include boost/proto/transform/impl.hpp

namespace boost { namespace proto
{
// Fwd declarations to be moved to proto_fwd.hpp
template
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename 
Local, void)
  , typename Transform = void

struct let;

templatetypename Tag
struct local;

namespace detail
{
// A structure that holds both a map of local variables as
// well as the original Data parameter passed to the let transform
templatetypename LocalMap, typename Data
struct let_scope
{
typedef LocalMap local_map_type;
typedef Data data_type;

let_scope(LocalMap l, Data d)
  : locals(l)
  , data(d)
{}

LocalMap locals;
Data data;

private:
let_scope operator=(let_scope const );
};

templatetypename Expr, typename State, typename Data
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PROTO_MAX_ARITY, 
typename Local, = void BOOST_PP_INTERCEPT)
  , typename Transform = void

struct init_local_map;

  

Re: [proto] : Proto transform with state

2010-12-06 Thread Thomas Heller
Eric Niebler wrote:

 On 11/18/2010 3:31 PM, Eric Niebler wrote:
 On 11/18/2010 1:45 PM, Thomas Heller wrote:
 Eric Niebler e...@... writes:
 It's REALLY hard. The let context needs to be bundled with the Expr,
 State, or Data parameters somehow, but in a way that's transparent. I
 don't actually know if it's possible.

 Very hard ... yeah. I am thinking that we can maybe save these variables
 in the transform?
 
 I'm thinking we just stuff it into the Data parameter. We have a
 let_scope template that is effectively a pair containing:
 
 1. The user's original Data, and
 2. A Fusion map from local variables (_a) to values.
 
 The let transform evaluates the bindings and stores the result in the
 let_scope's Fusion map alongside the user's Data. We pass the let_scope
 as the new Data parameter. _a is itself a transform that looks up the
 value in Data's Fusion map. The proto::_data transform is changed to be
 aware of let_scope and return only the original user's Data. This can
 work. We also need to be sure not to break the new
 proto::external_transform.
 
 The problems with this approach as I see it:
 
 1. It's not completely transparent. Custom primitive transforms will see
 that the Data parameter has been monkeyed with.
 
 2. Local variables like _a are not lexically scoped. They are, in fact,
 dynamically scoped. That is, you can access _a outside of a let
 clause, as long as you've been called from within a let clause.
 
 Might be worth it. But as there's no pressing need, I'm content to let
 this simmer. Maybe we can think of something better.
 
 I played with the let transform idea over the weekend. It *may* be
 possible to accomplish without the two problems I described above. See
 the attached let transform (needs latest Proto trunk). I'm also
 attaching the Renumber example, reworked to use let.
 
 This code is NOT ready for prime time. I'm not convinced it behaves
 sensibly in all cases. I'm only posting it as a curiosity. You're insane
 if you use this in production code. Etc, etc.

Without having looked at it too much ... this looks a lot like the 
environment in phoenix. Maybe this helps in cleaning it out a bit.
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-11-18 Thread Thomas Heller
Eric Niebler e...@... writes:
 
 On 11/17/2010 2:18 PM, joel falcou wrote:
  On 17/11/10 19:46, Eric Niebler wrote:
  See the attached code. I wish I had a better answer. It sure would be
  nice to generalize this for other times when new state needs to bubble
  up and back down.
  
  Just chiming in. We had the exact same problem in quaff where needed to
  carry on a process ID over the trasnform of parallel statement. If it can
  make you worry less Eric, we ended with the exact same workaround.
 
 There's another issue. Look here:
 
   // don't evaluate T at runtime, but default-construct
   // an object of T's result type.
   templatetypename T
   struct type_of
 : proto::makeproto::callT 
   {};
 
   struct RenumberFun
 : proto::fold
   _
 , make_pair(fusion::vector0(), proto::_state)
 , make_pair(
   push_back(
   first(proto::_state)
 //--1
 , first(Renumber(_, second(proto::_state)))
   )
 //---2
 , type_ofsecond(Renumber(_, second(proto::_state))) 
   )
   
   {};
 
 Notice that the Renumber algorithm needs to be invoked twice with the
 same arguments. In this case, we can avoid the runtime overhead of the
 second invocation by just using the type information, but that's not
 always going to be the case. There doesn't seem to be a way around it,
 either.
 
 I think Proto transforms need a let statement for storing intermediate
 results. Maybe something like this:
 
   struct RenumberFun
 : proto::fold
   _
 , make_pair(fusion::vector0(), proto::_state)
 , let
   _a( Renumber(_, second(proto::_state)) )
 , make_pair(
   push_back(
   first(proto::_state)
 , first(_a)
   )
 , type_ofsecond(_a) 
   )
   
   
   {};
 
 I haven't a clue how this would be implemented.
 
 It's fun to think about this stuff, but I wish it actually payed the bills.

Ok ... I implemented let!

Here goes the renumbering example:
http://codepad.org/K0TZamPb

The change is in line 296 rendering RenumberFun to:
struct RenumberFun
  : proto::fold
_
  , make_pair(fusion::vector(), proto::_state)
  , let
_a(Renumber(_, second(proto::_state)))
  , make_pair(
push_back(
first(proto::_state)
  , first(_a)
)
  , type_ofsecond(_a) 
)


{};

The implementation of let actually was quite easy ... here is how it works:

letLocals, Transform is a transform taking definitions of local variables and 
the transform these locals will get applied to.
A local definition is in the form of: LocalName(LocalTransform)
If the specified transform has LocalName embedded, it will get replaced by 
LocalTransform.
I also implemented the definition of more than one local ... this is done by 
reusing proto::and_:

letproto::and_LocalName0(LocalTransform0), ... LocalNameN(LocalTransformN), 
Transform
The replacement is done from the end to the beginning, making it possible to 
refer in a LocalTransformN to a LocalNameN-1, this gets replaced automatically!

Hope that helps!

Thomas



___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-11-17 Thread joel falcou

On 17/11/10 19:46, Eric Niebler wrote:

See the attached code. I wish I had a better answer. It sure would be
nice to generalize this for other times when new state needs to bubble
up and back down.


Just chiming in. We had the exact same problem in quaff where needed to
carry on a process ID over the trasnform of parallel statement. If it can
make you worry less Eric, we ended with the exact same workaround.

___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] : Proto transform with state

2010-11-17 Thread Eric Niebler
On 11/17/2010 2:18 PM, joel falcou wrote:
 On 17/11/10 19:46, Eric Niebler wrote:
 See the attached code. I wish I had a better answer. It sure would be
 nice to generalize this for other times when new state needs to bubble
 up and back down.
 
 Just chiming in. We had the exact same problem in quaff where needed to
 carry on a process ID over the trasnform of parallel statement. If it can
 make you worry less Eric, we ended with the exact same workaround.

There's another issue. Look here:

  // don't evaluate T at runtime, but default-construct
  // an object of T's result type.
  templatetypename T
  struct type_of
: proto::makeproto::callT 
  {};

  struct RenumberFun
: proto::fold
  _
, make_pair(fusion::vector0(), proto::_state)
, make_pair(
  push_back(
  first(proto::_state)
//--1
, first(Renumber(_, second(proto::_state)))
  )
//---2
, type_ofsecond(Renumber(_, second(proto::_state))) 
  )
  
  {};

Notice that the Renumber algorithm needs to be invoked twice with the
same arguments. In this case, we can avoid the runtime overhead of the
second invocation by just using the type information, but that's not
always going to be the case. There doesn't seem to be a way around it,
either.

I think Proto transforms need a let statement for storing intermediate
results. Maybe something like this:

  struct RenumberFun
: proto::fold
  _
, make_pair(fusion::vector0(), proto::_state)
, let
  _a( Renumber(_, second(proto::_state)) )
, make_pair(
  push_back(
  first(proto::_state)
, first(_a)
  )
, type_ofsecond(_a) 
  )
  
  
  {};

I haven't a clue how this would be implemented.

It's fun to think about this stuff, but I wish it actually payed the bills.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto