Initial revision
[luabind.git] / luabind / function.hpp
blob226779c17eafd81ae0a951984f4634e8ffbca463
1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
24 #if !BOOST_PP_IS_ITERATING
26 #ifndef LUABIND_FUNCTIONS_HPP_INCLUDED
27 #define LUABIND_FUNCTIONS_HPP_INCLUDED
29 #include <luabind/config.hpp>
31 #include <boost/config.hpp>
32 #include <boost/preprocessor/repeat.hpp>
33 #include <boost/preprocessor/iteration/iterate.hpp>
34 #include <boost/preprocessor/repetition/enum.hpp>
35 #include <boost/preprocessor/repetition/enum_params.hpp>
36 #include <boost/preprocessor/cat.hpp>
38 #include <luabind/detail/signature_match.hpp>
39 #include <luabind/detail/call_function.hpp>
40 #include <luabind/detail/get_overload_signature.hpp>
41 #include <luabind/detail/overload_rep_base.hpp>
43 namespace luabind
45 namespace detail
48 namespace free_functions
51 struct overload_rep: public overload_rep_base
54 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 1))
55 #include BOOST_PP_ITERATE()
57 inline bool operator==(const overload_rep& o) const
59 if (o.m_arity != m_arity) return false;
60 if (o.m_num_args != m_num_args) return false;
61 for (int i = 0; i < m_num_args; ++i)
62 if (!(LUABIND_TYPE_INFO_EQUAL(m_params[i], o.m_params[i]))) return false;
63 return true;
66 typedef int(*call_ptr)(lua_State*, void(*)());
68 inline void set_fun(call_ptr f) { call_fun = f; }
69 inline int call(lua_State* L, void(*f)()) const { return call_fun(L, f); }
71 // this is the actual function pointer to be called when this overload is invoked
72 void (*fun)();
74 private:
76 int m_num_args;
77 call_ptr call_fun;
79 // the number of parameters this overload takes
80 // these are used to detect when a function by a derived class.
81 // int m_arity;
82 // the types of the parameter it takes
83 LUABIND_TYPE_INFO m_params[LUABIND_MAX_ARITY];
89 struct function_rep
91 void add_overload(const free_functions::overload_rep& o)
93 std::vector<free_functions::overload_rep>::iterator i = std::find(m_overloads.begin(), m_overloads.end(), o);
95 // if the overload already exists, overwrite the existing function
96 if (i != m_overloads.end())
98 *i = o;
100 else
102 m_overloads.push_back(o);
106 const std::vector<overload_rep>& overloads() const throw() { return m_overloads; }
108 #ifdef LUABIND_DONT_COPY_STRINGS
109 const char* name;
110 #else
111 std::string name;
112 #endif
114 private:
115 // this have to be write protected, since each time an overload is
116 // added it has to be checked for existence. add_overload() should
117 // be used.
118 std::vector<free_functions::overload_rep> m_overloads;
123 // returns generates functions that calls function pointers
125 #define LUABIND_DECL(z, n, text) typedef typename detail::get_policy<n+1,Policies>::type BOOST_PP_CAT(a##n,_policy); \
126 typedef typename BOOST_PP_CAT(a##n,_policy)::head BOOST_PP_CAT(a##n,_param_converter_intermediate); \
127 typedef typename BOOST_PP_CAT(a##n,_param_converter_intermediate)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(p##n,_conv);
129 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(p##n,_conv)::apply(L, LUABIND_DECORATE_TYPE(A##n), n + 1)
132 #define LUABIND_DECL(z, n, text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
133 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<A##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
135 #define LUABIND_ADD_INDEX(z,n,text) + BOOST_PP_CAT(converter_policy,n)::has_arg
136 #define LUABIND_INDEX_MAP(z,n,text) 1 BOOST_PP_REPEAT(n, LUABIND_ADD_INDEX, _)
137 #define LUABIND_PARAMS(z,n,text) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_))
138 #define LUABIND_POSTCALL(z,n,text) BOOST_PP_CAT(c,n).converter_postcall(L, LUABIND_DECORATE_TYPE(A##n), LUABIND_INDEX_MAP(_,n,_));
140 template<class T>
141 struct returns
143 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 2))
144 #include BOOST_PP_ITERATE()
147 template<>
148 struct returns<void>
150 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 3))
151 #include BOOST_PP_ITERATE()
154 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 4))
155 #include BOOST_PP_ITERATE()
158 #undef LUABIND_PARAMS
159 #undef LUABIND_DECL
160 #undef LUABIND_POSTCALL
161 #undef LUABIND_ADD_INDEX
162 #undef LUABIND_INDEX_MAP
165 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/function.hpp>, 5))
166 #include BOOST_PP_ITERATE()
171 struct function_registry
173 std::map<const char*, free_functions::function_rep, ltstr> m_functions;
174 #ifndef LUABIND_DONT_COPY_STRINGS
175 std::vector<char*> m_strings;
177 ~function_registry()
179 for (std::vector<char*>::iterator i = m_strings.begin(); i != m_strings.end(); ++i)
180 delete[] *i;
182 #endif
185 template<class F, class Policies>
186 struct function_callback_s
188 static inline int apply(lua_State* L, void(*fun)())
190 return free_functions::call(reinterpret_cast<F>(fun), L, static_cast<const Policies*>(0));
194 template<class F, class Policies>
195 struct match_function_callback_s
197 static inline int apply(lua_State* L)
199 F fptr = 0;
200 return free_functions::match(fptr, L, static_cast<Policies*>(0));
203 static int callback(lua_State* L)
205 F fptr = 0;
206 return free_functions::match(fptr, L, static_cast<Policies*>(0));
210 inline int function_dispatcher(lua_State* L)
212 function_rep* rep = static_cast<function_rep*>(lua_touserdata(L, lua_upvalueindex(1)));
214 bool ambiguous = false;
215 int min_match = std::numeric_limits<int>::max();
216 int match_index = -1;
217 bool ret;
219 #ifdef LUABIND_NO_ERROR_CHECKING
221 if (rep->overloads().size() == 1)
223 match_index = 0;
225 else
228 #endif
229 int num_params = lua_gettop(L);
230 ret = find_best_match(L, rep->overloads().begin(), rep->overloads().end(), ambiguous, min_match, match_index, num_params);
232 #ifdef LUABIND_NO_ERROR_CHECKING
235 #else
237 if (!ret)
239 // this bock is needed to make sure the std::string is destructed
241 std::string msg = "no match for function call '";
242 msg += rep->name;
243 msg += "' with the parameters (";
244 msg += stack_content_by_name(L, 1);
245 msg += ")\ncandidates are:\n";
247 msg += get_overload_signatures(L, rep->overloads().begin(), rep->overloads().end(), rep->name);
249 lua_pushstring(L, msg.c_str());
251 lua_error(L);
254 if (ambiguous)
256 // this bock is needed to make sure the std::string is destructed
258 std::string msg = "call of overloaded function '";
259 msg += rep->name;
260 msg += "(";
261 msg += stack_content_by_name(L, 1);
262 msg += ") is ambiguous\nnone of the overloads have a best conversion:";
264 std::vector<free_functions::overload_rep> candidates;
265 find_exact_match(L, rep->overloads().begin(), rep->overloads().end(), min_match, num_params, candidates);
267 msg += get_overload_signatures(L, candidates.begin(), candidates.end(), rep->name);
269 lua_pushstring(L, msg.c_str());
271 lua_error(L);
273 #endif
274 const overload_rep& ov_rep = rep->overloads()[match_index];
275 return ov_rep.call(L, ov_rep.fun);
280 template<class F, class Policies>
281 void function(lua_State* L, const char* name, F f, const Policies&)
283 detail::free_functions::function_registry* registry = 0;
284 lua_pushstring(L, "__lua_free_functions");
285 lua_gettable(L, LUA_REGISTRYINDEX);
287 registry = static_cast<detail::free_functions::function_registry*>(lua_touserdata(L, -1));
288 lua_pop(L, 1);
290 // if you hit this assert you have not called luabind::open() for
291 // this lua_State. See the documentation for more information.
292 assert(registry != 0);
294 #ifdef LUABIND_DONT_COPY_STRINGS
295 detail::free_functions::function_rep& rep = registry->m_functions[name];
296 #else
297 registry->m_strings.push_back(detail::dup_string(name));
298 detail::free_functions::function_rep& rep = registry->m_functions[registry->m_strings.back()];
299 #endif
301 detail::free_functions::overload_rep o(f, static_cast<Policies*>(0));
303 o.set_match_fun(&detail::free_functions::match_function_callback_s<F, Policies>::apply);
304 o.set_fun(&detail::free_functions::function_callback_s<F, Policies>::apply);
306 #ifndef LUABIND_NO_ERROR_CHECKING
307 o.set_sig_fun(&detail::get_free_function_signature<F>::apply);
308 #endif
310 rep.add_overload(o);
311 rep.name = name;
313 lua_pushstring(L, name);
314 lua_pushlightuserdata(L, &rep);
315 lua_pushcclosure(L, detail::free_functions::function_dispatcher, 1);
316 lua_settable(L, LUA_GLOBALSINDEX);
319 template<class F>
320 void function(lua_State* L, const char* name, F f)
322 luabind::function(L, name, f, detail::null_type());
325 } // namespace luabind
328 #endif // LUABIND_FUNCTION_HPP_INCLUDED
330 #elif BOOST_PP_ITERATION_FLAGS() == 1
332 // overloaded template funtion that initializes the parameter list
333 // called m_params and the m_arity member.
335 #define LUABIND_INIT_PARAM(z, n, _) m_params[n] = LUABIND_TYPEID(A##n);
336 #define LUABIND_POLICY_DECL(z,n,text) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(p,n);
337 #define LUABIND_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg
339 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A), class Policies>
340 overload_rep(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), Policies*)
341 : fun(reinterpret_cast<void(*)()>(f))
342 , m_num_args(BOOST_PP_ITERATION())
344 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_INIT_PARAM, _)
345 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POLICY_DECL, _)
347 m_arity = 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_ARITY, _);
350 #undef LUABIND_INIT_PARAM
351 #undef LUABIND_POLICY_DECL
352 #undef LUABIND_ARITY
354 #elif BOOST_PP_ITERATION_FLAGS() == 2
356 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
357 static int call(T(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
359 /* typedef typename get_policy<0, Policies>::type ret_policy;
360 typedef typename ret_policy::head return_value_converter_intermediate;
361 typedef typename return_value_converter_intermediate::template generate_converter<T, cpp_to_lua>::type ret_conv;*/
363 int nargs = lua_gettop(L);
365 // typedef typename get_policy_list<0, Policies>::type policy_list_ret;
366 // typedef typename find_converter_policy<policy_list_ret>::type converter_policy_ret;
367 typedef typename find_conversion_policy<0, Policies>::type converter_policy_ret;
368 typename converter_policy_ret::template generate_converter<T, cpp_to_lua>::type converter_ret;
370 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
371 converter_ret.apply(L, f
373 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
375 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
377 int nret = lua_gettop(L) - nargs;
379 const int indices[] =
381 -1 /* self */,
382 nargs + nret /* result*/
383 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
386 policy_list_postcall<Policies>::apply(L, indices);
388 return nret;
393 #elif BOOST_PP_ITERATION_FLAGS() == 3
395 template<class Policies BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
396 static int call(void(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies*)
398 int nargs = lua_gettop(L);
400 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
403 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAMS, _)
405 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_POSTCALL, _)
407 int nret = lua_gettop(L) - nargs;
409 const int indices[] =
411 -1 /* self */,
412 nargs + nret /* result*/
413 BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION(), LUABIND_INDEX_MAP, _)
416 policy_list_postcall<Policies>::apply(L, indices);
418 return nret;
422 #elif BOOST_PP_ITERATION_FLAGS() == 4
424 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
425 int call(R(*f)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
427 return free_functions::returns<R>::call(f, L, policies);
430 #elif BOOST_PP_ITERATION_FLAGS() == 5
432 template<class Policies, class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
433 static int match(R(*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)), lua_State* L, const Policies* policies)
435 //if (lua_gettop(L) != BOOST_PP_ITERATION()) return -1;
436 typedef constructor<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)> ParameterTypes;
437 return match_params(L, 1, static_cast<ParameterTypes*>(0), policies);
442 #endif