Initial revision
[luabind.git] / luabind / detail / operators.hpp
blob8d4a1dc1d1c84465d2e67a6fd4e5a21ce9565701
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 #if defined (BOOST_MSVC) && (BOOST_MSVC <= 1200)
53 #define LUABIND_MSVC6_NO_TYPENAME
54 #else
55 #define LUABIND_MSVC6_NO_TYPENAME typename
56 #endif
58 //#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
59 #define LUABIND_CONVERT_PARAMETER conv_self.apply(L, LUABIND_DECORATE_TYPE(Self&), 1)
60 //#else
61 // #define LUABIND_CONVERT_PARAMETER conv_self::template apply<Self_>(L, LUABIND_DECORATE_TYPE(Self&), 1)
62 //#endif
65 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 1))
66 #include BOOST_PP_ITERATE()
68 #define LUABIND_UNWRAP_PARAM(z,n,_) LUABIND_MSVC6_NO_TYPENAME unwrap_other<A##n>::type
70 // Signature is a constructor<...> with all the parameter types in it
71 // constant is true if the application operator is const
72 template<class Signature, bool Constant, class Policies = null_type>
73 struct application_operator
75 template<class Self>
76 struct apply: execute_selector<Signature::arity>::template apply<Signature, Constant, Self, Policies> {};
78 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
79 static inline int match_impl(
80 lua_State* L,
81 const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*)
83 typedef constructor<BOOST_PP_ENUM(LUABIND_MAX_ARITY, LUABIND_UNWRAP_PARAM, _)> unwrapped_sig;
85 object_rep* obj = is_class_object(L, 1);
86 if (obj == 0) return -1;
88 bool constant_obj = obj->flags() & object_rep::constant;
90 if (!Constant && constant_obj) return -1;
91 // if (lua_gettop(L) != Signature::arity + 1) return -1;
93 int i = match_params(L, 2, static_cast<const unwrapped_sig*>(0), static_cast<const Policies*>(0));
94 if (Constant && !constant_obj) i++;
95 return i;
98 static inline int match(lua_State* L)
100 return match_impl(L, static_cast<const Signature*>(0));
104 #undef LUABIND_UNWRAP_PARAM
106 // this is the type that represents all the operators
107 // this is returned from all operators on self_t
108 template<class id, class L, class R = null_type>
109 struct operator_
113 struct self_t : boost::arg<-1>
115 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 2))
116 #include BOOST_PP_ITERATE()
118 operator_<op_tostring_tag, self_t, null_type> tostring;
121 struct const_self_t : boost::arg<-1>
123 #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/detail/operators.hpp>, 3))
124 #include BOOST_PP_ITERATE()
126 operator_<op_tostring_tag, const_self_t, null_type> tostring;
129 // TODO: fix this. The type cannot be a value type for all cases
130 template<class T, class Policy>
131 inline int convert_result(lua_State* L, T v, const Policy*)
133 typedef typename find_conversion_policy<0, Policy>::type converter_policy;
134 typename converter_policy::template generate_converter<T, cpp_to_lua>::type ret_converter;
135 ret_converter.apply(L, v);
136 return 1;
139 // this is an implementation that is specialized
140 // for each operator and used by operator_
141 template<class id>
142 struct binary_operator
144 template<class Policies, class Left, class Right>
145 struct impl;
148 template<class id>
149 struct unary_operator
151 template<class Policies, class Left> struct impl;
154 template<class Policies, class id, class Self, class L, class R = null_type>
155 struct operator_unwrapper :
156 ::boost::mpl::if_<
157 ::boost::is_same<detail::null_type, R>,
158 // if this is true, it is a unary operator
159 typename unary_operator<id>::template impl<
160 Policies,
161 typename ::boost::mpl::if_<
162 boost::is_same<detail::self_t, L>,
163 Self&,
164 typename ::boost::mpl::if_<
165 ::boost::is_same<detail::const_self_t, L>,
166 const Self&,
167 typename unwrap_other<L>::type
168 >::type
169 >::type
171 // else, if this is a binary operator
172 typename binary_operator<id>::template impl<
173 Policies,
174 // extract the left type and substitute self_t and const_self_t with the real self type
175 // also, unwrap the type if it's wrapped in other<>
176 typename ::boost::mpl::if_<
177 boost::is_same<detail::self_t, L>,
178 Self&,
179 typename ::boost::mpl::if_<
180 ::boost::is_same<detail::const_self_t, L>,
181 const Self&,
182 typename unwrap_other<L>::type>::type
183 >::type,
184 // same thing but with the right type
185 typename ::boost::mpl::if_<
186 boost::is_same<detail::self_t, R>,
187 Self&,
188 typename ::boost::mpl::if_<
189 ::boost::is_same<detail::const_self_t, R>,
190 const Self&,
191 typename unwrap_other<R>::type
192 >::type
193 >::type
195 >::type
199 namespace luabind
201 namespace
203 detail::self_t self;
204 detail::const_self_t const_self;
207 #define LUABIND_BINARY_OPERATOR(id, op)\
208 namespace detail {\
209 template<>\
210 struct binary_operator<op_##id##_tag>\
212 template<class Policies, class Left, class Right>\
213 struct impl\
215 typedef typename unwrap_other<Left>::type left_t; \
216 typedef typename unwrap_other<Right>::type right_t; \
217 static inline operator_id get_id() { return op_##id; } \
218 static inline int execute(lua_State* L)\
220 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left; \
221 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left; \
222 typedef typename find_conversion_policy<2, Policies>::type converter_policy_right; \
223 typename converter_policy_right::template generate_converter<right_t, lua_to_cpp>::type converter_right; \
224 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));\
225 return ret;\
227 static int match(lua_State* L)\
229 return match_params(L, 1, static_cast<constructor<left_t, right_t>*>(0), static_cast<Policies*>(0));\
235 namespace detail\
237 inline detail::operator_<detail::op_##id##_tag, detail::self_t, detail::self_t> operator op(const detail::self_t&, const detail::self_t&)\
239 return detail::operator_<detail::op_##id##_tag, detail::self_t, detail::self_t>();\
241 template<class L>\
242 inline detail::operator_<detail::op_##id##_tag, L, detail::self_t> operator op(const L&, const detail::self_t&)\
244 return detail::operator_<detail::op_##id##_tag, L, detail::self_t>();\
246 template<class R>\
247 inline detail::operator_<detail::op_##id##_tag, detail::self_t, R> operator op(const detail::self_t&, const R&)\
249 return detail::operator_<detail::op_##id##_tag, detail::self_t, R>();\
251 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&)\
253 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::const_self_t>();\
255 template<class L>\
256 inline detail::operator_<detail::op_##id##_tag, L, detail::const_self_t> operator op(const L&, const detail::const_self_t&)\
258 return detail::operator_<detail::op_##id##_tag, L, detail::const_self_t>();\
260 template<class R>\
261 inline detail::operator_<detail::op_##id##_tag, detail::const_self_t, R> operator op(const detail::const_self_t&, const R&)\
263 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, R>();\
267 LUABIND_BINARY_OPERATOR(add,+)
268 LUABIND_BINARY_OPERATOR(sub,-)
269 LUABIND_BINARY_OPERATOR(div,/)
270 LUABIND_BINARY_OPERATOR(mul,*)
271 LUABIND_BINARY_OPERATOR(pow,^)
272 LUABIND_BINARY_OPERATOR(lt,<)
273 LUABIND_BINARY_OPERATOR(le,<=)
274 LUABIND_BINARY_OPERATOR(eq,==)
276 #undef LUABIND_BINARY_OPERATOR
279 #define LUABIND_UNARY_OPERATOR(id, op)\
280 namespace detail\
282 template<>\
283 struct unary_operator<op_##id##_tag>\
285 template<class Policies, class Left>\
286 struct impl\
288 typedef typename unwrap_other<Left>::type left_t;\
289 typedef detail::null_type right_t;\
290 static inline operator_id get_id() { return op_##id; }\
291 static inline int execute(lua_State* L)\
293 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left; \
294 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left;\
295 return convert_result(L, op converter_left.apply(L, LUABIND_DECORATE_TYPE(left_t), 1), static_cast<const Policies*>(0));\
297 static inline int match(lua_State* L)\
299 return match_params(L, 1, static_cast<constructor<left_t>*>(0), static_cast<Policies*>(0));\
305 inline detail::operator_<detail::op_##id##_tag, detail::self_t, detail::null_type> operator op(const detail::self_t&)\
307 return detail::operator_<detail::op_##id##_tag, detail::self_t, detail::null_type>();\
309 inline detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::null_type> operator op(const detail::const_self_t&)\
311 return detail::operator_<detail::op_##id##_tag, detail::const_self_t, detail::null_type>();\
314 LUABIND_UNARY_OPERATOR(unm,-);
316 namespace detail
318 template<>
319 struct unary_operator<op_tostring_tag>
321 template<class Policies, class Left>
322 struct impl
324 typedef typename unwrap_other<Left>::type left_t;
325 typedef detail::null_type right_t;
326 static inline operator_id get_id() { return op_tostring; }
327 static inline int execute(lua_State* L)
329 // TODO: Should policies apply to this operator? shouldn't the string returntype be enforced?
330 typedef typename find_conversion_policy<1, Policies>::type converter_policy_left;
331 typename converter_policy_left::template generate_converter<left_t, lua_to_cpp>::type converter_left;
332 std::stringstream s;
333 s << converter_left.apply(L, LUABIND_DECORATE_TYPE(left_t), 1) << std::ends;
334 return convert_result(L, s.str(), static_cast<const Policies*>(0));
336 static inline int match(lua_State* L)
338 return match_params(L, 1, static_cast<constructor<left_t>*>(0), static_cast<Policies*>(0));
344 inline detail::operator_<detail::op_tostring_tag, detail::self_t, detail::null_type> tostring(const detail::self_t&)
346 return detail::operator_<detail::op_tostring_tag, detail::self_t, detail::null_type>();
348 inline detail::operator_<detail::op_tostring_tag, detail::const_self_t, detail::null_type> tostring(const detail::const_self_t&)
350 return detail::operator_<detail::op_tostring_tag, detail::const_self_t, detail::null_type>();
354 #undef LUABIND_UNARY_OPERATOR
355 #undef LUABIND_MSVC6_NO_TYPENAME
358 #endif // LUABIND_OPERATORS_HPP_INCLUDED
361 #elif BOOST_PP_ITERATION_FLAGS() == 1
363 #define LUABIND_DECL(z,n,_) typedef typename find_conversion_policy<n + 1, Policies>::type BOOST_PP_CAT(converter_policy,n); \
364 typedef typename unwrap_other<A##n>::type unwrapped_a##n; \
365 typename BOOST_PP_CAT(converter_policy,n)::template generate_converter<unwrapped_a##n, lua_to_cpp>::type BOOST_PP_CAT(c,n);
367 #define LUABIND_PARAM(z,n,_) BOOST_PP_CAT(c,n).apply(L, LUABIND_DECORATE_TYPE(unwrapped_a##n), n+2)
369 template<>
370 struct execute_selector<BOOST_PP_ITERATION()>
372 template<class Signature, bool Constant, class Self_, class Policies>
373 struct apply
375 static inline int execute(lua_State* L)
377 return execute_impl(L, static_cast<const Signature*>(0));
380 template<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, class A)>
381 static inline int execute_impl(
382 lua_State* L,
383 const constructor<BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A)>*)
385 // TODO: use policies here, instead of default_policy, or shouldn't we?
386 typename boost::mpl::apply_if_c<Constant,
387 LUABIND_MSVC6_NO_TYPENAME default_policy::template generate_converter<const Self_&, lua_to_cpp>,
388 LUABIND_MSVC6_NO_TYPENAME default_policy::template generate_converter<Self_&, lua_to_cpp>
389 >::type conv_self;
391 typedef typename boost::mpl::if_c<Constant,
392 const Self_,
393 Self_
394 >::type Self;
396 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_DECL, _)
398 return convert_result(L, LUABIND_CONVERT_PARAMETER
400 BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_PARAM, _)
401 ), static_cast<const Policies*>(0));
406 #undef LUABIND_DECL
407 #undef LUABIND_PARAM
409 #elif BOOST_PP_ITERATION_FLAGS() == 2 // self_t
411 #define LUABIND_UNWRAP_PARAM(z,n,_) A##n
413 #if BOOST_PP_ITERATION() > 0
414 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
415 #endif
416 application_operator< constructor<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_UNWRAP_PARAM, _)>, false>*
417 operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) { return 0; }
419 #undef LUABIND_UNWRAP_PARAM
421 #elif BOOST_PP_ITERATION_FLAGS() == 3 // const_self_t
423 #define LUABIND_UNWRAP_PARAM(z,n,_) A##n
425 #if BOOST_PP_ITERATION() > 0
426 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
427 #endif
428 application_operator< constructor<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_UNWRAP_PARAM, _)>, true>*
429 operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), A)) { return 0; }
431 #undef LUABIND_UNWRAP_PARAM
433 #endif