From dde4aa64fcbacd09cf066aad5eee7482fb984877 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 19 Feb 2017 05:00:11 -0500 Subject: [PATCH] simple_usertype now responds with nil on bad lookups and sets items into place properly when new_index'd --- single/sol/sol.hpp | 27 ++++++++++-------- sol/function_types_overloaded.hpp | 2 +- sol/simple_usertype_metatable.hpp | 17 ++++++----- sol/usertype_metatable.hpp | 4 +-- test_simple_usertypes.cpp | 47 +++++++++++++++++++++++++++++-- test_usertypes.cpp | 10 +++++++ 6 files changed, 82 insertions(+), 25 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 88c5f0ea..ff868d73 100644 --- a/single/sol/sol.hpp +++ b/single/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 2017-02-19 02:59:41.608823 UTC -// This header was generated with sol v2.15.8 (revision a9cfe4b) +// Generated 2017-02-19 09:59:38.638408 UTC +// This header was generated with sol v2.15.8 (revision 0c8ec82) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -8552,7 +8552,7 @@ namespace sol { template int call(types, index_value, types, types, lua_State* L, int, int) { auto& func = std::get(overloads); - return call_detail::call_wrapped(L, func); + return call_detail::call_wrapped(L, func); } int operator()(lua_State* L) { @@ -10156,9 +10156,9 @@ namespace sol { auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); if (is_index) - return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); else - return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); } template @@ -10729,10 +10729,13 @@ namespace sol { lua_settop(L, 0); return 0; } - lua_pop(L, 1); return indexing_fail(L); } + inline int simple_indexing_fail(lua_State* L) { + return stack::push(L, sol::lua_nil); + } + template inline int simple_core_indexing_call(lua_State* L) { simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); @@ -10840,7 +10843,7 @@ namespace sol { } template - void insert_prepare(std::true_type, lua_State* L, N&& n, F&& f, Args&&... args) { + void insert_prepare(std::true_type, lua_State* L, N&&, F&& f, Args&&... args) { object o = make_object(L, std::forward(f), function_detail::call_indicator(), std::forward(args)...); callconstructfunc = std::move(o); } @@ -10956,7 +10959,7 @@ namespace sol { template simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) : callconstructfunc(lua_nil), - indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::indexing_fail), + indexfunc(&usertype_detail::simple_indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex), indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), baseclasscheck(nullptr), baseclasscast(nullptr), @@ -11186,15 +11189,15 @@ namespace sol { stack::set_field(L, meta_function::index, make_closure(&usertype_detail::simple_index_call, make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex, + umx.indexfunc, + umx.newindexfunc, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, meta_function::new_index, make_closure(&usertype_detail::simple_new_index_call, make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex, + umx.indexfunc, + umx.newindexfunc, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, metatable_key, metabehind, t.stack_index()); diff --git a/sol/function_types_overloaded.hpp b/sol/function_types_overloaded.hpp index 42fd4042..9591297d 100644 --- a/sol/function_types_overloaded.hpp +++ b/sol/function_types_overloaded.hpp @@ -45,7 +45,7 @@ namespace sol { template int call(types, index_value, types, types, lua_State* L, int, int) { auto& func = std::get(overloads); - return call_detail::call_wrapped(L, func); + return call_detail::call_wrapped(L, func); } int operator()(lua_State* L) { diff --git a/sol/simple_usertype_metatable.hpp b/sol/simple_usertype_metatable.hpp index 72e377a8..efb06d4e 100644 --- a/sol/simple_usertype_metatable.hpp +++ b/sol/simple_usertype_metatable.hpp @@ -98,10 +98,13 @@ namespace sol { lua_settop(L, 0); return 0; } - lua_pop(L, 1); return indexing_fail(L); } + inline int simple_indexing_fail(lua_State* L) { + return stack::push(L, sol::lua_nil); + } + template inline int simple_core_indexing_call(lua_State* L) { simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); @@ -209,7 +212,7 @@ namespace sol { } template - void insert_prepare(std::true_type, lua_State* L, N&& n, F&& f, Args&&... args) { + void insert_prepare(std::true_type, lua_State* L, N&&, F&& f, Args&&... args) { object o = make_object(L, std::forward(f), function_detail::call_indicator(), std::forward(args)...); callconstructfunc = std::move(o); } @@ -325,7 +328,7 @@ namespace sol { template simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) : callconstructfunc(lua_nil), - indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::indexing_fail), + indexfunc(&usertype_detail::simple_indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex), indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), baseclasscheck(nullptr), baseclasscast(nullptr), @@ -555,15 +558,15 @@ namespace sol { stack::set_field(L, meta_function::index, make_closure(&usertype_detail::simple_index_call, make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex, + umx.indexfunc, + umx.newindexfunc, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, meta_function::new_index, make_closure(&usertype_detail::simple_new_index_call, make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex, + umx.indexfunc, + umx.newindexfunc, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, metatable_key, metabehind, t.stack_index()); diff --git a/sol/usertype_metatable.hpp b/sol/usertype_metatable.hpp index 37693227..33aa63ba 100644 --- a/sol/usertype_metatable.hpp +++ b/sol/usertype_metatable.hpp @@ -107,9 +107,9 @@ namespace sol { auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); if (is_index) - return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); else - return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); } template diff --git a/test_simple_usertypes.cpp b/test_simple_usertypes.cpp index dc92a71f..528cc1b1 100644 --- a/test_simple_usertypes.cpp +++ b/test_simple_usertypes.cpp @@ -489,6 +489,10 @@ TEST_CASE("usertype/simple-class-propogation", "make sure methods and variables } TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-based constructors can be serialized") { + struct thing {}; + struct v_test { + + }; struct f_test { int i; f_test(int i) : i(i) {} }; @@ -503,11 +507,10 @@ TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-bas lua.open_libraries(sol::lib::base); auto f = sol::factories([]() {return f_test(30); }); - lua.new_simple_usertype("f_test", sol::call_constructor, sol::factories([]() { - return f_test(20); - }), + return f_test(20); + }), "new", f ); @@ -535,4 +538,42 @@ TEST_CASE("usertype/simple-call-constructor", "ensure that all kinds of call-bas REQUIRE(b.i == 21); REQUIRE(c.i == 22); REQUIRE(d.i == 30); + + auto vfactories = sol::factories( + [](const sol::table& tbl) { + for (auto v : tbl) + { + REQUIRE(v.second.valid()); + + // This fails only when the call_constructor is used: + REQUIRE(v.second.is()); + } + return v_test(); + } + ); + + lua.new_simple_usertype("v_test", + sol::meta_function::construct, vfactories, + sol::call_constructor, vfactories + ); + + lua.new_simple_usertype("thing"); + lua.script("things = {thing.new(), thing.new()}"); + + SECTION("new") { + REQUIRE_NOTHROW(lua.script("a = v_test.new(things)")); + } + SECTION("call_constructor") { + REQUIRE_NOTHROW(lua.script("b = v_test(things)")); + } +} + +TEST_CASE("usertype/simple-missing-key", "make sure a missing key returns nil") { + struct thing {}; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_simple_usertype("thing"); + REQUIRE_NOTHROW(lua.script("print(thing.missingKey)")); } diff --git a/test_usertypes.cpp b/test_usertypes.cpp index 2a35732e..7478c58a 100644 --- a/test_usertypes.cpp +++ b/test_usertypes.cpp @@ -1493,3 +1493,13 @@ a = A(24.3) A& a = lua["a"]; REQUIRE(a.f == 24.3); } + +TEST_CASE("usertype/missing-key", "make sure a missing key returns nil") { + struct thing {}; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("thing"); + REQUIRE_NOTHROW(lua.script("print(thing.missingKey)")); +}