mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Reworked the architecture of usertype functions to include a shim table between it and the actual metatables.
This means that usertype tables visible in the code and bound to the name specified with `new_usertype` and friends will be normal tables, and those tables delegate their responsibilities to the 3 backend tables of `sol.unique_usertype<T>`, `sol.T`, and `sol.T*`. This separation allows for a few caveats for updating and overriding members of `new_simple_usertype` tables to 'just work' without any serious hassle, and to have a single point that lets up decide how to perform updates properly. It also restores an optimization we had to turn off by ham-fisting whether ot not indexing was turned on the usertype metatables themselves. o wow wow wow it's such a nice commit message look at how organized it is PFFFFFFFFFF.
This commit is contained in:
parent
007fd19b8d
commit
c2d219ea7d
|
@ -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 2016-10-06 00:53:22.017715 UTC
|
||||
// This header was generated with sol v2.14.9 (revision 0ba4650)
|
||||
// Generated 2016-10-11 09:41:28.136959 UTC
|
||||
// This header was generated with sol v2.14.9 (revision 007fd19)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -4524,6 +4524,7 @@ namespace sol {
|
|||
static const std::string name;
|
||||
static const std::string qualified_name;
|
||||
static const std::string metatable;
|
||||
static const std::string user_metatable;
|
||||
static const std::string user_gc_metatable;
|
||||
static const std::string gc_table;
|
||||
};
|
||||
|
@ -4537,6 +4538,9 @@ namespace sol {
|
|||
template<typename T>
|
||||
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::user_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user");
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::user_gc_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
|
||||
|
||||
|
@ -7386,7 +7390,7 @@ namespace sol {
|
|||
inline int construct(lua_State* L) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable[0], 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
|
@ -7624,7 +7628,7 @@ namespace sol {
|
|||
static int call(lua_State* L, F&) {
|
||||
const auto& metakey = usertype_traits<T>::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, &usertype_traits<T>::user_metatable[0], 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
|
@ -7679,7 +7683,7 @@ namespace sol {
|
|||
};
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
|
||||
call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable[0]);
|
||||
int syntaxval = static_cast<int>(syntax);
|
||||
int argcount = lua_gettop(L) - syntaxval;
|
||||
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
|
||||
|
@ -10108,7 +10112,7 @@ namespace sol {
|
|||
}
|
||||
// metatable on the metatable
|
||||
// for call constructor purposes and such
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_createtable(L, 0, 3);
|
||||
stack_reference metabehind(L, -1);
|
||||
if (um.callconstructfunc != nullptr) {
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||
|
@ -10121,9 +10125,26 @@ namespace sol {
|
|||
metabehind.pop();
|
||||
// We want to just leave the table
|
||||
// in the registry only, otherwise we return it
|
||||
if (i < 2) {
|
||||
t.pop();
|
||||
t.pop();
|
||||
}
|
||||
|
||||
// Now for the shim-table that actually gets assigned to the name
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable[0]);
|
||||
stack_reference t(L, -1);
|
||||
stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, value_table.data(), 1);
|
||||
{
|
||||
lua_createtable(L, 0, 3);
|
||||
stack_reference metabehind(L, -1);
|
||||
if (um.callconstructfunc != nullptr) {
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||
}
|
||||
if (um.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -10141,6 +10162,8 @@ namespace sol {
|
|||
namespace sol {
|
||||
|
||||
namespace usertype_detail {
|
||||
const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001);
|
||||
|
||||
struct variable_wrapper {
|
||||
virtual int index(lua_State* L) = 0;
|
||||
virtual int new_index(lua_State* L) = 0;
|
||||
|
@ -10178,8 +10201,31 @@ namespace sol {
|
|||
|
||||
template <typename T>
|
||||
inline int simple_metatable_newindex(lua_State* L) {
|
||||
if (stack::stack_detail::check_metatable<T, false>(L, 1)) {
|
||||
stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), 1);
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) {
|
||||
// Pointer types, AKA "references" from C++
|
||||
const char* metakey = nullptr;
|
||||
switch (i) {
|
||||
case 0:
|
||||
metakey = &usertype_traits<T*>::metatable[0];
|
||||
break;
|
||||
case 1:
|
||||
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
metakey = &usertype_traits<T>::metatable[0];
|
||||
break;
|
||||
}
|
||||
luaL_getmetatable(L, metakey);
|
||||
int tableindex = lua_gettop(L);
|
||||
if (type_of(L, tableindex) == type::nil) {
|
||||
continue;
|
||||
}
|
||||
stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -10369,15 +10415,15 @@ namespace sol {
|
|||
|
||||
template <typename... Bases>
|
||||
void add(lua_State*, base_classes_tag, bases<Bases...>) {
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform");
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report.");
|
||||
if (sizeof...(Bases) < 1) {
|
||||
return;
|
||||
}
|
||||
mustindex = true;
|
||||
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... };
|
||||
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||
indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>;
|
||||
|
@ -10388,11 +10434,11 @@ namespace sol {
|
|||
template<std::size_t... I, typename Tuple>
|
||||
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
|
||||
: callconstructfunc(nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::simple_metatable_newindex<T>),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(true), secondarymeta(true) {
|
||||
mustindex(false), secondarymeta(false) {
|
||||
(void)detail::swallow{ 0,
|
||||
(add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)...
|
||||
};
|
||||
|
@ -10466,6 +10512,40 @@ namespace sol {
|
|||
bool hasequals = false;
|
||||
bool hasless = false;
|
||||
bool haslessequals = false;
|
||||
auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) {
|
||||
if (first == name_of(meta_function::equal_to)) {
|
||||
hasequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than)) {
|
||||
hasless = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than_or_equal_to)) {
|
||||
haslessequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
else if (first == name_of(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack::set_field(L, first, second, t.stack_index());
|
||||
};
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
// Pointer types, AKA "references" from C++
|
||||
const char* metakey = nullptr;
|
||||
|
@ -10486,38 +10566,7 @@ namespace sol {
|
|||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
if (first == name_of(meta_function::equal_to)) {
|
||||
hasequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than)) {
|
||||
hasless = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than_or_equal_to)) {
|
||||
haslessequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
else if (first == name_of(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack::set_field(L, first, second, t.stack_index());
|
||||
register_kvp(i, t, first, second);
|
||||
}
|
||||
luaL_Reg opregs[4]{};
|
||||
int opregsindex = 0;
|
||||
|
@ -10550,7 +10599,6 @@ namespace sol {
|
|||
|
||||
if (umx.mustindex) {
|
||||
// use indexing function
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report.");
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
|
@ -10570,7 +10618,7 @@ namespace sol {
|
|||
}
|
||||
// metatable on the metatable
|
||||
// for call constructor purposes and such
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
|
@ -10592,9 +10640,44 @@ namespace sol {
|
|||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
||||
if (i < 2)
|
||||
t.pop();
|
||||
t.pop();
|
||||
}
|
||||
|
||||
// Now for the shim-table that actually gets pushed
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable[0]);
|
||||
stack_reference t(L, -1);
|
||||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
register_kvp(2, t, first, second);
|
||||
}
|
||||
{
|
||||
lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
}
|
||||
// use indexing function
|
||||
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<T>,
|
||||
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<T>,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
}
|
||||
|
||||
// Don't pop the table when we're done;
|
||||
// return it
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace sol {
|
|||
inline int construct(lua_State* L) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
int argcount = lua_gettop(L);
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot;
|
||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable[0], 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
|
@ -346,7 +346,7 @@ namespace sol {
|
|||
static int call(lua_State* L, F&) {
|
||||
const auto& metakey = usertype_traits<T>::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, &usertype_traits<T>::user_metatable[0], 1) : call_syntax::dot;
|
||||
argcount -= static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
|
@ -401,7 +401,7 @@ namespace sol {
|
|||
};
|
||||
|
||||
static int call(lua_State* L, F& f) {
|
||||
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::metatable);
|
||||
call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable[0]);
|
||||
int syntaxval = static_cast<int>(syntax);
|
||||
int argcount = lua_gettop(L) - syntaxval;
|
||||
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
namespace sol {
|
||||
|
||||
namespace usertype_detail {
|
||||
const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001);
|
||||
|
||||
struct variable_wrapper {
|
||||
virtual int index(lua_State* L) = 0;
|
||||
virtual int new_index(lua_State* L) = 0;
|
||||
|
@ -68,8 +70,31 @@ namespace sol {
|
|||
|
||||
template <typename T>
|
||||
inline int simple_metatable_newindex(lua_State* L) {
|
||||
if (stack::stack_detail::check_metatable<T, false>(L, 1)) {
|
||||
stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), 1);
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) {
|
||||
// Pointer types, AKA "references" from C++
|
||||
const char* metakey = nullptr;
|
||||
switch (i) {
|
||||
case 0:
|
||||
metakey = &usertype_traits<T*>::metatable[0];
|
||||
break;
|
||||
case 1:
|
||||
metakey = &usertype_traits<detail::unique_usertype<T>>::metatable[0];
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
metakey = &usertype_traits<T>::metatable[0];
|
||||
break;
|
||||
}
|
||||
luaL_getmetatable(L, metakey);
|
||||
int tableindex = lua_gettop(L);
|
||||
if (type_of(L, tableindex) == type::nil) {
|
||||
continue;
|
||||
}
|
||||
stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -259,15 +284,15 @@ namespace sol {
|
|||
|
||||
template <typename... Bases>
|
||||
void add(lua_State*, base_classes_tag, bases<Bases...>) {
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform");
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report.");
|
||||
if (sizeof...(Bases) < 1) {
|
||||
return;
|
||||
}
|
||||
mustindex = true;
|
||||
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... };
|
||||
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
|
||||
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report.");
|
||||
baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
|
||||
baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
|
||||
indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>;
|
||||
|
@ -278,11 +303,11 @@ namespace sol {
|
|||
template<std::size_t... I, typename Tuple>
|
||||
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
|
||||
: callconstructfunc(nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::simple_metatable_newindex<T>),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(true), secondarymeta(true) {
|
||||
mustindex(false), secondarymeta(false) {
|
||||
(void)detail::swallow{ 0,
|
||||
(add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)...
|
||||
};
|
||||
|
@ -356,6 +381,40 @@ namespace sol {
|
|||
bool hasequals = false;
|
||||
bool hasless = false;
|
||||
bool haslessequals = false;
|
||||
auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) {
|
||||
if (first == name_of(meta_function::equal_to)) {
|
||||
hasequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than)) {
|
||||
hasless = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than_or_equal_to)) {
|
||||
haslessequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
else if (first == name_of(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack::set_field(L, first, second, t.stack_index());
|
||||
};
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
// Pointer types, AKA "references" from C++
|
||||
const char* metakey = nullptr;
|
||||
|
@ -376,38 +435,7 @@ namespace sol {
|
|||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
if (first == name_of(meta_function::equal_to)) {
|
||||
hasequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than)) {
|
||||
hasless = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::less_than_or_equal_to)) {
|
||||
haslessequals = true;
|
||||
}
|
||||
else if (first == name_of(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
else if (first == name_of(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (first == name_of(meta_function::garbage_collect)) {
|
||||
stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack::set_field(L, first, second, t.stack_index());
|
||||
register_kvp(i, t, first, second);
|
||||
}
|
||||
luaL_Reg opregs[4]{};
|
||||
int opregsindex = 0;
|
||||
|
@ -440,7 +468,6 @@ namespace sol {
|
|||
|
||||
if (umx.mustindex) {
|
||||
// use indexing function
|
||||
static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report.");
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
|
@ -460,7 +487,7 @@ namespace sol {
|
|||
}
|
||||
// metatable on the metatable
|
||||
// for call constructor purposes and such
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
|
@ -482,9 +509,44 @@ namespace sol {
|
|||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
||||
if (i < 2)
|
||||
t.pop();
|
||||
t.pop();
|
||||
}
|
||||
|
||||
// Now for the shim-table that actually gets pushed
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable[0]);
|
||||
stack_reference t(L, -1);
|
||||
for (auto& kvp : varmap.functions) {
|
||||
auto& first = std::get<0>(kvp);
|
||||
auto& second = std::get<1>(kvp);
|
||||
register_kvp(2, t, first, second);
|
||||
}
|
||||
{
|
||||
lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
|
||||
stack_reference metabehind(L, -1);
|
||||
if (umx.callconstructfunc.valid()) {
|
||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||
}
|
||||
// use indexing function
|
||||
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<T>,
|
||||
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<T>,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
}
|
||||
|
||||
// Don't pop the table when we're done;
|
||||
// return it
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -554,7 +554,7 @@ namespace sol {
|
|||
}
|
||||
// metatable on the metatable
|
||||
// for call constructor purposes and such
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_createtable(L, 0, 3);
|
||||
stack_reference metabehind(L, -1);
|
||||
if (um.callconstructfunc != nullptr) {
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||
|
@ -567,9 +567,26 @@ namespace sol {
|
|||
metabehind.pop();
|
||||
// We want to just leave the table
|
||||
// in the registry only, otherwise we return it
|
||||
if (i < 2) {
|
||||
t.pop();
|
||||
t.pop();
|
||||
}
|
||||
|
||||
// Now for the shim-table that actually gets assigned to the name
|
||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable[0]);
|
||||
stack_reference t(L, -1);
|
||||
stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, value_table.data(), 1);
|
||||
{
|
||||
lua_createtable(L, 0, 3);
|
||||
stack_reference metabehind(L, -1);
|
||||
if (um.callconstructfunc != nullptr) {
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||
}
|
||||
if (um.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace sol {
|
|||
static const std::string name;
|
||||
static const std::string qualified_name;
|
||||
static const std::string metatable;
|
||||
static const std::string user_metatable;
|
||||
static const std::string user_gc_metatable;
|
||||
static const std::string gc_table;
|
||||
};
|
||||
|
@ -44,6 +45,9 @@ namespace sol {
|
|||
template<typename T>
|
||||
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::user_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user");
|
||||
|
||||
template<typename T>
|
||||
const std::string usertype_traits<T>::user_gc_metatable = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB");
|
||||
|
||||
|
|
|
@ -453,7 +453,11 @@ TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta tab
|
|||
table["func"] = &A::func;
|
||||
A a;
|
||||
lua.set("a", &a);
|
||||
lua.set("pa", &a);
|
||||
lua.set("ua", std::make_unique<A>());
|
||||
REQUIRE_NOTHROW(
|
||||
lua.script("assert(a:func() == 5000)")
|
||||
lua.script("assert(a:func() == 5000)");
|
||||
lua.script("assert(pa:func() == 5000)");
|
||||
lua.script("assert(ua:func() == 5000)");
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user