]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/============================================================================== |
2 | Copyright (C) 2001-2010 Joel de Guzman | |
3 | Copyright (C) 2001-2005 Dan Marsden | |
4 | Copyright (C) 2001-2010 Thomas Heller | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ===============================================================================/] | |
9 | ||
10 | [section:actor Actors in Detail] | |
11 | ||
12 | [heading Actor] | |
13 | ||
14 | The main concept is the `Actor`. An `Actor` is a model of the __PFO__ concept | |
15 | (that can accept 0 to N arguments (where N is a predefined maximum). | |
16 | ||
17 | An `Actor` contains a valid Phoenix Expression, a call to one of the function | |
18 | call operator overloads, starts the evaluation process. | |
19 | ||
20 | [note You can set `BOOST_PHOENIX_LIMIT`, the predefined maximum arity an | |
21 | actor can take. By default, `BOOST_PHOENIX_LIMIT` is set to 10.] | |
22 | ||
23 | The `actor` template class models the `Actor` concept: | |
24 | ||
25 | template <typename Expr> | |
26 | struct actor | |
27 | { | |
28 | template <typename Sig> | |
29 | struct result; | |
30 | ||
31 | typename result_of::actor<Expr>::type | |
32 | operator()() const; | |
33 | ||
34 | template <typename T0> | |
35 | typename result_of::actor<Expr, T0 &>::type | |
36 | operator()(T0& _0) const; | |
37 | ||
38 | template <typename T0> | |
39 | typename result_of::actor<Expr, T0 const &>::type | |
40 | operator()(T0 const & _0) const; | |
41 | ||
42 | //... | |
43 | }; | |
44 | ||
45 | [table Actor Concept Requirements | |
46 | [ | |
47 | [Expression] | |
48 | [Semantics] | |
49 | ] | |
50 | [ | |
51 | [`actor(arg0, arg1, ..., argN)`] | |
52 | [Function call operators to start the evaluation] | |
53 | ] | |
54 | [ | |
55 | [`boost::result_of<Actor<Expr>(Arg0, Arg1, ..., ArgN)>::type`] | |
56 | [Result of the evaluation] | |
57 | ] | |
58 | [ | |
59 | [`result_of::actor<Expr, Arg0, Arg1, ..., ArgN>::type`] | |
60 | [Result of the evaluation] | |
61 | ] | |
62 | ] | |
63 | ||
64 | [heading Function Call Operators] | |
65 | ||
66 | There are 2*N function call operators for 0 to N arguments (N == `BOOST_PHOENIX_LIMIT`). | |
67 | The actor class accepts the arguments and forwards the arguments to the default | |
68 | evaluation action. | |
69 | ||
70 | Additionally, there exist function call operators accepting permutations of const | |
71 | and non-const references. These operators are created for all N <= | |
72 | `BOOST_PHOENIX_PERFECT_FORWARD_LIMIT` (which defaults to 3). | |
73 | ||
74 | [def $http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm] | |
75 | ||
76 | [note *Forwarding Function Problem* | |
77 | ||
78 | There is a known issue with current C++ called the "__forwarding__". | |
79 | The problem is that given an arbitrary function `F`, using current C++ | |
80 | language rules, one cannot create a forwarding function `FF` that | |
81 | transparently assumes the arguments of `F`. | |
82 | ] | |
83 | ||
84 | [heading Context] | |
85 | ||
86 | On an actor function call, before calling the evaluation function, the actor created a *context*. | |
87 | This context consists of an `Environment` and an `Action` part. These contain all information | |
88 | necessary to evaluate the given expression. | |
89 | ||
90 | [table Context Concept Requirements | |
91 | [ | |
92 | [Expression] | |
93 | [Semantics] | |
94 | ] | |
95 | [ | |
96 | [`result_of::context<Env, Actions>::type`] | |
97 | [Type of a Context] | |
98 | ] | |
99 | [ | |
100 | [`context(e, a)`] | |
101 | [A Context containing environment `e` and actions `a`] | |
102 | ] | |
103 | [ | |
104 | [`result_of::env<Context>::type`] | |
105 | [Type of the contained Environment] | |
106 | ] | |
107 | [ | |
108 | [`env(ctx)`] | |
109 | [The environment] | |
110 | ] | |
111 | [ | |
112 | [`result_of::actions<Context>::type`] | |
113 | [Type of the contained Actions] | |
114 | ] | |
115 | [ | |
116 | [`actions(ctx)`] | |
117 | [The actions] | |
118 | ] | |
119 | ] | |
120 | ||
121 | [heading Environment] | |
122 | ||
123 | The Environment is a model of __random_access__. | |
124 | ||
125 | The arguments passed to the actor's function call operator are collected inside the Environment: | |
126 | ||
127 | [$images/funnel_in.png] | |
128 | ||
129 | Other parts of the library (e.g. the scope module) extends the `Environment` | |
130 | concept to hold other information such as local variables, etc. | |
131 | ||
132 | [heading Actions] | |
133 | ||
134 | Actions is the part of Phoenix which are responsible for giving the actual expressions | |
135 | a specific behaviour. During the traversal of the Phoenix Expression Tree these actions | |
136 | are called whenever a specified rule in the grammar matches. | |
137 | ||
138 | struct actions | |
139 | { | |
140 | template <typename Rule> | |
141 | struct when; | |
142 | }; | |
143 | ||
144 | The nested `when` template is required to be __proto_primitive_transform__. No | |
145 | worries, you don't have to learn __proto__ just yet! Phoenix provides some wrappers | |
146 | to let you define simple actions without the need to dive deep into proto. | |
147 | ||
148 | Phoenix ships with a predefined `default_actions` class that evaluates the expressions with | |
149 | C++ semantics: | |
150 | ||
151 | struct default_actions | |
152 | { | |
153 | template <typename Rule, typename Dummy = void> | |
154 | struct when | |
155 | : proto::_default<meta_grammar> | |
156 | {}; | |
157 | }; | |
158 | ||
159 | For more information on how to use the default_actions class and how to attach custom actions | |
160 | to the evaluation process, see [link phoenix.inside.actions more on actions]. | |
161 | ||
162 | [heading Evaluation] | |
163 | ||
164 | struct evaluator | |
165 | { | |
166 | template <typename Expr, typename Context> | |
167 | __unspecified__ operator()(Expr &, Context &); | |
168 | }; | |
169 | ||
170 | evaluator const eval = {}; | |
171 | ||
172 | The evaluation of a Phoenix expression is started by a call to the function call operator of | |
173 | `evaluator`. | |
174 | ||
175 | The evaluator is called by the `actor` function operator overloads after the context is built up. | |
176 | For reference, here is a typical `actor::operator()` that accepts two arguments: | |
177 | ||
178 | template <typename T0, typename T1> | |
179 | typename result_of::actor<Expr, T0 &, T1 &>::type | |
180 | operator()(T0 &t0, T1 &t1) const | |
181 | { | |
182 | fusion::vector2<T0 &, T1 &> env(t0, t1); | |
183 | ||
184 | return eval(*this, context(env, default_actions())); | |
185 | } | |
186 | ||
187 | [heading result_of::actor] | |
188 | ||
189 | For reasons of symmetry to the family of `actor::operator()` there is a special | |
190 | metafunction usable for actor result type calculation named `result_of::actor`. This | |
191 | metafunction allows us to directly specify the types of the parameters to be | |
192 | passed to the `actor::operator()` function. Here's a typical `actor_result` that | |
193 | accepts two arguments: | |
194 | ||
195 | namespace result_of | |
196 | { | |
197 | template <typename Expr, typename T0, typename T1> | |
198 | struct actor | |
199 | { | |
200 | typedef fusion::vector2<T0, T1> env_tpe; | |
201 | typedef typename result_of::context<env_type, default_actions>::type ctx_type | |
202 | typedef typename boost::result_of<evaluator(Expr const&, ctx_type)>::type type; | |
203 | }; | |
204 | } | |
205 | ||
206 | [endsect] |