Boost logo

Boost Users :

Subject: Re: [Boost-users] [phoenix][v3] Evaluating a terminal expression in the custom actions class.
From: Eric Niebler (eric_at_[hidden])
Date: 2011-03-02 20:42:55


On 3/3/2011 7:46 AM, Alexander Ospin wrote:
> 02.03.2011 19:00, Thomas Heller пишет:
>> On Wed, Mar 2, 2011 at 3:03 PM, Alexander Ospin<aospin_at_[hidden]> wrote:
>>> Is it possible to evaluate terminal and custom_terminal expressions
>>> in the
>>> some custom actions class? For instance how to implement
>>> "terminal_eval" to
>>> print something in the following code?
>>>
>>> #include<boost/phoenix/phoenix.hpp>
>>> #include<iostream>
>>>
>>> using namespace boost;
>>>
>>> struct actions
>>> {
>>> template<typename Rule, typename Dummy = void> struct when;
>>> };
>>>
>>> template<>
>>> struct actions::when<phoenix::rule::terminal> :
>>> phoenix::call<terminal_eval> {};
>>>
>>> int main()
>>> {
>>> int var = 11;
>>> phoenix::eval(phoenix::val(var), phoenix::context(int(),
>>> actions()));
>>> return 0;
>>> }
>>>
>>>
>>> I've tried to use the following form, but encountered some compiler
>>> errors:
>>> (GCC-4.2.1[FreeBSD], boost and phoenix were taken from SVN, latest
>>> versions)
>>>
>>> struct terminal_eval
>>> {
>>> typedef void result_type;
>>> template<typename Context, typename Expr>
>>> result_type operator ()(Context const&ctx, Expr const&expr)
>>> {
>>> std::cout<< "terminal"<< std::endl;
>>> }
>>> };
>>
>> Hi,
>>
>> phoenix::call does not work with terminals (which have an arity of 0).
>> The reason for this is because I didn't want to dictate what should be
>> passed to the eval function, the possibilities are: the value of the
>> terminal, or the proto::terminal type itself, the reason i couldn't
>> decide is because phoenix::call passes along proto expressions to the
>> to be called function object, and not the result of the evaluation.
>>
>> You're code will work by doing the following:
>>
>> template<>
>> struct actions::when<phoenix::rule::terminal> :
>> proto::call<terminal_eval(phoenix::_ctx, proto::_)>
>> {};
>>
>> or:
>>
>> template<>
>> struct actions::when<phoenix::rule::terminal> :
>> proto::call<terminal_eval(phoenix::_ctx, proto::_value)>
>> {};
>>
>> HTH,
>> Thomas
>
> Thanks, I understood the problem, but your solution doesn't work (same
> errors) because detail::call_impl uses proto::arity_of<Expr>::value for
> Arity parameter where Expr is staying the same (terminal or
> custom_terminal) and there are no template specialization for Arity = 0
> as you pointed. Of course if I specify in my code
> boost::phoenix::detail::call_impl for zero arity, I can ever use my code
> from the initial post of this thread, but in my opinion it is not the
> best option to externally use detail parts of the library.
> Can you explain more clearly why it is a problem to select between
> passing expression value and expression itself? I didn't understand you
> last phrase, but from the usage point of view, I think, passing an
> expression itself is a good option, because you can still transform an
> expression tree like in the inverse example (same coding style) and in
> the same time easily get an expression value by calling inside evaluator
> the proto::value function instead of phoenix::eval.

Agree that there should be some default behavior for call with
terminals, and that passing the whole terminal rather than the value is
probably the best default.

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

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net