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>
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
;
53 struct policies_with_storage
: T
58 #if defined (BOOST_MSVC) && (BOOST_MSVC <= 1200)
59 #define LUABIND_MSVC6_NO_TYPENAME
61 #define LUABIND_MSVC6_NO_TYPENAME typename
64 //#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
65 #define LUABIND_CONVERT_PARAMETER conv_self.apply(L, LUABIND_DECORATE_TYPE(Self&), 1)
67 // #define LUABIND_CONVERT_PARAMETER conv_self::template apply<Self_>(L, LUABIND_DECORATE_TYPE(Self&), 1)
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
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(
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
++;
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
>
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
);
145 // this is an implementation that is specialized
146 // for each operator and used by operator_
148 struct binary_operator
150 template<class Policies
, class Left
, class Right
>
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
:
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
<
167 typename ::boost::mpl::if_
<
168 boost::is_same
<detail::self_t
, L
>,
170 typename ::boost::mpl::if_
<
171 ::boost::is_same
<detail::const_self_t
, L
>,
173 typename unwrap_other
<L
>::type
177 // else, if this is a binary operator
178 typename binary_operator
<id
>::template impl
<
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
>,
185 typename ::boost::mpl::if_
<
186 ::boost::is_same
<detail::const_self_t
, L
>,
188 typename unwrap_other
<L
>::type
>::type
190 // same thing but with the right type
191 typename ::boost::mpl::if_
<
192 boost::is_same
<detail::self_t
, R
>,
194 typename ::boost::mpl::if_
<
195 ::boost::is_same
<detail::const_self_t
, R
>,
197 typename unwrap_other
<R
>::type
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)\
216 struct binary_operator<op_##id##_tag>\
218 template<class Policies, class Left, class Right>\
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));\
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));\
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>();\
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>();\
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>();\
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>();\
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)\
289 struct unary_operator<op_##id##_tag>\
291 template<class Policies, class Left>\
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
,-);
325 struct unary_operator
<op_tostring_tag
>
327 template<class Policies
, class Left
>
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
;
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)
376 struct execute_selector
<BOOST_PP_ITERATION()>
378 template<class Signature
, bool Constant
, class Self_
, class Policies
>
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(
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
>
397 typedef typename
boost::mpl::if_c
<Constant
,
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));
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
)>
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
)>
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