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<></classname> 14 </computeroutput> and 15 <computeroutput> 16 <classname alt="boost::proto::otherwise">proto::otherwise<></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><transforms_type, <replaceable>see-below</replaceable>></type> 42 <parameter name="value"> 43 <paramtype>Value &</paramtype> 44 </parameter> 45 </signature> 46 <signature cv="const"> 47 <template> 48 <template-type-parameter name="Value"/> 49 </template> 50 <type><classname>env</classname><transforms_type, <replaceable>see-below</replaceable>></type> 51 <parameter name="value"> 52 <paramtype>Value const &</paramtype> 53 </parameter> 54 </signature> 55 <description> 56 <para> 57 If <code>Value</code> is a specialization <code>boost::reference_wrapper<T></code>, 58 this function returns <code><classname>env</classname><transforms_type, T &>(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><transforms_type, Value <replaceable>cv</replaceable> &>(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><transforms_type, Value>(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<></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_<0>(). 101struct CountLeaves : 102 <classname>proto::or_</classname>< 103 proto::when<<classname>proto::terminal</classname><<classname>proto::_</classname>>, mpl::next<<classname>proto::_state</classname>>()>, 104 proto::otherwise<<classname>proto::fold</classname><<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves> > 105 > 106{};</programlisting> 107 </para> 108 <para> 109 In <computeroutput>proto::when<G, T></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<proto::when<G,T>(E,S,V)>::type</computeroutput> is the same as 116 <computeroutput>boost::result_of<T(E,S,V)>::type</computeroutput>. 117 </para> 118 </listitem> 119 <listitem> 120 <para> 121 <computeroutput>proto::when<G,T>()(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>< Grammar, Fun ></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<G, T0(T1(_))></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>< when<Grammar, R(A...)> ></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<></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<G, R(A...)></computeroutput> form accepts either a 181 <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its 182 second parameter. <computeroutput>proto::when<></computeroutput> uses 183 <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput> to 184 distinguish between the two, and uses 185 <computeroutput><classname>proto::call<></classname></computeroutput> to evaluate 186 <conceptname>CallableTransform</conceptname>s and 187 <computeroutput><classname>proto::make<></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>< Expr, State, Data ></type></inherit> 198 <typedef name="call_"> 199 <purpose>For exposition only</purpose> 200 <type><classname>proto::call</classname><R(A...)></type> 201 </typedef> 202 <typedef name="make_"> 203 <purpose>For exposition only</purpose> 204 <type><classname>proto::make</classname><R(A...)></type> 205 </typedef> 206 <typedef name="which"> 207 <purpose>For exposition only</purpose> 208 <type>typename mpl::if_<<classname>proto::is_callable</classname><R>,call_,make_>::type</type> 209 </typedef> 210 <typedef name="result_type"> 211 <type>typename boost::result_of<which(Expr, State, Data)>::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<></classname></computeroutput> or with 238 <computeroutput><classname>proto::make<></classname></computeroutput> depending 239 on whether <computeroutput><classname>proto::is_callable</classname><R>::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><Expr, Grammar>::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>< when<Grammar, R(A..., ...)> ></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<></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<G, R(A..., ...)></computeroutput> form accepts either a 283 <conceptname>CallableTransform</conceptname> or an <conceptname>ObjectTransform</conceptname> as its 284 second parameter. <computeroutput>proto::when<></computeroutput> uses 285 <computeroutput><classname>proto::is_callable</classname><R>::value</computeroutput> to 286 distinguish between the two, and uses 287 <computeroutput><classname>proto::call<></classname></computeroutput> to evaluate 288 <conceptname>CallableTransform</conceptname>s and 289 <computeroutput><classname>proto::make<></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<G, R(A..., ...)></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>< Expr, State, Data ></type></inherit> 306 <typedef name="call_"> 307 <purpose>For exposition only</purpose> 308 <type><classname>proto::call</classname><R(A..., ...)></type> 309 </typedef> 310 <typedef name="make_"> 311 <purpose>For exposition only</purpose> 312 <type><classname>proto::make</classname><R(A..., ...)></type> 313 </typedef> 314 <typedef name="which"> 315 <purpose>For exposition only</purpose> 316 <type>typename mpl::if_<<classname>proto::is_callable</classname><R>,call_,make_>::type</type> 317 </typedef> 318 <typedef name="result_type"> 319 <type>typename boost::result_of<which(Expr, State, Data)>::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<></classname></computeroutput> or with 346 <computeroutput><classname>proto::make<></classname></computeroutput> depending 347 on whether <computeroutput><classname>proto::is_callable</classname><R>::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><Expr, Grammar>::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>< when<Grammar, <classname>proto::external_transform</classname>> ></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<></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<G, <classname>proto::external_transform</classname>></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< 409 typename mpl::eval_if_c< 410 <classname>proto::result_of::has_env_var</classname><Data, <classname>proto::transforms_type</classname>>::value, 411 <classname>proto::result_of::env_var</classname><Data, <classname>proto::transforms_type</classname>>, 412 <classname>proto::result_of::env_var</classname><Data, <classname>proto::data_type</classname>> 413 >::type 414 >::type 415 ::template when< Grammar > 416 ::template impl< Expr, State, Data ></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>< <classname>proto::_</classname>, Fun ></type></inherit> 437 <purpose> 438 Syntactic sugar for <computeroutput><classname>proto::when</classname>< <classname>proto::_</classname>, Fun ></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<T></computeroutput> in your grammars as a synonym for 444 <computeroutput><classname>proto::when</classname>< <classname>proto::_</classname>, Fun ></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_<0>(). 450struct CountLeaves : 451 <classname>proto::or_</classname>< 452 proto::when<<classname>proto::terminal</classname><<classname>proto::_</classname>>, mpl::next<<classname>proto::_state</classname>>()>, 453 proto::otherwise<<classname>proto::fold</classname><<classname>proto::_</classname>, <classname>proto::_state</classname>, CountLeaves> > 454 > 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< typename to_mpl_pair< When >::type... ></type> 478 </typedef> 479 <struct name="when"> 480 <template> 481 <template-type-parameter name="Grammar"/> 482 </template> 483 <inherit><type><classname>proto::otherwise</classname>< typename mpl::at< map_type, Grammar >::type ></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< some_grammar, proto::external_transform ></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><int> 499{}; 500 501struct char_terminal 502 : <classname>proto::terminal</classname><char> 503{}; 504 505struct my_grammar 506 : <classname>proto::or_</classname>< 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>< int_terminal, <classname>proto::external_transform</classname> > 511 , <classname>proto::when</classname>< char_terminal, <classname>proto::external_transform</classname> > 512 , <classname>proto::when</classname>< 513 <classname>proto::plus</classname>< my_grammar, my_grammar > 514 , <classname>proto::fold</classname>< <classname>proto::_</classname>, int(), my_grammar > 515 > 516 > 517{}; 518 519// Here is where the transforms are associated with the 520// grammar rules above. 521struct my_transforms 522 : proto::external_transforms< 523 <classname>proto::when</classname><int_terminal, print(<classname>proto::_value</classname>)> 524 , <classname>proto::when</classname><char_terminal, print(<classname>proto::_value</classname>)> 525 > 526{}; 527 528// ... 529 530<classname>proto::literal</classname><int> i(1); 531<classname>proto::literal</classname><char> 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