added finalizers
[luabind.git] / luabind / detail / operators.hpp
blob77fe0ea96914f80b019072309662f1f12eaeafc0
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_OPERATORS_HPP_INCLUDED
27 #define LUABIND_OPERATORS_HPP_INCLUDED
29 #include <luabind/config.hpp>
31 #include <sstream>
33 #include <boost/preprocessor/repeat.hpp>
34 #include <boost/preprocessor/repetition/enum.hpp>
35 #include <boost/preprocessor/repetition/enum_params.hpp>
36 #include <boost/preprocessor/iteration.hpp>
39 #include <boost/mpl/if.hpp>
40 #include <boost/mpl/vector.hpp>
42 #include <luabind/detail/other.hpp>
43 #include <luabind/detail/operator_id.hpp>
44 #include <luabind/detail/signature_match.hpp>
45 #include <luabind/detail/policy.hpp>
47 namespace luabind { namespace detail {
50 template<int N> struct execute_selector;
52 template<class T>
53 struct policies_with_storage : T
55 char storage;
58 #if defined (BOOST_MSVC) && (BOOST_MSVC <= 1200)
59 #define LUABIND_MSVC6_NO_TYPENAME
60 #else
61 #define LUABIND_MSVC6_NO_TYPENAME typename
62 #endif
64 //#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
65 #define LUABIND_CONVERT_PARAMETER conv_self.apply(L, LUABIND_DECORATE_TYPE(Self&), 1)
66 //#else
67 // #define LUABIND_CONVERT_PARAMETER conv_self::template apply<Self_>(L, LUABIND_DECORATE_TYPE(Self&), 1)
68 //#endif
71 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 1))
72 #include BOOST_PP_ITERATE()
74 #define LUABIND_UNWRAP_PARAM(z,n,_) LUABIND_MSVC6_NO_TYPENAME unwrap_other<A##n>::type
76 // Signature is a constructor<...> with all the parameter types in it
77 // constant is true if the application operator is const
78 template<class Signature, bool Constant, class Policies = null_type>
79 struct application_operator
81 template<class Self>
82 struct apply: execute_selector<Signature::arity>::template apply<Signature, Constant, Self, Policies> {};
84 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
85 static inline int match_impl(
86 lua_State* L,
87 const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*)
89 typedef constructor<BOOST_PP_ENUM(LUABIND_MAX_ARITY, LUABIND_UNWRAP_PARAM, _)> unwrapped_sig;
91 object_rep* obj = is_class_object(L, 1);
92 if (obj == 0) return -1;
94 bool constant_obj = obj->flags() & object_rep::constant;
96 if (!Constant && constant_obj) return -1;
97 // if (lua_gettop(L) != Signature::arity + 1) return -1;
99 int i = match_params(L, 2, static_cast<const unwrapped_sig*>(0), static_cast<const Policies*>(0));
100 if (Constant && !constant_obj) i++;
101 return i;
104 static inline int match(lua_State* L)
106 return match_impl(L, static_cast<const Signature*>(0));
110 #undef LUABIND_UNWRAP_PARAM
112 // this is the type that represents all the operators
113 // this is returned from all operators on self_t
114 template<class id, class L, class R = null_type>
115 struct operator_
119 struct self_t : boost::arg<-1>
121 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 2))
122 #include BOOST_PP_ITERATE()
124 operator_<op_tostring_tag, self_t, null_type> tostring;
127 struct const_self_t : boost::arg<-1>
129 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 3))
130 #include BOOST_PP_ITERATE()
132 operator_<op_tostring_tag, const_self_t, null_type> tostring;
135 // TODO: fix this. The type cannot be a value type for all cases
136 template<class T, class Policy>
137 inline int convert_result(lua_State* L, T v, const Policy*)
139 typedef typename find_conversion_policy<0, Policy>::type converter_policy;
140 typename converter_policy::template generate_converter<T, cpp_to_lua>::type ret_converter;
141 ret_converter.apply(L, v);
142 return 1;
145 // this is an implementation that is specialized
146 // for each operator and used by operator_
147 template<class id>
148 struct binary_operator
150 template<class Policies, class Left, class Right>
151 struct impl;
154 template<class id>
155 struct unary_operator
157 template<class Policies, class Left> struct impl;
160 template<class Policies, class id, class Self, class L, class R = null_type>
161 struct operator_unwrapper :
162 ::boost::mpl::if_<
163 ::boost::is_same<detail::null_type, R>,
164 // if this is true, it is a unary operator
165 typename unary_operator<id>::template impl<
166 Policies,
167 typename ::boost::mpl::if_<
168 boost::is_same<detail::self_t, L>,
169 Self&,
170 typename ::boost::mpl::if_<
171 ::boost::is_same<detail::const_self_t, L>,
172 const Self&,
173 typename unwrap_other<L>::type
174 >::type
175 >::type
177 // else, if this is a binary operator
178 typename binary_operator<id>::template impl<
179 Policies,
180 // extract the left type and substitute self_t and const_self_t with the real self type
181 // also, unwrap the type if it's wrapped in other<>
182 typename ::boost::mpl::if_<
183 boost::is_same<detail::self_t, L>,
184 Self&,
185 typename ::boost::mpl::if_<
186 ::boost::is_same<detail::const_self_t, L>,
187 const Self&,
188 typename unwrap_other<L>::type>::type
189 >::type,
190 // same thing but with the right type
191 typename ::boost::mpl::if_<
192 boost::is_same<detail::self_t, R>,
193 Self&,
194 typename ::boost::mpl::if_<
195 ::boost::is_same<detail::const_self_t, R>,
196 const Self&,
197 typename unwrap_other<R>::type
198 >::type
199 >::type
201 >::type
205 namespace luabind
207 namespace
209 LUABIND_ANONYMOUS_FIX detail::self_t self;
210 LUABIND_ANONYMOUS_FIX detail::const_self_t const_self;
213 #define LUABIND_BINARY_OPERATOR(id, op)\
214 namespace detail {\
215 template<>\
216 struct binary_operator<op_##id##_tag>\
218 template<class Policies, class Left, class Right>\
219 struct impl\
221 typedef typename unwrap_other<Left>::type left_t; \
222 typedef typename unwrap_other<Right>::type right_t; \
223 static inline operator_id get_id() { return op_##id; } \
224 static inline int execute(lua_State* L)\
226 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left; \
227 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left; \
228 typedef typename find_conversion_policy<2, Policies>::type converter_policy_right; \
229 typename converter_policy_right::template generate_converter<right_t, lua_to_cpp>::type converter_right; \
230 int ret = convert_result(L, converter_left.apply(L, LUABIND_DECORATE_TYPE(left_t), 1) op converter_right.apply(L, LUABIND_DECORATE_TYPE(right_t), 2), static_cast<const Policies*>(0));\
231 return ret;\
233 static int match(lua_State* L)\
235 return match_params(L, 1, static_cast<constructor<left_t, right_t>*>(0), static_cast<Policies*>(0));\
241 namespace detail\
243 inline detail::operator_<detail::op_##id##_tag, detail::self_t, detail::self_t> operator op(const detail::self_t&, const detail::self_t&)\
245 return detail::operator_<detail::op_##id##_tag, detail::self_t, detail::self_t>();\
247 template<class L>\
248 inline detail::operator_<detail::op_##id##_tag, L, detail::self_t> operator op(const L&, const detail::self_t&)\
250 return detail::operator_<detail::op_##id##_tag, L, detail::self_t>();\
252 template<class R>\
253 inline detail::operator_<detail::op_##id##_tag, detail::self_t, R> operator op(const detail::self_t&, const R&)\
255 return detail::operator_<detail::op_##id##_tag, detail::self_t, R>();\
257 inline detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::const_self_t> operator op(const detail::const_self_t&, const detail::const_self_t&)\
259 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::const_self_t>();\
261 template<class L>\
262 inline detail::operator_<detail::op_##id##_tag, L, detail::const_self_t> operator op(const L&, const detail::const_self_t&)\
264 return detail::operator_<detail::op_##id##_tag, L, detail::const_self_t>();\
266 template<class R>\
267 inline detail::operator_<detail::op_##id##_tag, detail::const_self_t, R> operator op(const detail::const_self_t&, const R&)\
269 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, R>();\
273 LUABIND_BINARY_OPERATOR(add,+)
274 LUABIND_BINARY_OPERATOR(sub,-)
275 LUABIND_BINARY_OPERATOR(div,/)
276 LUABIND_BINARY_OPERATOR(mul,*)
277 LUABIND_BINARY_OPERATOR(pow,^)
278 LUABIND_BINARY_OPERATOR(lt,<)
279 LUABIND_BINARY_OPERATOR(le,<=)
280 LUABIND_BINARY_OPERATOR(eq,==)
282 #undef LUABIND_BINARY_OPERATOR
285 #define LUABIND_UNARY_OPERATOR(id, op)\
286 namespace detail\
288 template<>\
289 struct unary_operator<op_##id##_tag>\
291 template<class Policies, class Left>\
292 struct impl\
294 typedef typename unwrap_other<Left>::type left_t;\
295 typedef detail::null_type right_t;\
296 static inline operator_id get_id() { return op_##id; }\
297 static inline int execute(lua_State* L)\
299 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left; \
300 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left;\
301 return convert_result(L, op converter_left.apply(L, LUABIND_DECORATE_TYPE(left_t), 1), static_cast<const Policies*>(0));\
303 static inline int match(lua_State* L)\
305 return match_params(L, 1, static_cast<constructor<left_t>*>(0), static_cast<Policies*>(0));\
311 inline detail::operator_<detail::op_##id##_tag, detail::self_t, detail::null_type> operator op(const detail::self_t&)\
313 return detail::operator_<detail::op_##id##_tag, detail::self_t, detail::null_type>();\
315 inline detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::null_type> operator op(const detail::const_self_t&)\
317 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::null_type>();\
320 LUABIND_UNARY_OPERATOR(unm,-);
322 namespace detail
324 template<>
325 struct unary_operator<op_tostring_tag>
327 template<class Policies, class Left>
328 struct impl
330 typedef typename unwrap_other<Left>::type left_t;
331 typedef detail::null_type right_t;
332 static inline operator_id get_id() { return op_tostring; }
333 static inline int execute(lua_State* L)
335 // TODO: Should policies apply to this operator? shouldn't the string returntype be enforced?
336 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left;
337 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left;
338 std::stringstream s;
339 s << converter_left.apply(L, LUABIND_DECORATE_TYPE(left_t), 1) << std::ends;
340 return convert_result(L, s.str(), static_cast<const Policies*>(0));
342 static inline int match(lua_State* L)
344 return match_params(L, 1, static_cast<constructor<left_t>*>(0), static_cast<Policies*>(0));
350 inline detail::operator_<detail::op_tostring_tag, detail::self_t, detail::null_type> tostring(const detail::self_t&)
352 return detail::operator_<detail::op_tostring_tag, detail::self_t, detail::null_type>();
354 inline detail::operator_<detail::op_tostring_tag, detail::const_self_t, detail::null_type> tostring(const detail::const_self_t&)
356 return detail::operator_<detail::op_tostring_tag, detail::const_self_t, detail::null_type>();
360 #undef LUABIND_UNARY_OPERATOR
361 #undef LUABIND_MSVC6_NO_TYPENAME
364 #endif // LUABIND_OPERATORS_HPP_INCLUDED
367 #elif BOOST_PP_ITERATION_FLAGS() == 1
369 #define LUABIND_DECL(z,n,_) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
370 typedef typename unwrap_other<A##n>::type unwrapped_a##n; \
371 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<unwrapped_a##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
373 #define LUABIND_PARAM(z,n,_) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(unwrapped_a##n), n+2)
375 template<>
376 struct execute_selector<BOOST_PP_ITERATION()>
378 template<class Signature, bool Constant, class Self_, class Policies>
379 struct apply
381 static inline int execute(lua_State* L)
383 return execute_impl(L, static_cast<const Signature*>(0));
386 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
387 static inline int execute_impl(
388 lua_State* L,
389 const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*)
391 // TODO: use policies here, instead of default_policy, or shouldn't we?
392 typename boost::mpl::apply_if_c<Constant,
393 LUABIND_MSVC6_NO_TYPENAME default_policy::template generate_converter<const Self_&, lua_to_cpp>,
394 LUABIND_MSVC6_NO_TYPENAME default_policy::template generate_converter<Self_&, lua_to_cpp>
395 >::type conv_self;
397 typedef typename boost::mpl::if_c<Constant,
398 const Self_,
399 Self_
400 >::type Self;
402 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
404 return convert_result(L, conv_self.apply(L, LUABIND_DECORATE_TYPE(Self&), 1)
406 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAM, _)
407 ), static_cast<Policies*>(0));
412 #undef LUABIND_DECL
413 #undef LUABIND_PARAM
415 #elif BOOST_PP_ITERATION_FLAGS() == 2 // self_t
417 #define LUABIND_UNWRAP_PARAM(z,n,_) A##n
419 #if BOOST_PP_ITERATION() > 0
420 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
421 #endif
422 application_operator< constructor<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_UNWRAP_PARAM, _)>, false>*
423 operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) { return 0; }
425 #undef LUABIND_UNWRAP_PARAM
427 #elif BOOST_PP_ITERATION_FLAGS() == 3 // const_self_t
429 #define LUABIND_UNWRAP_PARAM(z,n,_) A##n
431 #if BOOST_PP_ITERATION() > 0
432 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
433 #endif
434 application_operator< constructor<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_UNWRAP_PARAM, _)>, true>*
435 operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) { return 0; }
437 #undef LUABIND_UNWRAP_PARAM
439 #endif