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 
80     namespace result_of
81     {
82 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
83         // Bring in the result_of::actor<>
84         #include <boost/phoenix/core/detail/cpp03/actor_result_of.hpp>
85 #else
86         template <typename Expr, typename... A>
87         struct actor_impl
88         {
89             typedef
90                 typename boost::phoenix::evaluator::impl<
91                     Expr const&
92                   , vector2<
93                         typename vector_chooser<sizeof...(A) + 1>::
94                           template apply<const ::boost::phoenix::actor<Expr> *, A...>::type&
95                       , default_actions
96                     > const &
97                   , proto::empty_env
98                 >::result_type
99                 type;
100         };
101 
102         template <typename Expr, typename... A>
103         struct actor : actor_impl<Expr, A...> {};
104 
105         template <typename Expr>
106         struct nullary_actor_result : actor_impl<Expr> {};
107 #endif
108 
109         template <typename Expr>
110         struct actor<Expr>
111         {
112             typedef
113                 // avoid calling result_of::actor when this is false
114                 typename mpl::eval_if_c<
115                     result_of::is_nullary<Expr>::value
116                   , nullary_actor_result<Expr>
117                   , mpl::identity<detail::error_expecting_arguments>
118                 >::type
119             type;
120         };
121     }
122 
123     ////////////////////////////////////////////////////////////////////////////
124     //
125     //  actor
126     //
127     //      The actor class. The main thing! In phoenix, everything is an actor
128     //      This class is responsible for full function evaluation. Partial
129     //      function evaluation involves creating a hierarchy of actor objects.
130     //
131     ////////////////////////////////////////////////////////////////////////////
132     template <typename Expr>
133     struct actor
134     {
135         typedef typename
136             mpl::eval_if_c<
137                 mpl::or_<
138                     is_custom_terminal<Expr>
139                   , mpl::bool_<is_placeholder<Expr>::value>
140                 >::value
141               , proto::terminal<Expr>
142               , mpl::identity<Expr>
143             >::type
144             expr_type;
145 
146         BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<Expr>, phoenix_domain)
147         BOOST_PROTO_EXTENDS_SUBSCRIPT()
148         BOOST_PROTO_EXTENDS_ASSIGN_()
149 
150         template <typename Sig>
151         struct result;
152 
153         typename result_of::actor<proto_base_expr>::type
operator ()boost::phoenix::actor154         operator()()
155         {
156             typedef vector1<const actor<Expr> *> env_type;
157             env_type env = {this};
158 
159             return phoenix::eval(*this, phoenix::context(env, default_actions()));
160         }
161 
162         typename result_of::actor<proto_base_expr>::type
operator ()boost::phoenix::actor163         operator()() const
164         {
165             typedef vector1<const actor<Expr> *> env_type;
166             env_type env = {this};
167 
168             return phoenix::eval(*this, phoenix::context(env, default_actions()));
169         }
170 
171         template <typename Env>
172         typename evaluator::impl<
173             proto_base_expr const &
174           , typename result_of::context<
175                 Env const &
176               , default_actions const &
177             >::type
178           , proto::empty_env
179         >::result_type
evalboost::phoenix::actor180         eval(Env const & env) const
181         {
182             return phoenix::eval(*this, phoenix::context(env, default_actions()));
183         }
184 
185 #ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
186         // Bring in the rest
187         #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp>
188 #else
189         template <typename This, typename... A>
190         struct result<This(A...)>
191             : result_of::actor<
192                 proto_base_expr
193               , typename mpl::if_<is_reference<A>, A, A const &>::type...
194             >
195         {};
196 
197         template <typename... A>
198         typename result<actor(A...)>::type
operator ()boost::phoenix::actor199         operator()(A &&... a)
200         {
201             typedef
202                 typename vector_chooser<sizeof...(A) + 1>::template apply<
203                     const actor<Expr> *
204                   , typename mpl::if_<is_reference<A>, A, A const &>::type...
205                 >::type
206             env_type;
207 
208             env_type env = {this, a...};
209             return phoenix::eval(*this, phoenix::context(env, default_actions()));
210         }
211 
212         template <typename... A>
213         typename result<actor(A...)>::type
operator ()boost::phoenix::actor214         operator()(A &&... a) const
215         {
216             typedef
217                 typename vector_chooser<sizeof...(A) + 1>::template apply<
218                     const actor<Expr> *
219                   , typename mpl::if_<is_reference<A>, A, A const &>::type...
220                 >::type
221             env_type;
222 
223             env_type env = {this, a...};
224             return phoenix::eval(*this, phoenix::context(env, default_actions()));
225         }
226 #endif
227 
228         BOOST_DELETED_FUNCTION(actor& operator=(actor const&))
229     };
230 }}
231 
232 namespace boost
233 {
234     // specialize boost::result_of to return the proper result type
235     template <typename Expr>
236     struct result_of<phoenix::actor<Expr>()>
237         : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
238     {};
239 
240     template <typename Expr>
241     struct result_of<phoenix::actor<Expr> const()>
242         : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
243     {};
244 }
245 
246 
247 #ifdef BOOST_MSVC
248 #pragma warning(pop)
249 #endif
250 
251 #endif
252 
253