1 /*============================================================================= 2 Copyright (c) 2005-2010 Joel de Guzman 3 Copyright (c) 2010 Eric Niebler 4 Copyright (c) 2010 Thomas Heller 5 Copyright (c) 2014 John Fletcher 6 7 Distributed under the Boost Software License, Version 1.0. (See accompanying 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 ==============================================================================*/ 10 #ifndef BOOST_PHOENIX_CORE_ACTOR_HPP 11 #define BOOST_PHOENIX_CORE_ACTOR_HPP 12 13 #include <boost/phoenix/core/limits.hpp> 14 15 #include <boost/is_placeholder.hpp> 16 #include <boost/mpl/identity.hpp> 17 #include <boost/mpl/eval_if.hpp> 18 #include <boost/phoenix/core/domain.hpp> 19 #include <boost/phoenix/core/environment.hpp> 20 #include <boost/phoenix/core/is_nullary.hpp> 21 #include <boost/phoenix/core/meta_grammar.hpp> 22 #include <boost/phoenix/support/iterate.hpp> 23 #include <boost/phoenix/support/vector.hpp> 24 #include <boost/proto/extends.hpp> 25 #include <boost/proto/make_expr.hpp> 26 #include <boost/utility/result_of.hpp> 27 #include <boost/mpl/void.hpp> 28 #include <cstring> 29 #ifndef BOOST_PHOENIX_NO_VARIADIC_ACTOR 30 # include <boost/mpl/if.hpp> 31 # include <boost/type_traits/is_reference.hpp> 32 # include <boost/phoenix/core/detail/index_sequence.hpp> 33 #endif 34 35 #ifdef BOOST_MSVC 36 #pragma warning(push) 37 #pragma warning(disable: 4522) // 'this' used in base member initializer list 38 #pragma warning(disable: 4510) // default constructor could not be generated 39 #pragma warning(disable: 4610) // can never be instantiated - user defined cons 40 #endif 41 42 namespace boost { namespace phoenix 43 { 44 template <typename Expr> 45 struct actor; 46 47 namespace detail 48 { 49 struct error_expecting_arguments 50 { 51 template <typename T> error_expecting_argumentsboost::phoenix::detail::error_expecting_arguments52 error_expecting_arguments(T const&) {} 53 }; 54 55 struct error_invalid_lambda_expr 56 { 57 template <typename T> error_invalid_lambda_exprboost::phoenix::detail::error_invalid_lambda_expr58 error_invalid_lambda_expr(T const&) {} 59 }; 60 61 template <typename T> 62 struct result_type_deduction_helper 63 { 64 typedef T const & type; 65 }; 66 67 template <typename T> 68 struct result_type_deduction_helper<T &> 69 { 70 typedef T & type; 71 }; 72 73 template <typename T> 74 struct result_type_deduction_helper<T const &> 75 { 76 typedef T const & type; 77 }; 78 79 struct do_assign 80 { 81 BOOST_PROTO_CALLABLE() 82 83 typedef void result_type; 84 85 template <typename T1, typename T2> operator ()boost::phoenix::detail::do_assign86 void operator()(T1 & t1, T2 const & t2) const 87 { 88 proto::value(t1) = proto::value(t2); 89 } 90 }; 91 92 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR 93 #include <boost/phoenix/core/detail/cpp03/assign.hpp> 94 #else 95 struct assign : proto::transform<assign> 96 { 97 typedef assign proto_grammer; 98 99 template <typename Expr, typename State, typename Data 100 , typename Indices = typename detail::make_index_sequence<proto::arity_of<Expr>::value>::type > 101 struct impl; 102 103 template <std::size_t> 104 struct proto_expr { typedef proto::_ type; }; 105 106 template <std::size_t Index> 107 struct nth_assign 108 { 109 typedef 110 assign type( 111 proto::_child_c<Index> 112 , proto::call<proto::_child_c<Index>(proto::_state)> 113 ) 114 ; 115 }; 116 117 template <typename Expr, typename State, typename Data> 118 struct impl<Expr, State, Data, detail::index_sequence<> > 119 : proto::when< 120 proto::terminal<proto::_> 121 , do_assign(proto::_, proto::_state) 122 >::template impl<Expr, State, Data> 123 { 124 }; 125 126 template <typename Expr, typename State, typename Data 127 , std::size_t... Indices> 128 struct impl<Expr, State, Data, detail::index_sequence<Indices...> > 129 : proto::when< 130 proto::nary_expr<typename proto_expr<Indices>::type...> 131 , proto::and_<typename nth_assign<Indices>::type...> 132 >::template impl<Expr, State, Data> 133 { 134 }; 135 }; 136 #endif 137 } 138 139 namespace result_of 140 { 141 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR 142 // Bring in the result_of::actor<> 143 #include <boost/phoenix/core/detail/cpp03/actor_result_of.hpp> 144 #else 145 template <typename Expr, typename... A> 146 struct actor_impl 147 { 148 typedef 149 typename boost::phoenix::evaluator::impl< 150 Expr const& 151 , vector2< 152 typename vector_chooser<sizeof...(A) + 1>:: 153 template apply<const ::boost::phoenix::actor<Expr> *, A...>::type& 154 , default_actions 155 > const & 156 , proto::empty_env 157 >::result_type 158 type; 159 }; 160 161 template <typename Expr, typename... A> 162 struct actor : actor_impl<Expr, A...> {}; 163 164 template <typename Expr> 165 struct nullary_actor_result : actor_impl<Expr> {}; 166 #endif 167 168 template <typename Expr> 169 struct actor<Expr> 170 { 171 typedef 172 // avoid calling result_of::actor when this is false 173 typename mpl::eval_if_c< 174 result_of::is_nullary<Expr>::value 175 , nullary_actor_result<Expr> 176 , mpl::identity<detail::error_expecting_arguments> 177 >::type 178 type; 179 }; 180 } 181 182 //////////////////////////////////////////////////////////////////////////// 183 // 184 // actor 185 // 186 // The actor class. The main thing! In phoenix, everything is an actor 187 // This class is responsible for full function evaluation. Partial 188 // function evaluation involves creating a hierarchy of actor objects. 189 // 190 //////////////////////////////////////////////////////////////////////////// 191 template <typename Expr> 192 struct actor 193 { 194 typedef typename 195 mpl::eval_if_c< 196 mpl::or_< 197 is_custom_terminal<Expr> 198 , mpl::bool_<is_placeholder<Expr>::value> 199 >::value 200 , proto::terminal<Expr> 201 , mpl::identity<Expr> 202 >::type 203 expr_type; 204 BOOST_PROTO_BASIC_EXTENDSboost::phoenix::actor205 BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<expr_type>, phoenix_domain) 206 207 // providing operator= to be assignable 208 actor& operator=(actor const& other) 209 { 210 detail::assign()(*this, other); 211 return *this; 212 } operator =boost::phoenix::actor213 actor& operator=(actor & other) 214 { 215 detail::assign()(*this, other); 216 return *this; 217 } 218 219 template <typename A0> 220 typename proto::result_of::make_expr< 221 proto::tag::assign 222 , phoenix_domain 223 , proto_base_expr 224 , A0 225 >::type const operator =boost::phoenix::actor226 operator=(A0 const & a0) const 227 { 228 return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0); 229 } 230 231 template <typename A0> 232 typename proto::result_of::make_expr< 233 proto::tag::assign 234 , phoenix_domain 235 , proto_base_expr 236 , A0 237 >::type const operator =boost::phoenix::actor238 operator=(A0 & a0) const 239 { 240 return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0); 241 } 242 243 template <typename A0> 244 typename proto::result_of::make_expr< 245 proto::tag::subscript 246 , phoenix_domain 247 , proto_base_expr 248 , A0 249 >::type const operator []boost::phoenix::actor250 operator[](A0 const & a0) const 251 { 252 return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0); 253 } 254 255 template <typename A0> 256 typename proto::result_of::make_expr< 257 proto::tag::subscript 258 , phoenix_domain 259 , proto_base_expr 260 , A0 261 >::type const operator []boost::phoenix::actor262 operator[](A0 & a0) const 263 { 264 return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0); 265 } 266 267 template <typename Sig> 268 struct result; 269 270 typename result_of::actor<proto_base_expr>::type operator ()boost::phoenix::actor271 operator()() 272 { 273 typedef vector1<const actor<Expr> *> env_type; 274 env_type env = {this}; 275 276 return phoenix::eval(*this, phoenix::context(env, default_actions())); 277 } 278 279 typename result_of::actor<proto_base_expr>::type operator ()boost::phoenix::actor280 operator()() const 281 { 282 typedef vector1<const actor<Expr> *> env_type; 283 env_type env = {this}; 284 285 return phoenix::eval(*this, phoenix::context(env, default_actions())); 286 } 287 288 template <typename Env> 289 typename evaluator::impl< 290 proto_base_expr const & 291 , typename result_of::context< 292 Env const & 293 , default_actions const & 294 >::type 295 , proto::empty_env 296 >::result_type evalboost::phoenix::actor297 eval(Env const & env) const 298 { 299 return phoenix::eval(*this, phoenix::context(env, default_actions())); 300 } 301 302 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR 303 // Bring in the rest 304 #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp> 305 #else 306 template <typename This, typename... A> 307 struct result<This(A...)> 308 : result_of::actor< 309 proto_base_expr 310 , typename mpl::if_<is_reference<A>, A, A const &>::type... 311 > 312 {}; 313 314 template <typename... A> 315 typename result<actor(A...)>::type operator ()boost::phoenix::actor316 operator()(A &&... a) 317 { 318 typedef 319 typename vector_chooser<sizeof...(A) + 1>::template apply< 320 const actor<Expr> * 321 , typename mpl::if_<is_reference<A>, A, A const &>::type... 322 >::type 323 env_type; 324 325 env_type env = {this, a...}; 326 return phoenix::eval(*this, phoenix::context(env, default_actions())); 327 } 328 329 template <typename... A> 330 typename result<actor(A...)>::type operator ()boost::phoenix::actor331 operator()(A &&... a) const 332 { 333 typedef 334 typename vector_chooser<sizeof...(A) + 1>::template apply< 335 const actor<Expr> * 336 , typename mpl::if_<is_reference<A>, A, A const &>::type... 337 >::type 338 env_type; 339 340 env_type env = {this, a...}; 341 return phoenix::eval(*this, phoenix::context(env, default_actions())); 342 } 343 #endif 344 }; 345 }} 346 347 namespace boost 348 { 349 // specialize boost::result_of to return the proper result type 350 template <typename Expr> 351 struct result_of<phoenix::actor<Expr>()> 352 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> 353 {}; 354 355 template <typename Expr> 356 struct result_of<phoenix::actor<Expr> const()> 357 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr> 358 {}; 359 } 360 361 362 #ifdef BOOST_MSVC 363 #pragma warning(pop) 364 #endif 365 366 #endif 367 368