Initial C++0x support.
[luabind.git] / luabind / detail / call.hpp
blob265a4370249ad3b8766aad032f3a87937fbf593f
1 // Copyright Daniel Wallin 2008. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 #if !BOOST_PP_IS_ITERATING
7 # ifndef LUABIND_CALL2_080911_HPP
8 # define LUABIND_CALL2_080911_HPP
10 # include <luabind/config.hpp>
12 # ifdef LUABIND_CPP0x
13 # include <luabind/detail/call_0x.hpp>
14 # else
16 # include <boost/mpl/apply_wrap.hpp>
17 # include <boost/mpl/begin_end.hpp>
18 # include <boost/mpl/deref.hpp>
19 # include <boost/mpl/front.hpp>
20 # include <boost/mpl/long.hpp>
21 # include <boost/mpl/size.hpp>
22 # include <boost/preprocessor/control/if.hpp>
23 # include <boost/preprocessor/iteration/iterate.hpp>
24 # include <boost/preprocessor/iteration/local.hpp>
25 # include <boost/preprocessor/repetition/enum.hpp>
26 # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
27 # include <boost/type_traits/is_void.hpp>
29 # include <luabind/detail/policy.hpp>
30 # include <luabind/yield_policy.hpp>
32 namespace luabind { namespace detail {
34 struct invoke_context;
36 struct LUABIND_API function_object
38 function_object(lua_CFunction entry)
39 : entry(entry)
40 , next(0)
43 virtual ~function_object()
46 virtual int call(
47 lua_State* L, invoke_context& ctx) const = 0;
48 virtual void format_signature(lua_State* L, char const* function) const = 0;
50 lua_CFunction entry;
51 std::string name;
52 function_object* next;
53 object keepalive;
56 struct LUABIND_API invoke_context
58 invoke_context()
59 : best_score((std::numeric_limits<int>::max)())
60 , candidate_index(0)
63 operator bool() const
65 return candidate_index == 1;
68 void format_error(lua_State* L, function_object const* overloads) const;
70 int best_score;
71 function_object const* candidates[10];
72 int candidate_index;
75 template <class F, class Signature, class Policies, class IsVoid>
76 inline int invoke0(
77 lua_State* L, function_object const& self, invoke_context& ctx
78 , F const& f, Signature, Policies const& policies, IsVoid, mpl::true_)
80 return invoke_member(
81 L, self, ctx, f, Signature(), policies
82 , mpl::long_<mpl::size<Signature>::value - 1>(), IsVoid()
86 template <class F, class Signature, class Policies, class IsVoid>
87 inline int invoke0(
88 lua_State* L, function_object const& self, invoke_context& ctx,
89 F const& f, Signature, Policies const& policies, IsVoid, mpl::false_)
91 return invoke_normal(
92 L, self, ctx, f, Signature(), policies
93 , mpl::long_<mpl::size<Signature>::value - 1>(), IsVoid()
97 template <class F, class Signature, class Policies>
98 inline int invoke(
99 lua_State* L, function_object const& self, invoke_context& ctx
100 , F const& f, Signature, Policies const& policies)
102 return invoke0(
103 L, self, ctx, f, Signature(), policies
104 , boost::is_void<typename mpl::front<Signature>::type>()
105 , boost::is_member_function_pointer<F>()
109 inline int maybe_yield_aux(lua_State*, int results, mpl::false_)
111 return results;
114 inline int maybe_yield_aux(lua_State* L, int results, mpl::true_)
116 return lua_yield(L, results);
119 template <class Policies>
120 int maybe_yield(lua_State* L, int results, Policies*)
122 return maybe_yield_aux(
123 L, results, has_policy<Policies, yield_policy>());
126 inline int sum_scores(int const* first, int const* last)
128 int result = 0;
130 for (; first != last; ++first)
132 if (*first < 0)
133 return *first;
134 result += *first;
137 return result;
140 # define LUABIND_INVOKE_NEXT_ITER(n) \
141 typename mpl::next< \
142 BOOST_PP_IF( \
143 n, BOOST_PP_CAT(iter,BOOST_PP_DEC(n)), first) \
144 >::type
146 # define LUABIND_INVOKE_NEXT_INDEX(n) \
147 BOOST_PP_IF( \
149 , BOOST_PP_CAT(index,BOOST_PP_DEC(n)) + \
150 BOOST_PP_CAT(c,BOOST_PP_DEC(n)).consumed_args() \
151 , 1 \
154 # define LUABIND_INVOKE_COMPUTE_ARITY(n) + BOOST_PP_CAT(c,n).consumed_args()
156 # define LUABIND_INVOKE_DECLARE_CONVERTER(n) \
157 typedef LUABIND_INVOKE_NEXT_ITER(n) BOOST_PP_CAT(iter,n); \
158 typedef typename mpl::deref<BOOST_PP_CAT(iter,n)>::type \
159 BOOST_PP_CAT(a,n); \
160 typedef typename find_conversion_policy<n + 1, Policies>::type \
161 BOOST_PP_CAT(p,n); \
162 typename mpl::apply_wrap2< \
163 BOOST_PP_CAT(p,n), BOOST_PP_CAT(a,n), lua_to_cpp>::type BOOST_PP_CAT(c,n); \
164 int const BOOST_PP_CAT(index,n) = LUABIND_INVOKE_NEXT_INDEX(n);
166 # define LUABIND_INVOKE_COMPUTE_SCORE(n) \
167 , BOOST_PP_CAT(c,n).match( \
168 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n))
170 # define LUABIND_INVOKE_ARG(z, n, base) \
171 BOOST_PP_CAT(c,base(n)).apply( \
172 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,base(n))), BOOST_PP_CAT(index,base(n)))
174 # define LUABIND_INVOKE_CONVERTER_POSTCALL(n) \
175 BOOST_PP_CAT(c,n).converter_postcall( \
176 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n));
178 # define BOOST_PP_ITERATION_PARAMS_1 \
179 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
180 # include BOOST_PP_ITERATE()
182 # define LUABIND_INVOKE_VOID
183 # define BOOST_PP_ITERATION_PARAMS_1 \
184 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
185 # include BOOST_PP_ITERATE()
187 # undef LUABIND_INVOKE_VOID
188 # define LUABIND_INVOKE_MEMBER
189 # define BOOST_PP_ITERATION_PARAMS_1 \
190 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
191 # include BOOST_PP_ITERATE()
193 # define LUABIND_INVOKE_VOID
194 # define BOOST_PP_ITERATION_PARAMS_1 \
195 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
196 # include BOOST_PP_ITERATE()
198 }} // namespace luabind::detail
200 # endif // LUABIND_CPP0x
202 # endif // LUABIND_CALL2_080911_HPP
204 #else // BOOST_PP_IS_ITERATING
206 # ifdef LUABIND_INVOKE_MEMBER
207 # define N BOOST_PP_INC(BOOST_PP_ITERATION())
208 # else
209 # define N BOOST_PP_ITERATION()
210 # endif
212 template <class F, class Signature, class Policies>
213 inline int
214 # ifdef LUABIND_INVOKE_MEMBER
215 invoke_member
216 # else
217 invoke_normal
218 # endif
220 lua_State* L, function_object const& self, invoke_context& ctx
221 , F const& f, Signature, Policies const&, mpl::long_<N>
222 # ifdef LUABIND_INVOKE_VOID
223 , mpl::true_
224 # else
225 , mpl::false_
226 # endif
229 typedef typename mpl::begin<Signature>::type first;
230 # ifndef LUABIND_INVOKE_VOID
231 typedef typename mpl::deref<first>::type result_type;
232 typedef typename find_conversion_policy<0, Policies>::type result_policy;
233 typename mpl::apply_wrap2<
234 result_policy, result_type, cpp_to_lua>::type result_converter;
235 # endif
237 # if N > 0
238 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_DECLARE_CONVERTER(n)
239 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
240 # include BOOST_PP_LOCAL_ITERATE()
241 # endif
243 int const arity = 0
244 # if N > 0
245 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_ARITY(n)
246 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
247 # include BOOST_PP_LOCAL_ITERATE()
248 # endif
251 int const arguments = lua_gettop(L);
253 int score = -1;
255 if (arity == arguments)
257 int const scores[] = {
259 # if N > 0
260 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_SCORE(n)
261 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
262 # include BOOST_PP_LOCAL_ITERATE()
263 # endif
266 score = sum_scores(scores + 1, scores + 1 + N);
269 if (score >= 0 && score < ctx.best_score)
271 ctx.best_score = score;
272 ctx.candidates[0] = &self;
273 ctx.candidate_index = 1;
275 else if (score == ctx.best_score)
277 ctx.candidates[ctx.candidate_index++] = &self;
280 int results = 0;
282 if (self.next)
284 results = self.next->call(L, ctx);
287 if (score == ctx.best_score && ctx.candidate_index == 1)
289 # ifndef LUABIND_INVOKE_VOID
290 result_converter.apply(
292 # endif
293 # ifdef LUABIND_INVOKE_MEMBER
294 (c0.apply(L, LUABIND_DECORATE_TYPE(a0), index0).*f)(
295 BOOST_PP_ENUM(BOOST_PP_DEC(N), LUABIND_INVOKE_ARG, BOOST_PP_INC)
297 # else
298 # define LUABIND_INVOKE_IDENTITY(x) x
300 BOOST_PP_ENUM(N, LUABIND_INVOKE_ARG, LUABIND_INVOKE_IDENTITY)
302 # undef LUABIND_INVOKE_IDENTITY
303 # endif
304 # ifndef LUABIND_INVOKE_VOID
306 # endif
309 # if N > 0
310 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_CONVERTER_POSTCALL(n)
311 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
312 # include BOOST_PP_LOCAL_ITERATE()
313 # endif
315 results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0);
317 int const indices[] = {
318 arguments + results BOOST_PP_ENUM_TRAILING_PARAMS(N, index)
321 policy_list_postcall<Policies>::apply(L, indices);
324 return results;
327 # undef N
329 #endif