Initial commit, includes Lua with broken Luabind as a backup for branching purposes
[terrastrategy.git] / include / luabind / detail / call_member.hpp
blob4d3a5dcbb8351b4bce34d6e6da834803d03f48e7
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_CALL_MEMBER_HPP_INCLUDED
27 #define LUABIND_CALL_MEMBER_HPP_INCLUDED
29 #include <luabind/config.hpp>
30 #include <luabind/detail/convert_to_lua.hpp>
31 #include <luabind/detail/pcall.hpp>
32 #include <luabind/error.hpp>
33 #include <luabind/detail/stack_utils.hpp>
34 #include <luabind/object.hpp> // TODO: REMOVE DEPENDENCY
36 #include <boost/tuple/tuple.hpp>
38 #include <boost/preprocessor/control/if.hpp>
39 #include <boost/preprocessor/facilities/expand.hpp>
41 #include <boost/mpl/apply_wrap.hpp>
43 namespace luabind
45 namespace detail
48 namespace mpl = boost::mpl;
50 // if the proxy_member_caller returns non-void
51 template<class Ret, class Tuple>
52 class proxy_member_caller
54 // friend class luabind::object;
55 public:
57 proxy_member_caller(lua_State* L_, const Tuple args)
58 : L(L_)
59 , m_args(args)
60 , m_called(false)
64 proxy_member_caller(const proxy_member_caller& rhs)
65 : L(rhs.L)
66 , m_args(rhs.m_args)
67 , m_called(rhs.m_called)
69 rhs.m_called = true;
72 ~proxy_member_caller()
74 if (m_called) return;
76 m_called = true;
78 // don't count the function and self-reference
79 // since those will be popped by pcall
80 int top = lua_gettop(L) - 2;
82 // pcall will pop the function and self reference
83 // and all the parameters
85 push_args_from_tuple<1>::apply(L, m_args);
86 if (pcall(L, boost::tuples::length<Tuple>::value + 1, 0))
88 assert(lua_gettop(L) == top + 1);
89 #ifndef LUABIND_NO_EXCEPTIONS
90 throw luabind::error(L);
91 #else
92 error_callback_fun e = get_error_callback();
93 if (e) e(L);
95 assert(0 && "the lua function threw an error and exceptions are disabled."
96 "If you want to handle this error use luabind::set_error_callback()");
97 std::terminate();
98 #endif
100 // pops the return values from the function
101 stack_pop pop(L, lua_gettop(L) - top);
104 operator Ret()
106 typename mpl::apply_wrap2<default_policy,Ret,lua_to_cpp>::type converter;
108 m_called = true;
110 // don't count the function and self-reference
111 // since those will be popped by pcall
112 int top = lua_gettop(L) - 2;
114 // pcall will pop the function and self reference
115 // and all the parameters
116 push_args_from_tuple<1>::apply(L, m_args);
117 if (pcall(L, boost::tuples::length<Tuple>::value + 1, 1))
119 assert(lua_gettop(L) == top + 1);
120 #ifndef LUABIND_NO_EXCEPTIONS
121 throw luabind::error(L);
122 #else
123 error_callback_fun e = get_error_callback();
124 if (e) e(L);
126 assert(0 && "the lua function threw an error and exceptions are disabled."
127 "If you want to handle this error use luabind::set_error_callback()");
128 std::terminate();
129 #endif
132 // pops the return values from the function
133 stack_pop pop(L, lua_gettop(L) - top);
135 #ifndef LUABIND_NO_ERROR_CHECKING
137 if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0)
139 assert(lua_gettop(L) == top + 1);
140 #ifndef LUABIND_NO_EXCEPTIONS
141 throw cast_failed(L, LUABIND_TYPEID(Ret));
142 #else
143 cast_failed_callback_fun e = get_cast_failed_callback();
144 if (e) e(L, LUABIND_TYPEID(Ret));
146 assert(0 && "the lua function's return value could not be converted."
147 "If you want to handle this error use luabind::set_error_callback()");
148 std::terminate();
149 #endif
151 #endif
152 return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1);
155 template<class Policies>
156 Ret operator[](const Policies& p)
158 typedef typename find_conversion_policy<0, Policies>::type converter_policy;
159 typename mpl::apply_wrap2<converter_policy,Ret,lua_to_cpp>::type converter;
161 m_called = true;
163 // don't count the function and self-reference
164 // since those will be popped by pcall
165 int top = lua_gettop(L) - 2;
167 // pcall will pop the function and self reference
168 // and all the parameters
170 detail::push_args_from_tuple<1>::apply(L, m_args, p);
171 if (pcall(L, boost::tuples::length<Tuple>::value + 1, 1))
173 assert(lua_gettop(L) == top + 1);
174 #ifndef LUABIND_NO_EXCEPTIONS
175 throw error(L);
176 #else
177 error_callback_fun e = get_error_callback();
178 if (e) e(L);
180 assert(0 && "the lua function threw an error and exceptions are disabled."
181 "If you want to handle this error use luabind::set_error_callback()");
182 std::terminate();
183 #endif
186 // pops the return values from the function
187 stack_pop pop(L, lua_gettop(L) - top);
189 #ifndef LUABIND_NO_ERROR_CHECKING
191 if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0)
193 assert(lua_gettop(L) == top + 1);
194 #ifndef LUABIND_NO_EXCEPTIONS
195 throw cast_failed(L, LUABIND_TYPEID(Ret));
196 #else
197 cast_failed_callback_fun e = get_cast_failed_callback();
198 if (e) e(L, LUABIND_TYPEID(Ret));
200 assert(0 && "the lua function's return value could not be converted."
201 "If you want to handle this error use luabind::set_error_callback()");
202 std::terminate();
203 #endif
205 #endif
206 return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1);
209 private:
211 lua_State* L;
212 Tuple m_args;
213 mutable bool m_called;
217 // if the proxy_member_caller returns void
218 template<class Tuple>
219 class proxy_member_void_caller
221 friend class luabind::object;
222 public:
224 proxy_member_void_caller(lua_State* L_, const Tuple args)
225 : L(L_)
226 , m_args(args)
227 , m_called(false)
231 proxy_member_void_caller(const proxy_member_void_caller& rhs)
232 : L(rhs.L)
233 , m_args(rhs.m_args)
234 , m_called(rhs.m_called)
236 rhs.m_called = true;
239 ~proxy_member_void_caller()
241 if (m_called) return;
243 m_called = true;
245 // don't count the function and self-reference
246 // since those will be popped by pcall
247 int top = lua_gettop(L) - 2;
249 // pcall will pop the function and self reference
250 // and all the parameters
252 push_args_from_tuple<1>::apply(L, m_args);
253 if (pcall(L, boost::tuples::length<Tuple>::value + 1, 0))
255 assert(lua_gettop(L) == top + 1);
256 #ifndef LUABIND_NO_EXCEPTIONS
257 throw luabind::error(L);
258 #else
259 error_callback_fun e = get_error_callback();
260 if (e) e(L);
262 assert(0 && "the lua function threw an error and exceptions are disabled."
263 "If you want to handle this error use luabind::set_error_callback()");
264 std::terminate();
265 #endif
267 // pops the return values from the function
268 stack_pop pop(L, lua_gettop(L) - top);
271 template<class Policies>
272 void operator[](const Policies& p)
274 m_called = true;
276 // don't count the function and self-reference
277 // since those will be popped by pcall
278 int top = lua_gettop(L) - 2;
280 // pcall will pop the function and self reference
281 // and all the parameters
283 detail::push_args_from_tuple<1>::apply(L, m_args, p);
284 if (pcall(L, boost::tuples::length<Tuple>::value + 1, 0))
286 assert(lua_gettop(L) == top + 1);
287 #ifndef LUABIND_NO_EXCEPTIONS
288 throw error(L);
289 #else
290 error_callback_fun e = get_error_callback();
291 if (e) e(L);
293 assert(0 && "the lua function threw an error and exceptions are disabled."
294 "If you want to handle this error use luabind::set_error_callback()");
295 std::terminate();
296 #endif
298 // pops the return values from the function
299 stack_pop pop(L, lua_gettop(L) - top);
302 private:
303 lua_State* L;
304 Tuple m_args;
305 mutable bool m_called;
309 } // detail
311 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/call_member.hpp>, 1))
312 #include BOOST_PP_ITERATE()
316 #endif // LUABIND_CALL_MEMBER_HPP_INCLUDED
318 #elif BOOST_PP_ITERATION_FLAGS() == 1
320 #define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
321 #define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n
323 template<class R BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
324 typename boost::mpl::if_<boost::is_void<R>
325 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
326 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
327 call_member(object const& obj, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _))
329 typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
330 #if BOOST_PP_ITERATION() == 0
331 tuple_t args;
332 #else
333 tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
334 #endif
336 typedef typename boost::mpl::if_<boost::is_void<R>
337 , luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
338 , luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;
340 // this will be cleaned up by the proxy object
341 // once the call has been made
343 // get the function
344 obj.push(obj.interpreter());
345 lua_pushstring(obj.interpreter(), name);
346 lua_gettable(obj.interpreter(), -2);
347 // duplicate the self-object
348 lua_pushvalue(obj.interpreter(), -2);
349 // remove the bottom self-object
350 lua_remove(obj.interpreter(), -3);
352 // now the function and self objects
353 // are on the stack. These will both
354 // be popped by pcall
355 return proxy_type(obj.interpreter(), args);
358 #undef LUABIND_OPERATOR_PARAMS
359 #undef LUABIND_TUPLE_PARAMS
361 #endif