From 22d5a70c2526f788e7c490432512aa96df2719a9 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 13 Sep 2016 12:38:13 -0400 Subject: [PATCH] [ci skip] upgrade single --- single/sol/sol.hpp | 469 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 363 insertions(+), 106 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 9e01bf1d..97b71414 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2016-09-11 00:47:45.107316 UTC -// This header was generated with sol v2.12.3 (revision edb8eac) +// Generated 2016-09-13 16:37:49.292465 UTC +// This header was generated with sol v2.12.4 (revision 0de30f3) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -2996,7 +2996,7 @@ namespace sol { template struct non_null {}; - template + template struct function_sig {}; struct upvalue_index { @@ -3093,12 +3093,17 @@ namespace sol { template struct function_arguments { std::tuple params; - template - function_arguments(Args&&... args) : params(std::forward(args)...) {} + template , function_arguments>> = meta::enabler> + function_arguments(Arg&& arg, Args&&... args) : params(std::forward(arg), std::forward(args)...) {} }; template , typename... Args> - function_arguments as_function(Args&&... args) { + function_arguments...> as_function(Args&&... args) { + return function_arguments...>(std::forward(args)...); + } + + template , typename... Args> + function_arguments as_function_reference(Args&&... args) { return function_arguments(std::forward(args)...); } @@ -3400,6 +3405,9 @@ namespace sol { template struct lua_type_of> : std::integral_constant {}; + template <> + struct lua_type_of : std::integral_constant {}; + template <> struct lua_type_of : std::integral_constant {}; @@ -6261,6 +6269,15 @@ namespace sol { } }; + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_rawget(L, tableindex); + } + }; + template struct field_getter { void get(lua_State* L, metatable_key_t, int tableindex = -1) { @@ -7658,6 +7675,14 @@ namespace sol { } }; + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.params)); + } + }; + template inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward(fx), std::forward(args)...); @@ -9387,6 +9412,8 @@ namespace sol { } }; + typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); + inline bool is_indexer(string_detail::string_shim s) { return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); } @@ -9419,6 +9446,12 @@ namespace sol { return string_detail::string_shim(detail::base_class_cast_key()); } + template + inline std::string make_string(Arg&& arg) { + string_detail::string_shim s = make_shim(arg); + return std::string(s.c_str(), s.size()); + } + template inline luaL_Reg make_reg(N&& n, lua_CFunction f) { luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; @@ -9440,6 +9473,57 @@ namespace sol { return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); } + template + static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { + if (found) + return; + const char* metakey = &usertype_traits::metatable[0]; + const char* gcmetakey = &usertype_traits::gc_table[0]; + const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); + + luaL_getmetatable(L, metakey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return; + } + stack::get_field(L, accessor.c_str(), lua_gettop(L)); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + } + else { + // Probably a function. Probably. + // Kick off metatable + lua_remove(L, -2); + // Return the field (which is probably a function) itself + found = true; + ret = 1; + return; + } + stack::get_field(L, basewalkkey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 2); + return; + } + lua_CFunction basewalkfunc = stack::pop(L); + lua_pop(L, 1); + + stack::get_field(L, gcmetakey); + int value = basewalkfunc(L); + if (value > -1) { + found = true; + ret = value; + } + } + + template + static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { + (void)L; + (void)found; + (void)ret; + (void)accessor; + (void)detail::swallow{ 0, (walk_single_base(L, found, ret, accessor), 0)... }; + } + template inline int operator_wrap(lua_State* L) { auto maybel = stack::check_get(L, 1); @@ -9524,7 +9608,6 @@ namespace sol { typedef std::tuple ...> Tuple; template struct check_binding : is_variable_binding> {}; - typedef void (*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); Tuple functions; lua_CFunction indexfunc; lua_CFunction newindexfunc; @@ -9532,8 +9615,8 @@ namespace sol { lua_CFunction callconstructfunc; lua_CFunction indexbase; lua_CFunction newindexbase; - base_walk indexbaseclasspropogation; - base_walk newindexbaseclasspropogation; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; void* baseclasscheck; void* baseclasscast; bool mustindex; @@ -9601,8 +9684,8 @@ namespace sol { 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."); baseclasscheck = (void*)&detail::inheritance::type_check; baseclasscast = (void*)&detail::inheritance::type_cast; - indexbaseclasspropogation = walk_all_bases; - newindexbaseclasspropogation = walk_all_bases; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; } template , base_classes_tag, call_construction>::value>> @@ -9646,7 +9729,7 @@ namespace sol { indexfunc(usertype_detail::indexing_fail), newindexfunc(usertype_detail::indexing_fail), destructfunc(nullptr), callconstructfunc(nullptr), indexbase(&core_indexing_call), newindexbase(&core_indexing_call), - indexbaseclasspropogation(walk_all_bases), newindexbaseclasspropogation(walk_all_bases), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(usertype_detail::walk_all_bases), baseclasscheck(nullptr), baseclasscast(nullptr), mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), hasequals(false), hasless(false), haslessequals(false) { @@ -9673,72 +9756,34 @@ namespace sol { ret = real_find_call(idx, L); } - template + template void propogating_call(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { - (void)detail::swallow{ 0, (find_call(std::integral_constant(), L, found, ret, accessor), 0)... }; + (void)detail::swallow{ 0, (find_call(std::integral_constant(), L, found, ret, accessor), 0)... }; } - template - static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { - if (found) - return; - const char* metakey = &usertype_traits::metatable[0]; - const char* gcmetakey = &usertype_traits::gc_table[0]; - const char* basewalkkey = b ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); - - luaL_getmetatable(L, metakey); - if (type_of(L, -1) == type::nil) { - lua_pop(L, 1); - return; - } - stack::get_field(L, basewalkkey); - if (type_of(L, -1) == type::nil) { - lua_pop(L, 2); - return; - } - lua_CFunction basewalkfunc = stack::pop(L); - lua_pop(L, 1); - - stack::get_field(L, gcmetakey); - int value = basewalkfunc(L); - if (value > -1) { - found = true; - ret = value; - } - } - - template - static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { - (void)L; - (void)found; - (void)ret; - (void)accessor; - (void)detail::swallow{ 0, (walk_single_base(L, found, ret, accessor), 0)... }; - } - - template + template static int core_indexing_call(lua_State* L) { usertype_metatable& f = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); - static const int keyidx = -2 + static_cast(b); + static const int keyidx = -2 + static_cast(is_index); if (toplevel && stack::get(L, keyidx) != type::string) { - return b ? f.indexfunc(L) : f.newindexfunc(L); + return is_index ? f.indexfunc(L) : f.newindexfunc(L); } string_detail::string_shim accessor = stack::get(L, keyidx); int ret = 0; bool found = false; - f.propogating_call(L, found, ret, accessor); + f.propogating_call(L, found, ret, accessor); if (found) { return ret; } // Otherwise, we need to do propagating calls through the bases - if (b) + if (is_index) f.indexbaseclasspropogation(L, found, ret, accessor); else f.newindexbaseclasspropogation(L, found, ret, accessor); if (found) { return ret; } - return toplevel ? (b ? f.indexfunc(L) : f.newindexfunc(L)) : -1; + return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; } static int real_index_call(lua_State* L) { @@ -9867,15 +9912,9 @@ namespace sol { if (um.baseclasscheck != nullptr) { stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); } - else { - stack::set_field(L, detail::base_class_check_key(), nil, t.stack_index()); - } if (um.baseclasscast != nullptr) { stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); } - else { - stack::set_field(L, detail::base_class_cast_key(), nil, t.stack_index()); - } stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); @@ -9922,33 +9961,156 @@ namespace sol { // beginning of sol/simple_usertype_metatable.hpp +#include + namespace sol { + namespace usertype_detail { + struct variable_wrapper { + virtual int index(lua_State* L) = 0; + virtual int new_index(lua_State* L) = 0; + virtual ~variable_wrapper() {}; + }; + + template + struct callable_binding : variable_wrapper { + F fx; + + template + callable_binding(Arg&& arg) : fx(std::forward(arg)) {} + + virtual int index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + + virtual int new_index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + }; + + typedef std::map, std::less<>> variable_map; + typedef std::map> function_map; + + struct simple_map { + variable_map variables; + function_map functions; + base_walk indexbaseclasspropogation; + base_walk newindexbaseclasspropogation; + + simple_map(base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} + }; + + template + inline int simple_core_indexing_call(lua_State* L) { + simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + variable_map& variables = sm.variables; + function_map& functions = sm.functions; + static const int keyidx = -2 + static_cast(is_index); + if (toplevel) { + if (stack::get(L, keyidx) != type::string) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + } + string_detail::string_shim accessor = stack::get(L, keyidx); + auto vit = variables.find(accessor.c_str()); + if (vit != variables.cend()) { + auto& varwrap = *(vit->second); + if (is_index) { + return varwrap.index(L); + } + return varwrap.new_index(L); + } + auto fit = functions.find(accessor.c_str()); + if (fit != functions.cend()) { + auto& func = (fit->second); + return stack::push(L, func); + } + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) { + sm.indexbaseclasspropogation(L, found, ret, accessor); + } + else { + sm.newindexbaseclasspropogation(L, found, ret, accessor); + } + if (found) { + return ret; + } + if (toplevel) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + return -1; + } + + static int simple_real_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + static int simple_real_new_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + static int simple_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_index_call)>(L); + } + + static int simple_new_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_new_index_call)>(L); + } + } + struct simple_tag {} const simple{}; template struct simple_usertype_metatable : usertype_detail::registrar { - std::vector> registrations; + public: + usertype_detail::function_map registrations; + usertype_detail::variable_map varmap; object callconstructfunc; - + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + template >> = meta::enabler> - void add(lua_State* L, N&& n, F&& f) { - registrations.emplace_back(make_object(L, std::forward(n)), make_object(L, as_function(std::forward(f)))); + void add_function(lua_State* L, N&& n, F&& f) { + registrations.emplace(usertype_detail::make_string(std::forward(n)), make_object(L, as_function_reference(std::forward(f)))); } template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + registrations.emplace(usertype_detail::make_string(std::forward(n)), make_object(L, std::forward(f))); + } + + template >> = meta::enabler> void add(lua_State* L, N&& n, F&& f) { - registrations.emplace_back(make_object(L, std::forward(n)), make_object(L, std::forward(f))); + add_function(L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add(lua_State*, N&& n, F&& f) { + varmap.emplace(usertype_detail::make_string(std::forward(n)), std::make_unique>>(std::forward(f))); + mustindex = true; + secondarymeta = true; } template void add(lua_State* L, N&& n, constructor_wrapper c) { - registrations.emplace_back(make_object(L, std::forward(n)), make_object(L, detail::tagged>{std::move(c)})); + registrations.emplace(usertype_detail::make_string(std::forward(n)), make_object(L, detail::tagged>{std::move(c)})); } template void add(lua_State* L, N&& n, constructor_list c) { - registrations.emplace_back(make_object(L, std::forward(n)), make_object(L, detail::tagged>{std::move(c)})); + registrations.emplace(usertype_detail::make_string(std::forward(n)), make_object(L, detail::tagged>{std::move(c)})); } template @@ -9956,15 +10118,37 @@ namespace sol { callconstructfunc = make_object(L, std::forward(f)); } + template + void add(lua_State*, base_classes_tag, bases) { + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform"); + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::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."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + template simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) - : callconstructfunc(nil) { - registrations.reserve(std::tuple_size>::value); + : callconstructfunc(nil), + indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::indexing_fail), + indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(false), secondarymeta(false) { (void)detail::swallow{ 0, (add(L, detail::forward_get(args), detail::forward_get(args)),0)... }; } + private: template simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence(), L, std::forward_as_tuple(std::forward(args)...)) {} @@ -10004,7 +10188,32 @@ namespace sol { struct pusher> { typedef simple_usertype_metatable umt_t; + static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable; + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table[0]; + stack::push>(L, metatable_key, uniquegcmetakey, umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations)); + stack_reference stackvarmap(L, -1); + stack::set_field(L, gcmetakey, stackvarmap); + stackvarmap.pop(); + + stack::get_field(L, gcmetakey); + usertype_detail::simple_map& varmap = stack::pop>(L); + return varmap; + } + static int push(lua_State* L, umt_t&& umx) { + auto& varmap = make_cleanup(L, umx); bool hasequals = false; bool hasless = false; bool haslessequals = false; @@ -10025,36 +10234,41 @@ namespace sol { } luaL_newmetatable(L, metakey); stack_reference t(L, -1); - for (auto& kvp : umx.registrations) { - if (kvp.first.template is()) { - std::string regname = kvp.first.template as(); - if (regname == name_of(meta_function::equal_to)) { - hasequals = true; - } - else if (regname == name_of(meta_function::less_than)) { - hasless = true; - } - else if (regname == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - switch (i) { - case 0: - if (regname == name_of(meta_function::garbage_collect)) { - continue; - } - break; - case 1: - if (regname == name_of(meta_function::garbage_collect)) { - stack::set_field(L, kvp.first, detail::unique_destruct, t.stack_index()); - continue; - } - break; - case 2: - default: - break; - } + 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; } - stack::set_field(L, kvp.first, kvp.second, t.stack_index()); + 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(); + } + else if (first == name_of(meta_function::new_index)) { + umx.newindexfunc = second.template as(); + } + 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.stack_index()); + continue; + } + break; + case 2: + default: + break; + } + stack::set_field(L, first, second, t.stack_index()); } luaL_Reg opregs[4]{}; int opregsindex = 0; @@ -10073,9 +10287,38 @@ namespace sol { t.push(); luaL_setfuncs(L, opregs, 0); t.pop(); - // Metatable indexes itself - stack::set_field(L, meta_function::index, t, t.stack_index()); + if (umx.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); + } + if (umx.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); + } + + // Base class propagation features + stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); + + 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), + umx.indexfunc, + umx.newindexfunc + ), 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 + ), t.stack_index()); + } + else { + // Metatable indexes itself + stack::set_field(L, meta_function::index, t, t.stack_index()); + } // metatable on the metatable // for call constructor purposes and such lua_createtable(L, 0, 1); @@ -10083,6 +10326,20 @@ namespace sol { if (umx.callconstructfunc.valid()) { stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); } + if (umx.secondarymeta) { + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), 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 + ), metabehind.stack_index()); + } stack::set_field(L, metatable_key, metabehind, t.stack_index()); metabehind.pop(); @@ -10976,12 +11233,12 @@ namespace sol { template>> = meta::enabler> void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { - set(std::forward(key), as_function(std::forward(fx), std::forward(args)...)); + set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); } template void set_resolved_function(Key&& key, Args&&... args) { - set(std::forward(key), as_function>(std::forward(args)...)); + set(std::forward(key), as_function_reference>(std::forward(args)...)); } public: