From 8ef3ceb8a00c3c7d538414948867a362e4204dec Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 16:27:20 -0500 Subject: [PATCH 1/8] New test cases for the order of returns. Apparently, its screwing up between both lua and C++. Have to test thoroughly. Changes currently are half-working. --- sol/function.hpp | 2 +- sol/lua_function.hpp | 69 +++++++++++++++++++++++++++++--------------- sol/stack.hpp | 35 +++++++++++++++++++++- sol/tuple.hpp | 11 ++++++- tests.cpp | 15 ++++++++++ 5 files changed, 105 insertions(+), 27 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 1f60a257..aac52037 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -36,7 +36,7 @@ private: template std::tuple invoke(types, std::size_t n) { luacall(n, sizeof...(Ret)); - return stack::pop_call(state(), std::make_tuple, types()); + return stack::pop_reverse_call(state(), std::make_tuple, types()); } template diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 89c56614..0d278f7b 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -62,6 +62,11 @@ template struct static_lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; + + template + static int typed_call(types<>, types t, fx_t* fx, lua_State* L) { + return (*this)(types(), t, fx, L); + } template static int typed_call(types, types t, fx_t* fx, lua_State* L) { @@ -69,11 +74,11 @@ struct static_lua_func { return 0; } - template - static int typed_call(types, types t, fx_t* fx, lua_State* L) { + template + static int typed_call(types, types t, fx_t* fx, lua_State* L) { auto r = stack::pop_call(L, fx, t); - stack::push(L, std::move(r)); - return sizeof...(TRn); + stack::push_reverse(L, std::move(r)); + return sizeof...(Ret); } static int call(lua_State* L) { @@ -101,9 +106,9 @@ struct static_object_lua_func { return 0; } - template - static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { - auto fx = [&item, &ifx](Args&&... args) -> TR { + template + static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { + auto fx = [&item, &ifx](Args&&... args) -> Ret { return (item.*ifx)(std::forward(args)...); }; auto r = stack::pop_call(L, fx, types()); @@ -111,12 +116,12 @@ struct static_object_lua_func { return 1; } - template - static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { - auto fx = [&item, &ifx](Args&&... args) -> std::tuple { return (item.*ifx)(std::forward(args)...); }; + template + static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { + auto fx = [&item, &ifx](Args&&... args) -> std::tuple { return (item.*ifx)(std::forward(args)...); }; auto r = stack::pop_call(L, fx, types()); - stack::push(L, std::move(r)); - return sizeof...(TRn); + stack::push_reverse(L, std::move(r)); + return sizeof...(Ret); } static int call(lua_State* L) { @@ -182,17 +187,23 @@ struct lambda_lua_func : public lua_func { return (*this)(tuple_types(), typename fx_traits::args_type(), L); } + template + int operator()(types<>, types t, lua_State* L) { + stack::pop_call(L, fx, t); + return 0; + } + template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator()(types, types t, lua_State* L) { + template + int operator()(types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); - stack::push(L, r); - return sizeof...(TRn); + stack::push_reverse(L, r); + return sizeof...(Ret); } }; @@ -209,17 +220,22 @@ struct explicit_lua_func : public lua_func { return (*this)(tuple_types(), typename fx_traits::args_type(), L); } + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator()(types, types t, lua_State* L) { + template + int operator()(types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); - stack::push(L, std::move(r)); - return sizeof...(TRn); + stack::push_reverse(L, std::move(r)); + return sizeof...(Ret); } }; @@ -247,17 +263,22 @@ struct explicit_lua_func : public lua_func { return (*this)(tuple_types(), typename fx_traits::args_type(), L); } + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } - template - int operator()(types, types t, lua_State* L) { + template + int operator()(types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); - stack::push(L, r); - return sizeof...(TRn); + stack::push_reverse(L, r); + return sizeof...(Ret); } }; diff --git a/sol/stack.hpp b/sol/stack.hpp index 782bd98d..a0c5c230 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -224,15 +224,43 @@ template auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(f(std::forward(vs)..., std::declval(), std::declval()...)) { return ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L)); } + +template +auto rtl_pop(lua_State*, F&& f, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { + return f(std::forward(vs)...); +} +template +auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...)) { + return rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...); +} +template +auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...)) { + return rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...); +} } // detail template inline void push(lua_State* L, const std::tuple& tuplen) { - detail::push_tuple(L, build_reverse_indices(), tuplen); + detail::push_tuple(L, build_indices(), tuplen); } template inline void push(lua_State* L, std::tuple&& tuplen) { + detail::push_tuple(L, build_indices(), std::move(tuplen)); +} + +template +inline void push_reverse(lua_State* L, T&& item) { + push(L, std::forward(item)); +} + +template +inline void push_reverse(lua_State* L, const std::tuple& tuplen) { + detail::push_tuple(L, build_reverse_indices(), tuplen); +} + +template +inline void push_reverse(lua_State* L, std::tuple&& tuplen) { detail::push_tuple(L, build_reverse_indices(), std::move(tuplen)); } @@ -241,6 +269,11 @@ inline auto pop_call(lua_State* L, TFx&& fx, types) -> decltype(detail: return detail::ltr_pop(L, std::forward(fx), types()); } +template +inline auto pop_reverse_call(lua_State* L, TFx&& fx, types) -> decltype(detail::rtl_pop(L, std::forward(fx), types())) { + return detail::rtl_pop(L, std::forward(fx), reversed()); +} + void push_args(lua_State*) { } diff --git a/sol/tuple.hpp b/sol/tuple.hpp index 31285b04..cecaa3e8 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -57,7 +57,16 @@ template struct build_reverse_indices<0, Ns...> : indices {}; template -struct types : build_indices {}; +struct types : build_indices { typedef types type; }; + +template +struct reversed_ : Acc{}; + +template +struct reversed_, Arg, Args...> : reversed_, Args...>{}; + +template +struct reversed : reversed_, Args...>{}; template struct tuple_types : types, std::false_type {}; diff --git a/tests.cpp b/tests.cpp index 5b020278..d9749f9b 100644 --- a/tests.cpp +++ b/tests.cpp @@ -220,6 +220,21 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work REQUIRE_NOTHROW(run_script(lua)); } +TEST_CASE("functions/return _order", "Check if return order is in the same reading order specified in Lua" ) { + const static std::tuple triple = std::make_tuple(10, 11, 12); + sol::state lua; + lua.set_function( "f", [ ] { + return std::make_tuple( 10, 11, 12 ); + } ); + lua.script( "function g() return 10, 11, 12 end" ); + auto tcpp = lua.get( "f" ).call( ); + auto tlua = lua.get( "g" ).call( ); + std::cout << std::get<0>( tcpp ) << ',' << std::get<1>( tcpp ) << ',' << std::get<2>( tcpp ) << std::endl; + std::cout << std::get<0>( tlua ) << ',' << std::get<1>( tlua ) << ',' << std::get<2>( tlua ) << std::endl; + REQUIRE( tcpp == triple ); + REQUIRE( tlua == triple ); +} + TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { sol::state lua; lua.open_libraries(sol::lib::base); From 94405d0346f8043ffa24e3aac0a91bdb1beeb4a3 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 16:45:40 -0500 Subject: [PATCH 2/8] Fixing lua function, attempting another fix for rtl_pop --- sol/lua_function.hpp | 16 +++++++++++----- sol/stack.hpp | 8 ++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 0d278f7b..b4fe39c4 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -63,11 +63,6 @@ struct static_lua_func { typedef typename std::remove_pointer::type>::type fx_t; typedef function_traits fx_traits; - template - static int typed_call(types<>, types t, fx_t* fx, lua_State* L) { - return (*this)(types(), t, fx, L); - } - template static int typed_call(types, types t, fx_t* fx, lua_State* L) { stack::pop_call(L, fx, t); @@ -81,6 +76,11 @@ struct static_lua_func { return sizeof...(Ret); } + template + static int typed_call(types<>, types t, fx_t* fx, lua_State* L) { + return typed_call(types(), t, fx, L); + } + static int call(lua_State* L) { int upvalue = 1; fx_t* fx; @@ -99,6 +99,7 @@ struct static_object_lua_func { typedef typename std::decay::type fx_t; typedef function_traits fx_traits; + template static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { auto fx = [&item, &ifx](Args&&... args) { (item.*ifx)(std::forward(args)...); }; @@ -124,6 +125,11 @@ struct static_object_lua_func { return sizeof...(Ret); } + template + static int typed_call(types<>, types, T& item, fx_t& ifx, lua_State* L) { + return typed_call(types(), item, ifx, L); + } + static int call(lua_State* L) { const static std::size_t data_t_count = (sizeof(fx_t)+(sizeof(void*)-1)) / sizeof(void*); typedef std::array data_t; diff --git a/sol/stack.hpp b/sol/stack.hpp index a0c5c230..769f38b3 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -233,8 +233,8 @@ template auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...)) { return rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...); } -template -auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...)) { +template +auto rtl_pop(lua_State* L, F&& f, types, types, Vs&&... vs) -> decltype(f(std::forward(declval())...)) { return rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...); } } // detail @@ -270,8 +270,8 @@ inline auto pop_call(lua_State* L, TFx&& fx, types) -> decltype(detail: } template -inline auto pop_reverse_call(lua_State* L, TFx&& fx, types) -> decltype(detail::rtl_pop(L, std::forward(fx), types())) { - return detail::rtl_pop(L, std::forward(fx), reversed()); +inline auto pop_reverse_call(lua_State* L, TFx&& fx, types) -> decltype(detail::rtl_pop(L, std::forward(fx), types(), reversed())) { + return detail::rtl_pop(L, std::forward(fx), types(), reversed()); } void push_args(lua_State*) { From b9b32baf1a8214813ab9dce05133406c3850ec19 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 16:46:57 -0500 Subject: [PATCH 3/8] declval is in the std namespace, derp. --- sol/stack.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 769f38b3..8d07774d 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -234,7 +234,7 @@ auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L return rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...); } template -auto rtl_pop(lua_State* L, F&& f, types, types, Vs&&... vs) -> decltype(f(std::forward(declval())...)) { +auto rtl_pop(lua_State* L, F&& f, types, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { return rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...); } } // detail From 63536dd8d00e40234ae4bf4613f0125dbe54b7d8 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 16:52:01 -0500 Subject: [PATCH 4/8] Why not cheat with an extra `types` ? Who needs type deduction when you can just pass the right types directly? --- sol/stack.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 8d07774d..4f7d1afd 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -225,17 +225,17 @@ auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype( return ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L)); } -template -auto rtl_pop(lua_State*, F&& f, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { +template +auto rtl_pop(lua_State*, F&& f, types, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { return f(std::forward(vs)...); } -template -auto rtl_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...)) { - return rtl_pop(L, std::forward(f), types<>(), pop(L), std::forward(vs)...); +template +auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { + return rtl_pop(L, std::forward(f), t, types<>(), pop(L), std::forward(vs)...); } template -auto rtl_pop(lua_State* L, F&& f, types, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { - return rtl_pop(L, std::forward(f), types(), pop(L), std::forward(vs)...); +auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { + return rtl_pop(L, std::forward(f), t, types(), pop(L), std::forward(vs)...); } } // detail From c8417d65ded074955390e5d14a5b966d32e08957 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 16:56:01 -0500 Subject: [PATCH 5/8] `decltype` with `types`. It seems unfair. --- sol/stack.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 4f7d1afd..18339656 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -230,11 +230,11 @@ auto rtl_pop(lua_State*, F&& f, types, types<>, Vs&&... vs) -> decltype return f(std::forward(vs)...); } template -auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { +auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { return rtl_pop(L, std::forward(f), t, types<>(), pop(L), std::forward(vs)...); } template -auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::forward(std::declval())...)) { +auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { return rtl_pop(L, std::forward(f), t, types(), pop(L), std::forward(vs)...); } } // detail From e0bcf5a11e59a0af9a730808dde109a3e5900e46 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 17:09:23 -0500 Subject: [PATCH 6/8] Ordering things more nicely for GCC and fixing calls to always used extra `types` parameters when they can for early-out decltype deduction, rather than recursive template reliance (compiles better for VC++ and resolves earlier for g++). --- sol/lua_function.hpp | 26 +++++++++++++------------- sol/stack.hpp | 26 +++++++++----------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index b4fe39c4..6a120d62 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -222,10 +222,6 @@ struct explicit_lua_func : public lua_func { template explicit_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} - virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); - } - template int operator()(types<>, types t, lua_State* L) { return (*this)(types(), t, L); @@ -243,6 +239,10 @@ struct explicit_lua_func : public lua_func { stack::push_reverse(L, std::move(r)); return sizeof...(Ret); } + + virtual int operator()(lua_State* L) override { + return (*this)(tuple_types(), typename fx_traits::args_type(), L); + } }; template @@ -265,8 +265,10 @@ struct explicit_lua_func : public lua_func { template explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward(fxargs)...) {} - virtual int operator()(lua_State* L) override { - return (*this)(tuple_types(), typename fx_traits::args_type(), L); + template + int operator()(types, types t, lua_State* L) { + stack::pop_call(L, fx, t); + return 0; } template @@ -274,18 +276,16 @@ struct explicit_lua_func : public lua_func { return (*this)(types(), t, L); } - template - int operator()(types, types t, lua_State* L) { - stack::pop_call(L, fx, t); - return 0; - } - template int operator()(types, types t, lua_State* L) { auto r = stack::pop_call(L, fx, t); - stack::push_reverse(L, r); + stack::push_reverse(L, std::move(r)); return sizeof...(Ret); } + + virtual int operator()(lua_State* L) override { + return (*this)(tuple_types(), typename fx_traits::args_type(), L); + } }; } // sol diff --git a/sol/stack.hpp b/sol/stack.hpp index 18339656..5866d6f5 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -212,27 +212,19 @@ inline void push_tuple(lua_State* L, indices, T&& tuplen) { swallow {'\0', (sol::stack::push(L, std::get(tuplen)), '\0')... }; } -template -auto ltr_pop(lua_State*, F&& f, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { +template +auto ltr_pop(lua_State*, F&& f, types t, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { return f(std::forward(vs)...); } -template -auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(ltr_pop(L, std::forward(f), types<>(), std::forward(vs)..., pop(L))) { - return ltr_pop(L, std::forward(f), types<>(), std::forward(vs)..., pop(L)); -} -template -auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype(f(std::forward(vs)..., std::declval(), std::declval()...)) { - return ltr_pop(L, std::forward(f), types(), std::forward(vs)..., pop(L)); +template +auto ltr_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { + return ltr_pop(L, std::forward(f), t, types(), std::forward(vs)..., pop(L)); } template auto rtl_pop(lua_State*, F&& f, types, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { return f(std::forward(vs)...); } -template -auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { - return rtl_pop(L, std::forward(f), t, types<>(), pop(L), std::forward(vs)...); -} template auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { return rtl_pop(L, std::forward(f), t, types(), pop(L), std::forward(vs)...); @@ -265,13 +257,13 @@ inline void push_reverse(lua_State* L, std::tuple&& tuplen) { } template -inline auto pop_call(lua_State* L, TFx&& fx, types) -> decltype(detail::ltr_pop(L, std::forward(fx), types())) { - return detail::ltr_pop(L, std::forward(fx), types()); +inline auto pop_call(lua_State* L, TFx&& fx, types t) -> decltype(detail::ltr_pop(L, std::forward(fx), t, t)) { + return detail::ltr_pop(L, std::forward(fx), t, t); } template -inline auto pop_reverse_call(lua_State* L, TFx&& fx, types) -> decltype(detail::rtl_pop(L, std::forward(fx), types(), reversed())) { - return detail::rtl_pop(L, std::forward(fx), types(), reversed()); +inline auto pop_reverse_call(lua_State* L, TFx&& fx, types t) -> decltype(detail::rtl_pop(L, std::forward(fx), t, reversed())) { + return detail::rtl_pop(L, std::forward(fx), t, reversed()); } void push_args(lua_State*) { From f8cfb80a451004bf26670179564e9794371bfc42 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 22:09:06 -0500 Subject: [PATCH 7/8] Fixed a bug with the return order and added tests to make sure it works. Added the ability to get mutiple values when doing `table.get` or `state.get`. Lua is hard. :c --- sol/function.hpp | 2 +- sol/lua_function.hpp | 77 ++++++++++++++++++++------------------------ sol/stack.hpp | 2 +- sol/state.hpp | 6 ++-- sol/table.hpp | 47 +++++++++++++++++++++++---- tests.cpp | 19 ++++++----- 6 files changed, 92 insertions(+), 61 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index aac52037..91da5d18 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -35,7 +35,7 @@ private: template std::tuple invoke(types, std::size_t n) { - luacall(n, sizeof...(Ret)); + luacall(n, sizeof...(Ret)); return stack::pop_reverse_call(state(), std::make_tuple, types()); } diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index 6a120d62..ba3df646 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -69,16 +69,17 @@ struct static_lua_func { return 0; } - template - static int typed_call(types, types t, fx_t* fx, lua_State* L) { - auto r = stack::pop_call(L, fx, t); - stack::push_reverse(L, std::move(r)); - return sizeof...(Ret); - } - template static int typed_call(types<>, types t, fx_t* fx, lua_State* L) { - return typed_call(types(), t, fx, L); + return typed_call(types(), t, fx, L); + } + + template + static int typed_call(types, types t, fx_t* fx, lua_State* L) { + typedef typename multi_return::type return_type; + return_type r = stack::pop_call(L, fx, t); + stack::push(L, std::move(r)); + return sizeof...(Ret); } static int call(lua_State* L) { @@ -99,7 +100,6 @@ struct static_object_lua_func { typedef typename std::decay::type fx_t; typedef function_traits fx_traits; - template static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { auto fx = [&item, &ifx](Args&&... args) { (item.*ifx)(std::forward(args)...); }; @@ -107,29 +107,20 @@ struct static_object_lua_func { return 0; } - template - static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { - auto fx = [&item, &ifx](Args&&... args) -> Ret { - return (item.*ifx)(std::forward(args)...); - }; - auto r = stack::pop_call(L, fx, types()); - stack::push(L, std::move(r)); - return 1; + template + static int typed_call(types<>, types t, T& item, fx_t& ifx, lua_State* L) { + return typed_call(types(), t, item, ifx, L); } template static int typed_call(types, types, T& item, fx_t& ifx, lua_State* L) { - auto fx = [&item, &ifx](Args&&... args) -> std::tuple { return (item.*ifx)(std::forward(args)...); }; - auto r = stack::pop_call(L, fx, types()); - stack::push_reverse(L, std::move(r)); + typedef typename multi_return::type return_type; + auto fx = [&item, &ifx](Args&&... args) -> return_type { return (item.*ifx)(std::forward(args)...); }; + return_type r = stack::pop_call(L, fx, types()); + stack::push(L, std::move(r)); return sizeof...(Ret); } - template - static int typed_call(types<>, types, T& item, fx_t& ifx, lua_State* L) { - return typed_call(types(), item, ifx, L); - } - static int call(lua_State* L) { const static std::size_t data_t_count = (sizeof(fx_t)+(sizeof(void*)-1)) / sizeof(void*); typedef std::array data_t; @@ -193,22 +184,22 @@ struct lambda_lua_func : public lua_func { return (*this)(tuple_types(), typename fx_traits::args_type(), L); } - template - int operator()(types<>, types t, lua_State* L) { - stack::pop_call(L, fx, t); - return 0; - } - template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + template int operator()(types, types t, lua_State* L) { - auto r = stack::pop_call(L, fx, t); - stack::push_reverse(L, r); + typedef typename multi_return::type return_type; + return_type r = stack::pop_call(L, fx, t); + stack::push(L, r); return sizeof...(Ret); } }; @@ -222,21 +213,22 @@ struct explicit_lua_func : public lua_func { template explicit_lua_func(FxArgs&&... fxargs): fx(std::forward(fxargs)...) {} - template - int operator()(types<>, types t, lua_State* L) { - return (*this)(types(), t, L); - } - template int operator()(types, types t, lua_State* L) { stack::pop_call(L, fx, t); return 0; } + template + int operator()(types<>, types t, lua_State* L) { + return (*this)(types(), t, L); + } + template int operator()(types, types t, lua_State* L) { - auto r = stack::pop_call(L, fx, t); - stack::push_reverse(L, std::move(r)); + typedef typename multi_return::type return_type; + return_type r = stack::pop_call(L, fx, t); + stack::push(L, std::move(r)); return sizeof...(Ret); } @@ -278,8 +270,9 @@ struct explicit_lua_func : public lua_func { template int operator()(types, types t, lua_State* L) { - auto r = stack::pop_call(L, fx, t); - stack::push_reverse(L, std::move(r)); + typedef typename multi_return::type return_type; + return_type r = stack::pop_call(L, fx, t); + stack::push(L, std::move(r)); return sizeof...(Ret); } diff --git a/sol/stack.hpp b/sol/stack.hpp index 5866d6f5..06381641 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -227,7 +227,7 @@ auto rtl_pop(lua_State*, F&& f, types, types<>, Vs&&... vs) -> decltype } template auto rtl_pop(lua_State* L, F&& f, types t, types, Vs&&... vs) -> decltype(f(std::declval()...)) { - return rtl_pop(L, std::forward(f), t, types(), pop(L), std::forward(vs)...); + return rtl_pop(L, std::forward(f), t, types(), pop(L), std::forward(vs)...); } } // detail diff --git a/sol/state.hpp b/sol/state.hpp index 9cac52e4..aebb136b 100644 --- a/sol/state.hpp +++ b/sol/state.hpp @@ -127,9 +127,9 @@ public: } } - template - T get(U&& key) const { - return global.get(std::forward(key)); + template + typename multi_return::type get(Keys&&... keys) const { + return global.get(types(), std::forward(keys)...); } template diff --git a/sol/table.hpp b/sol/table.hpp index b5c44a79..09421897 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -41,15 +41,11 @@ T* get_ptr(T* val) { } // detail class table : public reference { + friend class state; template struct proxy; -public: - table() noexcept : reference() {} - table(lua_State* L, int index = -1) : reference(L, index) { - type_assert(L, index, type::table); - } template - T get(U&& key) const { + T single_get(U&& key) const { push(); stack::push(state(), std::forward(key)); lua_gettable(state(), -2); @@ -59,6 +55,45 @@ public: return result; } + template + typename std::tuple_element>::type element_get(types, Tup&& key) const { + typedef typename std::tuple_element>::type T; + typedef typename std::tuple_element::type U; + push(); + stack::push(state(), std::get(key)); + lua_gettable(state(), -2); + type_assert(state(), -1, type_of()); + T result = stack::pop(state()); + lua_pop(state(), 1); + return result; + } + + template + typename multi_return::type tuple_get(types t, indices, Tup&& tup) const { + return std::make_tuple(element_get(t, std::forward(tup))...); + } + + template + Ret tuple_get(types t, indices<0>, Tup&& tup) const { + return element_get<0>(t, std::forward(tup)); + } + + template + typename multi_return::type get(types t, Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "Must have same number of keys as return values"); + return tuple_get(t, t, std::make_tuple(std::forward(keys)...)); + } +public: + table() noexcept : reference() {} + table(lua_State* L, int index = -1) : reference(L, index) { + type_assert(L, index, type::table); + } + + template + typename multi_return::type get(Keys&&... keys) const { + return get(types(), std::forward(keys)...); + } + template table& set(T&& key, U&& value) { push(); diff --git a/tests.cpp b/tests.cpp index d9749f9b..940b95fd 100644 --- a/tests.cpp +++ b/tests.cpp @@ -224,15 +224,18 @@ TEST_CASE("functions/return _order", "Check if return order is in the same readi const static std::tuple triple = std::make_tuple(10, 11, 12); sol::state lua; lua.set_function( "f", [ ] { - return std::make_tuple( 10, 11, 12 ); + return std::make_tuple( 10, 11, 12 ); } ); - lua.script( "function g() return 10, 11, 12 end" ); - auto tcpp = lua.get( "f" ).call( ); - auto tlua = lua.get( "g" ).call( ); - std::cout << std::get<0>( tcpp ) << ',' << std::get<1>( tcpp ) << ',' << std::get<2>( tcpp ) << std::endl; - std::cout << std::get<0>( tlua ) << ',' << std::get<1>( tlua ) << ',' << std::get<2>( tlua ) << std::endl; - REQUIRE( tcpp == triple ); - REQUIRE( tlua == triple ); + lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); + auto tcpp = lua.get("f").call(); + auto tlua = lua.get("g").call(); + auto tluaget = lua.get("x", "y", "z"); + std::cout << "cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp) << std::endl; + std::cout << "lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua) << std::endl; + std::cout << "lua.xyz: " << lua.get("x") << ',' << lua.get("y") << ',' << lua.get("z") << std::endl; + REQUIRE(tcpp == triple); + REQUIRE(tlua == triple); + REQUIRE(tluaget == triple); } TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { From cb492e7c293f9181542f5b89a73991236868d29d Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 15 Dec 2013 22:14:56 -0500 Subject: [PATCH 8/8] Squashing those GCC warnings. --- sol/stack.hpp | 2 +- sol/table.hpp | 1 - tests.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 06381641..6bb1608f 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -213,7 +213,7 @@ inline void push_tuple(lua_State* L, indices, T&& tuplen) { } template -auto ltr_pop(lua_State*, F&& f, types t, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { +auto ltr_pop(lua_State*, F&& f, types, types<>, Vs&&... vs) -> decltype(f(std::forward(vs)...)) { return f(std::forward(vs)...); } template diff --git a/sol/table.hpp b/sol/table.hpp index 09421897..5ab57618 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -58,7 +58,6 @@ class table : public reference { template typename std::tuple_element>::type element_get(types, Tup&& key) const { typedef typename std::tuple_element>::type T; - typedef typename std::tuple_element::type U; push(); stack::push(state(), std::get(key)); lua_gettable(state(), -2); diff --git a/tests.cpp b/tests.cpp index 940b95fd..c986f73c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -220,7 +220,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work REQUIRE_NOTHROW(run_script(lua)); } -TEST_CASE("functions/return _order", "Check if return order is in the same reading order specified in Lua" ) { +TEST_CASE("functions/return_order_and_multi_get", "Check if return order is in the same reading order specified in Lua" ) { const static std::tuple triple = std::make_tuple(10, 11, 12); sol::state lua; lua.set_function( "f", [ ] {