static indexing is a real thing now

This commit is contained in:
ThePhD 2019-04-29 01:38:01 -04:00
parent 67231f707f
commit c442c6c620
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
5 changed files with 180 additions and 25 deletions

View File

@ -795,12 +795,14 @@ namespace sol {
call_construct,
storage,
gc_names,
static_index,
static_new_index,
};
typedef meta_function meta_method;
inline const std::array<std::string, 35>& meta_function_names() {
static const std::array<std::string, 35> names = { { "new",
inline const std::array<std::string, 37>& meta_function_names() {
static const std::array<std::string, 37> names = { { "new",
"__index",
"__newindex",
"__mode",
@ -837,7 +839,9 @@ namespace sol {
"__typeinfo",
"__sol.call_new",
"__sol.storage",
"__sol.gc_names" } };
"__sol.gc_names",
"__sol.static_index",
"__sol.static_new_index" } };
return names;
}

View File

@ -36,7 +36,7 @@ namespace sol { namespace u_detail {
template <typename T>
struct usertype_storage;
optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, const char* gcmetakey);
optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, int index);
usertype_storage_base& get_usertype_storage_base(lua_State* L, const char* gcmetakey);
template <typename T>
optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L);
@ -158,6 +158,8 @@ namespace sol { namespace u_detail {
bool is_destruction = false;
bool is_index = false;
bool is_new_index = false;
bool is_static_index = false;
bool is_static_new_index = false;
bool poison_indexing = false;
bool is_unqualified_lua_CFunction = false;
bool is_unqualified_lua_reference = false;
@ -207,7 +209,7 @@ namespace sol { namespace u_detail {
t.pop();
return;
}
if (is_index || is_new_index) {
if (is_index || is_new_index || is_static_index || is_static_new_index) {
// do not serialize the new_index and index functions here directly
// we control those...
t.pop();
@ -294,6 +296,7 @@ namespace sol { namespace u_detail {
reference gc_names_table;
reference named_metatable;
new_index_call_storage base_index;
new_index_call_storage static_base_index;
bool is_using_index;
bool is_using_new_index;
std::bitset<64> properties;
@ -310,6 +313,7 @@ namespace sol { namespace u_detail {
, gc_names_table(make_reference(L, create))
, named_metatable(make_reference(L, create))
, base_index()
, static_base_index()
, is_using_index(false)
, is_using_new_index(false)
, properties() {
@ -317,6 +321,10 @@ namespace sol { namespace u_detail {
base_index.index = index_target_fail;
base_index.new_index = new_index_target_fail;
base_index.new_binding_data = nullptr;
static_base_index.binding_data = nullptr;
static_base_index.index = index_target_fail;
static_base_index.new_binding_data = this;
static_base_index.new_index = new_index_target_set;
}
template <typename Fx>
@ -521,11 +529,10 @@ namespace sol { namespace u_detail {
}
else if constexpr (from_named_metatable) {
if constexpr (is_new_index) {
self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3)));
return 0;
return self.static_base_index.new_index(L, self.static_base_index.new_binding_data);
}
else {
return index_fail(L);
return self.static_base_index.index(L, self.static_base_index.binding_data);
}
}
else {
@ -568,6 +575,12 @@ namespace sol { namespace u_detail {
template <typename T = void, typename Key, typename Value>
void set(lua_State* L, Key&& key, Value&& value);
static int new_index_target_set(lua_State* L, void* target) {
usertype_storage_base& self = *static_cast<usertype_storage_base*>(target);
self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3)));
return 0;
}
};
template <typename T>
@ -662,19 +675,23 @@ namespace sol { namespace u_detail {
bool is_index = (s == to_string(meta_function::index));
bool is_new_index = (s == to_string(meta_function::new_index));
bool is_static_index = (s == to_string(meta_function::static_index));
bool is_static_new_index = (s == to_string(meta_function::static_new_index));
bool is_destruction = s == to_string(meta_function::garbage_collect);
bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index);
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
index_call_storage ics;
ics.binding_data = b.data();
ics.index = is_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
ics.new_index
= is_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
= is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
string_for_each_metatable_func for_each_fx;
for_each_fx.is_destruction = is_destruction;
for_each_fx.is_index = is_index;
for_each_fx.is_new_index = is_new_index;
for_each_fx.is_static_index = is_static_index;
for_each_fx.is_static_new_index = is_static_new_index;
for_each_fx.poison_indexing = poison_indexing;
for_each_fx.p_key = &s;
for_each_fx.p_ics = &ics;
@ -706,6 +723,14 @@ namespace sol { namespace u_detail {
this->base_index.new_index = ics.new_index;
this->base_index.new_binding_data = ics.binding_data;
}
if (is_static_index) {
this->static_base_index.index = ics.index;
this->static_base_index.binding_data = ics.binding_data;
}
if (is_static_new_index) {
this->static_base_index.new_index = ics.new_index;
this->static_base_index.new_binding_data = ics.binding_data;
}
this->for_each_table(L, for_each_fx);
this->add_entry(s, std::move(ics));
}

View File

@ -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-04-28 20:45:14.775010 UTC
// This header was generated with sol v3.0.1-beta2 (revision 3426947)
// Generated 2019-04-29 05:20:05.556326 UTC
// This header was generated with sol v3.0.1-beta2 (revision 67231f7)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP

View File

@ -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-04-28 20:45:14.470847 UTC
// This header was generated with sol v3.0.1-beta2 (revision 3426947)
// Generated 2019-04-29 05:20:05.284047 UTC
// This header was generated with sol v3.0.1-beta2 (revision 67231f7)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -6948,12 +6948,14 @@ namespace sol {
call_construct,
storage,
gc_names,
static_index,
static_new_index,
};
typedef meta_function meta_method;
inline const std::array<std::string, 35>& meta_function_names() {
static const std::array<std::string, 35> names = { { "new",
inline const std::array<std::string, 37>& meta_function_names() {
static const std::array<std::string, 37> names = { { "new",
"__index",
"__newindex",
"__mode",
@ -6990,7 +6992,9 @@ namespace sol {
"__typeinfo",
"__sol.call_new",
"__sol.storage",
"__sol.gc_names" } };
"__sol.gc_names",
"__sol.static_index",
"__sol.static_new_index" } };
return names;
}
@ -20683,7 +20687,7 @@ namespace sol { namespace u_detail {
template <typename T>
struct usertype_storage;
optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, const char* gcmetakey);
optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, int index);
usertype_storage_base& get_usertype_storage_base(lua_State* L, const char* gcmetakey);
template <typename T>
optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L);
@ -20805,6 +20809,8 @@ namespace sol { namespace u_detail {
bool is_destruction = false;
bool is_index = false;
bool is_new_index = false;
bool is_static_index = false;
bool is_static_new_index = false;
bool poison_indexing = false;
bool is_unqualified_lua_CFunction = false;
bool is_unqualified_lua_reference = false;
@ -20854,7 +20860,7 @@ namespace sol { namespace u_detail {
t.pop();
return;
}
if (is_index || is_new_index) {
if (is_index || is_new_index || is_static_index || is_static_new_index) {
// do not serialize the new_index and index functions here directly
// we control those...
t.pop();
@ -20941,6 +20947,7 @@ namespace sol { namespace u_detail {
reference gc_names_table;
reference named_metatable;
new_index_call_storage base_index;
new_index_call_storage static_base_index;
bool is_using_index;
bool is_using_new_index;
std::bitset<64> properties;
@ -20957,6 +20964,7 @@ namespace sol { namespace u_detail {
, gc_names_table(make_reference(L, create))
, named_metatable(make_reference(L, create))
, base_index()
, static_base_index()
, is_using_index(false)
, is_using_new_index(false)
, properties() {
@ -20964,6 +20972,10 @@ namespace sol { namespace u_detail {
base_index.index = index_target_fail;
base_index.new_index = new_index_target_fail;
base_index.new_binding_data = nullptr;
static_base_index.binding_data = nullptr;
static_base_index.index = index_target_fail;
static_base_index.new_binding_data = this;
static_base_index.new_index = new_index_target_set;
}
template <typename Fx>
@ -21168,11 +21180,10 @@ namespace sol { namespace u_detail {
}
else if constexpr (from_named_metatable) {
if constexpr (is_new_index) {
self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3)));
return 0;
return self.static_base_index.new_index(L, self.static_base_index.new_binding_data);
}
else {
return index_fail(L);
return self.static_base_index.index(L, self.static_base_index.binding_data);
}
}
else {
@ -21215,6 +21226,12 @@ namespace sol { namespace u_detail {
template <typename T = void, typename Key, typename Value>
void set(lua_State* L, Key&& key, Value&& value);
static int new_index_target_set(lua_State* L, void* target) {
usertype_storage_base& self = *static_cast<usertype_storage_base*>(target);
self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3)));
return 0;
}
};
template <typename T>
@ -21309,19 +21326,23 @@ namespace sol { namespace u_detail {
bool is_index = (s == to_string(meta_function::index));
bool is_new_index = (s == to_string(meta_function::new_index));
bool is_static_index = (s == to_string(meta_function::static_index));
bool is_static_new_index = (s == to_string(meta_function::static_new_index));
bool is_destruction = s == to_string(meta_function::garbage_collect);
bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index);
void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this));
index_call_storage ics;
ics.binding_data = b.data();
ics.index = is_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value> : &Binding::template index_call_with_<true, is_var_bind::value>;
ics.new_index
= is_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
= is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value> : &Binding::template index_call_with_<false, is_var_bind::value>;
string_for_each_metatable_func for_each_fx;
for_each_fx.is_destruction = is_destruction;
for_each_fx.is_index = is_index;
for_each_fx.is_new_index = is_new_index;
for_each_fx.is_static_index = is_static_index;
for_each_fx.is_static_new_index = is_static_new_index;
for_each_fx.poison_indexing = poison_indexing;
for_each_fx.p_key = &s;
for_each_fx.p_ics = &ics;
@ -21353,6 +21374,14 @@ namespace sol { namespace u_detail {
this->base_index.new_index = ics.new_index;
this->base_index.new_binding_data = ics.binding_data;
}
if (is_static_index) {
this->static_base_index.index = ics.index;
this->static_base_index.binding_data = ics.binding_data;
}
if (is_static_new_index) {
this->static_base_index.new_index = ics.new_index;
this->static_base_index.new_binding_data = ics.binding_data;
}
this->for_each_table(L, for_each_fx);
this->add_entry(s, std::move(ics));
}

View File

@ -31,6 +31,44 @@
#include <list>
#include <memory>
#include <unordered_map>
#include <string_view>
struct static_special_property_object {
static int named_set_calls;
static int named_get_calls;
struct obj_hash {
std::size_t operator()(const sol::object& obj) const noexcept {
return std::hash<const void*>()(obj.pointer());
}
};
std::unordered_map<sol::object, sol::object, obj_hash> props;
sol::object get_property_lua(sol::stack_object key) const {
if (auto it = props.find(key); it != props.cend()) {
return it->second;
}
return sol::lua_nil;
}
void set_property_lua(sol::stack_object key, sol::stack_object value) {
props.insert_or_assign(key, sol::object(value));
}
static void named_get_property_lua(sol::this_state L) {
++named_get_calls;
luaL_error(L, "absolutely not");
}
static void named_set_property_lua(sol::this_state L) {
++named_set_calls;
luaL_error(L, "absolutely not");
}
};
int static_special_property_object::named_get_calls = 0;
int static_special_property_object::named_set_calls = 0;
struct special_property_object {
struct obj_hash {
@ -435,7 +473,6 @@ TEST_CASE("usertype/object and class extensible", "make sure that a class which
lua["add_class_func"] = [](sol::this_state L, special_property_object&) {
sol::stack_userdata self = sol::stack::get<sol::stack_userdata>(L, 1);
sol::usertype<special_property_object> mt = self[sol::metatable_key];
std::string s = mt["__name"];
mt["additional_function"] = []() { return 24; };
};
@ -468,3 +505,63 @@ TEST_CASE("usertype/object and class extensible", "make sure that a class which
sol::script_pass_on_error);
REQUIRE(result1.has_value());
}
TEST_CASE("usertypes/static new index and static index", "ensure static index and static new index provide the proper interface") {
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<static_special_property_object>("static_special_property_object",
sol::meta_function::index,
&static_special_property_object::get_property_lua,
sol::meta_function::new_index,
&static_special_property_object::set_property_lua,
sol::meta_function::static_index,
&static_special_property_object::named_get_property_lua,
sol::meta_function::static_new_index,
&static_special_property_object::named_set_property_lua);
lua["add_object_func"] = [](sol::this_state L, static_special_property_object&) {
sol::stack_userdata self = sol::stack::get<sol::stack_userdata>(L, 1);
self["specific_function"] = []() { return 23; };
};
sol::optional<sol::error> result0 = lua.safe_script(R"(
s = static_special_property_object.new()
s2 = static_special_property_object.new()
add_object_func(s)
value2 = s:specific_function()
assert(value2 == 23)
)",
sol::script_pass_on_error);
REQUIRE_FALSE(result0.has_value());
int value2 = lua["value2"];
REQUIRE(value2 == 23);
sol::optional<sol::error> result1 = lua.safe_script(R"(
function static_special_property_object:additional_function ()
return 24
end
value = s:additional_function()
assert(value == 24)
)",
sol::script_pass_on_error);
REQUIRE(result1.has_value());
bool is_value_valid = lua["value"].valid();
REQUIRE_FALSE(is_value_valid);
sol::optional<sol::error> result2 = lua.safe_script(R"(
value3 = s2:specific_function()
assert(value3 == 23)
)",
sol::script_pass_on_error);
REQUIRE(result2.has_value());
sol::optional<sol::error> result3 = lua.safe_script(R"(
assert(static_special_property_object.non_existent == nil)
)",
sol::script_pass_on_error);
REQUIRE(result3.has_value());
REQUIRE(static_special_property_object::named_get_calls == 1);
REQUIRE(static_special_property_object::named_set_calls == 1);
}