1 /*============================================================================== 2 Copyright (c) 2005-2010 Joel de Guzman 3 Copyright (c) 2010-2011 Thomas Heller 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_CORE_ENVIRONMENT_HPP 9 #define BOOST_PHOENIX_CORE_ENVIRONMENT_HPP 10 11 #include <boost/phoenix/core/limits.hpp> 12 #include <boost/fusion/sequence/intrinsic/at.hpp> 13 #include <boost/fusion/support/is_sequence.hpp> 14 #include <boost/phoenix/support/vector.hpp> 15 #include <boost/proto/transform/impl.hpp> 16 #include <boost/utility/enable_if.hpp> 17 #include <boost/utility/result_of.hpp> 18 19 #include <typeinfo> 20 21 namespace boost { namespace phoenix 22 { 23 struct unused {}; 24 25 namespace result_of 26 { 27 template <typename Env, typename Actions> 28 struct context 29 { 30 typedef vector2<Env, Actions> type; 31 }; 32 33 template <typename Env, typename Actions> 34 struct make_context 35 : context<Env, Actions> 36 {}; 37 38 template <typename Context> 39 struct env 40 { 41 typedef 42 typename fusion::result_of::at_c< 43 typename boost::remove_reference<Context>::type 44 , 0 45 >::type 46 type; 47 }; 48 49 template <typename Context> 50 struct actions 51 { 52 typedef 53 typename fusion::result_of::at_c< 54 typename boost::remove_reference<Context>::type 55 , 1 56 >::type 57 type; 58 }; 59 } 60 61 namespace functional 62 { 63 struct context 64 { 65 BOOST_PROTO_CALLABLE() 66 67 template <typename Sig> 68 struct result; 69 70 template <typename This, typename Env, typename Actions> 71 struct result<This(Env, Actions)> 72 : result<This(Env const &, Actions const &)> 73 {}; 74 75 template <typename This, typename Env, typename Actions> 76 struct result<This(Env &, Actions)> 77 : result<This(Env &, Actions const &)> 78 {}; 79 80 template <typename This, typename Env, typename Actions> 81 struct result<This(Env, Actions &)> 82 : result<This(Env const &, Actions &)> 83 {}; 84 85 template <typename This, typename Env, typename Actions> 86 struct result<This(Env &, Actions &)> 87 : result_of::context<Env &, Actions &> 88 {}; 89 90 template <typename Env, typename Actions> 91 typename result_of::context<Env &, Actions &>::type operator ()boost::phoenix::functional::context92 operator()(Env & env, Actions & actions) const 93 { 94 vector2<Env &, Actions &> e = {env, actions}; 95 return e; 96 } 97 98 template <typename Env, typename Actions> 99 typename result_of::context<Env const &, Actions &>::type operator ()boost::phoenix::functional::context100 operator()(Env const & env, Actions & actions) const 101 { 102 vector2<Env const &, Actions &> e = {env, actions}; 103 return e; 104 } 105 106 template <typename Env, typename Actions> 107 typename result_of::context<Env &, Actions const &>::type operator ()boost::phoenix::functional::context108 operator()(Env & env, Actions const & actions) const 109 { 110 vector2<Env &, Actions const &> e = {env, actions}; 111 return e; 112 } 113 114 template <typename Env, typename Actions> 115 typename result_of::context<Env const &, Actions const &>::type operator ()boost::phoenix::functional::context116 operator()(Env const & env, Actions const & actions) const 117 { 118 vector2<Env const&, Actions const &> e = {env, actions}; 119 return e; 120 } 121 }; 122 123 struct make_context 124 : context 125 {}; 126 127 struct env 128 { 129 BOOST_PROTO_CALLABLE() 130 131 template <typename Sig> 132 struct result; 133 134 template <typename This, typename Context> 135 struct result<This(Context)> 136 : result<This(Context const &)> 137 {}; 138 139 template <typename This, typename Context> 140 struct result<This(Context &)> 141 : result_of::env<Context> 142 {}; 143 144 template <typename Context> 145 typename result_of::env<Context const>::type operator ()boost::phoenix::functional::env146 operator()(Context const & ctx) const 147 { 148 return fusion::at_c<0>(ctx); 149 } 150 151 template <typename Context> 152 typename result_of::env<Context>::type operator ()boost::phoenix::functional::env153 operator()(Context & ctx) const 154 { 155 return fusion::at_c<0>(ctx); 156 } 157 }; 158 159 struct actions 160 { 161 BOOST_PROTO_CALLABLE() 162 163 template <typename Sig> 164 struct result; 165 166 template <typename This, typename Context> 167 struct result<This(Context)> 168 : result<This(Context const &)> 169 {}; 170 171 template <typename This, typename Context> 172 struct result<This(Context &)> 173 : result_of::actions<Context> 174 {}; 175 176 template <typename Context> 177 typename result_of::actions<Context const>::type operator ()boost::phoenix::functional::actions178 operator()(Context const & ctx) const 179 { 180 return fusion::at_c<1>(ctx); 181 } 182 183 template <typename Context> 184 typename result_of::actions<Context>::type operator ()boost::phoenix::functional::actions185 operator()(Context & ctx) const 186 { 187 return fusion::at_c<1>(ctx); 188 } 189 }; 190 191 } 192 193 struct _context 194 : proto::transform<_context> 195 { 196 template <typename Expr, typename State, typename Data> 197 struct impl 198 : proto::transform_impl<Expr, State, Data> 199 { 200 typedef vector2<State, Data> result_type; 201 operator ()boost::phoenix::_context::impl202 result_type operator()( 203 typename impl::expr_param 204 , typename impl::state_param s 205 , typename impl::data_param d 206 ) const 207 { 208 vector2<State, Data> e = {s, d}; 209 return e; 210 } 211 }; 212 }; 213 214 template <typename Env, typename Actions> 215 inline 216 typename result_of::context<Env const &, Actions const&>::type const context(Env const & env,Actions const & actions)217 context(Env const& env, Actions const& actions) 218 { 219 vector2<Env const&, Actions const &> e = {env, actions}; 220 return e; 221 } 222 223 template <typename Env, typename Actions> 224 inline 225 typename result_of::context<Env const &, Actions const&>::type const make_context(Env const & env,Actions const & actions)226 make_context(Env const& env, Actions const& actions) 227 { 228 return context(env, actions); 229 } 230 231 template <typename Env, typename Actions> 232 inline 233 typename result_of::context<Env &, Actions const&>::type const context(Env & env,Actions const & actions)234 context(Env & env, Actions const& actions) 235 { 236 vector2<Env &, Actions const &> e = {env, actions}; 237 return e; 238 } 239 240 template <typename Env, typename Actions> 241 inline 242 typename result_of::context<Env &, Actions const&>::type const make_context(Env & env,Actions const & actions)243 make_context(Env & env, Actions const& actions) 244 { 245 return context(env, actions); 246 } 247 248 template <typename Env, typename Actions> 249 inline 250 typename result_of::context<Env const &, Actions &>::type const context(Env const & env,Actions & actions)251 context(Env const& env, Actions & actions) 252 { 253 vector2<Env const&, Actions &> e = {env, actions}; 254 return e; 255 } 256 257 template <typename Env, typename Actions> 258 inline 259 typename result_of::context<Env const &, Actions &>::type const make_context(Env const & env,Actions & actions)260 make_context(Env const& env, Actions & actions) 261 { 262 return context(env, actions); 263 } 264 265 template <typename Env, typename Actions> 266 inline 267 typename result_of::context<Env &, Actions &>::type const context(Env & env,Actions & actions)268 context(Env & env, Actions & actions) 269 { 270 vector2<Env &, Actions &> e = {env, actions}; 271 return e; 272 } 273 274 template <typename Env, typename Actions> 275 inline 276 typename result_of::context<Env &, Actions &>::type const make_context(Env & env,Actions & actions)277 make_context(Env & env, Actions & actions) 278 { 279 return context(env, actions); 280 } 281 282 struct _env 283 : proto::transform<_env> 284 { 285 template <typename Expr, typename State, typename Data> 286 struct impl 287 : proto::transform_impl<Expr, State, Data> 288 { 289 typedef State result_type; 290 operator ()boost::phoenix::_env::impl291 result_type operator()( 292 typename impl::expr_param 293 , typename impl::state_param s 294 , typename impl::data_param 295 ) const 296 { 297 return s; 298 } 299 }; 300 }; 301 302 template <typename Expr, typename State> 303 struct _env::impl<Expr, State, proto::empty_env> 304 : proto::transform_impl<Expr, State, proto::empty_env> 305 { 306 typedef 307 typename fusion::result_of::at_c< 308 typename boost::remove_reference<State>::type 309 , 0 310 >::type 311 result_type; 312 operator ()boost::phoenix::_env::impl313 result_type operator()( 314 typename impl::expr_param 315 , typename impl::state_param s 316 , typename impl::data_param 317 ) const 318 { 319 return fusion::at_c<0>(s); 320 } 321 }; 322 323 template <typename Expr, typename State> 324 struct _env::impl<Expr, State, unused> 325 : _env::impl<Expr, State, proto::empty_env> 326 {}; 327 328 template <typename Context> 329 inline 330 typename fusion::result_of::at_c<Context, 0>::type env(Context & ctx)331 env(Context & ctx) 332 { 333 return fusion::at_c<0>(ctx); 334 } 335 336 template <typename Context> 337 inline 338 typename fusion::result_of::at_c<Context const, 0>::type env(Context const & ctx)339 env(Context const & ctx) 340 { 341 return fusion::at_c<0>(ctx); 342 } 343 344 struct _actions 345 : proto::transform<_actions> 346 { 347 template <typename Expr, typename State, typename Data> 348 struct impl 349 : proto::transform_impl<Expr, State, Data> 350 { 351 typedef Data result_type; 352 operator ()boost::phoenix::_actions::impl353 result_type operator()( 354 typename impl::expr_param 355 , typename impl::state_param 356 , typename impl::data_param d 357 ) const 358 { 359 return d; 360 } 361 }; 362 }; 363 364 template <typename Expr, typename State> 365 struct _actions::impl<Expr, State, proto::empty_env> 366 : proto::transform_impl<Expr, State, proto::empty_env> 367 { 368 typedef 369 typename fusion::result_of::at_c< 370 typename boost::remove_reference<State>::type 371 , 1 372 >::type 373 result_type; 374 operator ()boost::phoenix::_actions::impl375 result_type operator()( 376 typename impl::expr_param 377 , typename impl::state_param s 378 , typename impl::data_param 379 ) const 380 { 381 return fusion::at_c<1>(s); 382 } 383 }; 384 385 template <typename Expr, typename State> 386 struct _actions::impl<Expr, State, unused> 387 : _actions::impl<Expr, State, proto::empty_env> 388 {}; 389 390 template <typename Context> 391 inline 392 typename fusion::result_of::at_c<Context, 1>::type actions(Context & ctx)393 actions(Context & ctx) 394 { 395 return fusion::at_c<1>(ctx); 396 } 397 398 template <typename Context> 399 inline 400 typename fusion::result_of::at_c<Context const, 1>::type actions(Context const & ctx)401 actions(Context const & ctx) 402 { 403 return fusion::at_c<1>(ctx); 404 } 405 406 namespace result_of 407 { 408 template < 409 BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( 410 BOOST_PHOENIX_LIMIT 411 , typename A 412 , mpl::void_ 413 ) 414 , typename Dummy = void 415 > 416 struct make_env; 417 418 #define M0(Z, N, D) \ 419 template <BOOST_PHOENIX_typename_A(N)> \ 420 struct make_env<BOOST_PHOENIX_A(N)> \ 421 { \ 422 typedef BOOST_PP_CAT(vector, N)<BOOST_PHOENIX_A(N)> type; \ 423 }; \ 424 /**/ 425 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _) 426 #undef M0 427 } 428 429 inline 430 result_of::make_env<>::type make_env()431 make_env() 432 { 433 return result_of::make_env<>::type(); 434 } 435 #define M0(Z, N, D) \ 436 template <BOOST_PHOENIX_typename_A(N)> \ 437 inline \ 438 typename result_of::make_env<BOOST_PHOENIX_A_ref(N)>::type \ 439 make_env(BOOST_PHOENIX_A_ref_a(N)) \ 440 { \ 441 typename result_of::make_env<BOOST_PHOENIX_A_ref(N)>::type \ 442 env = \ 443 { \ 444 BOOST_PHOENIX_a(N) \ 445 }; \ 446 return env; \ 447 } \ 448 template <BOOST_PHOENIX_typename_A(N)> \ 449 inline \ 450 typename result_of::make_env<BOOST_PHOENIX_A_const_ref(N)>::type \ 451 make_env(BOOST_PHOENIX_A_const_ref_a(N)) \ 452 { \ 453 typename result_of::make_env<BOOST_PHOENIX_A_const_ref(N)>::type \ 454 env = \ 455 { \ 456 BOOST_PHOENIX_a(N) \ 457 }; \ 458 return env; \ 459 } \ 460 /**/ 461 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _) 462 #undef M0 463 464 template <typename T, typename Enable = void> 465 struct is_environment : fusion::traits::is_sequence<T> {}; 466 }} 467 468 #endif 469 470