mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
fix index and newindex semantics on simple_usertypes
we do not have to hit the metatable by-name since we go to special lengths to ensure we have a simple usertype table we can use
This commit is contained in:
parent
acee4dbbc9
commit
c6d11a2bac
|
@ -57,7 +57,8 @@ int main() {
|
|||
// Mix it all together!
|
||||
lua.script(R"(
|
||||
mdata = my_data.new()
|
||||
|
||||
)");
|
||||
lua.script(R"(
|
||||
local g = generator.new()
|
||||
g.data = mdata.first
|
||||
list1 = g:generate_list()
|
||||
|
@ -65,7 +66,8 @@ g.data = mdata.second
|
|||
list2 = g:generate_list()
|
||||
g.data = mdata.third
|
||||
list3 = g:generate_list()
|
||||
|
||||
)");
|
||||
lua.script(R"(
|
||||
print("From lua: ")
|
||||
for i = 1, #list1 do
|
||||
print("\tlist1[" .. i .. "] = " .. list1[i])
|
||||
|
|
|
@ -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-05-21 00:02:50.302747 UTC
|
||||
// This header was generated with sol v2.17.4 (revision 6047f48)
|
||||
// Generated 2017-05-28 23:13:00.247039 UTC
|
||||
// This header was generated with sol v2.17.4 (revision acee4db)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||
|
@ -3177,26 +3177,46 @@ namespace sol {
|
|||
|
||||
struct upvalue_index {
|
||||
int index;
|
||||
upvalue_index(int idx) : index(lua_upvalueindex(idx)) {}
|
||||
operator int() const { return index; }
|
||||
upvalue_index(int idx) : index(lua_upvalueindex(idx)) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct raw_index {
|
||||
int index;
|
||||
raw_index(int i) : index(i) {}
|
||||
operator int() const { return index; }
|
||||
raw_index(int i) : index(i) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct absolute_index {
|
||||
int index;
|
||||
absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {}
|
||||
operator int() const { return index; }
|
||||
absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct ref_index {
|
||||
int index;
|
||||
ref_index(int idx) : index(idx) {}
|
||||
operator int() const { return index; }
|
||||
ref_index(int idx) : index(idx) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct lightuserdata_value {
|
||||
|
@ -10565,6 +10585,15 @@ namespace sol {
|
|||
|
||||
namespace sol {
|
||||
namespace usertype_detail {
|
||||
const int metatable_index = 2;
|
||||
const int metatable_core_index = 3;
|
||||
const int filler_index = 4;
|
||||
const int magic_index = 5;
|
||||
|
||||
const int simple_metatable_index = 2;
|
||||
const int index_function_index = 3;
|
||||
const int newindex_function_index = 4;
|
||||
|
||||
typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&);
|
||||
typedef int(*member_search)(lua_State*, void*, int);
|
||||
|
||||
|
@ -10608,10 +10637,15 @@ namespace sol {
|
|||
const char* metakey;
|
||||
variable_map variables;
|
||||
function_map functions;
|
||||
object index;
|
||||
object newindex;
|
||||
base_walk indexbaseclasspropogation;
|
||||
base_walk newindexbaseclasspropogation;
|
||||
|
||||
simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {}
|
||||
simple_map(const char* mkey, base_walk index, base_walk newindex, object i, object ni, variable_map&& vars, function_map&& funcs)
|
||||
: metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)),
|
||||
index(std::move(i)), newindex(std::move(ni)),
|
||||
indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10680,20 +10714,32 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
inline bool is_indexer(string_detail::string_shim s) {
|
||||
return s == to_string(meta_function::index) || s == to_string(meta_function::new_index);
|
||||
inline int is_indexer(string_detail::string_shim s) {
|
||||
if (s == to_string(meta_function::index)) {
|
||||
return 1;
|
||||
}
|
||||
else if (s == to_string(meta_function::new_index)) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(meta_function mf) {
|
||||
return mf == meta_function::index || mf == meta_function::new_index;
|
||||
inline int is_indexer(meta_function mf) {
|
||||
if (mf == meta_function::index) {
|
||||
return 1;
|
||||
}
|
||||
else if (mf == meta_function::new_index) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(call_construction) {
|
||||
return false;
|
||||
inline int is_indexer(call_construction) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(base_classes_tag) {
|
||||
return false;
|
||||
inline int is_indexer(base_classes_tag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline auto make_shim(string_detail::string_shim s) {
|
||||
|
@ -10735,7 +10781,7 @@ namespace sol {
|
|||
};
|
||||
|
||||
inline int runtime_object_call(lua_State* L, void*, int runtimetarget) {
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
std::vector<object>& runtime = umc.runtime;
|
||||
object& runtimeobj = runtime[runtimetarget];
|
||||
return stack::push(L, runtimeobj);
|
||||
|
@ -10750,7 +10796,7 @@ namespace sol {
|
|||
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
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum);
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(magic_index), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
if (lua_getmetatable(L, 1) == 1) {
|
||||
int metatarget = lua_gettop(L);
|
||||
|
@ -10774,11 +10820,11 @@ namespace sol {
|
|||
template <typename T, bool is_simple>
|
||||
inline int metatable_newindex(lua_State* L) {
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum);
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(magic_index), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
auto non_indexable = [&L]() {
|
||||
if (is_simple) {
|
||||
simple_map& sm = stack::get<user<simple_map>>(L, upvalue_index(1));
|
||||
simple_map& sm = stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index));
|
||||
function_map& functions = sm.functions;
|
||||
optional<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
|
||||
if (!maybeaccessor) {
|
||||
|
@ -10794,7 +10840,7 @@ namespace sol {
|
|||
}
|
||||
return;
|
||||
}
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
bool mustindex = umc.mustindex;
|
||||
if (!mustindex)
|
||||
return;
|
||||
|
@ -10855,7 +10901,7 @@ namespace sol {
|
|||
}
|
||||
|
||||
inline int runtime_new_index(lua_State* L, void*, int runtimetarget) {
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
std::vector<object>& runtime = umc.runtime;
|
||||
object& runtimeobj = runtime[runtimetarget];
|
||||
runtimeobj = object(L, 3);
|
||||
|
@ -10985,7 +11031,7 @@ namespace sol {
|
|||
|
||||
bool contains_index() const {
|
||||
bool idx = false;
|
||||
(void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get<I * 2>(functions))), 0) ... };
|
||||
(void)detail::swallow{ 0, ((idx |= (usertype_detail::is_indexer(std::get<I * 2>(functions)) != 0)), 0) ... };
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -11101,7 +11147,11 @@ namespace sol {
|
|||
if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) {
|
||||
return real_call_with<I1, is_index, true>(L, f);
|
||||
}
|
||||
int upvalues = stack::push(L, light<usertype_metatable>(f));
|
||||
// set up upvalues
|
||||
// for a chained call
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, light<usertype_metatable>(f));
|
||||
auto cfunc = &call<I1, is_index>;
|
||||
return stack::push(L, c_closure(cfunc, upvalues));
|
||||
}
|
||||
|
@ -11114,7 +11164,9 @@ namespace sol {
|
|||
|
||||
template <bool is_index, bool toplevel = false>
|
||||
static int core_indexing_call(lua_State* L) {
|
||||
usertype_metatable& f = toplevel ? stack::get<light<usertype_metatable>>(L, upvalue_index(1)) : stack::pop<light<usertype_metatable>>(L);
|
||||
usertype_metatable& f = toplevel
|
||||
? stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index))
|
||||
: stack::pop<light<usertype_metatable>>(L);
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel && stack::get<type>(L, keyidx) != type::string) {
|
||||
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
|
||||
|
@ -11150,7 +11202,7 @@ namespace sol {
|
|||
|
||||
template <std::size_t Idx, bool is_index = true, bool is_variable = false>
|
||||
static int real_call(lua_State* L) {
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(1));
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index));
|
||||
return real_call_with<Idx, is_index, is_variable>(L, f);
|
||||
}
|
||||
|
||||
|
@ -11267,8 +11319,10 @@ namespace sol {
|
|||
}
|
||||
luaL_newmetatable(L, metakey);
|
||||
stack_reference t(L, -1);
|
||||
stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, metaregs, 1);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, metaregs, upvalues);
|
||||
|
||||
if (um.baseclasscheck != nullptr) {
|
||||
stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index());
|
||||
|
@ -11277,14 +11331,14 @@ namespace sol {
|
|||
stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index());
|
||||
}
|
||||
|
||||
stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
|
||||
if (mustindex) {
|
||||
// Basic index pushing: specialize
|
||||
// index and newindex to give variables and stuff
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
}
|
||||
else {
|
||||
// If there's only functions, we can use the fast index version
|
||||
|
@ -11295,11 +11349,11 @@ namespace sol {
|
|||
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), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
if (um.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
@ -11311,17 +11365,19 @@ namespace sol {
|
|||
// 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);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, value_table.data(), upvalues);
|
||||
{
|
||||
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), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
@ -11342,16 +11398,36 @@ namespace sol {
|
|||
namespace sol {
|
||||
|
||||
namespace usertype_detail {
|
||||
template <bool is_index, bool toplevel = false>
|
||||
inline int call_indexing_object(lua_State* L, object& f) {
|
||||
int before = lua_gettop(L);
|
||||
f.push();
|
||||
for (int i = 1; i <= before; ++i) {
|
||||
lua_pushvalue(L, i);
|
||||
}
|
||||
lua_callk(L, before, LUA_MULTRET, 0, nullptr);
|
||||
int after = lua_gettop(L);
|
||||
return after - before;
|
||||
}
|
||||
|
||||
template <typename T, bool is_index, bool toplevel = false, bool has_indexing = false>
|
||||
inline int simple_core_indexing_call(lua_State* L) {
|
||||
simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L);
|
||||
simple_map& sm = toplevel
|
||||
? stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index))
|
||||
: stack::pop<user<simple_map>>(L);
|
||||
variable_map& variables = sm.variables;
|
||||
function_map& functions = sm.functions;
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel) {
|
||||
if (stack::get<type>(L, keyidx) != type::string) {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return usertype_detail::indexing_fail<T, is_index>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, keyidx);
|
||||
|
@ -11371,11 +11447,20 @@ namespace sol {
|
|||
return stack::push(L, func);
|
||||
}
|
||||
else {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return is_index
|
||||
? usertype_detail::indexing_fail<T, is_index>(L)
|
||||
: usertype_detail::metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check table storage first for a method that works
|
||||
/* Check table storage first for a method that works
|
||||
luaL_getmetatable(L, sm.metakey);
|
||||
if (type_of(L, -1) != type::lua_nil) {
|
||||
stack::get_field<false, true>(L, accessor.c_str(), lua_gettop(L));
|
||||
|
@ -11387,7 +11472,8 @@ namespace sol {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
*/
|
||||
|
||||
int ret = 0;
|
||||
bool found = false;
|
||||
// Otherwise, we need to do propagating calls through the bases
|
||||
|
@ -11401,26 +11487,37 @@ namespace sol {
|
|||
return ret;
|
||||
}
|
||||
if (toplevel) {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return usertype_detail::metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_real_index_call(lua_State* L) {
|
||||
return simple_core_indexing_call<true, true>(L);
|
||||
return simple_core_indexing_call<T, true, true, has_indexing>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_real_new_index_call(lua_State* L) {
|
||||
return simple_core_indexing_call<false, true>(L);
|
||||
return simple_core_indexing_call<T, false, true, has_indexing>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_index_call(lua_State* L) {
|
||||
return detail::static_trampoline<(&simple_real_index_call)>(L);
|
||||
return detail::static_trampoline<(&simple_real_index_call<T, has_indexing>)>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_new_index_call(lua_State* L) {
|
||||
return detail::static_trampoline<(&simple_real_new_index_call)>(L);
|
||||
return detail::static_trampoline<(&simple_real_new_index_call<T, has_indexing>)>(L);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11432,8 +11529,8 @@ namespace sol {
|
|||
usertype_detail::function_map registrations;
|
||||
usertype_detail::variable_map varmap;
|
||||
object callconstructfunc;
|
||||
lua_CFunction indexfunc;
|
||||
lua_CFunction newindexfunc;
|
||||
object indexfunc;
|
||||
object newindexfunc;
|
||||
lua_CFunction indexbase;
|
||||
lua_CFunction newindexbase;
|
||||
usertype_detail::base_walk indexbaseclasspropogation;
|
||||
|
@ -11446,6 +11543,15 @@ namespace sol {
|
|||
template <typename N>
|
||||
void insert(N&& n, object&& o) {
|
||||
std::string key = usertype_detail::make_string(std::forward<N>(n));
|
||||
int is_indexer = static_cast<int>(usertype_detail::is_indexer(n));
|
||||
if (is_indexer == 1) {
|
||||
indexfunc = o;
|
||||
mustindex = true;
|
||||
}
|
||||
else if (is_indexer == 2) {
|
||||
newindexfunc = o;
|
||||
mustindex = true;
|
||||
}
|
||||
auto hint = registrations.find(key);
|
||||
if (hint == registrations.cend()) {
|
||||
registrations.emplace_hint(hint, std::move(key), std::move(o));
|
||||
|
@ -11572,8 +11678,8 @@ 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(lua_nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<T, true>), newindexfunc(&usertype_detail::metatable_newindex<T, true>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexfunc(lua_nil), newindexfunc(lua_nil),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<T, true>), newindexbase(&usertype_detail::simple_core_indexing_call<T, false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(false), secondarymeta(false) {
|
||||
|
@ -11642,6 +11748,7 @@ namespace sol {
|
|||
const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
|
||||
stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0],
|
||||
umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation,
|
||||
std::move(umx.indexfunc), std::move(umx.newindexfunc),
|
||||
std::move(umx.varmap), std::move(umx.registrations)
|
||||
);
|
||||
stack_reference stackvarmap(L, -1);
|
||||
|
@ -11654,7 +11761,11 @@ namespace sol {
|
|||
}
|
||||
|
||||
static int push(lua_State* L, umt_t&& umx) {
|
||||
bool hasindex = umx.indexfunc.valid();
|
||||
bool hasnewindex = umx.newindexfunc.valid();
|
||||
auto& varmap = make_cleanup(L, umx);
|
||||
auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>;
|
||||
auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>;
|
||||
bool hasequals = false;
|
||||
bool hasless = false;
|
||||
bool haslessequals = false;
|
||||
|
@ -11669,10 +11780,10 @@ namespace sol {
|
|||
haslessequals = true;
|
||||
}
|
||||
else if (first == to_string(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
umx.indexfunc = second;
|
||||
}
|
||||
else if (first == to_string(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
umx.newindexfunc = second;
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
|
@ -11693,7 +11804,6 @@ namespace sol {
|
|||
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;
|
||||
switch (i) {
|
||||
case 0:
|
||||
|
@ -11746,16 +11856,14 @@ namespace sol {
|
|||
if (umx.mustindex) {
|
||||
// use indexing function
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), t.stack_index());
|
||||
}
|
||||
else {
|
||||
|
@ -11771,16 +11879,14 @@ namespace sol {
|
|||
}
|
||||
if (umx.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
|
@ -11805,17 +11911,19 @@ namespace sol {
|
|||
}
|
||||
// use indexing function
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
|
|
|
@ -31,16 +31,36 @@
|
|||
namespace sol {
|
||||
|
||||
namespace usertype_detail {
|
||||
template <bool is_index, bool toplevel = false>
|
||||
inline int call_indexing_object(lua_State* L, object& f) {
|
||||
int before = lua_gettop(L);
|
||||
f.push();
|
||||
for (int i = 1; i <= before; ++i) {
|
||||
lua_pushvalue(L, i);
|
||||
}
|
||||
lua_callk(L, before, LUA_MULTRET, 0, nullptr);
|
||||
int after = lua_gettop(L);
|
||||
return after - before;
|
||||
}
|
||||
|
||||
template <typename T, bool is_index, bool toplevel = false, bool has_indexing = false>
|
||||
inline int simple_core_indexing_call(lua_State* L) {
|
||||
simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L);
|
||||
simple_map& sm = toplevel
|
||||
? stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index))
|
||||
: stack::pop<user<simple_map>>(L);
|
||||
variable_map& variables = sm.variables;
|
||||
function_map& functions = sm.functions;
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel) {
|
||||
if (stack::get<type>(L, keyidx) != type::string) {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return usertype_detail::indexing_fail<T, is_index>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, keyidx);
|
||||
|
@ -60,11 +80,20 @@ namespace sol {
|
|||
return stack::push(L, func);
|
||||
}
|
||||
else {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return is_index
|
||||
? usertype_detail::indexing_fail<T, is_index>(L)
|
||||
: usertype_detail::metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check table storage first for a method that works
|
||||
/* Check table storage first for a method that works
|
||||
luaL_getmetatable(L, sm.metakey);
|
||||
if (type_of(L, -1) != type::lua_nil) {
|
||||
stack::get_field<false, true>(L, accessor.c_str(), lua_gettop(L));
|
||||
|
@ -76,7 +105,8 @@ namespace sol {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
*/
|
||||
|
||||
int ret = 0;
|
||||
bool found = false;
|
||||
// Otherwise, we need to do propagating calls through the bases
|
||||
|
@ -90,26 +120,37 @@ namespace sol {
|
|||
return ret;
|
||||
}
|
||||
if (toplevel) {
|
||||
lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3));
|
||||
return indexingfunc(L);
|
||||
if (has_indexing) {
|
||||
object& indexingfunc = is_index
|
||||
? sm.index
|
||||
: sm.newindex;
|
||||
return call_indexing_object(L, indexingfunc);
|
||||
}
|
||||
else {
|
||||
return usertype_detail::metatable_newindex<T, true>(L);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_real_index_call(lua_State* L) {
|
||||
return simple_core_indexing_call<true, true>(L);
|
||||
return simple_core_indexing_call<T, true, true, has_indexing>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_real_new_index_call(lua_State* L) {
|
||||
return simple_core_indexing_call<false, true>(L);
|
||||
return simple_core_indexing_call<T, false, true, has_indexing>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_index_call(lua_State* L) {
|
||||
return detail::static_trampoline<(&simple_real_index_call)>(L);
|
||||
return detail::static_trampoline<(&simple_real_index_call<T, has_indexing>)>(L);
|
||||
}
|
||||
|
||||
template <typename T, bool has_indexing = false>
|
||||
inline int simple_new_index_call(lua_State* L) {
|
||||
return detail::static_trampoline<(&simple_real_new_index_call)>(L);
|
||||
return detail::static_trampoline<(&simple_real_new_index_call<T, has_indexing>)>(L);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +162,8 @@ namespace sol {
|
|||
usertype_detail::function_map registrations;
|
||||
usertype_detail::variable_map varmap;
|
||||
object callconstructfunc;
|
||||
lua_CFunction indexfunc;
|
||||
lua_CFunction newindexfunc;
|
||||
object indexfunc;
|
||||
object newindexfunc;
|
||||
lua_CFunction indexbase;
|
||||
lua_CFunction newindexbase;
|
||||
usertype_detail::base_walk indexbaseclasspropogation;
|
||||
|
@ -135,6 +176,15 @@ namespace sol {
|
|||
template <typename N>
|
||||
void insert(N&& n, object&& o) {
|
||||
std::string key = usertype_detail::make_string(std::forward<N>(n));
|
||||
int is_indexer = static_cast<int>(usertype_detail::is_indexer(n));
|
||||
if (is_indexer == 1) {
|
||||
indexfunc = o;
|
||||
mustindex = true;
|
||||
}
|
||||
else if (is_indexer == 2) {
|
||||
newindexfunc = o;
|
||||
mustindex = true;
|
||||
}
|
||||
auto hint = registrations.find(key);
|
||||
if (hint == registrations.cend()) {
|
||||
registrations.emplace_hint(hint, std::move(key), std::move(o));
|
||||
|
@ -261,8 +311,8 @@ 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(lua_nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<T, true>), newindexfunc(&usertype_detail::metatable_newindex<T, true>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexfunc(lua_nil), newindexfunc(lua_nil),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<T, true>), newindexbase(&usertype_detail::simple_core_indexing_call<T, false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(false), secondarymeta(false) {
|
||||
|
@ -331,6 +381,7 @@ namespace sol {
|
|||
const char* gcmetakey = &usertype_traits<T>::gc_table()[0];
|
||||
stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0],
|
||||
umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation,
|
||||
std::move(umx.indexfunc), std::move(umx.newindexfunc),
|
||||
std::move(umx.varmap), std::move(umx.registrations)
|
||||
);
|
||||
stack_reference stackvarmap(L, -1);
|
||||
|
@ -343,7 +394,11 @@ namespace sol {
|
|||
}
|
||||
|
||||
static int push(lua_State* L, umt_t&& umx) {
|
||||
bool hasindex = umx.indexfunc.valid();
|
||||
bool hasnewindex = umx.newindexfunc.valid();
|
||||
auto& varmap = make_cleanup(L, umx);
|
||||
auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>;
|
||||
auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>;
|
||||
bool hasequals = false;
|
||||
bool hasless = false;
|
||||
bool haslessequals = false;
|
||||
|
@ -358,10 +413,10 @@ namespace sol {
|
|||
haslessequals = true;
|
||||
}
|
||||
else if (first == to_string(meta_function::index)) {
|
||||
umx.indexfunc = second.template as<lua_CFunction>();
|
||||
umx.indexfunc = second;
|
||||
}
|
||||
else if (first == to_string(meta_function::new_index)) {
|
||||
umx.newindexfunc = second.template as<lua_CFunction>();
|
||||
umx.newindexfunc = second;
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
|
@ -382,7 +437,6 @@ namespace sol {
|
|||
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;
|
||||
switch (i) {
|
||||
case 0:
|
||||
|
@ -435,16 +489,14 @@ namespace sol {
|
|||
if (umx.mustindex) {
|
||||
// use indexing function
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), t.stack_index());
|
||||
}
|
||||
else {
|
||||
|
@ -460,16 +512,14 @@ namespace sol {
|
|||
}
|
||||
if (umx.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap)
|
||||
), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
|
@ -494,17 +544,19 @@ namespace sol {
|
|||
}
|
||||
// use indexing function
|
||||
stack::set_field(L, meta_function::index,
|
||||
make_closure(&usertype_detail::simple_index_call,
|
||||
make_closure(sic,
|
||||
nullptr,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index,
|
||||
make_closure(&usertype_detail::simple_new_index_call,
|
||||
make_closure(snic,
|
||||
nullptr,
|
||||
make_light(varmap),
|
||||
umx.indexfunc,
|
||||
umx.newindexfunc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
usertype_detail::toplevel_magic
|
||||
), metabehind.stack_index());
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
|
|
|
@ -185,26 +185,46 @@ namespace sol {
|
|||
|
||||
struct upvalue_index {
|
||||
int index;
|
||||
upvalue_index(int idx) : index(lua_upvalueindex(idx)) {}
|
||||
operator int() const { return index; }
|
||||
upvalue_index(int idx) : index(lua_upvalueindex(idx)) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct raw_index {
|
||||
int index;
|
||||
raw_index(int i) : index(i) {}
|
||||
operator int() const { return index; }
|
||||
raw_index(int i) : index(i) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct absolute_index {
|
||||
int index;
|
||||
absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {}
|
||||
operator int() const { return index; }
|
||||
absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct ref_index {
|
||||
int index;
|
||||
ref_index(int idx) : index(idx) {}
|
||||
operator int() const { return index; }
|
||||
ref_index(int idx) : index(idx) {
|
||||
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return index;
|
||||
}
|
||||
};
|
||||
|
||||
struct lightuserdata_value {
|
||||
|
|
|
@ -36,6 +36,15 @@
|
|||
|
||||
namespace sol {
|
||||
namespace usertype_detail {
|
||||
const int metatable_index = 2;
|
||||
const int metatable_core_index = 3;
|
||||
const int filler_index = 4;
|
||||
const int magic_index = 5;
|
||||
|
||||
const int simple_metatable_index = 2;
|
||||
const int index_function_index = 3;
|
||||
const int newindex_function_index = 4;
|
||||
|
||||
typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&);
|
||||
typedef int(*member_search)(lua_State*, void*, int);
|
||||
|
||||
|
@ -79,10 +88,15 @@ namespace sol {
|
|||
const char* metakey;
|
||||
variable_map variables;
|
||||
function_map functions;
|
||||
object index;
|
||||
object newindex;
|
||||
base_walk indexbaseclasspropogation;
|
||||
base_walk newindexbaseclasspropogation;
|
||||
|
||||
simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {}
|
||||
simple_map(const char* mkey, base_walk index, base_walk newindex, object i, object ni, variable_map&& vars, function_map&& funcs)
|
||||
: metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)),
|
||||
index(std::move(i)), newindex(std::move(ni)),
|
||||
indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -151,20 +165,32 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
inline bool is_indexer(string_detail::string_shim s) {
|
||||
return s == to_string(meta_function::index) || s == to_string(meta_function::new_index);
|
||||
inline int is_indexer(string_detail::string_shim s) {
|
||||
if (s == to_string(meta_function::index)) {
|
||||
return 1;
|
||||
}
|
||||
else if (s == to_string(meta_function::new_index)) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(meta_function mf) {
|
||||
return mf == meta_function::index || mf == meta_function::new_index;
|
||||
inline int is_indexer(meta_function mf) {
|
||||
if (mf == meta_function::index) {
|
||||
return 1;
|
||||
}
|
||||
else if (mf == meta_function::new_index) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(call_construction) {
|
||||
return false;
|
||||
inline int is_indexer(call_construction) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool is_indexer(base_classes_tag) {
|
||||
return false;
|
||||
inline int is_indexer(base_classes_tag) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline auto make_shim(string_detail::string_shim s) {
|
||||
|
@ -206,7 +232,7 @@ namespace sol {
|
|||
};
|
||||
|
||||
inline int runtime_object_call(lua_State* L, void*, int runtimetarget) {
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
std::vector<object>& runtime = umc.runtime;
|
||||
object& runtimeobj = runtime[runtimetarget];
|
||||
return stack::push(L, runtimeobj);
|
||||
|
@ -221,7 +247,7 @@ namespace sol {
|
|||
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
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum);
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(magic_index), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
if (lua_getmetatable(L, 1) == 1) {
|
||||
int metatarget = lua_gettop(L);
|
||||
|
@ -245,11 +271,11 @@ namespace sol {
|
|||
template <typename T, bool is_simple>
|
||||
inline int metatable_newindex(lua_State* L) {
|
||||
int isnum = 0;
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum);
|
||||
lua_Integer magic = lua_tointegerx(L, upvalue_index(magic_index), &isnum);
|
||||
if (isnum != 0 && magic == toplevel_magic) {
|
||||
auto non_indexable = [&L]() {
|
||||
if (is_simple) {
|
||||
simple_map& sm = stack::get<user<simple_map>>(L, upvalue_index(1));
|
||||
simple_map& sm = stack::get<user<simple_map>>(L, upvalue_index(simple_metatable_index));
|
||||
function_map& functions = sm.functions;
|
||||
optional<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
|
||||
if (!maybeaccessor) {
|
||||
|
@ -265,7 +291,7 @@ namespace sol {
|
|||
}
|
||||
return;
|
||||
}
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
bool mustindex = umc.mustindex;
|
||||
if (!mustindex)
|
||||
return;
|
||||
|
@ -326,7 +352,7 @@ namespace sol {
|
|||
}
|
||||
|
||||
inline int runtime_new_index(lua_State* L, void*, int runtimetarget) {
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(2));
|
||||
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
|
||||
std::vector<object>& runtime = umc.runtime;
|
||||
object& runtimeobj = runtime[runtimetarget];
|
||||
runtimeobj = object(L, 3);
|
||||
|
@ -456,7 +482,7 @@ namespace sol {
|
|||
|
||||
bool contains_index() const {
|
||||
bool idx = false;
|
||||
(void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get<I * 2>(functions))), 0) ... };
|
||||
(void)detail::swallow{ 0, ((idx |= (usertype_detail::is_indexer(std::get<I * 2>(functions)) != 0)), 0) ... };
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -572,7 +598,11 @@ namespace sol {
|
|||
if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) {
|
||||
return real_call_with<I1, is_index, true>(L, f);
|
||||
}
|
||||
int upvalues = stack::push(L, light<usertype_metatable>(f));
|
||||
// set up upvalues
|
||||
// for a chained call
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, light<usertype_metatable>(f));
|
||||
auto cfunc = &call<I1, is_index>;
|
||||
return stack::push(L, c_closure(cfunc, upvalues));
|
||||
}
|
||||
|
@ -585,7 +615,9 @@ namespace sol {
|
|||
|
||||
template <bool is_index, bool toplevel = false>
|
||||
static int core_indexing_call(lua_State* L) {
|
||||
usertype_metatable& f = toplevel ? stack::get<light<usertype_metatable>>(L, upvalue_index(1)) : stack::pop<light<usertype_metatable>>(L);
|
||||
usertype_metatable& f = toplevel
|
||||
? stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index))
|
||||
: stack::pop<light<usertype_metatable>>(L);
|
||||
static const int keyidx = -2 + static_cast<int>(is_index);
|
||||
if (toplevel && stack::get<type>(L, keyidx) != type::string) {
|
||||
return is_index ? f.indexfunc(L) : f.newindexfunc(L);
|
||||
|
@ -621,7 +653,7 @@ namespace sol {
|
|||
|
||||
template <std::size_t Idx, bool is_index = true, bool is_variable = false>
|
||||
static int real_call(lua_State* L) {
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(1));
|
||||
usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(usertype_detail::metatable_index));
|
||||
return real_call_with<Idx, is_index, is_variable>(L, f);
|
||||
}
|
||||
|
||||
|
@ -738,8 +770,10 @@ namespace sol {
|
|||
}
|
||||
luaL_newmetatable(L, metakey);
|
||||
stack_reference t(L, -1);
|
||||
stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, metaregs, 1);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, metaregs, upvalues);
|
||||
|
||||
if (um.baseclasscheck != nullptr) {
|
||||
stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index());
|
||||
|
@ -748,14 +782,14 @@ namespace sol {
|
|||
stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index());
|
||||
}
|
||||
|
||||
stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
|
||||
if (mustindex) {
|
||||
// Basic index pushing: specialize
|
||||
// index and newindex to give variables and stuff
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), t.stack_index());
|
||||
}
|
||||
else {
|
||||
// If there's only functions, we can use the fast index version
|
||||
|
@ -766,11 +800,11 @@ namespace sol {
|
|||
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), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
if (um.secondarymeta) {
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
@ -782,17 +816,19 @@ namespace sol {
|
|||
// 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);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push(L, make_light(um));
|
||||
luaL_setfuncs(L, value_table.data(), upvalues);
|
||||
{
|
||||
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), make_light(umc)), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||
}
|
||||
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||
|
||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||
metabehind.pop();
|
||||
|
|
|
@ -876,3 +876,39 @@ TEST_CASE("simple_usertype/static-properties", "allow for static functions to ge
|
|||
double v2a = lua["v2a"];
|
||||
REQUIRE(v2a == 60.5);
|
||||
}
|
||||
|
||||
TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed/new_indexed properly without breaking") {
|
||||
static int val = 0;
|
||||
|
||||
class indexing_test {
|
||||
public:
|
||||
indexing_test() { val = 0; }
|
||||
|
||||
sol::object getter(const std::string& name, sol::this_state _s) {
|
||||
REQUIRE(name == "a");
|
||||
return sol::make_object(_s, 2);
|
||||
}
|
||||
|
||||
void setter(std::string name, sol::object n) {
|
||||
REQUIRE(name == "unknown");
|
||||
val = n.as<int>();
|
||||
}
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
lua.new_simple_usertype<indexing_test>("test",
|
||||
sol::meta_function::index, &indexing_test::getter,
|
||||
sol::meta_function::new_index, &indexing_test::setter
|
||||
);
|
||||
|
||||
lua.script(R"(
|
||||
local t = test.new()
|
||||
v = t.a;
|
||||
print(v)
|
||||
t.unknown = 50;
|
||||
)");
|
||||
int v = lua["v"];
|
||||
REQUIRE(v == 2);
|
||||
REQUIRE(val == 50);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user