1 // Copyright (c) 2004 Daniel Wallin and Arvid Norberg 2 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: 9 10 // The above copyright notice and this permission notice shall be included 11 // in all copies or substantial portions of the Software. 12 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. 22 23 #ifndef OPERATOR_040729_HPP 24 #define OPERATOR_040729_HPP 25 26 #include <luabind/detail/other.hpp> 27 #include <luabind/raw_policy.hpp> 28 29 #include <boost/mpl/apply_wrap.hpp> 30 #include <boost/mpl/eval_if.hpp> 31 #include <boost/mpl/identity.hpp> 32 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 33 #include <boost/preprocessor/repetition/enum_params.hpp> 34 #include <boost/preprocessor/repetition/enum_trailing.hpp> 35 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 36 #include <boost/type_traits/is_same.hpp> 37 38 #if defined(__GNUC__) && __GNUC__ < 3 39 # define LUABIND_NO_STRINGSTREAM 40 #else 41 # if defined(BOOST_NO_STRINGSTREAM) 42 # define LUABIND_NO_STRINGSTREAM 43 # endif 44 #endif 45 46 #ifdef LUABIND_NO_STRINGSTREAM 47 #include <strstream> 48 #else 49 #include <sstream> 50 #endif 51 52 namespace luabind { namespace detail { 53 54 template<class W, class T> struct unwrap_parameter_type; 55 template<class Derived> struct operator_ {}; 56 57 struct operator_void_return {}; 58 59 template<class T> operator ,(T const & x,operator_void_return)60 inline T const& operator,(T const& x, operator_void_return) 61 { 62 return x; 63 } 64 65 }} // namespace luabind 66 67 #include <boost/preprocessor/iteration/iterate.hpp> 68 69 namespace luabind { namespace operators { 70 71 #define BOOST_PP_ITERATION_PARAMS_1 (3, \ 72 (0, LUABIND_MAX_ARITY, <luabind/detail/call_operator_iterate.hpp>)) 73 #include BOOST_PP_ITERATE() 74 75 }} // namespace luabind::operators 76 77 #include <boost/preprocessor/iteration/local.hpp> 78 79 namespace luabind { 80 81 template<class Derived> 82 struct self_base 83 { operator ()luabind::self_base84 operators::call_operator0<Derived> operator()() const 85 { 86 return 0; 87 } 88 89 #define BOOST_PP_LOCAL_MACRO(n) \ 90 template<BOOST_PP_ENUM_PARAMS(n, class A)> \ 91 BOOST_PP_CAT(operators::call_operator, n)< \ 92 Derived \ 93 BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \ 94 >\ 95 operator()( \ 96 BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \ 97 ) const \ 98 { \ 99 return 0; \ 100 } 101 102 #define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY) 103 #include BOOST_PP_LOCAL_ITERATE() 104 105 }; 106 107 struct self_type : self_base<self_type> 108 { 109 }; 110 111 struct const_self_type : self_base<const_self_type> 112 { 113 }; 114 115 namespace detail { 116 117 template<class W, class T> 118 struct unwrap_parameter_type 119 { 120 typedef typename boost::mpl::eval_if< 121 boost::is_same<T, self_type> 122 , boost::mpl::identity<W&> 123 , boost::mpl::eval_if< 124 boost::is_same<T, const_self_type> 125 , boost::mpl::identity<W const&> 126 , unwrap_other<T> 127 > 128 >::type type; 129 }; 130 131 template<class Derived, class A, class B> 132 struct binary_operator 133 : operator_<binary_operator<Derived, A, B> > 134 { binary_operatorluabind::detail::binary_operator135 binary_operator(int) {} 136 137 template<class T, class Policies> 138 struct apply 139 { 140 typedef typename unwrap_parameter_type<T, A>::type arg0; 141 typedef typename unwrap_parameter_type<T, B>::type arg1; 142 executeluabind::detail::binary_operator::apply143 static void execute(lua_State* L, arg0 _0, arg1 _1) 144 { 145 Derived::template apply<arg0, arg1, Policies>::execute( 146 L, _0, _1); 147 } 148 }; 149 nameluabind::detail::binary_operator150 static char const* name() 151 { 152 return Derived::name(); 153 } 154 }; 155 156 template<class Derived, class A> 157 struct unary_operator 158 : operator_<unary_operator<Derived, A> > 159 { unary_operatorluabind::detail::unary_operator160 unary_operator(int) {} 161 162 template<class T, class Policies> 163 struct apply 164 { 165 typedef typename unwrap_parameter_type<T, A>::type arg0; 166 executeluabind::detail::unary_operator::apply167 static void execute(lua_State* L, arg0 _0) 168 { 169 Derived::template apply<arg0, Policies>::execute(L, _0); 170 } 171 }; 172 nameluabind::detail::unary_operator173 static char const* name() 174 { 175 return Derived::name(); 176 } 177 }; 178 179 template<class Policies> operator_result(lua_State *,operator_void_return,Policies *)180 inline void operator_result(lua_State*, operator_void_return, Policies*) 181 { 182 } 183 184 namespace mpl = boost::mpl; 185 186 template<class T, class Policies> operator_result(lua_State * L,T const & x,Policies *)187 inline void operator_result(lua_State* L, T const& x, Policies*) 188 { 189 typedef typename find_conversion_policy< 190 0 191 , Policies 192 >::type cv_policy; 193 194 typename mpl::apply_wrap2<cv_policy,T,cpp_to_lua>::type cv; 195 196 cv.apply(L, x); 197 } 198 199 }} // namespace detail::luabind 200 201 namespace luabind { 202 203 #define LUABIND_BINARY_OPERATOR(name_, op) \ 204 namespace operators { \ 205 \ 206 struct name_ \ 207 { \ 208 template<class T0, class T1, class Policies> \ 209 struct apply \ 210 { \ 211 static void execute(lua_State* L, T0 _0, T1 _1) \ 212 { \ 213 detail::operator_result(L, _0 op _1, static_cast<Policies*>(0)); \ 214 } \ 215 }; \ 216 \ 217 static char const* name() \ 218 { \ 219 return "__" # name_; \ 220 } \ 221 }; \ 222 \ 223 } \ 224 \ 225 template<class T, class U> \ 226 detail::binary_operator< \ 227 operators::name_ \ 228 , U \ 229 , T \ 230 > \ 231 inline operator op(self_base<U>, T const&) \ 232 { \ 233 return 0; \ 234 } \ 235 \ 236 template<class T, class U> \ 237 detail::binary_operator< \ 238 operators::name_ \ 239 , T \ 240 , U \ 241 > \ 242 inline operator op(T const&, self_base<U>) \ 243 { \ 244 return 0; \ 245 } \ 246 \ 247 detail::binary_operator< \ 248 operators::name_ \ 249 , self_type \ 250 , self_type \ 251 > \ 252 inline operator op(self_type, self_type) \ 253 { \ 254 return 0; \ 255 } \ 256 \ 257 detail::binary_operator< \ 258 operators::name_ \ 259 , self_type \ 260 , const_self_type \ 261 > \ 262 inline operator op(self_type, const_self_type) \ 263 { \ 264 return 0; \ 265 } \ 266 \ 267 detail::binary_operator< \ 268 operators::name_ \ 269 , const_self_type \ 270 , self_type \ 271 > \ 272 inline operator op(const_self_type, self_type) \ 273 { \ 274 return 0; \ 275 } \ 276 \ 277 detail::binary_operator< \ 278 operators::name_ \ 279 , const_self_type \ 280 , const_self_type \ 281 > \ 282 inline operator op(const_self_type, const_self_type) \ 283 { \ 284 return 0; \ 285 } 286 287 LUABIND_BINARY_OPERATOR(add, +) 288 LUABIND_BINARY_OPERATOR(sub, -) 289 LUABIND_BINARY_OPERATOR(mul, *) 290 LUABIND_BINARY_OPERATOR(div, /) 291 LUABIND_BINARY_OPERATOR(mod, %) 292 LUABIND_BINARY_OPERATOR(pow, ^) 293 LUABIND_BINARY_OPERATOR(lt, <) 294 LUABIND_BINARY_OPERATOR(le, <=) 295 LUABIND_BINARY_OPERATOR(eq, ==) 296 297 #undef LUABIND_BINARY_OPERATOR 298 299 #define LUABIND_UNARY_OPERATOR(name_, op, fn) \ 300 namespace operators { \ 301 \ 302 struct name_ \ 303 { \ 304 template<class T, class Policies> \ 305 struct apply \ 306 { \ 307 static void execute(lua_State* L, T x) \ 308 { \ 309 detail::operator_result(L, op(x), static_cast<Policies*>(0)); \ 310 } \ 311 }; \ 312 \ 313 static char const* name() \ 314 { \ 315 return "__" # name_; \ 316 } \ 317 }; \ 318 \ 319 } \ 320 \ 321 template<class T> \ 322 detail::unary_operator< \ 323 operators::name_ \ 324 , T \ 325 > \ 326 inline fn(self_base<T>) \ 327 { \ 328 return 0; \ 329 } 330 331 template<class T> tostring_operator(T const & x)332 std::string tostring_operator(T const& x) 333 { 334 #ifdef LUABIND_NO_STRINGSTREAM 335 std::strstream s; 336 s << x << std::ends; 337 #else 338 std::stringstream s; 339 s << x; 340 #endif 341 return s.str(); 342 } 343 344 LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring) 345 LUABIND_UNARY_OPERATOR(unm, -, operator-) 346 347 #undef LUABIND_UNARY_OPERATOR 348 349 // defined in operator.cpp 350 LUABIND_API extern self_type self; 351 LUABIND_API extern const_self_type const_self; 352 } // namespace luabind 353 354 #endif // OPERATOR_040729_HPP 355