diff --git a/docs/source/api/compatibility.rst b/docs/source/api/compatibility.rst index b5e9069d..3299bff9 100644 --- a/docs/source/api/compatibility.rst +++ b/docs/source/api/compatibility.rst @@ -7,6 +7,8 @@ This is a detail header used to maintain compatability with the 5.2 and 5.3 APIs It is not fully documented as this header's only purpose is for internal use to make sure Sol compiles across all platforms / distributions with no errors or missing Lua functionality. If you think there's some compatibility features we are missing or if you are running into redefinition errors, please make an `issue in the issue tracker`_. +If you have this already in your project or you have your own compatibility layer, then please ``#define SOL_NO_COMPAT 1`` before including ``sol.hpp`` or pass this flag on the command line to turn off the compatibility wrapper. + For the licenses, see :doc:`here<../licenses>` .. _issue in the issue tracker: https://github.com/ThePhD/sol2/issues/ diff --git a/sol/bind_traits.hpp b/sol/bind_traits.hpp index 0a30e932..5b18b403 100644 --- a/sol/bind_traits.hpp +++ b/sol/bind_traits.hpp @@ -1,218 +1,242 @@ -#pragma once +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_BIND_TRAITS_HPP +#define SOL_BIND_TRAITS_HPP #include "tuple.hpp" namespace sol { -namespace meta { -namespace meta_detail { + namespace meta { + namespace meta_detail { -template -struct check_deducible_signature { - struct nat {}; - template - static auto test(int) -> decltype(&G::operator(), void()); - template - static auto test(...) -> nat; + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...)->nat; - using type = std::is_void(0))>; -}; -} // meta_detail + using type = std::is_void(0))>; + }; + } // meta_detail -template -struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; -namespace meta_detail { + namespace meta_detail { -template -struct void_tuple_element : meta::tuple_element {}; + template + struct void_tuple_element : meta::tuple_element {}; -template -struct void_tuple_element> { typedef void type; }; + template + struct void_tuple_element> { typedef void type; }; -template -using void_tuple_element_t = typename void_tuple_element::type; + template + using void_tuple_element_t = typename void_tuple_element::type; -template -struct basic_traits { -private: - typedef std::conditional_t::value, int, T>& first_type; + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; -public: - static const bool is_member_function = std::is_void::value; - static const bool has_c_var_arg = has_c_variadic; - static const std::size_t arity = sizeof...(Args); - static const std::size_t free_arity = sizeof...(Args) + static_cast(!std::is_void::value); - typedef types args_list; - typedef std::tuple args_tuple; - typedef T object_type; - typedef R return_type; - typedef tuple_types returns_list; - typedef R(function_type)(Args...); - typedef std::conditional_t::value, args_list, types> free_args_list; - typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; - typedef std::conditional_t::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; - typedef std::remove_pointer_t signature_type; - template - using arg_at = void_tuple_element_t; -}; + public: + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args)+static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; -template::value> -struct fx_traits : basic_traits {}; + template::value> + struct fx_traits : basic_traits {}; -// Free Functions -template -struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...); -}; + // Free Functions + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; -template -struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...); -}; + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; -template -struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...); -}; + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; -template -struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...); -}; + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; -// Member Functions -/* C-Style Variadics */ -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...); -}; + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...); -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; -/* Const Volatile */ -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const; -}; + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; -/* Member Function Qualifiers */ -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) &; -}; + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) &; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const &; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const &; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile &; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && ; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && ; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &&; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &&; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &&; + }; -template -struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; -}; + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; + }; -template -struct fx_traits : fx_traits::function_type, false> {}; + template + struct fx_traits : fx_traits::function_type, false> {}; -template::value> -struct callable_traits : fx_traits> { + template::value> + struct callable_traits : fx_traits> { -}; + }; -template -struct callable_traits { - typedef R Arg; - typedef T object_type; - using signature_type = R(T::*); - static const bool is_member_function = false; - static const std::size_t arity = 1; - static const std::size_t free_arity = 2; - typedef std::tuple args_tuple; - typedef R return_type; - typedef types args_list; - typedef meta::tuple_types returns_list; - typedef R(function_type)(T&, R); - typedef R(*function_pointer_type)(T&, R); - typedef R(*free_function_pointer_type)(T&, R); - template - using arg_at = void_tuple_element_t; -}; -} // meta_detail + template + struct callable_traits { + typedef R Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef R return_type; + typedef types args_list; + typedef meta::tuple_types returns_list; + typedef R(function_type)(T&, R); + typedef R(*function_pointer_type)(T&, R); + typedef R(*free_function_pointer_type)(T&, R); + template + using arg_at = void_tuple_element_t; + }; + } // meta_detail -template -struct bind_traits : meta_detail::callable_traits {}; + template + struct bind_traits : meta_detail::callable_traits {}; -template -using function_args_t = typename bind_traits::args_list; + template + using function_args_t = typename bind_traits::args_list; -template -using function_signature_t = typename bind_traits::signature_type; + template + using function_signature_t = typename bind_traits::signature_type; -template -using function_return_t = typename bind_traits::return_type; + template + using function_return_t = typename bind_traits::return_type; -} // meta -} // sol \ No newline at end of file + } // meta +} // sol + +#endif // SOL_BIND_TRAITS diff --git a/sol/call.hpp b/sol/call.hpp index 94201548..45796c0b 100644 --- a/sol/call.hpp +++ b/sol/call.hpp @@ -1,6 +1,6 @@ // The MIT License (MIT) -// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in @@ -26,294 +26,114 @@ #include "property.hpp" #include "stack.hpp" -namespace sol { -namespace call_detail { - - template - inline decltype(auto) pick(std::integral_constant, F&& f) { - return std::forward(f); - } +namespace sol { + namespace call_detail { - template - inline auto& pick(std::true_type, property_wrapper& f) { - return f.read; - } - - template - inline auto& pick(std::false_type, property_wrapper& f) { - return f.write; - } - - template - struct void_call; - - template - struct void_call> { - static void call(Args...) {} - }; - - template - struct constructor_match { - T* obj; - - constructor_match(T* obj) : obj(obj) {} - - template - int operator()(types, index_value, types r, types a, lua_State* L, int, int start) const { - detail::default_construct func{}; - return stack::call_into_lua(r, a, L, start, func, obj); - } - }; - - template - inline int destruct(lua_State* L) { - T* obj = stack::get>(L, 1); - std::allocator alloc{}; - alloc.destroy(obj); - return 0; - } - - namespace overload_detail { - template - inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence, Match&&, lua_State* L, int, int, Args&&...) { - return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + template + inline decltype(auto) pick(std::integral_constant, F&& f) { + return std::forward(f); } - template - inline int overload_match_arity(sol::types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; - typedef meta::tuple_types return_types; - typedef typename traits::free_args_list args_list; - typedef typename args_list::indices args_indices; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v, index_value...>::value) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + template + inline auto& pick(std::true_type, property_wrapper& f) { + return f.read; + } + + template + inline auto& pick(std::false_type, property_wrapper& f) { + return f.write; + } + + template + struct void_call; + + template + struct void_call> { + static void call(Args...) {} + }; + + template + struct constructor_match { + T* obj; + + constructor_match(T* obj) : obj(obj) {} + + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start) const { + detail::default_construct func{}; + return stack::call_into_lua(r, a, L, start, func, obj); } - if (traits::free_arity != fxarity) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - if (!stack::stack_detail::check_types().check(args_list(), args_indices(), L, start, no_panic)) { - return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); - } - } // overload_detail + }; - template - inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - - template - inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { - int fxarity = lua_gettop(L) - (start - 1); - return overload_match_arity(std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - - template - inline int construct(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - // use same overload resolution matching as all other parts of the framework - return overload_match_arity::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); - } - - template - inline int construct(lua_State* L) { - static const auto& meta = usertype_traits::metatable; - int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot; - argcount -= static_cast(syntax); - - T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast(pointerpointer + 1); - referencepointer = obj; - reference userdataref(L, -1); - userdataref.pop(); - - construct(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); - - userdataref.push(); - luaL_getmetatable(L, &meta[0]); - if (type_of(L, -1) == type::nil) { - lua_pop(L, 1); - return luaL_error(L, "sol: unable to get usertype metatable"); - } - - lua_setmetatable(L, -2); - return 1; - } - - template - struct agnostic_lua_call_wrapper { - static int var_call(std::true_type, lua_State* L, F& f) { - typedef wrapper> wrap; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::free_args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f); - } - - static int var_call(std::false_type, lua_State* L, F& f) { - typedef wrapper> wrap; - typedef typename wrap::free_args_list args_list; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f); - } - - static int call(lua_State* L, F& f) { - return var_call(std::integral_constant(), L, f); - } - }; - - template - struct agnostic_lua_call_wrapper::value>> { - static int call(lua_State* L, F& f) { - typedef wrapper> wrap; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - typedef typename wrap::object_type object_type; - -#ifdef SOL_SAFE_USERTYPE - object_type* o = stack::get(L, 1); - if (o == nullptr) { - return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); - } - return stack::call_into_lua(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o); -#else - object_type& o = stack::get(L, 1); - return stack::call_into_lua(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o); -#endif // Safety - } - }; - - template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, lua_r_CFunction f) { - return f(L); - } - }; - - template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, lua_CFunction f) { - return f(L); - } - }; - - template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, no_prop&) { - return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); - } - }; - - template - struct agnostic_lua_call_wrapper::value>> { - typedef sol::lua_bind_traits traits_type; - - static int call_assign(std::true_type, lua_State* L, F& f) { - typedef wrapper> wrap; - typedef typename wrap::args_list args_list; - typedef typename wrap::object_type object_type; - typedef typename wrap::caller caller; -#ifdef SOL_SAFE_USERTYPE - object_type* o = stack::get(L, 1); - if (o == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); - } - return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); - } - return stack::call_into_lua(types(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o); -#else - object_type& o = stack::get(L, 1); - return stack::call_into_lua(types(), args_list(), L, is_variable ? 3 : 2, caller(), f, o); -#endif // Safety - } - - static int call_assign(std::false_type, lua_State* L, F&) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - static int call_const(std::false_type, lua_State* L, F& f) { - typedef typename traits_type::return_type R; - return call_assign(std::is_assignable>, R>(), L, f); - } - - static int call_const(std::true_type, lua_State* L, F&) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - static int call(lua_State* L, F& f) { - return call_const(std::is_const(), L, f); - } - }; - - template - struct agnostic_lua_call_wrapper::value>> { - typedef sol::lua_bind_traits traits_type; - - static int call(lua_State* L, F& f) { - typedef wrapper> wrap; - typedef typename wrap::object_type object_type; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; -#ifdef SOL_SAFE_USERTYPE - object_type* o = stack::get(L, 1); - if (o == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); - } - return stack::call_into_lua(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o); -#else - object_type& o = stack::get(L, 1); - return stack::call_into_lua(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o); -#endif // Safety - } - }; - - template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, no_construction&) { - return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); - } - }; - - template - struct agnostic_lua_call_wrapper, is_index, is_variable, C> { - static int call(lua_State*, bases&) { - // Uh. How did you even call this, lul + template + inline int destruct(lua_State* L) { + T* obj = stack::get>(L, 1); + std::allocator alloc{}; + alloc.destroy(obj); return 0; } - }; - template - struct lua_call_wrapper : agnostic_lua_call_wrapper {}; + namespace overload_detail { + template + inline int overload_match_arity(sol::types<>, std::index_sequence<>, std::index_sequence, Match&&, lua_State* L, int, int, Args&&...) { + return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + } - template - struct lua_call_wrapper, is_index, is_variable, C> { - typedef sol::constructor_list F; + template + inline int overload_match_arity(sol::types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + typedef typename args_list::indices args_indices; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (!stack::stack_detail::check_types().check(args_list(), args_indices(), L, start, no_panic)) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } // overload_detail - static int call(lua_State* L, F&) { - static const auto& metakey = usertype_traits::metatable; + template + inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_detail::overload_match_arity(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { + int fxarity = lua_gettop(L) - (start - 1); + return overload_match_arity(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + // use same overload resolution matching as all other parts of the framework + return overload_match_arity::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct(lua_State* L) { + static const auto& meta = usertype_traits::metatable; int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot; argcount -= static_cast(syntax); T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - reference userdataref(L, -1); T*& referencepointer = *pointerpointer; T* obj = reinterpret_cast(pointerpointer + 1); referencepointer = obj; - - construct(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); + reference userdataref(L, -1); + userdataref.pop(); + + construct(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); userdataref.push(); - luaL_getmetatable(L, &metakey[0]); + luaL_getmetatable(L, &meta[0]); if (type_of(L, -1) == type::nil) { lua_pop(L, 1); return luaL_error(L, "sol: unable to get usertype metatable"); @@ -322,108 +142,288 @@ namespace call_detail { lua_setmetatable(L, -2); return 1; } - }; - template - struct lua_call_wrapper, is_index, is_variable, C> { - typedef sol::constructor_wrapper F; + template + struct agnostic_lua_call_wrapper { + static int var_call(std::true_type, lua_State* L, F& f) { + typedef wrapper> wrap; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::free_args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f); + } + + static int var_call(std::false_type, lua_State* L, F& f) { + typedef wrapper> wrap; + typedef typename wrap::free_args_list args_list; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, 1, caller(), f); + } + + static int call(lua_State* L, F& f) { + return var_call(std::integral_constant(), L, f); + } + }; + + template + struct agnostic_lua_call_wrapper::value>> { + static int call(lua_State* L, F& f) { + typedef wrapper> wrap; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + typedef typename wrap::object_type object_type; + +#ifdef SOL_SAFE_USERTYPE + object_type* o = stack::get(L, 1); + if (o == nullptr) { + return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); + } + return stack::call_into_lua(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o); +#else + object_type& o = stack::get(L, 1); + return stack::call_into_lua(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o); +#endif // Safety + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_r_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, no_prop&) { + return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); + } + }; + + template + struct agnostic_lua_call_wrapper::value>> { + typedef sol::lua_bind_traits traits_type; + + static int call_assign(std::true_type, lua_State* L, F& f) { + typedef wrapper> wrap; + typedef typename wrap::args_list args_list; + typedef typename wrap::object_type object_type; + typedef typename wrap::caller caller; +#ifdef SOL_SAFE_USERTYPE + object_type* o = stack::get(L, 1); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + return stack::call_into_lua(types(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o); +#else + object_type& o = stack::get(L, 1); + return stack::call_into_lua(types(), args_list(), L, is_variable ? 3 : 2, caller(), f, o); +#endif // Safety + } + + static int call_assign(std::false_type, lua_State* L, F&) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + static int call_const(std::false_type, lua_State* L, F& f) { + typedef typename traits_type::return_type R; + return call_assign(std::is_assignable>, R>(), L, f); + } + + static int call_const(std::true_type, lua_State* L, F&) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + static int call(lua_State* L, F& f) { + return call_const(std::is_const(), L, f); + } + }; + + template + struct agnostic_lua_call_wrapper::value>> { + typedef sol::lua_bind_traits traits_type; + + static int call(lua_State* L, F& f) { + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; +#ifdef SOL_SAFE_USERTYPE + object_type* o = stack::get(L, 1); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); + } + return stack::call_into_lua(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o); +#else + object_type& o = stack::get(L, 1); + return stack::call_into_lua(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o); +#endif // Safety + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, no_construction&) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + }; + + template + struct agnostic_lua_call_wrapper, is_index, is_variable, C> { + static int call(lua_State*, bases&) { + // Uh. How did you even call this, lul + return 0; + } + }; + + template + struct lua_call_wrapper : agnostic_lua_call_wrapper {}; + + template + struct lua_call_wrapper, is_index, is_variable, C> { + typedef sol::constructor_list F; + + static int call(lua_State* L, F&) { + static const auto& metakey = usertype_traits::metatable; + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot; + argcount -= static_cast(syntax); - struct onmatch { - template - int operator()(types, index_value, types r, types a, lua_State* L, int, int start, F& f) { T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); reference userdataref(L, -1); T*& referencepointer = *pointerpointer; T* obj = reinterpret_cast(pointerpointer + 1); referencepointer = obj; - auto& func = std::get(f.set); - stack::call_into_lua<1, false>(r, a, L, start, func, detail::implicit_wrapper(obj)); + construct(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); userdataref.push(); - luaL_getmetatable(L, &usertype_traits::metatable[0]); + luaL_getmetatable(L, &metakey[0]); if (type_of(L, -1) == type::nil) { lua_pop(L, 1); - std::string err = "sol: unable to get usertype metatable for "; - err += usertype_traits::name; - return luaL_error(L, err.c_str()); + return luaL_error(L, "sol: unable to get usertype metatable"); } - lua_setmetatable(L, -2); + lua_setmetatable(L, -2); return 1; } }; - static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, usertype_traits::metatable); - int syntaxval = static_cast(syntax); - int argcount = lua_gettop(L) - syntaxval; - return construct>...>(onmatch(), L, argcount, 1 + syntaxval, f); - } + template + struct lua_call_wrapper, is_index, is_variable, C> { + typedef sol::constructor_wrapper F; - }; + struct onmatch { + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start, F& f) { + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; - template - struct lua_call_wrapper, is_index, is_variable, std::enable_if_t::value>> { - typedef sol::destructor_wrapper F; + auto& func = std::get(f.set); + stack::call_into_lua<1, false>(r, a, L, start, func, detail::implicit_wrapper(obj)); - static int call(lua_State* L, F&) { - return destruct(L); - } - }; + userdataref.push(); + luaL_getmetatable(L, &usertype_traits::metatable[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + std::string err = "sol: unable to get usertype metatable for "; + err += usertype_traits::name; + return luaL_error(L, err.c_str()); + } + lua_setmetatable(L, -2); - template - struct lua_call_wrapper, is_index, is_variable, std::enable_if_t::value>> { - typedef sol::destructor_wrapper F; + return 1; + } + }; - static int call(lua_State* L, F& f) { - T* obj = stack::get>(L); - f.fx(detail::implicit_wrapper(obj)); - return 0; - } - }; + static int call(lua_State* L, F& f) { + call_syntax syntax = stack::get_call_syntax(L, usertype_traits::metatable); + int syntaxval = static_cast(syntax); + int argcount = lua_gettop(L) - syntaxval; + return construct>...>(onmatch(), L, argcount, 1 + syntaxval, f); + } - template - struct lua_call_wrapper, is_index, is_variable, C> { - typedef overload_set F; + }; - struct on_match { - template - int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { - auto& f = std::get(fx.set); - return lua_call_wrapper{}.call(L, f); + template + struct lua_call_wrapper, is_index, is_variable, std::enable_if_t::value>> { + typedef sol::destructor_wrapper F; + + static int call(lua_State* L, F&) { + return destruct(L); } }; - static int call(lua_State* L, F& fx) { - return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + template + struct lua_call_wrapper, is_index, is_variable, std::enable_if_t::value>> { + typedef sol::destructor_wrapper F; + + static int call(lua_State* L, F& f) { + T* obj = stack::get>(L); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, C> { + typedef overload_set F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.set); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + int call_wrapped(lua_State* L, Fx&& fx) { + return lua_call_wrapper, is_index, is_variable>{}.call(L, std::forward(fx)); } - }; - template - int call_wrapped(lua_State* L, Fx&& fx) { - return lua_call_wrapper, is_index, is_variable>{}.call(L, std::forward(fx)); - } + template + struct is_var_bind : std::false_type {}; - template - struct is_var_bind : std::false_type {}; + template + struct is_var_bind::value>> : std::true_type {}; + + template <> + struct is_var_bind : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + + } // call_detail template - struct is_var_bind::value>> : std::true_type {}; + struct is_variable_binding : call_detail::is_var_bind> {}; - template <> - struct is_var_bind : std::true_type {}; - - template - struct is_var_bind> : std::true_type {}; - -} // call_detail - -template -struct is_variable_binding : call_detail::is_var_bind> {}; - -template -struct is_function_binding : meta::neg> {}; + template + struct is_function_binding : meta::neg> {}; } // sol diff --git a/sol/compatibility.hpp b/sol/compatibility.hpp index 374074d5..81e7742d 100644 --- a/sol/compatibility.hpp +++ b/sol/compatibility.hpp @@ -27,9 +27,10 @@ // but has been modified in many places for use with Sol and luajit, // though the core abstractions remain the same +#include "compatibility/version.hpp" + #ifndef SOL_NO_COMPAT -#include "compatibility/version.hpp" #ifdef __cplusplus extern "C" { #endif diff --git a/sol/coroutine.hpp b/sol/coroutine.hpp index 5d442bdc..3060d657 100644 --- a/sol/coroutine.hpp +++ b/sol/coroutine.hpp @@ -28,88 +28,89 @@ #include "thread.hpp" namespace sol { -class coroutine : public reference { -private: - call_status stats = call_status::yielded; + class coroutine : public reference { + private: + call_status stats = call_status::yielded; - void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { #if SOL_LUA_VERSION < 502 - stats = static_cast(lua_resume(lua_state(), static_cast(argcount))); + stats = static_cast(lua_resume(lua_state(), static_cast(argcount))); #else - stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount))); + stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount))); #endif // Lua 5.1 compat - } + } - template - auto invoke( types, std::index_sequence, std::ptrdiff_t n ) { - luacall(n, sizeof...(Ret)); - return stack::pop>(lua_state()); - } + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, sizeof...(Ret)); + return stack::pop>(lua_state()); + } - template - Ret invoke(types, std::index_sequence, std::ptrdiff_t n) { - luacall(n, 1); - return stack::pop(lua_state()); - } + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 1); + return stack::pop(lua_state()); + } - template - void invoke(types, std::index_sequence, std::ptrdiff_t n) { - luacall(n, 0); - } + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 0); + } - protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { - int stacksize = lua_gettop( lua_state() ); - int firstreturn = (std::max)( 1, stacksize - static_cast( n ) ); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop(lua_state()); - int returncount = poststacksize - (firstreturn - 1); - return protected_function_result( lua_state( ), firstreturn, returncount, returncount, status() ); - } + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { + int stacksize = lua_gettop(lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); + } -public: - coroutine() noexcept = default; - coroutine(const coroutine&) noexcept = default; - coroutine& operator=(const coroutine&) noexcept = default; - coroutine(lua_State* L, int index = -1) : reference(L, index) { + public: + coroutine() noexcept = default; + coroutine(const coroutine&) noexcept = default; + coroutine& operator=(const coroutine&) noexcept = default; + coroutine(lua_State* L, int index = -1) : reference(L, index) { #ifdef SOL_CHECK_ARGUMENTS - stack::check(L, index, type_panic); + stack::check(L, index, type_panic); #endif // Safety - } + } - call_status status() const noexcept { - return stats; - } + call_status status() const noexcept { + return stats; + } - bool error() const noexcept { - call_status cs = status(); - return cs != call_status::ok && cs != call_status::yielded; - } + bool error() const noexcept { + call_status cs = status(); + return cs != call_status::ok && cs != call_status::yielded; + } - bool runnable () const noexcept { - return valid() - && (status() == call_status::yielded); - } + bool runnable() const noexcept { + return valid() + && (status() == call_status::yielded); + } - explicit operator bool() const noexcept { - return runnable(); - } + explicit operator bool() const noexcept { + return runnable(); + } - template - protected_function_result operator()( Args&&... args ) { - return call<>( std::forward( args )... ); - } + template + protected_function_result operator()(Args&&... args) { + return call<>(std::forward(args)...); + } - template - decltype(auto) operator()( types, Args&&... args ) { - return call( std::forward( args )... ); - } + template + decltype(auto) operator()(types, Args&&... args) { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) { + push(); + int pushcount = stack::multi_push(lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; +} // sol - template - decltype(auto) call( Args&&... args ) { - push(); - int pushcount = stack::multi_push( lua_state(), std::forward( args )... ); - return invoke( types( ), std::make_index_sequence(), pushcount ); - } -}; -} #endif // SOL_COUROUTINE_HPP diff --git a/sol/debug.hpp b/sol/debug.hpp index 061792f6..08180051 100644 --- a/sol/debug.hpp +++ b/sol/debug.hpp @@ -26,29 +26,29 @@ #include namespace sol { -namespace detail { -namespace debug { -inline std::string dump_types(lua_State* L) { - std::string visual; - std::size_t size = lua_gettop(L) + 1; - for(std::size_t i = 1; i < size; ++i) { - if(i != 1) { - visual += " | "; - } - visual += type_name(L, stack::get(L, static_cast(i))); - } - return visual; -} + namespace detail { + namespace debug { + inline std::string dump_types(lua_State* L) { + std::string visual; + std::size_t size = lua_gettop(L) + 1; + for (std::size_t i = 1; i < size; ++i) { + if (i != 1) { + visual += " | "; + } + visual += type_name(L, stack::get(L, static_cast(i))); + } + return visual; + } -inline void print_stack(lua_State* L) { - std::cout << dump_types(L) << std::endl; -} + inline void print_stack(lua_State* L) { + std::cout << dump_types(L) << std::endl; + } -inline void print_section(const std::string& message, lua_State* L) { - std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; -} -} // detail -} // debug + inline void print_section(const std::string& message, lua_State* L) { + std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; + } + } // detail + } // debug } // sol #endif // SOL_DEBUG_HPP diff --git a/sol/demangle.hpp b/sol/demangle.hpp index 5cade575..295fe6de 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -32,121 +32,121 @@ #endif namespace sol { -namespace detail { + namespace detail { #ifdef _MSC_VER #ifndef SOL_NO_RTTI -inline std::string get_type_name(const std::type_info& id) { - std::string realname = id.name(); - const static std::array removals = { { "struct ", "class " } }; - for (std::size_t r = 0; r < removals.size(); ++r) { - auto found = realname.find(removals[r]); - while (found != std::string::npos) { - realname.erase(found, removals[r].size()); - found = realname.find(removals[r]); - } - } - return realname; -} + inline std::string get_type_name(const std::type_info& id) { + std::string realname = id.name(); + const static std::array removals = { { "struct ", "class " } }; + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = realname.find(removals[r]); + while (found != std::string::npos) { + realname.erase(found, removals[r].size()); + found = realname.find(removals[r]); + } + } + return realname; + } #endif // No RTII -template -inline std::string ctti_get_type_name() { - std::string name = __FUNCSIG__; - std::size_t start = name.find("get_type_name"); - if (start == std::string::npos) - start = 0; - else - start += 13; - if (start < name.size() - 1) - start += 1; - std::size_t end = name.find_last_of('>'); - if (end == std::string::npos) - end = name.size(); - name = name.substr(start, end - start); - if (name.find("struct", 0) == 0) - name.replace(0, 6, "", 0); - if (name.find("class", 0) == 0) - name.replace(0, 5, "", 0); - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin()); - while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end()); - return name; -} + template + inline std::string ctti_get_type_name() { + std::string name = __FUNCSIG__; + std::size_t start = name.find("get_type_name"); + if (start == std::string::npos) + start = 0; + else + start += 13; + if (start < name.size() - 1) + start += 1; + std::size_t end = name.find_last_of('>'); + if (end == std::string::npos) + end = name.size(); + name = name.substr(start, end - start); + if (name.find("struct", 0) == 0) + name.replace(0, 6, "", 0); + if (name.find("class", 0) == 0) + name.replace(0, 5, "", 0); + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin()); + while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end()); + return name; + } #elif defined(__GNUC__) || defined(__clang__) -template -inline std::string ctti_get_type_name() { - std::string name = __PRETTY_FUNCTION__; - std::size_t start = name.find_last_of('['); - start = name.find_first_of('=', start); - std::size_t end = name.find_last_of(']'); - if (end == std::string::npos) - end = name.size(); - if (start == std::string::npos) - start = 0; - if (start < name.size() - 1) - start += 1; - name = name.substr(start, end - start); - start = name.find(";"); - if (start != std::string::npos) { - name.erase(start, name.length()); - } - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin()); - while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end()); - return name; -} + template + inline std::string ctti_get_type_name() { + std::string name = __PRETTY_FUNCTION__; + std::size_t start = name.find_last_of('['); + start = name.find_first_of('=', start); + std::size_t end = name.find_last_of(']'); + if (end == std::string::npos) + end = name.size(); + if (start == std::string::npos) + start = 0; + if (start < name.size() - 1) + start += 1; + name = name.substr(start, end - start); + start = name.find(";"); + if (start != std::string::npos) { + name.erase(start, name.length()); + } + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin(), ++name.begin()); + while (!name.empty() && std::isblank(name.back())) name.erase(--name.end(), name.end()); + return name; + } #ifndef SOL_NO_RTTI #if defined(__clang__) -inline std::string get_type_name(const std::type_info& id) { - int status; - char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); - std::string realname = unmangled; - std::free(unmangled); - return realname; -} + inline std::string get_type_name(const std::type_info& id) { + int status; + char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); + std::string realname = unmangled; + std::free(unmangled); + return realname; + } #elif defined(__GNUC__) -inline std::string get_type_name(const std::type_info& id) { - int status; - char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); - std::string realname = unmangled; - std::free(unmangled); - return realname; -} + inline std::string get_type_name(const std::type_info& id) { + int status; + char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status); + std::string realname = unmangled; + std::free(unmangled); + return realname; + } #endif // g++ || clang++ #endif // No RTII #else #error Compiler not supported for demangling #endif // compilers -template -inline std::string demangle_once() { + template + inline std::string demangle_once() { #ifndef SOL_NO_RTTI - std::string realname = get_type_name(typeid(T)); + std::string realname = get_type_name(typeid(T)); #else - std::string realname = ctti_get_type_name(); + std::string realname = ctti_get_type_name(); #endif // No Runtime Type Information - return realname; -} + return realname; + } -template -inline std::string short_demangle_once() { - std::string realname = ctti_get_type_name(); - std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23); - if (idx != std::string::npos) { - realname.erase(0, realname.length() < idx ? realname.length() : idx + 1); - } - return realname; -} + template + inline std::string short_demangle_once() { + std::string realname = ctti_get_type_name(); + std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23); + if (idx != std::string::npos) { + realname.erase(0, realname.length() < idx ? realname.length() : idx + 1); + } + return realname; + } -template -inline std::string demangle() { - static const std::string d = demangle_once(); - return d; -} + template + inline std::string demangle() { + static const std::string d = demangle_once(); + return d; + } -template -inline std::string short_demangle() { - static const std::string d = short_demangle_once(); - return d; -} -} // detail + template + inline std::string short_demangle() { + static const std::string d = short_demangle_once(); + return d; + } + } // detail } // sol #endif // SOL_DEMANGLE_HPP diff --git a/sol/deprecate.hpp b/sol/deprecate.hpp index 8e2f6e09..8636ffb7 100644 --- a/sol/deprecate.hpp +++ b/sol/deprecate.hpp @@ -33,12 +33,15 @@ #endif // SOL_DEPRECATED namespace sol { -namespace detail { - template - struct SOL_DEPRECATED deprecate_type { - using type = T; - }; -} // detail + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + + template + using deprecate_type_t = typename deprecate_type::type; + } // detail } // sol #endif // SOL_DEPRECATE_HPP diff --git a/sol/error.hpp b/sol/error.hpp index 5c170e72..cf85fece 100644 --- a/sol/error.hpp +++ b/sol/error.hpp @@ -26,28 +26,30 @@ #include namespace sol { -namespace detail { -struct direct_error_tag {}; -const auto direct_error = direct_error_tag{}; -} // detail -class error : public std::runtime_error { -private: - // Because VC++ is a fuccboi - std::string w; -public: - error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} - error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} - error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // detail + + class error : public std::runtime_error { + private: + // Because VC++ is a fuccboi + std::string w; + public: + error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} + error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} + error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} - error(const error& e) = default; - error(error&& e) = default; - error& operator=(const error& e) = default; - error& operator=(error&& e) = default; + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; - virtual const char* what() const noexcept override { - return w.c_str(); - } -}; } // sol #endif // SOL_ERROR_HPP diff --git a/sol/function.hpp b/sol/function.hpp index 5fdbb37a..ea6aa372 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -31,106 +31,106 @@ #include namespace sol { -template -class basic_function : public base_t { -private: - void luacall( std::ptrdiff_t argcount, std::ptrdiff_t resultcount ) const { - lua_callk( base_t::lua_state( ), static_cast( argcount ), static_cast( resultcount ), 0, nullptr ); - } + template + class basic_function : public base_t { + private: + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { + lua_callk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), 0, nullptr); + } - template - auto invoke( types, std::index_sequence, std::ptrdiff_t n ) const { - luacall( n, sizeof...( Ret ) ); - return stack::pop>( base_t::lua_state( ) ); - } + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, sizeof...(Ret)); + return stack::pop>(base_t::lua_state()); + } - template - Ret invoke(types, std::index_sequence, std::ptrdiff_t n ) const { - luacall( n, 1 ); - return stack::pop( base_t::lua_state( ) ); - } + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, 1); + return stack::pop(base_t::lua_state()); + } - template - void invoke(types, std::index_sequence, std::ptrdiff_t n) const { - luacall( n, 0 ); - } + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, 0); + } - function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const { - int stacksize = lua_gettop( base_t::lua_state( ) ); - int firstreturn = (std::max)( 1, stacksize - static_cast( n ) ); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop( base_t::lua_state( ) ); - int returncount = poststacksize - (firstreturn - 1); - return function_result( base_t::lua_state( ), firstreturn, returncount ); - } + function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { + int stacksize = lua_gettop(base_t::lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(base_t::lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return function_result(base_t::lua_state(), firstreturn, returncount); + } -public: - basic_function() = default; - basic_function(const basic_function&) = default; - basic_function& operator=(const basic_function&) = default; - basic_function(basic_function&&) = default; - basic_function& operator=(basic_function&&) = default; - basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} - basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} - basic_function(lua_State* L, int index = -1): base_t(L, index) { + public: + basic_function() = default; + basic_function(const basic_function&) = default; + basic_function& operator=(const basic_function&) = default; + basic_function(basic_function&&) = default; + basic_function& operator=(basic_function&&) = default; + basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(lua_State* L, int index = -1) : base_t(L, index) { #ifdef SOL_CHECK_ARGUMENTS - stack::check(L, index, type_panic); + stack::check(L, index, type_panic); #endif // Safety - } - - template - function_result operator()( Args&&... args ) const { - return call<>( std::forward( args )... ); - } + } - template - decltype(auto) operator()( types, Args&&... args ) const { - return call( std::forward( args )... ); - } + template + function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } - template - decltype(auto) call( Args&&... args ) const { - base_t::push( ); - int pushcount = stack::multi_push_reference( base_t::lua_state( ), std::forward( args )... ); - return invoke( types( ), std::make_index_sequence(), pushcount ); - } -}; + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } -namespace stack { -template -struct getter> { - typedef meta::bind_traits fx_t; - typedef typename fx_t::args_list args_lists; - typedef meta::tuple_types return_types; + template + decltype(auto) call(Args&&... args) const { + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; - template - static std::function get_std_func(types, types, lua_State* L, int index = -1) { - sol::function f(L, index); - auto fx = [f, L, index](Args&&... args) -> meta::return_type_t { - return f.call(std::forward(args)...); - }; - return std::move(fx); - } + namespace stack { + template + struct getter> { + typedef meta::bind_traits fx_t; + typedef typename fx_t::args_list args_lists; + typedef meta::tuple_types return_types; - template - static std::function get_std_func(types, types, lua_State* L, int index = -1) { - sol::function f(L, index); - auto fx = [f, L, index](FxArgs&&... args) -> void { - f(std::forward(args)...); - }; - return std::move(fx); - } + template + static std::function get_std_func(types, types, lua_State* L, int index = -1) { + sol::function f(L, index); + auto fx = [f, L, index](Args&&... args) -> meta::return_type_t { + return f.call(std::forward(args)...); + }; + return std::move(fx); + } - template - static std::function get_std_func(types<>, types t, lua_State* L, int index = -1) { - return get_std_func(types(), t, L, index); - } + template + static std::function get_std_func(types, types, lua_State* L, int index = -1) { + sol::function f(L, index); + auto fx = [f, L, index](FxArgs&&... args) -> void { + f(std::forward(args)...); + }; + return std::move(fx); + } - static std::function get(lua_State* L, int index) { - return get_std_func(return_types(), args_lists(), L, index); - } -}; -} // stack + template + static std::function get_std_func(types<>, types t, lua_State* L, int index = -1) { + return get_std_func(types(), t, L, index); + } + + static std::function get(lua_State* L, int index) { + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack } // sol #endif // SOL_FUNCTION_HPP diff --git a/sol/function_result.hpp b/sol/function_result.hpp index 59a4fe52..6e6f8d0d 100644 --- a/sol/function_result.hpp +++ b/sol/function_result.hpp @@ -29,52 +29,52 @@ #include namespace sol { -struct function_result : public proxy_base { -private: - lua_State* L; - int index; - int returncount; + struct function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; -public: - function_result() = default; - function_result(lua_State* L, int index = -1, int returncount = 0): L(L), index(index), returncount(returncount) { - - } - function_result(const function_result&) = default; - function_result& operator=(const function_result&) = default; - function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - } - function_result& operator=(function_result&& o) { - L = o.L; - index = o.index; - returncount = o.returncount; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - return *this; - } + public: + function_result() = default; + function_result(lua_State* L, int index = -1, int returncount = 0) : L(L), index(index), returncount(returncount) { - template - decltype(auto) get() const { - return stack::get(L, index); - } + } + function_result(const function_result&) = default; + function_result& operator=(const function_result&) = default; + function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + } + function_result& operator=(function_result&& o) { + L = o.L; + index = o.index; + returncount = o.returncount; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + return *this; + } - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; + template + decltype(auto) get() const { + return stack::get(L, index); + } - ~function_result() { - lua_pop(L, returncount); - } -}; + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + + ~function_result() { + lua_pop(L, returncount); + } + }; } // sol #endif // SOL_FUNCTION_RESULT_HPP diff --git a/sol/function_types.hpp b/sol/function_types.hpp index 038d8af7..767841bc 100644 --- a/sol/function_types.hpp +++ b/sol/function_types.hpp @@ -31,217 +31,217 @@ #include "call.hpp" namespace sol { -template -struct function_arguments { - std::tuple params; - template - function_arguments(Args&&... args) : params(std::forward(args)...) {} -}; + template + struct function_arguments { + std::tuple params; + template + function_arguments(Args&&... args) : params(std::forward(args)...) {} + }; -template , typename... Args> -function_arguments function_args( Args&&... args ) { - return function_arguments(std::forward(args)...); -} + template , typename... Args> + function_arguments function_args(Args&&... args) { + return function_arguments(std::forward(args)...); + } -namespace stack { -template -struct pusher> { - template - static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::remove_pointer_t> clean_fx; - std::unique_ptr sptr = std::make_unique>(std::forward(fx), std::forward(args)...); - set_fx(L, std::move(sptr)); - } + namespace stack { + template + struct pusher> { + template + static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + std::unique_ptr sptr = std::make_unique>(std::forward(fx), std::forward(args)...); + set_fx(L, std::move(sptr)); + } - template - static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { - using fx_ptr_t = R(*)(A...); - fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); - select_function(std::true_type(), L, fxptr, std::forward(args)...); - } + template + static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { + using fx_ptr_t = R(*)(A...); + fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); + select_function(std::true_type(), L, fxptr, std::forward(args)...); + } - template - static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::decay_t>> raw_fx_t; - typedef R(* fx_ptr_t)(A...); - typedef std::is_convertible is_convertible; - select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); - } + template + static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::decay_t>> raw_fx_t; + typedef R(*fx_ptr_t)(A...); + typedef std::is_convertible is_convertible; + select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); + } - template - static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { - typedef meta::function_signature_t>> Sig; - select_convertible(types(), L, std::forward(fx), std::forward(args)...); - } + template + static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t>> Sig; + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } - template - static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::remove_pointer_t> clean_fx; - std::unique_ptr sptr = std::make_unique, clean_fx>>(std::forward(fx), std::forward(obj), std::forward(args)... ); - set_fx(L, std::move(sptr)); - } + template + static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + std::unique_ptr sptr = std::make_unique, clean_fx>>(std::forward(fx), std::forward(obj), std::forward(args)...); + set_fx(L, std::move(sptr)); + } - template - static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t dFx; - dFx memfxptr(std::forward(fx)); - auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; + template + static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } - template - static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_convertible(types(), L, std::forward(fx), std::forward(args)...); - } + template + static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } - template - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean>::value || std::is_pointer::value> is_reference; - select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); - } + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } - template - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } - template - static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::remove_pointer_t> clean_fx; - std::unique_ptr sptr = std::make_unique>, clean_fx>>(std::forward(fx), std::forward(obj), std::forward(args)... ); - set_fx(L, std::move(sptr)); - } + template + static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + std::unique_ptr sptr = std::make_unique>, clean_fx>>(std::forward(fx), std::forward(obj), std::forward(args)...); + set_fx(L, std::move(sptr)); + } - template - static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t dFx; - dFx memfxptr(std::forward(fx)); - auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; + template + static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } - template - static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); - } + template + static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); + } - template - static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean>::value || std::is_pointer::value> is_reference; - select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); - } + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } - template - static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } - template - static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); - } + template + static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); + } - template - static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { - std::decay_t target(std::forward(fx), std::forward(args)...); - lua_CFunction freefunc = &function_detail::upvalue_free_function::call; + template + static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { + std::decay_t target(std::forward(fx), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, target); - stack::push(L, c_closure(freefunc, upvalues)); - } + int upvalues = stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } - static void select_function(std::true_type, lua_State* L, lua_CFunction f) { - stack::push(L, f); - } + static void select_function(std::true_type, lua_State* L, lua_CFunction f) { + stack::push(L, f); + } - template - static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); - } + template + static void select(lua_State* L, Fx&& fx, Args&&... args) { + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + } - static void set_fx(lua_State* L, std::unique_ptr luafunc) { - function_detail::base_function* target = luafunc.release(); - void* targetdata = static_cast(target); - lua_CFunction freefunc = function_detail::call; + static void set_fx(lua_State* L, std::unique_ptr luafunc) { + function_detail::base_function* target = luafunc.release(); + void* targetdata = static_cast(target); + lua_CFunction freefunc = function_detail::call; - stack::push(L, userdata_value(targetdata)); - function_detail::free_function_cleanup(L); - lua_setmetatable(L, -2); - stack::push(L, c_closure(freefunc, 1)); - } + stack::push(L, userdata_value(targetdata)); + function_detail::free_function_cleanup(L); + lua_setmetatable(L, -2); + stack::push(L, c_closure(freefunc, 1)); + } - template - static int push(lua_State* L, Args&&... args) { - // Set will always place one thing (function) on the stack - select(L, std::forward(args)...); - return 1; - } -}; + template + static int push(lua_State* L, Args&&... args) { + // Set will always place one thing (function) on the stack + select(L, std::forward(args)...); + return 1; + } + }; -template -struct pusher> { - template - static int push_func(std::index_sequence, lua_State* L, FP&& fp) { - return stack::push(L, detail::forward_get(fp.params)...); - } + template + struct pusher> { + template + static int push_func(std::index_sequence, lua_State* L, FP&& fp) { + return stack::push(L, detail::forward_get(fp.params)...); + } - template - static int push(lua_State* L, FP&& fp) { - return push_func(std::make_index_sequence(), L, std::forward(fp)); - } -}; + template + static int push(lua_State* L, FP&& fp) { + return push_func(std::make_index_sequence(), L, std::forward(fp)); + } + }; -template -struct pusher> { - static int push(lua_State* L, std::function fx) { - return pusher>{}.push(L, std::move(fx)); - } -}; + template + struct pusher> { + static int push(lua_State* L, std::function fx) { + return pusher>{}.push(L, std::move(fx)); + } + }; -template -struct pusher::value>> { - template - static int push(lua_State* L, F&& f) { - return pusher>{}.push(L, std::forward(f)); - } -}; + template + struct pusher::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; -template -struct pusher, meta::neg>, meta::neg>>>::value>> { - template - static int push(lua_State* L, F&& f) { - return pusher>{}.push(L, std::forward(f)); - } -}; + template + struct pusher, meta::neg>, meta::neg>>>::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; -template -struct pusher> { - static int push(lua_State* L, overload_set&& set) { - pusher>{}.set_fx(L, std::make_unique>(std::move(set.set))); - return 1; - } + template + struct pusher> { + static int push(lua_State* L, overload_set&& set) { + pusher>{}.set_fx(L, std::make_unique>(std::move(set.set))); + return 1; + } - static int push(lua_State* L, const overload_set& set) { - pusher>{}.set_fx(L, std::make_unique>(set.set)); - return 1; - } -}; + static int push(lua_State* L, const overload_set& set) { + pusher>{}.set_fx(L, std::make_unique>(set.set)); + return 1; + } + }; -} // stack + } // stack } // sol #endif // SOL_FUNCTION_TYPES_HPP diff --git a/sol/function_types_basic.hpp b/sol/function_types_basic.hpp index 5489458c..67fd4c05 100644 --- a/sol/function_types_basic.hpp +++ b/sol/function_types_basic.hpp @@ -25,178 +25,178 @@ #include "stack.hpp" namespace sol { -namespace function_detail { -template -struct upvalue_free_function { - typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + namespace function_detail { + template + struct upvalue_free_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { - auto udata = stack::stack_detail::get_as_upvalues(L); - function_type* fx = udata.first; - int r = stack::call_into_lua(meta::tuple_types(), typename traits_type::args_list(), L, 1, fx); - return r; - } + static int real_call(lua_State* L) { + auto udata = stack::stack_detail::get_as_upvalues(L); + function_type* fx = udata.first; + int r = stack::call_into_lua(meta::tuple_types(), typename traits_type::args_list(), L, 1, fx); + return r; + } - static int call (lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } - int operator()(lua_State* L) { - return call(L); - } -}; + int operator()(lua_State* L) { + return call(L); + } + }; -template -struct upvalue_member_function { - typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + template + struct upvalue_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member function pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); - function_type& memfx = memberdata.first; - auto& item = *objdata.first; - auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type { - return (item.*memfx)(std::forward(args)...); - }; - return stack::call_into_lua(meta::tuple_types(), typename traits_type::args_list(), L, 1, fx); - } + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member function pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + function_type& memfx = memberdata.first; + auto& item = *objdata.first; + auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type { + return (item.*memfx)(std::forward(args)...); + }; + return stack::call_into_lua(meta::tuple_types(), typename traits_type::args_list(), L, 1, fx); + } - static int call (lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } - int operator()(lua_State* L) { - return call(L); - } -}; + int operator()(lua_State* L) { + return call(L); + } + }; -template -int set_assignable(std::false_type, lua_State* L, M&, V&) { - lua_pop(L, N); - return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available"); -} + template + int set_assignable(std::false_type, lua_State* L, M&, V&) { + lua_pop(L, N); + return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available"); + } -template -int set_assignable(std::true_type, lua_State* L, M& mem, V& var) { - (mem.*var) = stack::get(L, N); - lua_pop(L, N); - return 0; -} + template + int set_assignable(std::true_type, lua_State* L, M& mem, V& var) { + (mem.*var) = stack::get(L, N); + lua_pop(L, N); + return 0; + } -template -int set_variable(std::true_type, lua_State* L, M& mem, V& var) { - return set_assignable(std::is_assignable, R>(), L, mem, var); -} + template + int set_variable(std::true_type, lua_State* L, M& mem, V& var) { + return set_assignable(std::is_assignable, R>(), L, mem, var); + } -template -int set_variable(std::false_type, lua_State* L, M&, V&) { - lua_pop(L, N); - return luaL_error(L, "sol: cannot write to a const variable"); -} + template + int set_variable(std::false_type, lua_State* L, M&, V&) { + lua_pop(L, N); + return luaL_error(L, "sol: cannot write to a const variable"); + } -template -struct upvalue_member_variable { - typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + template + struct upvalue_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); - auto& mem = *objdata.first; - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 0: - stack::push(L, (mem.*var)); - return 1; - case 1: - set_variable<1, typename traits_type::return_type>(meta::neg>(), L, mem, var); - return 0; - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + stack::push(L, (mem.*var)); + return 1; + case 1: + set_variable<1, typename traits_type::return_type>(meta::neg>(), L, mem, var); + return 0; + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } - static int call (lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } - int operator()(lua_State* L) { - return call(L); - } -}; + int operator()(lua_State* L) { + return call(L); + } + }; -template -struct upvalue_this_member_function { - typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + template + struct upvalue_this_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); - function_type& memfx = memberdata.first; - auto fx = [&L, &memfx](auto&&... args) -> typename traits_type::return_type { - auto& item = stack::get(L, 1); - return (item.*memfx)(std::forward(args)...); - }; - int n = stack::call_into_lua<1>(meta::tuple_types(), typename traits_type::args_list(), L, 2, fx); - return n; - } + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& memfx = memberdata.first; + auto fx = [&L, &memfx](auto&&... args) -> typename traits_type::return_type { + auto& item = stack::get(L, 1); + return (item.*memfx)(std::forward(args)...); + }; + int n = stack::call_into_lua<1>(meta::tuple_types(), typename traits_type::args_list(), L, 2, fx); + return n; + } - static int call (lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } - int operator()(lua_State* L) { - return call(L); - } -}; + int operator()(lua_State* L) { + return call(L); + } + }; -template -struct upvalue_this_member_variable { - typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + template + struct upvalue_this_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); - auto& mem = stack::get(L, 1); - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 1: - lua_pop(L, 1); - stack::push(L, (mem.*var)); - return 1; - case 2: - set_variable<2, typename traits_type::return_type>(meta::neg>(), L, mem, var); - return 0; - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto& mem = stack::get(L, 1); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + lua_pop(L, 1); + stack::push(L, (mem.*var)); + return 1; + case 2: + set_variable<2, typename traits_type::return_type>(meta::neg>(), L, mem, var); + return 0; + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } - static int call (lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } - int operator()(lua_State* L) { - return call(L); - } -}; -} // function_detail + int operator()(lua_State* L) { + return call(L); + } + }; + } // function_detail } // sol #endif // SOL_FUNCTION_TYPES_BASIC_HPP diff --git a/sol/function_types_core.hpp b/sol/function_types_core.hpp index b55d6bfd..dcbbfb03 100644 --- a/sol/function_types_core.hpp +++ b/sol/function_types_core.hpp @@ -27,91 +27,91 @@ #include namespace sol { -namespace function_detail { -inline decltype(auto) cleanup_key() { - const auto& name = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧"; - return name; -} + namespace function_detail { + inline decltype(auto) cleanup_key() { + const auto& name = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧"; + return name; + } -struct base_function { - virtual int operator()(lua_State* L) { - return luaL_error(L, "sol: failure to call specialized wrapped C++ function from Lua"); - } + struct base_function { + virtual int operator()(lua_State* L) { + return luaL_error(L, "sol: failure to call specialized wrapped C++ function from Lua"); + } - virtual ~base_function() {} -}; + virtual ~base_function() {} + }; -static int base_call(lua_State* L, void* inheritancedata) { - if (inheritancedata == nullptr) { - return luaL_error(L, "sol: call from Lua to C++ function has null data"); - } + static int base_call(lua_State* L, void* inheritancedata) { + if (inheritancedata == nullptr) { + return luaL_error(L, "sol: call from Lua to C++ function has null data"); + } - base_function* pfx = static_cast(inheritancedata); - base_function& fx = *pfx; - return detail::trampoline(L, fx); -} + base_function* pfx = static_cast(inheritancedata); + base_function& fx = *pfx; + return detail::trampoline(L, fx); + } -static int base_gc(lua_State* L, void* udata) { - if (udata == nullptr) { - return luaL_error(L, "sol: call from lua to C++ gc function with null data"); - } + static int base_gc(lua_State* L, void* udata) { + if (udata == nullptr) { + return luaL_error(L, "sol: call from lua to C++ gc function with null data"); + } - base_function* ptr = static_cast(udata); - std::default_delete dx{}; - dx(ptr); - return 0; -} + base_function* ptr = static_cast(udata); + std::default_delete dx{}; + dx(ptr); + return 0; + } -template -static void func_gc(std::true_type, lua_State*) { + template + static void func_gc(std::true_type, lua_State*) { -} + } -template -static void func_gc(std::false_type, lua_State* L) { - for (std::size_t i = 0; i < limit; ++i) { - void* value = stack::get(L, up_value_index(static_cast(i + 1))); - if (value == nullptr) - continue; - base_function* obj = static_cast(value); - std::allocator alloc{}; - alloc.destroy(obj); - alloc.deallocate(obj, 1); - } -} + template + static void func_gc(std::false_type, lua_State* L) { + for (std::size_t i = 0; i < limit; ++i) { + void* value = stack::get(L, up_value_index(static_cast(i + 1))); + if (value == nullptr) + continue; + base_function* obj = static_cast(value); + std::allocator alloc{}; + alloc.destroy(obj); + alloc.deallocate(obj, 1); + } + } -inline int call(lua_State* L) { - void* ludata = stack::get(L, up_value_index(1)); - void** pinheritancedata = static_cast(ludata); - return base_call(L, *pinheritancedata); -} + inline int call(lua_State* L) { + void* ludata = stack::get(L, up_value_index(1)); + void** pinheritancedata = static_cast(ludata); + return base_call(L, *pinheritancedata); + } -inline int gc(lua_State* L) { - void* udata = stack::get(L, 1); - void** pudata = static_cast(udata); - return base_gc(L, *pudata); -} + inline int gc(lua_State* L) { + void* udata = stack::get(L, 1); + void** pudata = static_cast(udata); + return base_gc(L, *pudata); + } -template -inline int usertype_call(lua_State* L) { - // Zero-based template parameter, but upvalues start at 1 - return base_call(L, stack::get(L, up_value_index(static_cast(I + 1)))); -} + template + inline int usertype_call(lua_State* L) { + // Zero-based template parameter, but upvalues start at 1 + return base_call(L, stack::get(L, up_value_index(static_cast(I + 1)))); + } -template -inline int usertype_gc(lua_State* L) { - func_gc(meta::boolean<(I < 1)>(), L); - return 0; -} + template + inline int usertype_gc(lua_State* L) { + func_gc(meta::boolean<(I < 1)>(), L); + return 0; + } -inline void free_function_cleanup(lua_State* L) { - const static char* metatablename = &cleanup_key()[0]; - int metapushed = luaL_newmetatable(L, metatablename); - if (metapushed == 1) { - stack::set_field(L, "__gc", function_detail::gc); - } -} -} // function_detail + inline void free_function_cleanup(lua_State* L) { + const static char* metatablename = &cleanup_key()[0]; + int metapushed = luaL_newmetatable(L, metatablename); + if (metapushed == 1) { + stack::set_field(L, "__gc", function_detail::gc); + } + } + } // function_detail } // sol #endif // SOL_FUNCTION_TYPES_CORE_HPP diff --git a/sol/function_types_overloaded.hpp b/sol/function_types_overloaded.hpp index 4d0691e4..257b4321 100644 --- a/sol/function_types_overloaded.hpp +++ b/sol/function_types_overloaded.hpp @@ -27,33 +27,33 @@ #include "function_types_core.hpp" namespace sol { -namespace function_detail { -template -struct overloaded_function : base_function { - typedef std::tuple overload_list; - typedef std::make_index_sequence indices; - overload_list overloads; + namespace function_detail { + template + struct overloaded_function : base_function { + typedef std::tuple overload_list; + typedef std::make_index_sequence indices; + overload_list overloads; - overloaded_function(overload_list set) - : overloads(std::move(set)) {} + overloaded_function(overload_list set) + : overloads(std::move(set)) {} - overloaded_function(Functions... fxs) - : overloads(fxs...) { + overloaded_function(Functions... fxs) + : overloads(fxs...) { - } + } - template - int call(types, index_value, types r, types a, lua_State* L, int, int start) { - auto& func = std::get(overloads); - return stack::call_into_lua<0, false>(r, a, L, start, func); - } + template + int call(types, index_value, types r, types a, lua_State* L, int, int start) { + auto& func = std::get(overloads); + return stack::call_into_lua<0, false>(r, a, L, start, func); + } - virtual int operator()(lua_State* L) override { - auto mfx = [&](auto&&... args){ return this->call(std::forward(args)...); }; - return call_detail::overload_match(mfx, L, 1); - } -}; -} // function_detail + virtual int operator()(lua_State* L) override { + auto mfx = [&](auto&&... args) { return this->call(std::forward(args)...); }; + return call_detail::overload_match(mfx, L, 1); + } + }; + } // function_detail } // sol #endif // SOL_FUNCTION_TYPES_OVERLOAD_HPP \ No newline at end of file diff --git a/sol/usertype_metatable.hpp b/sol/usertype_metatable.hpp index 323421e6..394b1426 100644 --- a/sol/usertype_metatable.hpp +++ b/sol/usertype_metatable.hpp @@ -142,13 +142,13 @@ namespace sol { int make_regs(regs_t& l, int index, sol::call_construction, F&&, Args&&... args) { callconstructfunc = call; secondarymeta = true; - int endindex = make_regs(l, index + 1, std::forward(args)...); + int endindex = make_regs(l, index, std::forward(args)...); return endindex; } template int make_regs(regs_t& l, int index, base_classes_tag, bases, Args&&... args) { - int endindex = make_regs(l, index + 1, std::forward(args)...); + int endindex = make_regs(l, index, std::forward(args)...); if (sizeof...(Bases) < 1) { (void)detail::swallow{ 0, ((detail::has_derived::value = false), 0)... }; return endindex; diff --git a/test_tables.cpp b/test_tables.cpp index e6eba074..da87b54c 100644 --- a/test_tables.cpp +++ b/test_tables.cpp @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include "test_stack_guard.hpp" std::string free_function() { @@ -530,4 +534,22 @@ TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily ev REQUIRE(present); REQUIRE(non_nope3.value() == 35); REQUIRE(non_nope4.value() == 35); -} \ No newline at end of file +} + +TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") { + static const int sz = 120; + + sol::state lua; + sol::table t = lua.create_table(sz, 0); + + std::vector bigvec( sz ); + std::iota(bigvec.begin(), bigvec.end(), 1); + + for (std::size_t i = 0; i < bigvec.size(); ++i) { + t.add(bigvec[i]); + } + for (std::size_t i = 0; i < bigvec.size(); ++i) { + int val = t[i + 1]; + REQUIRE(val == bigvec[i]); + } +}