From bafac3abbdd3be50ad31abb38bdf948c2ba8a2a0 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Sep 2019 00:43:44 -0400 Subject: [PATCH] Change how proxies are done for the sake of efficiency. --- README.md | 2 +- examples/source/table_proxy.cpp | 2 +- include/sol/forward.hpp | 2 +- include/sol/state_view.hpp | 4 +- include/sol/table_core.hpp | 8 +- include/sol/{proxy.hpp => table_proxy.hpp} | 92 ++++++----- include/sol/types.hpp | 43 +++-- single/include/sol/forward.hpp | 6 +- single/include/sol/sol.hpp | 147 ++++++++++-------- tests/compile_tests/source/proxy.cpp | 2 +- tests/runtime_tests/source/basic.cpp | 2 +- .../runtime_tests/source/container_table.cpp | 49 +++--- tests/runtime_tests/source/containers.cpp | 19 ++- tests/runtime_tests/source/coroutines.cpp | 101 +++++++----- .../source/customizations_private.cpp | 19 ++- tests/runtime_tests/source/environments.cpp | 94 +++++++---- tests/runtime_tests/source/functions.cpp | 2 +- tests/runtime_tests/source/large_integer.cpp | 96 +++++++----- tests/runtime_tests/source/tables.cpp | 36 ++++- .../runtime_tests/source/tables.insertion.cpp | 14 +- 20 files changed, 456 insertions(+), 284 deletions(-) rename include/sol/{proxy.hpp => table_proxy.hpp} (76%) diff --git a/README.md b/README.md index d641d2ff..dfb0a564 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The library is header-only for easy integration with projects. ## Documentation -Find it [here](http://sol2.rtfd.io/). A run-through kind of tutorial is [here](http://sol2.readthedocs.io/en/latest/tutorial/all-the-things.html)! The API documentation goes over most cases (particularly, the "api/usertype" and "api/proxy" and "api/function" sections) that should still get you off your feet and going, and there's an examples directory [here](https://github.com/ThePhD/sol2/tree/develop/examples) as well. +Find it [here](http://sol2.rtfd.io/). A run-through kind of tutorial is [here](http://sol2.readthedocs.io/en/latest/tutorial/all-the-things.html)! The API documentation goes over most cases (particularly, the "api/usertype" and "api/table_proxy" and "api/function" sections) that should still get you off your feet and going, and there's an examples directory [here](https://github.com/ThePhD/sol2/tree/develop/examples) as well. ## Sneak Peek diff --git a/examples/source/table_proxy.cpp b/examples/source/table_proxy.cpp index 899143ab..516fc16f 100644 --- a/examples/source/table_proxy.cpp +++ b/examples/source/table_proxy.cpp @@ -19,7 +19,7 @@ int main () { lua.open_libraries(sol::lib::base); lua.script(code); - // produces proxy, implicitly converts to std::string, quietly destroys proxy + // produces table_proxy, implicitly converts to std::string, quietly destroys table_proxy std::string arf_string = lua["bark"]["woof"][2]; // lazy-evaluation of tables diff --git a/include/sol/forward.hpp b/include/sol/forward.hpp index 666be2cf..1e81da74 100644 --- a/include/sol/forward.hpp +++ b/include/sol/forward.hpp @@ -59,7 +59,7 @@ namespace sol { template struct proxy_base; template - struct proxy; + struct table_proxy; template class basic_table_core; diff --git a/include/sol/state_view.hpp b/include/sol/state_view.hpp index cb5f1ead..6ba092e4 100644 --- a/include/sol/state_view.hpp +++ b/include/sol/state_view.hpp @@ -682,12 +682,12 @@ namespace sol { } template - proxy> operator[](T&& key) { + table_proxy> operator[](T&& key) { return global[std::forward(key)]; } template - proxy> operator[](T&& key) const { + table_proxy> operator[](T&& key) const { return global[std::forward(key)]; } diff --git a/include/sol/table_core.hpp b/include/sol/table_core.hpp index bd0ac084..d68c180b 100644 --- a/include/sol/table_core.hpp +++ b/include/sol/table_core.hpp @@ -24,7 +24,7 @@ #ifndef SOL_TABLE_CORE_HPP #define SOL_TABLE_CORE_HPP -#include "proxy.hpp" +#include "table_proxy.hpp" #include "stack.hpp" #include "function_types.hpp" #include "table_iterator.hpp" @@ -575,17 +575,17 @@ namespace sol { template auto operator[](T&& key) & { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) const& { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) && { - return proxy>(std::move(*this), std::forward(key)); + return table_proxy>(std::move(*this), std::forward(key)); } template diff --git a/include/sol/proxy.hpp b/include/sol/table_proxy.hpp similarity index 76% rename from include/sol/proxy.hpp rename to include/sol/table_proxy.hpp index 9993ca2c..52b787be 100644 --- a/include/sol/proxy.hpp +++ b/include/sol/table_proxy.hpp @@ -21,8 +21,8 @@ // 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_PROXY_HPP -#define SOL_PROXY_HPP +#ifndef SOL_TABLE_PROXY_HPP +#define SOL_TABLE_PROXY_HPP #include "traits.hpp" #include "function.hpp" @@ -32,12 +32,12 @@ namespace sol { template - struct proxy : public proxy_base> { + struct table_proxy : public proxy_base> { private: using key_type = detail::proxy_key_t; template - decltype(auto) tuple_get(std::index_sequence) const & { + decltype(auto) tuple_get(std::index_sequence) const& { return tbl.template traverse_get(std::get(key)...); } @@ -74,36 +74,35 @@ namespace sol { key_type key; template - proxy(Table table, T&& k) - : tbl(table), key(std::forward(k)) { + table_proxy(Table table, T&& k) : tbl(table), key(std::forward(k)) { } template - proxy& set(T&& item) & { + table_proxy& set(T&& item) & { tuple_set(std::make_index_sequence>>(), std::forward(item)); return *this; } template - proxy&& set(T&& item) && { + table_proxy&& set(T&& item) && { tuple_set(std::make_index_sequence>>(), std::forward(item)); return std::move(*this); } template - proxy& set_function(Args&&... args) & { + table_proxy& set_function(Args&&... args) & { tbl.set_function(key, std::forward(args)...); return *this; } template - proxy&& set_function(Args&&... args) && { + table_proxy&& set_function(Args&&... args) && { tbl.set_function(std::move(key), std::forward(args)...); return std::move(*this); } template - proxy& operator=(T&& other) & { + table_proxy& operator=(T&& other) & { using Tu = meta::unwrap_unqualified_t; if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { return set_function(std::forward(other)); @@ -114,7 +113,7 @@ namespace sol { } template - proxy&& operator=(T&& other) && { + table_proxy&& operator=(T&& other) && { using Tu = meta::unwrap_unqualified_t; if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { return std::move(*this).set_function(std::forward(other)); @@ -125,17 +124,17 @@ namespace sol { } template - proxy& operator=(std::initializer_list other) & { + table_proxy& operator=(std::initializer_list other) & { return set(std::move(other)); } template - proxy&& operator=(std::initializer_list other) && { + table_proxy&& operator=(std::initializer_list other) && { return std::move(*this).set(std::move(other)); } template - decltype(auto) get() const & { + decltype(auto) get() const& { using idx_seq = std::make_index_sequence>>; return tuple_get(idx_seq()); } @@ -165,7 +164,7 @@ namespace sol { return static_cast(std::forward(otherwise)); } - + template decltype(auto) get_or_create() { return get_or_create(new_table()); @@ -182,29 +181,28 @@ namespace sol { template decltype(auto) operator[](K&& k) const& { auto keys = meta::tuplefy(key, std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) operator[](K&& k) & { auto keys = meta::tuplefy(key, std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) operator[](K&& k) && { auto keys = meta::tuplefy(std::move(key), std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) call(Args&&... args) { -#if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000 - // MSVC is ass sometimes - return get().call(std::forward(args)...); -#else - return get().template call(std::forward(args)...); -#endif + lua_State* L = this->lua_state(); + push(L); + int idx = lua_gettop(L); + stack_aligned_function func(L, idx); + return func.call(std::forward(args)...); } template @@ -224,7 +222,22 @@ namespace sol { } int push(lua_State* L) const noexcept { - return get().push(L); + if constexpr (std::is_same_v, global_table> || is_stack_table_v>) { + auto pp = stack::push_pop(tbl); + int top_index = lua_gettop(L); + stack::get_field(lua_state(), key, -1); + lua_replace(L, top_index + 1); + lua_settop(L, top_index + 1); + } + else { + auto pp = stack::push_pop(tbl); + int tableindex = pp.index_of(tbl); + int aftertableindex = lua_gettop(L); + stack::get_field(lua_state(), key, tableindex); + lua_replace(L, tableindex); + lua_settop(L, aftertableindex + 1); + } + return 1; } type get_type() const { @@ -242,7 +255,7 @@ namespace sol { return tbl.lua_state(); } - proxy& force() { + table_proxy& force() { if (!this->valid()) { this->set(new_table()); } @@ -251,46 +264,46 @@ namespace sol { }; template - inline bool operator==(T&& left, const proxy& right) { + inline bool operator==(T&& left, const table_proxy& right) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() == left; } template - inline bool operator==(const proxy& right, T&& left) { + inline bool operator==(const table_proxy& right, T&& left) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() == left; } template - inline bool operator!=(T&& left, const proxy& right) { + inline bool operator!=(T&& left, const table_proxy& right) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() != left; } template - inline bool operator!=(const proxy& right, T&& left) { + inline bool operator!=(const table_proxy& right, T&& left) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() != left; } template - inline bool operator==(lua_nil_t, const proxy& right) { + inline bool operator==(lua_nil_t, const table_proxy& right) { return !right.valid(); } template - inline bool operator==(const proxy& right, lua_nil_t) { + inline bool operator==(const table_proxy& right, lua_nil_t) { return !right.valid(); } template - inline bool operator!=(lua_nil_t, const proxy& right) { + inline bool operator!=(lua_nil_t, const table_proxy& right) { return right.valid(); } template - inline bool operator!=(const proxy& right, lua_nil_t) { + inline bool operator!=(const table_proxy& right, lua_nil_t) { return right.valid(); } @@ -312,13 +325,12 @@ namespace sol { namespace stack { template - struct unqualified_pusher> { - static int push(lua_State* L, const proxy& p) { - reference r = p; - return r.push(L); + struct unqualified_pusher> { + static int push(lua_State* L, const table_proxy& p) { + return p.push(L); } }; } // namespace stack } // namespace sol -#endif // SOL_PROXY_HPP +#endif // SOL_TABLE_PROXY_HPP diff --git a/include/sol/types.hpp b/include/sol/types.hpp index 7441df30..96c62e82 100644 --- a/include/sol/types.hpp +++ b/include/sol/types.hpp @@ -422,7 +422,7 @@ namespace sol { struct as_container_t { private: T value_; - + public: using type = T; @@ -504,7 +504,7 @@ namespace sol { return std::move(value_); } - const T& value() const & { + const T& value() const& { return value_; } }; @@ -867,16 +867,14 @@ namespace sol { } template - struct is_lua_reference : std::integral_constant || std::is_base_of_v - || std::is_base_of_v> {}; + struct is_lua_reference + : std::integral_constant || std::is_base_of_v || std::is_base_of_v> {}; template inline constexpr bool is_lua_reference_v = is_lua_reference::value; template - struct is_lua_reference_or_proxy - : std::integral_constant || meta::is_specialization_of_v> {}; + struct is_lua_reference_or_proxy : std::integral_constant || meta::is_specialization_of_v> {}; template inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy::value; @@ -901,7 +899,8 @@ namespace sol { template struct is_container : std::integral_constant && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { + !std::is_same_v && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { }; template @@ -1098,7 +1097,8 @@ namespace sol { struct lua_type_of : std::integral_constant {}; template - struct lua_type_of || std::is_same_v || std::is_same_v>> : std::integral_constant {}; + struct lua_type_of || std::is_same_v || std::is_same_v>> + : std::integral_constant {}; template struct lua_type_of>> : std::integral_constant {}; @@ -1114,8 +1114,7 @@ namespace sol { #endif // SOL_CXX17_FEATURES template - struct lua_type_of> - : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; + struct lua_type_of> : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; @@ -1172,11 +1171,10 @@ namespace sol { template struct is_lua_primitive : std::integral_constant - || ((type::userdata == lua_type_of_v) && detail::has_internal_marker_v> - && !detail::has_internal_marker_v>) - || is_lua_reference_v || meta::is_specialization_of_v - || meta::is_specialization_of_v> {}; + type::userdata + != lua_type_of_v< + T> || ((type::userdata == lua_type_of_v)&&detail::has_internal_marker_v> && !detail::has_internal_marker_v>) + || is_lua_reference_or_proxy_v || meta::is_specialization_of_v || meta::is_specialization_of_v> {}; template constexpr inline bool is_lua_primitive_v = is_lua_primitive::value; @@ -1265,6 +1263,16 @@ namespace sol { template inline constexpr bool is_table_v = is_table::value; + template + struct is_stack_table : std::false_type {}; + template + struct is_stack_table> : std::integral_constant> {}; + template + struct is_stack_table> : std::integral_constant> {}; + + template + inline constexpr bool is_stack_table_v = is_stack_table::value; + template struct is_function : std::false_type {}; template @@ -1300,7 +1308,8 @@ namespace sol { template struct is_automagical : std::integral_constant> || !std::is_same_v, state> || !std::is_same_v, state_view>> {}; + std::is_array_v> || !std::is_same_v, state> || !std::is_same_v, state_view>> { + }; template inline type type_of() { diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index 8c5d1f8e..3718ffec 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-09-08 23:53:48.445628 UTC -// This header was generated with sol v3.0.3 (revision 29c03ea) +// Generated 2019-09-15 04:36:38.687873 UTC +// This header was generated with sol v3.0.3 (revision b2c22ea) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP @@ -281,7 +281,7 @@ namespace sol { template struct proxy_base; template - struct proxy; + struct table_proxy; template class basic_table_core; diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index a84c0ac1..e3a63b79 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-09-08 23:53:47.830273 UTC -// This header was generated with sol v3.0.3 (revision 29c03ea) +// Generated 2019-09-15 04:36:35.549872 UTC +// This header was generated with sol v3.0.3 (revision b2c22ea) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -307,7 +307,7 @@ namespace sol { template struct proxy_base; template - struct proxy; + struct table_proxy; template class basic_table_core; @@ -6649,7 +6649,7 @@ namespace sol { struct as_container_t { private: T value_; - + public: using type = T; @@ -6731,7 +6731,7 @@ namespace sol { return std::move(value_); } - const T& value() const & { + const T& value() const& { return value_; } }; @@ -7094,16 +7094,14 @@ namespace sol { } template - struct is_lua_reference : std::integral_constant || std::is_base_of_v - || std::is_base_of_v> {}; + struct is_lua_reference + : std::integral_constant || std::is_base_of_v || std::is_base_of_v> {}; template inline constexpr bool is_lua_reference_v = is_lua_reference::value; template - struct is_lua_reference_or_proxy - : std::integral_constant || meta::is_specialization_of_v> {}; + struct is_lua_reference_or_proxy : std::integral_constant || meta::is_specialization_of_v> {}; template inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy::value; @@ -7128,7 +7126,8 @@ namespace sol { template struct is_container : std::integral_constant && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { + !std::is_same_v && !std::is_same_v && !meta::is_initializer_list_v && !meta::is_string_like_v && !meta::is_string_literal_array_v && !is_transparent_argument_v && !is_lua_reference_v && (meta::has_begin_end_v || std::is_array_v)> { }; template @@ -7325,7 +7324,8 @@ namespace sol { struct lua_type_of : std::integral_constant {}; template - struct lua_type_of || std::is_same_v || std::is_same_v>> : std::integral_constant {}; + struct lua_type_of || std::is_same_v || std::is_same_v>> + : std::integral_constant {}; template struct lua_type_of>> : std::integral_constant {}; @@ -7341,8 +7341,7 @@ namespace sol { #endif // SOL_CXX17_FEATURES template - struct lua_type_of> - : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; + struct lua_type_of> : meta::conditional_t<::sol::is_container_v, std::integral_constant, lua_type_of> {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; @@ -7399,11 +7398,10 @@ namespace sol { template struct is_lua_primitive : std::integral_constant - || ((type::userdata == lua_type_of_v) && detail::has_internal_marker_v> - && !detail::has_internal_marker_v>) - || is_lua_reference_v || meta::is_specialization_of_v - || meta::is_specialization_of_v> {}; + type::userdata + != lua_type_of_v< + T> || ((type::userdata == lua_type_of_v)&&detail::has_internal_marker_v> && !detail::has_internal_marker_v>) + || is_lua_reference_or_proxy_v || meta::is_specialization_of_v || meta::is_specialization_of_v> {}; template constexpr inline bool is_lua_primitive_v = is_lua_primitive::value; @@ -7492,6 +7490,16 @@ namespace sol { template inline constexpr bool is_table_v = is_table::value; + template + struct is_stack_table : std::false_type {}; + template + struct is_stack_table> : std::integral_constant> {}; + template + struct is_stack_table> : std::integral_constant> {}; + + template + inline constexpr bool is_stack_table_v = is_stack_table::value; + template struct is_function : std::false_type {}; template @@ -7526,7 +7534,8 @@ namespace sol { template struct is_automagical : std::integral_constant> || !std::is_same_v, state> || !std::is_same_v, state_view>> {}; + std::is_array_v> || !std::is_same_v, state> || !std::is_same_v, state_view>> { + }; template inline type type_of() { @@ -22335,17 +22344,17 @@ namespace sol { // beginning of sol/table_core.hpp -// beginning of sol/proxy.hpp +// beginning of sol/table_proxy.hpp namespace sol { template - struct proxy : public proxy_base> { + struct table_proxy : public proxy_base> { private: using key_type = detail::proxy_key_t; template - decltype(auto) tuple_get(std::index_sequence) const & { + decltype(auto) tuple_get(std::index_sequence) const& { return tbl.template traverse_get(std::get(key)...); } @@ -22382,36 +22391,35 @@ namespace sol { key_type key; template - proxy(Table table, T&& k) - : tbl(table), key(std::forward(k)) { + table_proxy(Table table, T&& k) : tbl(table), key(std::forward(k)) { } template - proxy& set(T&& item) & { + table_proxy& set(T&& item) & { tuple_set(std::make_index_sequence>>(), std::forward(item)); return *this; } template - proxy&& set(T&& item) && { + table_proxy&& set(T&& item) && { tuple_set(std::make_index_sequence>>(), std::forward(item)); return std::move(*this); } template - proxy& set_function(Args&&... args) & { + table_proxy& set_function(Args&&... args) & { tbl.set_function(key, std::forward(args)...); return *this; } template - proxy&& set_function(Args&&... args) && { + table_proxy&& set_function(Args&&... args) && { tbl.set_function(std::move(key), std::forward(args)...); return std::move(*this); } template - proxy& operator=(T&& other) & { + table_proxy& operator=(T&& other) & { using Tu = meta::unwrap_unqualified_t; if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { return set_function(std::forward(other)); @@ -22422,7 +22430,7 @@ namespace sol { } template - proxy&& operator=(T&& other) && { + table_proxy&& operator=(T&& other) && { using Tu = meta::unwrap_unqualified_t; if constexpr (!is_lua_reference_or_proxy_v && meta::is_callable_v) { return std::move(*this).set_function(std::forward(other)); @@ -22433,17 +22441,17 @@ namespace sol { } template - proxy& operator=(std::initializer_list other) & { + table_proxy& operator=(std::initializer_list other) & { return set(std::move(other)); } template - proxy&& operator=(std::initializer_list other) && { + table_proxy&& operator=(std::initializer_list other) && { return std::move(*this).set(std::move(other)); } template - decltype(auto) get() const & { + decltype(auto) get() const& { using idx_seq = std::make_index_sequence>>; return tuple_get(idx_seq()); } @@ -22489,29 +22497,28 @@ namespace sol { template decltype(auto) operator[](K&& k) const& { auto keys = meta::tuplefy(key, std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) operator[](K&& k) & { auto keys = meta::tuplefy(key, std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) operator[](K&& k) && { auto keys = meta::tuplefy(std::move(key), std::forward(k)); - return proxy(tbl, std::move(keys)); + return table_proxy(tbl, std::move(keys)); } template decltype(auto) call(Args&&... args) { -#if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000 - // MSVC is ass sometimes - return get().call(std::forward(args)...); -#else - return get().template call(std::forward(args)...); -#endif + lua_State* L = this->lua_state(); + push(L); + int idx = lua_gettop(L); + stack_aligned_function func(L, idx); + return func.call(std::forward(args)...); } template @@ -22531,7 +22538,22 @@ namespace sol { } int push(lua_State* L) const noexcept { - return get().push(L); + if constexpr (std::is_same_v, global_table> || is_stack_table_v>) { + auto pp = stack::push_pop(tbl); + int top_index = lua_gettop(L); + stack::get_field(lua_state(), key, -1); + lua_replace(L, top_index + 1); + lua_settop(L, top_index + 1); + } + else { + auto pp = stack::push_pop(tbl); + int tableindex = pp.index_of(tbl); + int aftertableindex = lua_gettop(L); + stack::get_field(lua_state(), key, tableindex); + lua_replace(L, tableindex); + lua_settop(L, aftertableindex + 1); + } + return 1; } type get_type() const { @@ -22549,7 +22571,7 @@ namespace sol { return tbl.lua_state(); } - proxy& force() { + table_proxy& force() { if (!this->valid()) { this->set(new_table()); } @@ -22558,46 +22580,46 @@ namespace sol { }; template - inline bool operator==(T&& left, const proxy& right) { + inline bool operator==(T&& left, const table_proxy& right) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() == left; } template - inline bool operator==(const proxy& right, T&& left) { + inline bool operator==(const table_proxy& right, T&& left) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() == left; } template - inline bool operator!=(T&& left, const proxy& right) { + inline bool operator!=(T&& left, const table_proxy& right) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() != left; } template - inline bool operator!=(const proxy& right, T&& left) { + inline bool operator!=(const table_proxy& right, T&& left) { using G = decltype(stack::get(nullptr, 0)); return right.template get>() != left; } template - inline bool operator==(lua_nil_t, const proxy& right) { + inline bool operator==(lua_nil_t, const table_proxy& right) { return !right.valid(); } template - inline bool operator==(const proxy& right, lua_nil_t) { + inline bool operator==(const table_proxy& right, lua_nil_t) { return !right.valid(); } template - inline bool operator!=(lua_nil_t, const proxy& right) { + inline bool operator!=(lua_nil_t, const table_proxy& right) { return right.valid(); } template - inline bool operator!=(const proxy& right, lua_nil_t) { + inline bool operator!=(const table_proxy& right, lua_nil_t) { return right.valid(); } @@ -22619,16 +22641,15 @@ namespace sol { namespace stack { template - struct unqualified_pusher> { - static int push(lua_State* L, const proxy& p) { - reference r = p; - return r.push(L); + struct unqualified_pusher> { + static int push(lua_State* L, const table_proxy& p) { + return p.push(L); } }; } // namespace stack } // namespace sol -// end of sol/proxy.hpp +// end of sol/table_proxy.hpp // beginning of sol/table_iterator.hpp @@ -23266,17 +23287,17 @@ namespace sol { template auto operator[](T&& key) & { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) const& { - return proxy>(*this, std::forward(key)); + return table_proxy>(*this, std::forward(key)); } template auto operator[](T&& key) && { - return proxy>(std::move(*this), std::forward(key)); + return table_proxy>(std::move(*this), std::forward(key)); } template @@ -25005,12 +25026,12 @@ namespace sol { } template - proxy> operator[](T&& key) { + table_proxy> operator[](T&& key) { return global[std::forward(key)]; } template - proxy> operator[](T&& key) const { + table_proxy> operator[](T&& key) const { return global[std::forward(key)]; } diff --git a/tests/compile_tests/source/proxy.cpp b/tests/compile_tests/source/proxy.cpp index 5751acc6..1077013e 100644 --- a/tests/compile_tests/source/proxy.cpp +++ b/tests/compile_tests/source/proxy.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/runtime_tests/source/basic.cpp b/tests/runtime_tests/source/basic.cpp index 2a8b7104..4339420b 100644 --- a/tests/runtime_tests/source/basic.cpp +++ b/tests/runtime_tests/source/basic.cpp @@ -217,7 +217,7 @@ TEST_CASE("simple/get_or", "check if table.get_or works correctly") { REQUIRE(bark == 55.6); } -TEST_CASE("simple/proxy get_or", "check if proxy.get_or works correctly") { +TEST_CASE("simple/table_proxy get_or", "check if table_proxy.get_or works correctly") { sol::state lua; auto bob_table = lua.create_table("bob"); diff --git a/tests/runtime_tests/source/container_table.cpp b/tests/runtime_tests/source/container_table.cpp index 9cda226d..3ee59382 100644 --- a/tests/runtime_tests/source/container_table.cpp +++ b/tests/runtime_tests/source/container_table.cpp @@ -37,13 +37,24 @@ #include #include +inline namespace sol2_test_container_table { + template + struct as_table_callable { + T* ptr; + + as_table_callable(T& ref_) : ptr(&ref_) { + } + + auto operator()() const { + return sol::as_table(*ptr); + } + }; +} // namespace sol2_test_container_table TEST_CASE("containers/vector table roundtrip", "make sure vectors can be round-tripped") { sol::state lua; std::vector v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -54,9 +65,7 @@ TEST_CASE("containers/vector table roundtrip", "make sure vectors can be round-t TEST_CASE("containers/deque table roundtrip", "make sure deques can be round-tripped") { sol::state lua; std::deque v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -67,9 +76,7 @@ TEST_CASE("containers/deque table roundtrip", "make sure deques can be round-tri TEST_CASE("containers/array table roundtrip", "make sure arrays can be round-tripped") { sol::state lua; std::array v{ { 1, 2, 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -80,9 +87,7 @@ TEST_CASE("containers/array table roundtrip", "make sure arrays can be round-tri TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripped") { sol::state lua; std::list v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -93,9 +98,7 @@ TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripp TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists can be round-tripped") { sol::state lua; std::forward_list v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -106,9 +109,7 @@ TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists ca TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped") { sol::state lua; std::map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -119,9 +120,7 @@ TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps can be round-tripped") { sol::state lua; std::unordered_map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -132,9 +131,7 @@ TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps TEST_CASE("containers/unordered_set table roundtrip", "make sure unordered_sets can be round-tripped") { sol::state lua; std::unordered_set v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; @@ -145,9 +142,7 @@ TEST_CASE("containers/unordered_set table roundtrip", "make sure unordered_sets TEST_CASE("containers/set table roundtrip", "make sure sets can be round-tripped") { sol::state lua; std::set v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); + lua.set_function("f", as_table_callable>(v)); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; diff --git a/tests/runtime_tests/source/containers.cpp b/tests/runtime_tests/source/containers.cpp index e03ed3f5..36ece12e 100644 --- a/tests/runtime_tests/source/containers.cpp +++ b/tests/runtime_tests/source/containers.cpp @@ -37,13 +37,24 @@ #include #include +inline namespace sol2_test_containers { + struct returns_callable { + std::vector* ptr; + + returns_callable(std::vector& ref_) : ptr(&ref_) { + } + + std::vector& operator()() const { + REQUIRE(ptr->size() == 3); + return *ptr; + } + }; +} // namespace sol2_test_containers + TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") { sol::state lua; std::vector v{ 1, 2, 3 }; - auto f = [&]() -> std::vector& { - REQUIRE(v.size() == 3); - return v; - }; + returns_callable f(v); lua.set_function("f", f); auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); REQUIRE(result1.valid()); diff --git a/tests/runtime_tests/source/coroutines.cpp b/tests/runtime_tests/source/coroutines.cpp index db074940..0729730b 100644 --- a/tests/runtime_tests/source/coroutines.cpp +++ b/tests/runtime_tests/source/coroutines.cpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -25,6 +25,39 @@ #include +inline namespace sol2_test_coroutines { + struct coroutine_thread_runner_state { + sol::state_view* prunner_thread_state; + + coroutine_thread_runner_state(sol::state_view& ref_) : prunner_thread_state(&ref_) { + } + + auto operator()() const { + sol::state_view& runner_thread_state = *prunner_thread_state; + sol::coroutine cr = runner_thread_state["loop"]; + sol::stack::push(runner_thread_state, 50); + sol::stack::push(runner_thread_state, 25); + int r = cr(); + return r; + } + }; + + struct coroutine_thread_runner { + sol::thread* prunner_thread; + + coroutine_thread_runner(sol::thread& ref_) : prunner_thread(&ref_) { + } + + auto operator()() const { + sol::thread& runner_thread = *prunner_thread; + sol::state_view th_state = runner_thread.state(); + sol::coroutine cr = th_state["loop"]; + int r = cr(); + return r; + } + }; +} // namespace sol2_test_coroutines + struct coro_h { int x = 500; int func() { @@ -151,13 +184,11 @@ TEST_CASE("coroutines/transfer", "test that things created inside of a coroutine for (std::size_t tries = 0; tries < 200; ++tries) { sol::state lua; sol::stack_guard luasg(lua); - + lua.open_libraries(); { sol::function f2; - lua["f"] = [&lua, &f2](sol::object t) { - f2 = sol::function(lua, t); - }; + lua["f"] = [&lua, &f2](sol::object t) { f2 = sol::function(lua, t); }; { auto code = R"( i = 0 @@ -241,10 +272,13 @@ co = nil lua.open_libraries(sol::lib::coroutine, sol::lib::base); lua.new_usertype("coro_test", - sol::constructors(), - "store", &coro_test::store, - "copy_store", &coro_test::copy_store, - "get", &coro_test::get); + sol::constructors(), + "store", + &coro_test::store, + "copy_store", + &coro_test::copy_store, + "get", + &coro_test::get); auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); @@ -299,8 +333,7 @@ co = nil std::string identifier; sol::reference obj; - coro_test_implicit(sol::this_state L, std::string id) - : identifier(id), obj(L, sol::lua_nil) { + coro_test_implicit(sol::this_state L, std::string id) : identifier(id), obj(L, sol::lua_nil) { } void store(sol::table ref) { @@ -325,10 +358,13 @@ co = nil lua.open_libraries(sol::lib::coroutine, sol::lib::base); lua.new_usertype("coro_test", - sol::constructors(), - "store", &coro_test_implicit::store, - "copy_store", &coro_test_implicit::copy_store, - "get", &coro_test_implicit::get); + sol::constructors(), + "store", + &coro_test_implicit::store, + "copy_store", + &coro_test_implicit::copy_store, + "get", + &coro_test_implicit::get); auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); @@ -382,10 +418,13 @@ collectgarbage() lua.open_libraries(sol::lib::coroutine, sol::lib::base); lua.new_usertype("coro_test", - sol::constructors(), - "store", &coro_test_implicit::store, - "copy_store", &coro_test_implicit::copy_store, - "get", &coro_test_implicit::get); + sol::constructors(), + "store", + &coro_test_implicit::store, + "copy_store", + &coro_test_implicit::copy_store, + "get", + &coro_test_implicit::get); auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); @@ -404,7 +443,8 @@ collectgarbage() REQUIRE(s == "SOME_TABLE"); } -TEST_CASE("coroutines/coroutine.create protection", "ensure that a thread picked up from coroutine.create does not throw off the lua stack entirely when called from C++") { +TEST_CASE("coroutines/coroutine.create protection", + "ensure that a thread picked up from coroutine.create does not throw off the lua stack entirely when called from C++") { sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::coroutine); @@ -425,12 +465,7 @@ loop_th = coroutine.create(loop) REQUIRE(r.valid()); sol::thread runner_thread = lua["loop_th"]; - auto test_resume = [&runner_thread]() { - sol::state_view th_state = runner_thread.state(); - sol::coroutine cr = th_state["loop"]; - int r = cr(); - return r; - }; + coroutine_thread_runner test_resume(runner_thread); lua.set_function("test_resume", std::ref(test_resume)); @@ -480,13 +515,7 @@ end // Resume from lua via thread and coroutine sol::thread runner_thread = lua["loop_th"]; sol::state_view runner_thread_state = runner_thread.state(); - auto test_resume = [&runner_thread_state]() { - sol::coroutine cr = runner_thread_state["loop"]; - sol::stack::push(runner_thread_state, 50); - sol::stack::push(runner_thread_state, 25); - int r = cr(); - return r; - }; + coroutine_thread_runner_state test_resume(runner_thread_state); lua.set_function("test_resume", std::ref(test_resume)); // Resume via getting a sol::function from the state @@ -504,7 +533,7 @@ end int v1 = test_resume(); int s1 = runner_thread_state.stack_top(); int v2; - { + { auto result = lua.safe_script("return test_resume()", sol::script_pass_on_error); REQUIRE(result.valid()); v2 = result; @@ -598,9 +627,7 @@ TEST_CASE("coroutines/yielding", "test that a sol3 bound function can yield when lua["hobj"] = &hobj; - lua.new_usertype("coro_h", - "h", sol::yielding(&coro_h::func) - ); + lua.new_usertype("coro_h", "h", sol::yielding(&coro_h::func)); sol::string_view code = R"( co4 = coroutine.create(function() diff --git a/tests/runtime_tests/source/customizations_private.cpp b/tests/runtime_tests/source/customizations_private.cpp index 4a0f5fb1..d19eb12d 100644 --- a/tests/runtime_tests/source/customizations_private.cpp +++ b/tests/runtime_tests/source/customizations_private.cpp @@ -117,6 +117,21 @@ namespace sol { } // namespace stack } // namespace sol +inline namespace sol2_test_customizations_private { + + struct boolean_set_true { + bool* pTwoThingsWorks; + + boolean_set_true(bool& ref_) : pTwoThingsWorks(&ref_) { + } + + void operator()(two_things) const { + bool& TwoThingsWorks = *pTwoThingsWorks; + TwoThingsWorks = true; + } + }; +} // namespace sol2_test_customizations_private + TEST_CASE("customization/split struct", "using the old customization points to handle different kinds of classes") { sol::state lua; @@ -166,8 +181,8 @@ TEST_CASE("customization/usertype", "using the old customization points to handl TEST_CASE("customization/overloading", "using multi-size customized types in an overload") { bool TwoThingsWorks = false, OverloadWorks = false; sol::state lua; - lua["test_two_things"] = [&](two_things) { TwoThingsWorks = true; }; - lua["test_overload"] = sol::overload([&](two_things) { OverloadWorks = true; }, [] {}); + lua["test_two_things"] = boolean_set_true(TwoThingsWorks); + lua["test_overload"] = sol::overload(boolean_set_true(OverloadWorks), [] {}); lua.script( "test_two_things(0, true)\n" diff --git a/tests/runtime_tests/source/environments.cpp b/tests/runtime_tests/source/environments.cpp index 8ee9b78b..5c0d859b 100644 --- a/tests/runtime_tests/source/environments.cpp +++ b/tests/runtime_tests/source/environments.cpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -27,6 +27,64 @@ #include +inline namespace sol2_test_environments { + struct check_g_env { + sol::state* plua; + sol::environment* penv_g; + + check_g_env(sol::state& lua, sol::environment& env_g) : plua(&lua), penv_g(&env_g) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::environment& env_g = *penv_g; + sol::stack_guard luasg(lua); + sol::environment target_env = sol::get_environment(target); + int test_env_g = env_g["test"]; + int test_target_env = target_env["test"]; + REQUIRE(test_env_g == test_target_env); + REQUIRE(test_env_g == 5); + REQUIRE(env_g == target_env); + } + }; + + struct check_f_env { + sol::state* plua; + sol::environment* penv_f; + + check_f_env(sol::state& lua, sol::environment& env_f) : plua(&lua), penv_f(&env_f) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::environment& env_f = *penv_f; + sol::stack_guard luasg(lua); + sol::environment target_env(sol::env_key, target); + int test_env_f = env_f["test"]; + int test_target_env = target_env["test"]; + REQUIRE(test_env_f == test_target_env); + REQUIRE(test_env_f == 31); + REQUIRE(env_f == target_env); + } + }; + + struct check_h_env { + sol::state* plua; + + check_h_env(sol::state& lua) : plua(&lua) { + } + + void operator()(sol::function target) const { + sol::state& lua = *plua; + sol::stack_guard luasg(lua); + sol::environment target_env = sol::get_environment(target); + // cannot strictly test + // if it's the global table, because different lua runtimes + // give different envs when there is no env + } + }; +} // namespace sol2_test_environments + TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { sol::state lua; sol::stack_guard luasg(lua); @@ -61,37 +119,15 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f auto result3 = lua.safe_script("h = function() end", sol::script_pass_on_error); REQUIRE(result3.valid()); - lua.set_function("check_f_env", - [&lua, &env_f](sol::object target) { - sol::stack_guard luasg(lua); - sol::environment target_env(sol::env_key, target); - int test_env_f = env_f["test"]; - int test_target_env = target_env["test"]; - REQUIRE(test_env_f == test_target_env); - REQUIRE(test_env_f == 31); - REQUIRE(env_f == target_env); - }); - lua.set_function("check_g_env", - [&lua, &env_g](sol::function target) { - sol::stack_guard luasg(lua); - sol::environment target_env = sol::get_environment(target); - int test_env_g = env_g["test"]; - int test_target_env = target_env["test"]; - REQUIRE(test_env_g == test_target_env); - REQUIRE(test_env_g == 5); - REQUIRE(env_g == target_env); - }); - lua.set_function("check_h_env", - [&lua](sol::function target) { - sol::stack_guard luasg(lua); - sol::environment target_env = sol::get_environment(target); - }); + lua.set_function("check_f_env", check_f_env(lua, env_f)); + lua.set_function("check_g_env", check_g_env(lua, env_g)); + lua.set_function("check_h_env", check_h_env(lua)); - auto checkf = lua.safe_script("check_f_env(f)"); + auto checkf = lua.safe_script("check_f_env(f)", sol::script_pass_on_error); REQUIRE(checkf.valid()); - auto checkg = lua.safe_script("check_g_env(g)"); + auto checkg = lua.safe_script("check_g_env(g)", sol::script_pass_on_error); REQUIRE(checkg.valid()); - auto checkh = lua.safe_script("check_h_env(h)"); + auto checkh = lua.safe_script("check_h_env(h)", sol::script_pass_on_error); REQUIRE(checkh.valid()); } diff --git a/tests/runtime_tests/source/functions.cpp b/tests/runtime_tests/source/functions.cpp index c68bbd83..33d652c3 100644 --- a/tests/runtime_tests/source/functions.cpp +++ b/tests/runtime_tests/source/functions.cpp @@ -239,7 +239,7 @@ end )", REQUIRE(v->v == 29); } -TEST_CASE("functions/pair and tuple and proxy tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") { +TEST_CASE("functions/pair and tuple and table_proxy tests", "Check if sol::reference and sol::table_proxy can be passed to functions as arguments") { sol::state lua; sol::stack_guard luasg(lua); diff --git a/tests/runtime_tests/source/large_integer.cpp b/tests/runtime_tests/source/large_integer.cpp index d5d08c7f..dc667726 100644 --- a/tests/runtime_tests/source/large_integer.cpp +++ b/tests/runtime_tests/source/large_integer.cpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -28,16 +28,44 @@ #include #include +inline namespace sol2_test_large_integer { + inline bool bool_roundtrip(bool num) { + REQUIRE(num == true); + return num; + } + + inline void trigger_passthrough_crash(sol::state& lua) { + sol::protected_function pf = lua["f"]; + auto result = pf(0xFFFFFFFFFFFFFFFFull); + (void)result; + } + + template + inline T intT_passthrough(T num) { + return num; + } + + template + inline T intT_roundtrip(T num) { + REQUIRE(num == std::numeric_limits::max()); + return num; + } + + inline std::uint64_t int53_roundtrip(std::uint64_t num) { + REQUIRE(num == 0x1FFFFFFFFFFFFFull); + return num; + } +} // namespace sol2_test_large_integer + TEST_CASE("large_integer/bool", "pass bool integral value to and from lua") { sol::state lua; lua.open_libraries(); - lua.set_function("f", [&](bool num) { - REQUIRE(num == true); - return num; - }); - auto result1 = lua.safe_script("x = f(true)\n" - "assert(x == true)", sol::script_pass_on_error); - REQUIRE(result1.valid()); + lua.set_function("f", bool_roundtrip); + sol::optional result1 = lua.safe_script( + "x = f(true)\n" + "assert(x == true)", + sol::script_pass_on_error); + REQUIRE_FALSE(result1.has_value()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == true); @@ -52,12 +80,11 @@ TEST_CASE("large_integers/unsigned32", "pass large unsigned 32bit values to and using T = std::uint32_t; sol::state lua; lua.open_libraries(); - lua.set_function("f", [&](T num) -> T { - REQUIRE(num == 0xFFFFFFFF); - return num; - }); - auto result1 = lua.safe_script("x = f(0xFFFFFFFF)\n" - "assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + lua.set_function("f", intT_roundtrip); + auto result1 = lua.safe_script( + "x = f(0xFFFFFFFF)\n" + "assert(x == 0xFFFFFFFF)", + sol::script_pass_on_error); REQUIRE(result1.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); @@ -68,12 +95,10 @@ TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and fr using T = std::uint64_t; sol::state lua; lua.open_libraries(); - lua.set_function("f", [&](T num) -> T { - REQUIRE(num == 0x1FFFFFFFFFFFFFull); - return num; - }); - auto result1 = lua.safe_script("x = f(0x1FFFFFFFFFFFFF)\n" - "assert(x == 0x1FFFFFFFFFFFFF)"); + lua.set_function("f", int53_roundtrip); + auto result1 = lua.safe_script( + "x = f(0x1FFFFFFFFFFFFF)\n" + "assert(x == 0x1FFFFFFFFFFFFF)"); REQUIRE(result1.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); @@ -83,32 +108,19 @@ TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and fr TEST_CASE("large_integer/unsigned64", "pass too large unsigned 64bit value to lua") { using T = std::int64_t; sol::state lua; - lua.set_function("f", [&](T num) -> T { - return num; - }); - REQUIRE_THROWS([&lua]() { - sol::protected_function pf = lua["f"]; - auto result = pf(0xFFFFFFFFFFFFFFFFull); - }()); + lua.set_function("f", intT_passthrough); + REQUIRE_THROWS(trigger_passthrough_crash(lua)); } TEST_CASE("large_integer/double", "pass negative and large positive values as signed and unsigned from and to lua") { sol::state lua; lua.open_libraries(); - lua.set_function("s32", [&](std::int32_t num) { - return num; - }); - lua.set_function("s64", [&](std::int64_t num) { - return num; - }); - lua.set_function("u32", [&](std::uint32_t num) { - return num; - }); - lua.set_function("u64", [&](std::uint64_t num) { - return num; - }); + lua.set_function("s32", intT_passthrough); + lua.set_function("s64", intT_passthrough); + lua.set_function("u32", intT_passthrough); + lua.set_function("u64", intT_passthrough); { - //signed 32bit + // signed 32bit auto result1 = lua.safe_script("x = s32(-1)", sol::script_pass_on_error); REQUIRE(result1.valid()); auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); @@ -125,7 +137,7 @@ TEST_CASE("large_integer/double", "pass negative and large positive values as si REQUIRE(x.as() == 0xFFFFFFFF); } - //unsigned 32bit + // unsigned 32bit { auto result1 = lua.safe_script("x = u32(0xFFFFFFFF)", sol::script_pass_on_error); REQUIRE(result1.valid()); @@ -141,7 +153,7 @@ TEST_CASE("large_integer/double", "pass negative and large positive values as si REQUIRE(x.is()); REQUIRE(x.as() == 0xFFFFFFFF); } - //signed 64bit + // signed 64bit { auto result1 = lua.safe_script("x = s64(-1)", sol::script_pass_on_error); REQUIRE(result1.valid()); diff --git a/tests/runtime_tests/source/tables.cpp b/tests/runtime_tests/source/tables.cpp index a6b45cc4..b43bde55 100644 --- a/tests/runtime_tests/source/tables.cpp +++ b/tests/runtime_tests/source/tables.cpp @@ -238,7 +238,8 @@ TEST_CASE("tables/optional move", "ensure pushing a sol::optional rvalue corr sol::state sol_state; struct move_only { int secret_code; - move_only(int sc) : secret_code(sc) {} + move_only(int sc) : secret_code(sc) { + } move_only(const move_only&) = delete; move_only(move_only&&) = default; @@ -248,3 +249,36 @@ TEST_CASE("tables/optional move", "ensure pushing a sol::optional rvalue corr sol_state["requires_move"] = sol::optional(move_only(0x4D)); REQUIRE(sol_state["requires_move"].get().secret_code == 0x4D); } + +TEST_CASE("table/stack table size", "make sure size() works correctly on stack tables") { + sol::state lua; + sol::stack_guard luasg(lua); + sol::stack_table t(lua, sol::create); + t[1] = 42; + auto sz1 = t.size(); + REQUIRE(sz1 == 1); + sol::stack::push(lua, "some string"); + auto sz2 = t.size(); + REQUIRE(sz2 == 1); + std::string s = sol::stack::pop(lua); + REQUIRE(s == "some string"); + sol::table t2 = sol::stack::pop(lua); + auto sz3 = t2.size(); + REQUIRE(sz1 == sz3); + REQUIRE(sz1 == sz2); +} + +TEST_CASE("table/proxy call", "test proxy calls put the variable in the right place") { + sol::state lua; + sol::stack_guard luasg(lua); + { + sol::stack_guard tsg(lua); + lua["t"] = std::initializer_list>{ { 1, "borf" }, { 2, "bjork" }, { 3, "waf" } }; + } + { + sol::stack_guard fsg(lua); + lua["f"] = [](std::string bjork) { REQUIRE(bjork == std::string("borf")); }; + } + auto prox = lua["t"][1]; + lua["f"](prox); +} diff --git a/tests/runtime_tests/source/tables.insertion.cpp b/tests/runtime_tests/source/tables.insertion.cpp index b16b9dda..85b9c47e 100644 --- a/tests/runtime_tests/source/tables.insertion.cpp +++ b/tests/runtime_tests/source/tables.insertion.cpp @@ -27,7 +27,7 @@ #include -TEST_CASE("tables/proxy override_value", "allow override_value by way of key") { +TEST_CASE("tables/table_proxy override_value", "allow override_value by way of key") { sol::state lua; sol::stack_guard luasg(lua); lua.open_libraries(sol::lib::base, sol::lib::io); @@ -59,7 +59,7 @@ TEST_CASE("tables/insertion override", "allow override all non-table values plus REQUIRE(*b_totally_there == 500); REQUIRE_FALSE(static_cast(totally_not_there)); } - SECTION("proxy") { + SECTION("table_proxy") { sol::state lua; sol::stack_guard luasg(lua); @@ -77,7 +77,7 @@ TEST_CASE("tables/insertion override", "allow override all non-table values plus REQUIRE(*b_totally_there == 500); REQUIRE_FALSE(static_cast(totally_not_there)); } - SECTION("complex proxy") { + SECTION("complex table_proxy") { sol::state lua; sol::stack_guard luasg(lua); @@ -104,7 +104,7 @@ TEST_CASE("tables/insertion update_if_empty", "allow updating a value only if it REQUIRE(static_cast(totally_there)); REQUIRE(*totally_there == 357); } - SECTION("proxy") { + SECTION("table_proxy") { sol::state lua; sol::stack_guard luasg(lua); @@ -120,7 +120,7 @@ TEST_CASE("tables/insertion update_if_empty", "allow updating a value only if it REQUIRE(static_cast(totally_there_still)); REQUIRE(*totally_there_still == 357); } - SECTION("proxy invoker") { + SECTION("table_proxy invoker") { sol::state lua; sol::stack_guard luasg(lua); @@ -165,7 +165,7 @@ TEST_CASE("tables/get create_if_nil", "create tables all the way down") { REQUIRE(static_cast(totally_created)); REQUIRE(static_cast(totally_there)); } - SECTION("proxy non-optional") { + SECTION("table_proxy non-optional") { sol::state lua; sol::stack_guard luasg_outer(lua); @@ -181,7 +181,7 @@ TEST_CASE("tables/get create_if_nil", "create tables all the way down") { } } - SECTION("proxy") { + SECTION("table_proxy") { sol::state lua; sol::stack_guard luasg(lua);