[Proto] Forwarding evaluation via tag

I have the following grammar that handles the evaluation of various matrix classes: struct eval_xpr : bp::or_< bp::when< bp::terminal< blockbp::_,bp::_ > , _load(bp::_) > , bp::when< bp::plus< eval_xpr,eval_xpr > , bp::call< functorbp::tag::plus(eval_xpr(bp::_left ), eval_xpr(bp::_right) ) > > > {}; As you can see, the functor<T> class is a Callable object but not a primitive Transform so I use call to be able to forward the proper things to it. Currently I only play with + but I wanted to know how i can use proto::tag_of and a clever way to conserve the recursive look so it works for any operator of any tag. Basically what should I do to have : bp::when< bp::nary_expr< bp::_, bp::vararg< eval_xpr > > , bp::call< functor< ???? >( eval_xpr(????), ???, ??? ) > > to work for any tag and any number of parameters while typiong the less code possible. I *think* I should make a new Primitive Transform that extarct tags and arguments from bp::_expr and then perform the call to functor but doesn't this mean I have to explicitly write the code for 1,2,3 etc arguments ?

Joel Falcou wrote:
I have the following grammar that handles the evaluation of various matrix classes:
struct eval_xpr : bp::or_< bp::when< bp::terminal< blockbp::_,bp::_ > , _load(bp::_) > , bp::when< bp::plus< eval_xpr,eval_xpr > , bp::call< functorbp::tag::plus(eval_xpr(bp::_left ), eval_xpr(bp::_right) ) > > > {};
As you can see, the functor<T> class is a Callable object but not a primitive Transform so I use call to be able to forward the proper things to it. Currently I only play with + but I wanted to know how i can use proto::tag_of and a clever way to conserve the recursive look so it works for any operator of any tag. Basically what should I do to have :
bp::when< bp::nary_expr< bp::_, bp::vararg< eval_xpr > > , bp::call< functor< ???? >( eval_xpr(????), ???, ??? ) > >
to work for any tag and any number of parameters while typiong the less code possible. I *think* I should make a new Primitive Transform that extarct tags and arguments from bp::_expr and then perform the call to functor but doesn't this mean I have to explicitly write the code for 1,2,3 etc arguments ?
I don't have a good solution at my fingertips or the time to come up with something really whiz-bang, but you can get part of the way with the proto::lazy transform. For instance, you can handle all binary expressions with: bp::when< bp::nary_expr< bp::_, eval_xpr, eval_xpr > , bp::lazy< functor< bp::tag_of< bp::_ > >( eval_xpr(bp::_left) , eval_xpr(bp::_right) )> > This uses proto::make to turn functor< bp::tag_of< bp::_ > > into, e.g., function< proto::tag::plus > and then uses proto::call to invoke it. Hope that moves you in the right direction, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
I don't have a good solution at my fingertips or the time to come up with something really whiz-bang, but you can get part of the way with the proto::lazy transform. For instance, you can handle all binary expressions with:
bp::when< bp::nary_expr< bp::_, eval_xpr, eval_xpr > , bp::lazy< functor< bp::tag_of< bp::_ > >( eval_xpr(bp::_left) , eval_xpr(bp::_right) )> >
This uses proto::make to turn functor< bp::tag_of< bp::_ > > into, e.g., function< proto::tag::plus > and then uses proto::call to invoke it.
Hope that moves you in the right direction, Aaaah bp::lazy ! I was indeed trying to find such thing like that.Maybe I can combine this with some fusion::fused or unfused somehow. I'll give this a try.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel wrote:
Eric Niebler wrote:
I don't have a good solution at my fingertips or the time to come up with something really whiz-bang, but you can get part of the way with the proto::lazy transform. For instance, you can handle all binary expressions with:
bp::when< bp::nary_expr< bp::_, eval_xpr, eval_xpr > , bp::lazy< functor< bp::tag_of< bp::_ > >( eval_xpr(bp::_left) , eval_xpr(bp::_right) )> >
This uses proto::make to turn functor< bp::tag_of< bp::_ > > into, e.g., function< proto::tag::plus > and then uses proto::call to invoke it.
Hope that moves you in the right direction,
Aaaah bp::lazy ! I was indeed trying to find such thing like that.Maybe I can combine this with some fusion::fused or unfused somehow. I'll give this a try.
Also look into proto::functional::unpack_expr, which turns a Fusion
sequence into a proto expression node. For instance, you might turn an
N-ary expression into an (N+1)-ary expression representing a function
invocation like (untested) ...
when< nary_expr< _, vararg

