From 3bece97a40894c77c17be0f35fc455bde401e176 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 15 Jun 2016 12:00:25 -0400 Subject: [PATCH] Statikk trampolines and new tests for the newly opened issue Closes #119 --- sol/usertype_metatable.hpp | 44 +++++++++++++++++++++++++++++--------- tests.cpp | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/sol/usertype_metatable.hpp b/sol/usertype_metatable.hpp index 6685f862..bff4233b 100644 --- a/sol/usertype_metatable.hpp +++ b/sol/usertype_metatable.hpp @@ -214,7 +214,7 @@ namespace sol { string_detail::string_shim name = usertype_detail::make_shim(std::get(functions)); if (accessor == name) { if (is_variable_binding(functions))>::value) { - return call_with(L, *this); + return real_call_with(L, *this); } return stack::push(L, c_closure(call, stack::push(L, light(*this)))); } @@ -222,27 +222,51 @@ namespace sol { } template - static int call(lua_State* L) { + static int real_call(lua_State* L) { usertype_metatable& f = stack::get>(L, up_value_index(1)); - return call_with(L, f); + return real_call_with(L, f); } template - static int call_with(lua_State* L, usertype_metatable& um) { + static int real_call_with(lua_State* L, usertype_metatable& um) { auto& f = call_detail::pick(std::integral_constant(), std::get(um.functions)); return call_detail::call_wrapped(L, f); } - static int index_call(lua_State* L) { + static int real_index_call(lua_State* L) { usertype_metatable& f = stack::get>(L, up_value_index(1)); - string_detail::string_shim accessor = stack::get(L, -1); - return f.find_call(std::true_type(), std::make_index_sequence::value>(), L, accessor); + if (stack::get(L, -1) == type::string) { + string_detail::string_shim accessor = stack::get(L, -1); + return f.find_call(std::true_type(), std::make_index_sequence::value>(), L, accessor); + } + return f.indexfunc(L); + } + + static int real_new_index_call(lua_State* L) { + usertype_metatable& f = stack::get>(L, up_value_index(1)); + if (stack::get(L, -2) == type::string) { + string_detail::string_shim accessor = stack::get(L, -2); + return f.find_call(std::false_type(), std::make_index_sequence::value>(), L, accessor); + } + return f.indexfunc(L); + } + + template + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + template + static int call_with(lua_State* L) { + return detail::static_trampoline<(&real_call_with)>(L); + } + + static int index_call(lua_State* L) { + return detail::static_trampoline<(&real_index_call)>(L); } static int new_index_call(lua_State* L) { - usertype_metatable& f = stack::get>(L, up_value_index(1)); - string_detail::string_shim accessor = stack::get(L, -2); - return f.find_call(std::false_type(), std::make_index_sequence::value>(), L, accessor); + return detail::static_trampoline<(&real_new_index_call)>(L); } virtual int push_um(lua_State* L) override { diff --git a/tests.cpp b/tests.cpp index eeace2e4..30063a18 100644 --- a/tests.cpp +++ b/tests.cpp @@ -416,3 +416,44 @@ print('name = ' .. obj.props.name) std::string name = lua["obj"]["props"]["name"]; REQUIRE(name == "test name"); } + +TEST_CASE("misc/indexing_numbers", "make sure indexing functions can be override on usertypes") { + class vector { + public: + double data[3]; + + vector() : data{ 0,0,0 } {} + + double& operator[](int i) + { + return data[i]; + } + + + static double my_index(vector& v, int i) + { + return v[i]; + } + + static void my_new_index(vector& v, int i, double x) + { + v[i] = x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("vector", sol::constructors>(), + sol::meta_function::index, &vector::my_index, + sol::meta_function::new_index, &vector::my_new_index); + lua.script("v = vector.new()\n" + "print(v[1])\n" + "v[2] = 3\n" + "print(v[2])\n" + ); + + vector& v = lua["v"]; + REQUIRE(v[0] == 0.0); + REQUIRE(v[1] == 0.0); + REQUIRE(v[2] == 3.0); +}