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
42namespace 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>
52 error_expecting_arguments(T const&) {}
53 };
54
55 struct error_invalid_lambda_expr
56 {
57 template <typename T>
58 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#if defined __clang__ && defined __has_warning
133# pragma clang diagnostic push
134# if __has_warning("-Wdeprecated-copy")
135# pragma clang diagnostic ignored "-Wdeprecated-copy"
136# endif
137#endif
138 template <typename Expr>
139 struct actor
140 {
141 typedef typename
142 mpl::eval_if_c<
143 mpl::or_<
144 is_custom_terminal<Expr>
145 , mpl::bool_<is_placeholder<Expr>::value>
146 >::value
147 , proto::terminal<Expr>
148 , mpl::identity<Expr>
149 >::type
150 expr_type;
151
152 BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<Expr>, phoenix_domain)
153 BOOST_PROTO_EXTENDS_SUBSCRIPT()
154 BOOST_PROTO_EXTENDS_ASSIGN_()
155
156 template <typename Sig>
157 struct result;
158
159 typename result_of::actor<proto_base_expr>::type
160 operator()()
161 {
162 typedef vector1<const actor<Expr> *> env_type;
163 env_type env = {this};
164
165 return phoenix::eval(*this, phoenix::context(env, default_actions()));
166 }
167
168 typename result_of::actor<proto_base_expr>::type
169 operator()() const
170 {
171 typedef vector1<const actor<Expr> *> env_type;
172 env_type env = {this};
173
174 return phoenix::eval(*this, phoenix::context(env, default_actions()));
175 }
176
177 template <typename Env>
178 typename evaluator::impl<
179 proto_base_expr const &
180 , typename result_of::context<
181 Env const &
182 , default_actions const &
183 >::type
184 , proto::empty_env
185 >::result_type
186 eval(Env const & env) const
187 {
188 return phoenix::eval(*this, phoenix::context(env, default_actions()));
189 }
190
191#ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
192 // Bring in the rest
193 #include <boost/phoenix/core/detail/cpp03/actor_operator.hpp>
194#else
195 template <typename This, typename... A>
196 struct result<This(A...)>
197 : result_of::actor<
198 proto_base_expr
199 , typename mpl::if_<is_reference<A>, A, A const &>::type...
200 >
201 {};
202
203 template <typename... A>
204 typename result<actor(A...)>::type
205 operator()(A &&... a)
206 {
207 typedef
208 typename vector_chooser<sizeof...(A) + 1>::template apply<
209 const actor<Expr> *
210 , typename mpl::if_<is_reference<A>, A, A const &>::type...
211 >::type
212 env_type;
213
214 env_type env = {this, a...};
215 return phoenix::eval(*this, phoenix::context(env, default_actions()));
216 }
217
218 template <typename... A>
219 typename result<actor(A...)>::type
220 operator()(A &&... a) const
221 {
222 typedef
223 typename vector_chooser<sizeof...(A) + 1>::template apply<
224 const actor<Expr> *
225 , typename mpl::if_<is_reference<A>, A, A const &>::type...
226 >::type
227 env_type;
228
229 env_type env = {this, a...};
230 return phoenix::eval(*this, phoenix::context(env, default_actions()));
231 }
232#endif
233
234 BOOST_DELETED_FUNCTION(actor& operator=(actor const&))
235 };
236#if defined __clang__ && defined __has_warning
237# pragma clang diagnostic pop
238#endif
239}}
240
241namespace boost
242{
243 // specialize boost::result_of to return the proper result type
244 template <typename Expr>
245 struct result_of<phoenix::actor<Expr>()>
246 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
247 {};
248
249 template <typename Expr>
250 struct result_of<phoenix::actor<Expr> const()>
251 : phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
252 {};
253}
254
255
256#ifdef BOOST_MSVC
257#pragma warning(pop)
258#endif
259
260#endif
261
262