[/============================================================================== Copyright (C) 2001-2010 Joel de Guzman Copyright (C) 2001-2005 Dan Marsden Copyright (C) 2001-2010 Thomas Heller 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) ===============================================================================/] [section:actor Actors in Detail] [heading Actor] The main concept is the `Actor`. An `Actor` is a model of the __PFO__ concept (that can accept 0 to N arguments (where N is a predefined maximum). An `Actor` contains a valid Phoenix Expression, a call to one of the function call operator overloads, starts the evaluation process. [note You can set `BOOST_PHOENIX_LIMIT`, the predefined maximum arity an actor can take. By default, `BOOST_PHOENIX_LIMIT` is set to 10.] The `actor` template class models the `Actor` concept: template struct actor { template struct result; typename result_of::actor::type operator()() const; template typename result_of::actor::type operator()(T0& _0) const; template typename result_of::actor::type operator()(T0 const & _0) const; //... }; [table Actor Concept Requirements [ [Expression] [Semantics] ] [ [`actor(arg0, arg1, ..., argN)`] [Function call operators to start the evaluation] ] [ [`boost::result_of(Arg0, Arg1, ..., ArgN)>::type`] [Result of the evaluation] ] [ [`result_of::actor::type`] [Result of the evaluation] ] ] [heading Function Call Operators] There are 2*N function call operators for 0 to N arguments (N == `BOOST_PHOENIX_LIMIT`). The actor class accepts the arguments and forwards the arguments to the default evaluation action. Additionally, there exist function call operators accepting permutations of const and non-const references. These operators are created for all N <= `BOOST_PHOENIX_PERFECT_FORWARD_LIMIT` (which defaults to 3). [def $http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm] [note *Forwarding Function Problem* There is a known issue with current C++ called the "__forwarding__". The problem is that given an arbitrary function `F`, using current C++ language rules, one cannot create a forwarding function `FF` that transparently assumes the arguments of `F`. ] [heading Context] On an actor function call, before calling the evaluation function, the actor created a *context*. This context consists of an `Environment` and an `Action` part. These contain all information necessary to evaluate the given expression. [table Context Concept Requirements [ [Expression] [Semantics] ] [ [`result_of::context::type`] [Type of a Context] ] [ [`context(e, a)`] [A Context containing environment `e` and actions `a`] ] [ [`result_of::env::type`] [Type of the contained Environment] ] [ [`env(ctx)`] [The environment] ] [ [`result_of::actions::type`] [Type of the contained Actions] ] [ [`actions(ctx)`] [The actions] ] ] [heading Environment] The Environment is a model of __random_access__. The arguments passed to the actor's function call operator are collected inside the Environment: [$images/funnel_in.png] Other parts of the library (e.g. the scope module) extends the `Environment` concept to hold other information such as local variables, etc. [heading Actions] Actions is the part of Phoenix which are responsible for giving the actual expressions a specific behaviour. During the traversal of the Phoenix Expression Tree these actions are called whenever a specified rule in the grammar matches. struct actions { template struct when; }; The nested `when` template is required to be __proto_primitive_transform__. No worries, you don't have to learn __proto__ just yet! Phoenix provides some wrappers to let you define simple actions without the need to dive deep into proto. Phoenix ships with a predefined `default_actions` class that evaluates the expressions with C++ semantics: struct default_actions { template struct when : proto::_default {}; }; For more information on how to use the default_actions class and how to attach custom actions to the evaluation process, see [link phoenix.inside.actions more on actions]. [heading Evaluation] struct evaluator { template __unspecified__ operator()(Expr &, Context &); }; evaluator const eval = {}; The evaluation of a Phoenix expression is started by a call to the function call operator of `evaluator`. The evaluator is called by the `actor` function operator overloads after the context is built up. For reference, here is a typical `actor::operator()` that accepts two arguments: template typename result_of::actor::type operator()(T0 &t0, T1 &t1) const { fusion::vector2 env(t0, t1); return eval(*this, context(env, default_actions())); } [heading result_of::actor] For reasons of symmetry to the family of `actor::operator()` there is a special metafunction usable for actor result type calculation named `result_of::actor`. This metafunction allows us to directly specify the types of the parameters to be passed to the `actor::operator()` function. Here's a typical `actor_result` that accepts two arguments: namespace result_of { template struct actor { typedef fusion::vector2 env_tpe; typedef typename result_of::context::type ctx_type typedef typename boost::result_of::type type; }; } [endsect]