1<?xml version="1.0" encoding="utf-8"?>
2<!--
3  Copyright 2012 Eric Niebler
4
5  Distributed under the Boost
6  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<header name="boost/proto/transform/when.hpp">
10  <para>
11    Definition of the
12    <computeroutput>
13      <classname alt="boost::proto::when">proto::when&lt;&gt;</classname>
14    </computeroutput> and
15    <computeroutput>
16      <classname alt="boost::proto::otherwise">proto::otherwise&lt;&gt;</classname>
17    </computeroutput> transforms.
18  </para>
19  <namespace name="boost">
20    <namespace name="proto">
21
22      <!-- struct transforms_type -->
23      <struct name="transforms_type">
24        <purpose>
25          The type used to define the global <code><globalname>proto::transforms</globalname></code>,
26          a key for use when creating and accessing a slot in a transform environment for
27          a set of external transforms.
28        </purpose>
29        <description>
30          <para>
31            The <code>proto::transforms_type</code> type, along with the <code><globalname>proto::transforms</globalname></code>
32            global, are declared using the <code><macroname>BOOST_PROTO_DEFINE_ENV_VAR</macroname>()</code> macro.
33          </para>
34        </description>
35        <method-group name="public member functions">
36          <overloaded-method name="operator=">
37            <signature cv="const">
38              <template>
39                <template-type-parameter name="Value"/>
40              </template>
41              <type><classname>env</classname>&lt;transforms_type, <replaceable>see-below</replaceable>&gt;</type>
42              <parameter name="value">
43                <paramtype>Value &amp;</paramtype>
44              </parameter>
45            </signature>
46            <signature cv="const">
47              <template>
48                <template-type-parameter name="Value"/>
49              </template>
50              <type><classname>env</classname>&lt;transforms_type, <replaceable>see-below</replaceable>&gt;</type>
51              <parameter name="value">
52                <paramtype>Value const &amp;</paramtype>
53              </parameter>
54            </signature>
55            <description>
56              <para>
57                If <code>Value</code> is a specialization <code>boost::reference_wrapper&lt;T&gt;</code>,
58                this function returns <code><classname>env</classname>&lt;transforms_type, T &amp;&gt;(value.get())</code>.
59              </para>
60              <para>
61                Else, if the type <code>Value</code> is non-copyable (i.e., a function, an array, abstract, or an ostream),
62                this function returns <code><classname>env</classname>&lt;transforms_type, Value <replaceable>cv</replaceable> &amp;&gt;(value)</code>,
63                where <code><replaceable>cv</replaceable></code> is <code>const</code> for the second overload, and empty
64                for the first.
65              </para>
66              <para>
67                Otherwise, this function returns <code><classname>env</classname>&lt;transforms_type, Value&gt;(value)</code>.
68              </para>
69            </description>
70          </overloaded-method>
71        </method-group>
72      </struct>
73
74      <data-member name="transforms">
75        <description>
76          <para>
77            A key key for use when creating and accessing a slot in a transform environment for
78            a set of external transforms.
79          </para>
80        </description>
81        <type><classname>proto::transforms_type</classname> const</type>
82      </data-member>
83
84      <struct name="when">
85        <template>
86          <template-type-parameter name="Grammar"/>
87          <template-type-parameter name="PrimitiveTransform">
88            <default>Grammar</default>
89          </template-type-parameter>
90        </template>
91        <purpose>A grammar element and a <conceptname>PrimitiveTransform</conceptname> that associates
92          a transform with the grammar.</purpose>
93        <description>
94          <para>
95            Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
96            transform with a custom transform. It is for used when composing larger transforms by
97            associating smaller transforms with individual rules in your grammar, as in the following
98            transform which counts the number of terminals in an expression.
99            <programlisting>// Count the terminals in an expression tree.
100// Must be invoked with initial state == mpl::int_&lt;0&gt;().
101struct CountLeaves :
102  <classname>proto::or_</classname>&lt;
103    proto::when&lt;<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;, mpl::next&lt;<classname>proto::_state</classname>&gt;()&gt;,
104    proto::otherwise&lt;<classname>proto::fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves&gt; &gt;
105  &gt;
106{};</programlisting>
107          </para>
108          <para>
109            In <computeroutput>proto::when&lt;G, T&gt;</computeroutput>, when <computeroutput>T</computeroutput>
110            is a class type it is a <conceptname>PrimitiveTransform</conceptname> and the following equivalencies hold:
111          </para>
112          <itemizedlist>
113            <listitem>
114              <para>
115                <computeroutput>boost::result_of&lt;proto::when&lt;G,T&gt;(E,S,V)&gt;::type</computeroutput> is the same as
116                <computeroutput>boost::result_of&lt;T(E,S,V)&gt;::type</computeroutput>.
117              </para>
118            </listitem>
119            <listitem>
120              <para>
121                <computeroutput>proto::when&lt;G,T&gt;()(e,s,d)</computeroutput> is the same as
122                <computeroutput>T()(e,s,d)</computeroutput>.
123              </para>
124            </listitem>
125          </itemizedlist>
126        </description>
127        <inherit><type>PrimitiveTransform</type></inherit>
128        <typedef name="proto_grammar">
129          <type>typename Grammar::proto_grammar</type>
130        </typedef>
131      </struct>
132
133      <struct-specialization name="when">
134        <template>
135          <template-type-parameter name="Grammar"/>
136          <template-type-parameter name="Fun"/>
137        </template>
138        <specialization>
139          <template-arg>Grammar</template-arg>
140          <template-arg>Fun *</template-arg>
141        </specialization>
142        <inherit><type><classname>proto::when</classname>&lt; Grammar, Fun &gt;</type></inherit>
143        <purpose>A specialization that treats function pointer <conceptname>Transform</conceptname>s as if they
144          were function type <conceptname>Transform</conceptname>s.</purpose>
145        <description>
146          <para>
147            This specialization requires that <computeroutput>Fun</computeroutput> is actually a function type.
148          </para>
149          <para>
150            This specialization is required for nested transforms such as
151            <computeroutput>proto::when&lt;G, T0(T1(_))&gt;</computeroutput>. In C++, functions that are used
152            as parameters to other functions automatically decay to funtion pointer types. In other words, the
153            type <computeroutput>T0(T1(_))</computeroutput> is indistinguishable from
154            <computeroutput>T0(T1(*)(_))</computeroutput>. This specialization is required to handle these
155            nested function pointer type transforms properly.
156          </para>
157        </description>
158      </struct-specialization>
159
160      <struct-specialization name="when">
161        <template>
162          <template-type-parameter name="Grammar"/>
163          <template-type-parameter name="R"/>
164          <template-type-parameter name="A" pack="1"/>
165        </template>
166        <specialization>
167          <template-arg>Grammar</template-arg>
168          <template-arg>R(A...)</template-arg>
169        </specialization>
170        <inherit><type><classname>proto::transform</classname>&lt; when&lt;Grammar, R(A...)&gt; &gt;</type></inherit>
171        <purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
172          transform with the grammar. </purpose>
173        <description>
174          <para>
175            Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
176            transform with a custom transform. It is for use when composing larger transforms by associating
177            smaller transforms with individual rules in your grammar.
178          </para>
179          <para>
180            The <computeroutput>when&lt;G, R(A...)&gt;</computeroutput> form accepts either a
181            <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
182            second parameter. <computeroutput>proto::when&lt;&gt;</computeroutput> uses
183            <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput> to
184            distinguish between the two, and uses
185            <computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> to evaluate
186            <conceptname>CallableTransform</conceptname>s and
187            <computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> to evaluate
188            <conceptname>ObjectTransform</conceptname>s.
189          </para>
190        </description>
191        <struct name="impl">
192          <template>
193            <template-type-parameter name="Expr"/>
194            <template-type-parameter name="State"/>
195            <template-type-parameter name="Data"/>
196          </template>
197          <inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
198          <typedef name="call_">
199            <purpose>For exposition only</purpose>
200            <type><classname>proto::call</classname>&lt;R(A...)&gt;</type>
201          </typedef>
202          <typedef name="make_">
203            <purpose>For exposition only</purpose>
204            <type><classname>proto::make</classname>&lt;R(A...)&gt;</type>
205          </typedef>
206          <typedef name="which">
207            <purpose>For exposition only</purpose>
208            <type>typename mpl::if_&lt;<classname>proto::is_callable</classname>&lt;R&gt;,call_,make_&gt;::type</type>
209          </typedef>
210          <typedef name="result_type">
211            <type>typename boost::result_of&lt;which(Expr, State, Data)&gt;::type</type>
212          </typedef>
213          <method-group name="public member functions">
214            <method name="operator()" cv="const">
215              <type>result_type</type>
216              <parameter name="expr">
217                <paramtype>typename impl::expr_param</paramtype>
218                <description>
219                  <para>The current expression </para>
220                </description>
221              </parameter>
222              <parameter name="state">
223                <paramtype>typename impl::state_param</paramtype>
224                <description>
225                  <para>The current state </para>
226                </description>
227              </parameter>
228              <parameter name="data">
229                <paramtype>typename impl::data_param</paramtype>
230                <description>
231                  <para>An arbitrary data </para>
232                </description>
233              </parameter>
234              <description>
235                <para>
236                  Evaluate <computeroutput>R(A...)</computeroutput> as a transform either with
237                  <computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> or with
238                  <computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> depending
239                  on whether <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput>
240                  is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
241                </para>
242              </description>
243              <requires>
244                <para>
245                  <computeroutput><classname>proto::matches</classname>&lt;Expr, Grammar&gt;::value</computeroutput>
246                  is <computeroutput>true</computeroutput>.
247                </para>
248              </requires>
249              <returns>
250                <para>
251                  <computeroutput>which()(expr, state, data)</computeroutput>
252                </para>
253              </returns>
254            </method>
255          </method-group>
256        </struct>
257        <typedef name="proto_grammar">
258          <type>typename Grammar::proto_grammar</type>
259        </typedef>
260      </struct-specialization>
261
262      <struct-specialization name="when">
263        <template>
264          <template-type-parameter name="Grammar"/>
265          <template-type-parameter name="R"/>
266          <template-type-parameter name="A" pack="1"/>
267        </template>
268        <specialization>
269          <template-arg>Grammar</template-arg>
270          <template-arg>R(A..., ...)</template-arg>
271        </specialization>
272        <inherit><type><classname>proto::transform</classname>&lt; when&lt;Grammar, R(A..., ...)&gt; &gt;</type></inherit>
273        <purpose>A grammar element and a <conceptname>Transform</conceptname> that associates a
274          transform with the grammar. </purpose>
275        <description>
276          <para>
277            Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
278            transform with a custom transform. It is for use when composing larger transforms by associating
279            smaller transforms with individual rules in your grammar.
280          </para>
281          <para>
282            The <computeroutput>when&lt;G, R(A..., ...)&gt;</computeroutput> form accepts either a
283            <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its
284            second parameter. <computeroutput>proto::when&lt;&gt;</computeroutput> uses
285            <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput> to
286            distinguish between the two, and uses
287            <computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> to evaluate
288            <conceptname>CallableTransform</conceptname>s and
289            <computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> to evaluate
290            <conceptname>ObjectTransform</conceptname>s.
291          </para>
292          <para>
293            <emphasis role="bold">Note:</emphasis> In the specialization
294            <computeroutput>when&lt;G, R(A..., ...)&gt;</computeroutput>, the first ellipsis denotes a
295            C++11-style variadic template (which is emulated for C++98 compilers). The second ellipsis
296            is a C-style vararg.
297          </para>
298        </description>
299        <struct name="impl">
300          <template>
301            <template-type-parameter name="Expr"/>
302            <template-type-parameter name="State"/>
303            <template-type-parameter name="Data"/>
304          </template>
305          <inherit><type><classname>proto::transform_impl</classname>&lt; Expr, State, Data &gt;</type></inherit>
306          <typedef name="call_">
307            <purpose>For exposition only</purpose>
308            <type><classname>proto::call</classname>&lt;R(A..., ...)&gt;</type>
309          </typedef>
310          <typedef name="make_">
311            <purpose>For exposition only</purpose>
312            <type><classname>proto::make</classname>&lt;R(A..., ...)&gt;</type>
313          </typedef>
314          <typedef name="which">
315            <purpose>For exposition only</purpose>
316            <type>typename mpl::if_&lt;<classname>proto::is_callable</classname>&lt;R&gt;,call_,make_&gt;::type</type>
317          </typedef>
318          <typedef name="result_type">
319            <type>typename boost::result_of&lt;which(Expr, State, Data)&gt;::type</type>
320          </typedef>
321          <method-group name="public member functions">
322            <method name="operator()" cv="const">
323              <type>result_type</type>
324              <parameter name="expr">
325                <paramtype>typename impl::expr_param</paramtype>
326                <description>
327                  <para>The current expression </para>
328                </description>
329              </parameter>
330              <parameter name="state">
331                <paramtype>typename impl::state_param</paramtype>
332                <description>
333                  <para>The current state </para>
334                </description>
335              </parameter>
336              <parameter name="data">
337                <paramtype>typename impl::data_param</paramtype>
338                <description>
339                  <para>An arbitrary data </para>
340                </description>
341              </parameter>
342              <description>
343                <para>
344                  Evaluate <computeroutput>R(A..., ...)</computeroutput> as a transform either with
345                  <computeroutput><classname>proto::call&lt;&gt;</classname></computeroutput> or with
346                  <computeroutput><classname>proto::make&lt;&gt;</classname></computeroutput> depending
347                  on whether <computeroutput><classname>proto::is_callable</classname>&lt;R&gt;::value</computeroutput>
348                  is <computeroutput>true</computeroutput> or <computeroutput>false</computeroutput>.
349                </para>
350              </description>
351              <requires>
352                <para>
353                  <computeroutput><classname>proto::matches</classname>&lt;Expr, Grammar&gt;::value</computeroutput>
354                  is <computeroutput>true</computeroutput>.
355                </para>
356              </requires>
357              <returns>
358                <para>
359                  <computeroutput>which()(expr, state, data)</computeroutput>
360                </para>
361              </returns>
362            </method>
363          </method-group>
364        </struct>
365        <typedef name="proto_grammar">
366          <type>typename Grammar::proto_grammar</type>
367        </typedef>
368      </struct-specialization>
369
370      <struct-specialization name="when">
371        <template>
372          <template-type-parameter name="Grammar"/>
373        </template>
374        <specialization>
375          <template-arg>Grammar</template-arg>
376          <template-arg><classname>proto::external_transform</classname></template-arg>
377        </specialization>
378        <inherit><type>
379  <classname>proto::transform</classname>&lt; when&lt;Grammar, <classname>proto::external_transform</classname>&gt; &gt;</type></inherit>
380        <purpose>A grammar element that associates an externally-specified transform with the grammar.
381          The transform is looked up in the Data parameter using the Grammar as a key.</purpose>
382        <description>
383          <para>
384            Use <computeroutput>proto::when&lt;&gt;</computeroutput> to override a grammar's default
385            transform with a custom transform. It is for use when composing larger transforms by associating
386            smaller transforms with individual rules in your grammar.
387          </para>
388          <para>
389            The <computeroutput>when&lt;G, <classname>proto::external_transform</classname>&gt;</computeroutput>
390            indicates that the associated transform is not yet known. It should be looked up when the transform
391            is about to be applied. It is found by looking it up in the passed-in Data parameter, which
392            behaves like a compile-time map from grammar types to transform types. The map is indexed using
393            <computeroutput>Grammar</computeroutput> as a key. The associated value type is used as the transform
394            to apply. In this way, the same grammar can be used to define multiple evaluating strategies that
395            can be added post-hoc.
396          </para>
397          <para>
398            See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
399          </para>
400        </description>
401        <struct name="impl">
402          <template>
403            <template-type-parameter name="Expr"/>
404            <template-type-parameter name="State"/>
405            <template-type-parameter name="Data"/>
406          </template>
407          <inherit><type>
408    boost::remove_reference&lt;
409      typename mpl::eval_if_c&lt;
410        <classname>proto::result_of::has_env_var</classname>&lt;Data, <classname>proto::transforms_type</classname>&gt;::value,
411        <classname>proto::result_of::env_var</classname>&lt;Data, <classname>proto::transforms_type</classname>&gt;,
412        <classname>proto::result_of::env_var</classname>&lt;Data, <classname>proto::data_type</classname>&gt;
413      &gt;::type
414    &gt;::type
415      ::template when&lt; Grammar &gt;
416        ::template impl&lt; Expr, State, Data &gt;</type></inherit>
417          <description>
418            <para>
419              The implementation of the <code>impl</code> struct depends on whether the <code>Data</code>
420              parameter is a transform environment that contains a value corresponding to the
421              <classname>proto::transforms_type</classname> key. If so, that value is treated as a
422              map from rules to transforms. Otherwise, the <code>Data</code> type itself is treated
423              as such a map.
424            </para>
425          </description>
426        </struct>
427        <typedef name="proto_grammar">
428          <type>typename Grammar::proto_grammar</type>
429        </typedef>
430      </struct-specialization>
431
432      <struct name="otherwise">
433        <template>
434          <template-type-parameter name="Fun"/>
435        </template>
436        <inherit><type><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</type></inherit>
437        <purpose>
438          Syntactic sugar for <computeroutput><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</computeroutput>,
439          for use in grammars to handle all the cases not yet handled.
440        </purpose>
441        <description>
442          <para>
443            Use <computeroutput>proto::otherwise&lt;T&gt;</computeroutput> in your grammars as a synonym for
444            <computeroutput><classname>proto::when</classname>&lt; <classname>proto::_</classname>, Fun &gt;</computeroutput>
445            as in the following transform which counts the number of terminals in an expression.
446          </para>
447          <para>
448            <programlisting>// Count the terminals in an expression tree.
449// Must be invoked with initial state == mpl::int_&lt;0&gt;().
450struct CountLeaves :
451  <classname>proto::or_</classname>&lt;
452    proto::when&lt;<classname>proto::terminal</classname>&lt;<classname>proto::_</classname>&gt;, mpl::next&lt;<classname>proto::_state</classname>&gt;()&gt;,
453    proto::otherwise&lt;<classname>proto::fold</classname>&lt;<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves&gt; &gt;
454  &gt;
455{};</programlisting>
456          </para>
457        </description>
458      </struct>
459
460      <struct name="external_transform">
461        <purpose>A placeholder for use as the second parameter for <computeroutput><classname>proto::when</classname></computeroutput>
462          to indicate that the rule's transform is specified externally.</purpose>
463        <description>
464          <para>
465            See <computeroutput><classname>proto::external_transforms</classname></computeroutput> for an example.
466          </para>
467        </description>
468      </struct>
469
470      <struct name="external_transforms">
471        <template>
472          <template-type-parameter name="When" pack="1"/>
473        </template>
474        <purpose>A map from grammars to transforms, used as a way to externally associate transforms.</purpose>
475        <typedef name="map_type">
476          <purpose>For exposition only.</purpose>
477          <type>mpl::map&lt; typename to_mpl_pair&lt; When &gt;::type... &gt;</type>
478        </typedef>
479        <struct name="when">
480          <template>
481            <template-type-parameter name="Grammar"/>
482          </template>
483          <inherit><type><classname>proto::otherwise</classname>&lt; typename mpl::at&lt; map_type, Grammar &gt;::type &gt;</type></inherit>
484        </struct>
485        <description>
486          <para>
487            It is sometimes desirable to define a grammar that can be customized with different sets of transforms.
488            To do that, where you would normally specify a transform within a grammar, you can instead put
489            <computeroutput><classname>proto::external_transform</classname></computeroutput>; for example:
490            <computeroutput>proto::when&lt; some_grammar, proto::external_transform &gt;</computeroutput>. Then, when
491            invoking the grammar, you can pass an approriately-defined instance of <computeroutput>proto::external_transforms</computeroutput>
492            as the Data parameter. When an expression matches <computeroutput>some_grammar</computeroutput>, Proto
493            will look up the approprite transform in the Data parameter using <computeroutput>some_grammar</computeroutput>
494            as a key.
495          </para>
496          <para>
497            <programlisting>struct int_terminal
498  : <classname>proto::terminal</classname>&lt;int&gt;
499{};
500
501struct char_terminal
502  : <classname>proto::terminal</classname>&lt;char&gt;
503{};
504
505struct my_grammar
506  : <classname>proto::or_</classname>&lt;
507        // The next two grammar rules are customization points.
508        // The associated transforms are specified externally
509        // using external_transforms below.
510        <classname>proto::when</classname>&lt; int_terminal, <classname>proto::external_transform</classname> &gt;
511      , <classname>proto::when</classname>&lt; char_terminal, <classname>proto::external_transform</classname> &gt;
512      , <classname>proto::when</classname>&lt;
513            <classname>proto::plus</classname>&lt; my_grammar, my_grammar &gt;
514          , <classname>proto::fold</classname>&lt; <classname>proto::_</classname>, int(), my_grammar &gt;
515        &gt;
516    &gt;
517{};
518
519// Here is where the transforms are associated with the
520// grammar rules above.
521struct my_transforms
522  : proto::external_transforms&lt;
523        <classname>proto::when</classname>&lt;int_terminal, print(<classname>proto::_value</classname>)&gt;
524      , <classname>proto::when</classname>&lt;char_terminal, print(<classname>proto::_value</classname>)&gt;
525    &gt;
526{};
527
528// ...
529
530<classname>proto::literal</classname>&lt;int&gt; i(1);
531<classname>proto::literal</classname>&lt;char&gt; c('a');
532my_transforms trx;
533
534// Evaluate "i+c" using my_grammar with the specified transforms:
535my_grammar()(i + c, 0, trx);
536
537// If you would also like to pass arbitrary data along with the
538// transforms, you can use a transform environment, as so:
539my_grammar()(i + c, 0, (proto::data = 42, proto::transforms = trx));</programlisting>
540          </para>
541        </description>
542      </struct>
543    </namespace>
544  </namespace>
545</header>
546