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>
13 # include <luabind/detail/call_0x.hpp>
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
)
43 virtual ~function_object()
47 lua_State
* L
, invoke_context
& ctx
) const = 0;
48 virtual void format_signature(lua_State
* L
, char const* function
) const = 0;
52 function_object
* next
;
56 struct LUABIND_API invoke_context
59 : best_score((std::numeric_limits
<int>::max
)())
65 return candidate_index
== 1;
68 void format_error(lua_State
* L
, function_object
const* overloads
) const;
71 function_object
const* candidates
[10];
75 template <class F
, class Signature
, class Policies
, class IsVoid
>
77 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
78 , F
const& f
, Signature
, Policies
const& policies
, IsVoid
, mpl::true_
)
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
>
88 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
,
89 F
const& f
, Signature
, Policies
const& policies
, IsVoid
, mpl::false_
)
92 L
, self
, ctx
, f
, Signature(), policies
93 , mpl::long_
<mpl::size
<Signature
>::value
- 1>(), IsVoid()
97 template <class F
, class Signature
, class Policies
>
99 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
100 , F
const& f
, Signature
, Policies
const& policies
)
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_
)
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
)
130 for (; first
!= last
; ++first
)
140 # define LUABIND_INVOKE_NEXT_ITER(n) \
141 typename mpl::next< \
143 n, BOOST_PP_CAT(iter,BOOST_PP_DEC(n)), first) \
146 # define LUABIND_INVOKE_NEXT_INDEX(n) \
149 , BOOST_PP_CAT(index,BOOST_PP_DEC(n)) + \
150 BOOST_PP_CAT(c,BOOST_PP_DEC(n)).consumed_args() \
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 \
160 typedef typename find_conversion_policy<n + 1, Policies>::type \
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())
209 # define N BOOST_PP_ITERATION()
212 template <class F
, class Signature
, class Policies
>
214 # ifdef LUABIND_INVOKE_MEMBER
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
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
;
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()
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()
251 int const arguments
= lua_gettop(L
);
255 if (arity
== arguments
)
257 int const scores
[] = {
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()
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
;
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(
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
)
298 # define LUABIND_INVOKE_IDENTITY(x) x
300 BOOST_PP_ENUM(N
, LUABIND_INVOKE_ARG
, LUABIND_INVOKE_IDENTITY
)
302 # undef LUABIND_INVOKE_IDENTITY
304 # ifndef LUABIND_INVOKE_VOID
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()
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
);