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 <boost/mpl/apply_wrap.hpp>
11 # include <boost/mpl/begin_end.hpp>
12 # include <boost/mpl/deref.hpp>
13 # include <boost/mpl/front.hpp>
14 # include <boost/mpl/long.hpp>
15 # include <boost/mpl/size.hpp>
16 # include <boost/preprocessor/control/if.hpp>
17 # include <boost/preprocessor/iteration/iterate.hpp>
18 # include <boost/preprocessor/iteration/local.hpp>
19 # include <boost/preprocessor/repetition/enum.hpp>
20 # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
21 # include <boost/type_traits/is_void.hpp>
23 # include <luabind/config.hpp>
24 # include <luabind/detail/policy.hpp>
25 # include <luabind/yield_policy.hpp>
27 namespace luabind
{ namespace detail
{
29 struct invoke_context
;
31 struct LUABIND_API function_object
33 function_object(lua_CFunction entry
)
38 virtual ~function_object()
42 lua_State
* L
, invoke_context
& ctx
) const = 0;
43 virtual void format_signature(lua_State
* L
, char const* function
) const = 0;
47 function_object
* next
;
51 struct LUABIND_API invoke_context
54 : best_score((std::numeric_limits
<int>::max
)())
60 return candidate_index
== 1;
63 void format_error(lua_State
* L
, function_object
const* overloads
) const;
66 function_object
const* candidates
[10];
70 template <class F
, class Signature
, class Policies
, class IsVoid
>
72 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
73 , F
const& f
, Signature
, Policies
const& policies
, IsVoid
, mpl::true_
)
76 L
, self
, ctx
, f
, Signature(), policies
77 , mpl::long_
<mpl::size
<Signature
>::value
- 1>(), IsVoid()
81 template <class F
, class Signature
, class Policies
, class IsVoid
>
83 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
,
84 F
const& f
, Signature
, Policies
const& policies
, IsVoid
, mpl::false_
)
87 L
, self
, ctx
, f
, Signature(), policies
88 , mpl::long_
<mpl::size
<Signature
>::value
- 1>(), IsVoid()
92 template <class F
, class Signature
, class Policies
>
94 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
95 , F
const& f
, Signature
, Policies
const& policies
)
98 L
, self
, ctx
, f
, Signature(), policies
99 , boost::is_void
<typename
mpl::front
<Signature
>::type
>()
100 , boost::is_member_function_pointer
<F
>()
104 inline int maybe_yield_aux(lua_State
*, int results
, mpl::false_
)
109 inline int maybe_yield_aux(lua_State
* L
, int results
, mpl::true_
)
111 return lua_yield(L
, results
);
114 template <class Policies
>
115 int maybe_yield(lua_State
* L
, int results
, Policies
*)
117 return maybe_yield_aux(
118 L
, results
, mpl::bool_
<has_yield
<Policies
>::value
>());
121 inline int sum_scores(int const* first
, int const* last
)
125 for (; first
!= last
; ++first
)
135 # define LUABIND_INVOKE_NEXT_ITER(n) \
136 typename mpl::next< \
138 n, BOOST_PP_CAT(iter,BOOST_PP_DEC(n)), first) \
141 # define LUABIND_INVOKE_NEXT_INDEX(n) \
144 , BOOST_PP_CAT(index,BOOST_PP_DEC(n)) + \
145 BOOST_PP_CAT(c,BOOST_PP_DEC(n)).consumed_args() \
149 # define LUABIND_INVOKE_COMPUTE_ARITY(n) + BOOST_PP_CAT(c,n).consumed_args()
151 # define LUABIND_INVOKE_DECLARE_CONVERTER(n) \
152 typedef LUABIND_INVOKE_NEXT_ITER(n) BOOST_PP_CAT(iter,n); \
153 typedef typename mpl::deref<BOOST_PP_CAT(iter,n)>::type \
155 typedef typename find_conversion_policy<n + 1, Policies>::type \
157 typename mpl::apply_wrap2< \
158 BOOST_PP_CAT(p,n), BOOST_PP_CAT(a,n), lua_to_cpp>::type BOOST_PP_CAT(c,n); \
159 int const BOOST_PP_CAT(index,n) = LUABIND_INVOKE_NEXT_INDEX(n);
161 # define LUABIND_INVOKE_COMPUTE_SCORE(n) \
162 , BOOST_PP_CAT(c,n).match( \
163 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n))
165 # define LUABIND_INVOKE_ARG(z, n, base) \
166 BOOST_PP_CAT(c,base(n)).apply( \
167 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,base(n))), BOOST_PP_CAT(index,base(n)))
169 # define LUABIND_INVOKE_CONVERTER_POSTCALL(n) \
170 BOOST_PP_CAT(c,n).converter_postcall( \
171 L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n));
173 # define BOOST_PP_ITERATION_PARAMS_1 \
174 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
175 # include BOOST_PP_ITERATE()
177 # define LUABIND_INVOKE_VOID
178 # define BOOST_PP_ITERATION_PARAMS_1 \
179 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
180 # include BOOST_PP_ITERATE()
182 # undef LUABIND_INVOKE_VOID
183 # define LUABIND_INVOKE_MEMBER
184 # define BOOST_PP_ITERATION_PARAMS_1 \
185 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
186 # include BOOST_PP_ITERATE()
188 # define LUABIND_INVOKE_VOID
189 # define BOOST_PP_ITERATION_PARAMS_1 \
190 (3, (0, LUABIND_MAX_ARITY, <luabind/detail/call.hpp>))
191 # include BOOST_PP_ITERATE()
193 }} // namespace luabind::detail
195 # endif // LUABIND_CALL2_080911_HPP
197 #else // BOOST_PP_IS_ITERATING
199 # ifdef LUABIND_INVOKE_MEMBER
200 # define N BOOST_PP_INC(BOOST_PP_ITERATION())
202 # define N BOOST_PP_ITERATION()
205 template <class F
, class Signature
, class Policies
>
207 # ifdef LUABIND_INVOKE_MEMBER
213 lua_State
* L
, function_object
const& self
, invoke_context
& ctx
214 , F
const& f
, Signature
, Policies
const&, mpl::long_
<N
>
215 # ifdef LUABIND_INVOKE_VOID
222 typedef typename
mpl::begin
<Signature
>::type first
;
223 # ifndef LUABIND_INVOKE_VOID
224 typedef typename
mpl::deref
<first
>::type result_type
;
225 typedef typename find_conversion_policy
<0, Policies
>::type result_policy
;
226 typename
mpl::apply_wrap2
<
227 result_policy
, result_type
, cpp_to_lua
>::type result_converter
;
231 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_DECLARE_CONVERTER(n)
232 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
233 # include BOOST_PP_LOCAL_ITERATE()
238 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_ARITY(n)
239 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
240 # include BOOST_PP_LOCAL_ITERATE()
244 int const arguments
= lua_gettop(L
);
248 if (arity
== arguments
)
250 int const scores
[] = {
253 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_SCORE(n)
254 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
255 # include BOOST_PP_LOCAL_ITERATE()
259 score
= sum_scores(scores
+ 1, scores
+ 1 + N
);
262 if (score
>= 0 && score
< ctx
.best_score
)
264 ctx
.best_score
= score
;
265 ctx
.candidates
[0] = &self
;
266 ctx
.candidate_index
= 1;
268 else if (score
== ctx
.best_score
)
270 ctx
.candidates
[ctx
.candidate_index
++] = &self
;
277 results
= self
.next
->call(L
, ctx
);
280 if (score
== ctx
.best_score
&& ctx
.candidate_index
== 1)
282 # ifndef LUABIND_INVOKE_VOID
283 result_converter
.apply(
286 # ifdef LUABIND_INVOKE_MEMBER
287 (c0
.apply(L
, LUABIND_DECORATE_TYPE(a0
), index0
).*f
)(
288 BOOST_PP_ENUM(BOOST_PP_DEC(N
), LUABIND_INVOKE_ARG
, BOOST_PP_INC
)
291 # define LUABIND_INVOKE_IDENTITY(x) x
293 BOOST_PP_ENUM(N
, LUABIND_INVOKE_ARG
, LUABIND_INVOKE_IDENTITY
)
295 # undef LUABIND_INVOKE_IDENTITY
297 # ifndef LUABIND_INVOKE_VOID
303 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_CONVERTER_POSTCALL(n)
304 # define BOOST_PP_LOCAL_LIMITS (0,N-1)
305 # include BOOST_PP_LOCAL_ITERATE()
308 results
= maybe_yield(L
, lua_gettop(L
) - arguments
, (Policies
*)0);
310 int const indices
[] = {
311 arguments
+ results
BOOST_PP_ENUM_TRAILING_PARAMS(N
, index
)
314 policy_list_postcall
<Policies
>::apply(L
, indices
);