Eric Niebler wrote:
Also look into proto::functional::unpack_expr, which turns a Fusion sequence into a proto expression node. For instance, you might turn an N-ary expression into an (N+1)-ary expression representing a function invocation like (untested) ...
when< nary_expr< _, vararg
> , function< vararg >( // #1 functional::unpack_exprtag::function( // #2 push_front(_, terminal > >()) // #3 ) ) > The idea here is to create an expression that, when evaluated by proto::function's pass-through transform (#1), does the Right Thing. You can accomplish that by first building a new expression from the old that (a) has an extra argument in the 0th position that is a terminal containing your function object, and (b) has a tag type of tag::function. First you build a new sequence with push_front (#3), and then you unpack that Fusion sequence into a new expression (#2).
push_front doesn't exist yet; you'll have to write it. Just create a callable function object that does what fusion::push_front does. OK, I like the idea. I tried to get it working but I stumple against the fatc that proto make_expr takes push_front() as a Sequence and don't try to evaulate it before hand, leading to a "no size for psuh_front" erro in fusion. I'll try to get this sorted though.
My main question is that, when and when not a transform call get evaluated ? Like if i do foo( bar ( _) ) is bar(_) evaluated before being evaluated by foo ? Sometimes it seems it does and sometimes no :/ -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel wrote:
Eric Niebler wrote:
Also look into proto::functional::unpack_expr, <snip>
OK, I like the idea. I tried to get it working but I stumple against the fatc that proto make_expr takes push_front() as a Sequence and don't try to evaulate it before hand, leading to a "no size for psuh_front" erro in fusion. I'll try to get this sorted though.
My main question is that, when and when not a transform call get evaluated ? Like if i do foo( bar ( _) )
is bar(_) evaluated before being evaluated by foo ? Sometimes it seems it does and sometimes no :/
You'll have to post your code ... I can't tell what problem you might be running into. -- Eric Niebler BoostPro Computing http://www.boostpro.com

You'll have to post your code ... I can't tell what problem you might be running into. Well, I decided to be a coward for today. I'll shelf this functional solution for later. I just added my own ternary_expr & quaternary_expr class for the moment as it seems it's all the client wants. I'll come back when I've digested those infos as I htink I'm just doing a small error.
For reference here is the code I wrote:
namespace bp = boost::proto;
struct push_front_
{
template<class Sig> struct result;
template

joel wrote:
You'll have to post your code ... I can't tell what problem you might be running into. Well, I decided to be a coward for today. I'll shelf this functional solution for later. I just added my own ternary_expr & quaternary_expr class for the moment as it seems it's all the client wants. I'll come back when I've digested those infos as I htink I'm just doing a small error.
For reference here is the code I wrote:
namespace bp = boost::proto;
struct push_front_
Must inherit from bp::callable.
{ template<class Sig> struct result; template
struct result { typedef typename boost::fusion::result_of::push_front ::type type; }; template
typename result ::type operator()(Elem const& e, Seq& s ) const
Sequence and Element argument order is reversed here.
{ return boost::fusion::push_front(s,e); } };
struct _load : bp::transform< _load > { template
struct impl : bp::transform_impl { typedef typename meta::strip<Expr>::type::value_type result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param , typename impl::data_param data ) const { return expr(data); } }; };
struct eval_xpr : bp::or_< bp::when< bp::terminal< blockbp::_,bp::_ > , _load(bp::_) > , bp::when< bp::nary_expr< bp::_, bp::vararg
> , bp::functional::unpack_exprbp::tag::function(
This will create the new expression but not evaluate it. I had incorrectly told you to use bp::function<> here for its pass-through transform, but that's not actually what you want. You want Proto's _default transform.
push_front_(bp::_, bp::terminal
bp::_ > >() ) ) ) > > {};
Here is some code that should get you going again:
#include

Eric Niebler wrote:
Hope that helps, It did ;)
So everything is working right now. Thanks again. Samll question, for a given eval_xpr, if I do : eval_xpr()(x+y, state, data); it seems that the operator()(Expr,State,Data) of the transform require the Expr to be a reference and so, the former call fails as x+y is a temporary. Is it on, purpose or is it a missing feature ?

Joel Falcou wrote:
Samll question, for a given eval_xpr, if I do :
eval_xpr()(x+y, state, data);
it seems that the operator()(Expr,State,Data) of the transform require the Expr to be a reference and so, the former call fails as x+y is a temporary. Is it on, purpose or is it a missing feature ?
eval_xpr gets an operator() overload defined by proto::transform that
looks like this:
template
participants (3)
-
Eric Niebler
-
joel
-
Joel Falcou