From 25f42b4bd3730b66151a83d19eff97dbf5d02bf8 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 00:15:14 -0500 Subject: [PATCH 1/7] A hefty slice of changes for functions on the proxy. Not necessary, but was fun to get around MSVC's ICE errors. --- sol/function.hpp | 7 ++++++- sol/stack.hpp | 2 +- sol/table.hpp | 15 +++++++++++++++ sol/traits.hpp | 16 ++++++++++++++++ sol/types.hpp | 2 ++ tests.cpp | 22 ++++++++++++++++++++++ 6 files changed, 62 insertions(+), 2 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index 6a68d728..33d5971b 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -65,9 +65,14 @@ public: void operator()(Args&&... args) { call<>(std::forward(args)...); } + + template + typename multi_return::type operator()(types, Args&&... args) { + return call(std::forward(args)...); + } template - auto call(Args&&... args) -> decltype(invoke(types(), sizeof...(Args))) { + typename multi_return::type call(Args&&... args) { push(); stack::push_args(state(), std::forward(args)...); return invoke(types(), sizeof...(Args)); diff --git a/sol/stack.hpp b/sol/stack.hpp index 5bc59091..617bc605 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -45,7 +45,7 @@ inline T get_unsigned(lua_State* L, std::false_type, int index = -1) { template inline T get_arithmetic(lua_State* L, std::false_type, int index = -1) { // T is a floating point - return lua_tonumber(L, index); + return static_cast(lua_tonumber(L, index)); } template diff --git a/sol/table.hpp b/sol/table.hpp index dcc5a10b..dc117917 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -118,6 +118,21 @@ private: operator U() const { return t.get(key); } + + template + void operator()( Args&&... args ) { + call<>( std::forward( args )... ); + } + + template + typename multi_return::type operator()(types, Args&&... args) { + return call(std::forward(args)...); + } + + template + typename multi_return::type call(Args&&... args) { + return t.get(key)(types(), std::forward(args)...); + } }; template diff --git a/sol/traits.hpp b/sol/traits.hpp index 26d71634..b782973e 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -22,6 +22,7 @@ #ifndef SOL_TRAITS_HPP #define SOL_TRAITS_HPP +#include "tuple.hpp" #include namespace sol { @@ -62,6 +63,21 @@ struct is_function_impl { }; } // detail +template +struct multi_return { + typedef std::tuple type; +}; + +template +struct multi_return { + typedef T type; +}; + +template <> +struct multi_return<> : types<>{ + typedef void type; +}; + template using Bool = std::integral_constant; diff --git a/sol/types.hpp b/sol/types.hpp index 44976ae6..c1cf4b4e 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -113,6 +113,8 @@ template<> inline type type_of() { return type::boolean; } + +inline bool operator==(nil_t, nil_t) { return true; } } // sol #endif // SOL_TYPES_HPP \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index 4f23f6e4..1c400c15 100644 --- a/tests.cpp +++ b/tests.cpp @@ -112,18 +112,40 @@ TEST_CASE("simple/callLambda", "A C++ lambda is exposed to lua and called") { } TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") { + const static std::string lol = "lol", str = "str"; + const static std::tuple heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); sol::state lua; REQUIRE_NOTHROW(lua.set_function("a", [ ] { return 42; })); + REQUIRE(lua["a"]( sol::types() ) == 42); + REQUIRE_NOTHROW(lua.set_function("b", [ ] { return 42u; })); + REQUIRE(lua["b"](sol::types()) == 42u); + REQUIRE_NOTHROW(lua.set_function("c", [ ] { return 3.14; })); + REQUIRE(lua["c"](sol::types()) == 3.14); + REQUIRE_NOTHROW(lua.set_function("d", [ ] { return 6.28f; })); + REQUIRE(lua["d"](sol::types()) == 6.28f); + REQUIRE_NOTHROW(lua.set_function("e", [ ] { return "lol"; })); + REQUIRE(lua["e"](sol::types()) == lol); + REQUIRE_NOTHROW(lua.set_function("f", [ ] { return true; })); + REQUIRE(lua["f"](sol::types())); + REQUIRE_NOTHROW(lua.set_function("g", [ ] { return std::string("str"); })); + REQUIRE(lua["g"](sol::types()) == str); + REQUIRE_NOTHROW(lua.set_function("h", [ ] { })); + REQUIRE_NOTHROW(lua["h"](sol::types<>())); + REQUIRE_THROWS(lua["h"](sol::types())); + REQUIRE_NOTHROW(lua.set_function("i", [ ] { return sol::nil; })); + REQUIRE(lua["i"](sol::types()) == sol::nil); + REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string( "heh" )); } )); + //REQUIRE(lua["j"](sol::types()) == heh_tuple); } TEST_CASE("advanced/callLambda2", "A C++ lambda is exposed to lua and called") { From 00795939660e3bce599a2b9a1b6ddd01bbf9f40f Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 00:19:02 -0500 Subject: [PATCH 2/7] Strangely enough, it's impossible for the API to know if the returned value is wrong, so this test will always fail (unless we do some crazy nonsense). --- tests.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests.cpp b/tests.cpp index 1c400c15..789c1d21 100644 --- a/tests.cpp +++ b/tests.cpp @@ -139,7 +139,6 @@ TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") { REQUIRE_NOTHROW(lua.set_function("h", [ ] { })); REQUIRE_NOTHROW(lua["h"](sol::types<>())); - REQUIRE_THROWS(lua["h"](sol::types())); REQUIRE_NOTHROW(lua.set_function("i", [ ] { return sol::nil; })); REQUIRE(lua["i"](sol::types()) == sol::nil); From 84f367ca23d27fd588091d11fc4781967545e9f3 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 00:32:45 -0500 Subject: [PATCH 3/7] Somehow, run_script got deelted on this file. Strange. --- tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.cpp b/tests.cpp index 789c1d21..24ff464a 100644 --- a/tests.cpp +++ b/tests.cpp @@ -199,7 +199,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work // l-value, can optomize auto lval = object(); lua.get("os").set_function("fun", &object::operator(), lval); - REQUIRE_NOTHROW((lua)); + REQUIRE_NOTHROW(run_script(lua)); // stateful lambda: non-convertible, unoptomizable int breakit = 50; From 4f197dbb9195e026011265c7586eee141c16b5dd Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 20:16:28 -0500 Subject: [PATCH 4/7] operator!= for `nil_t` --- sol/types.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/sol/types.hpp b/sol/types.hpp index c1cf4b4e..e84682e0 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -115,6 +115,7 @@ inline type type_of() { } inline bool operator==(nil_t, nil_t) { return true; } +inline bool operator!=(nil_t, nil_t) { return false; } } // sol #endif // SOL_TYPES_HPP \ No newline at end of file From 913611c042e3b29e255d152081f60453c25b2fb2 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 22:21:06 -0500 Subject: [PATCH 5/7] Forgot to make sure this test was running! --- tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.cpp b/tests.cpp index 24ff464a..98cfde39 100644 --- a/tests.cpp +++ b/tests.cpp @@ -144,7 +144,7 @@ TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") { REQUIRE(lua["i"](sol::types()) == sol::nil); REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string( "heh" )); } )); - //REQUIRE(lua["j"](sol::types()) == heh_tuple); + REQUIRE(lua["j"](sol::types()) == heh_tuple); } TEST_CASE("advanced/callLambda2", "A C++ lambda is exposed to lua and called") { From ed0b83f8b06fbffea018766433285a955c945dca Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 23:25:44 -0500 Subject: [PATCH 6/7] Several changes. I took away operator() for the proxy type, because it'd interfere with the `Callable` type and all. Alas, good things do die I suppose. =[ But! I left it on the `sol::function` type, because it's necessary to discard returns. The .call is still there, though, just incase you need it. <3 reverse_indices_builder is also there, to make sure we can push and pop without the lua api taking our types and breaking them for the std::tuple returns. All is at it should be~ --- sol/function.hpp | 2 +- sol/stack.hpp | 9 +++++++-- sol/table.hpp | 10 ---------- sol/traits.hpp | 6 +++--- sol/tuple.hpp | 23 ++++++++++++++++++++++- tests.cpp | 23 +++++++++++------------ 6 files changed, 44 insertions(+), 29 deletions(-) diff --git a/sol/function.hpp b/sol/function.hpp index bf260ac0..1f60a257 100644 --- a/sol/function.hpp +++ b/sol/function.hpp @@ -68,7 +68,7 @@ public: template typename multi_return::type operator()(types, Args&&... args) { - return call(std::forward(args)...); + return call(std::forward(args)...); } template diff --git a/sol/stack.hpp b/sol/stack.hpp index 617bc605..821645f2 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -207,7 +207,7 @@ inline int push_user(lua_State* L, T& item) { namespace detail { template -inline void push(lua_State* L, indices, const T& tuplen) { +inline void push_tuple(lua_State* L, indices, T&& tuplen) { using swallow = char[ 1 + sizeof...(I) ]; swallow {'\0', (sol::stack::push(L, std::get(tuplen)), '\0')... }; } @@ -228,7 +228,12 @@ auto ltr_pop(lua_State* L, F&& f, types, Vs&&... vs) -> decltype( template inline void push(lua_State* L, const std::tuple& tuplen) { - detail::push(L, build_indices(), tuplen); + detail::push_tuple(L, build_reverse_indices(), tuplen); +} + +template +inline void push(lua_State* L, std::tuple&& tuplen) { + detail::push_tuple(L, build_reverse_indices(), std::move(tuplen)); } template diff --git a/sol/table.hpp b/sol/table.hpp index df3155e4..b5c44a79 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -119,16 +119,6 @@ private: return t.get(key); } - template - void operator()( Args&&... args ) { - call<>( std::forward( args )... ); - } - - template - typename multi_return::type operator()(types, Args&&... args) { - return call(std::forward(args)...); - } - template typename multi_return::type call(Args&&... args) { return t.get(key)(types(), std::forward(args)...); diff --git a/sol/traits.hpp b/sol/traits.hpp index fdc70d93..c90a08c6 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -63,17 +63,17 @@ struct is_function_impl { }; } // detail -template +template struct multi_return { typedef std::tuple type; }; -template +template struct multi_return { typedef T type; }; -template <> +template<> struct multi_return<> : types<>{ typedef void type; }; diff --git a/sol/tuple.hpp b/sol/tuple.hpp index 5a0ed438..31285b04 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -26,8 +26,23 @@ #include namespace sol { +template +struct reverse_tuple; + +template<> +struct reverse_tuple> { + using type = std::tuple<>; +}; + +template +struct reverse_tuple> { + using head = std::tuple; + using tail = typename reverse_tuple>::type; + using type = decltype(std::tuple_cat(std::declval(), std::declval())); +}; + template -struct indices {}; +struct indices { typedef indices type; }; template struct build_indices : build_indices {}; @@ -35,6 +50,12 @@ struct build_indices : build_indices {}; template struct build_indices<0, Ns...> : indices {}; +template +struct build_reverse_indices : build_reverse_indices {}; + +template +struct build_reverse_indices<0, Ns...> : indices {}; + template struct types : build_indices {}; diff --git a/tests.cpp b/tests.cpp index 98cfde39..5b020278 100644 --- a/tests.cpp +++ b/tests.cpp @@ -117,34 +117,33 @@ TEST_CASE("advanced/callLambdaReturns", "Checks for lambdas returning values") { sol::state lua; REQUIRE_NOTHROW(lua.set_function("a", [ ] { return 42; })); - REQUIRE(lua["a"]( sol::types() ) == 42); + REQUIRE(lua["a"].call() == 42); REQUIRE_NOTHROW(lua.set_function("b", [ ] { return 42u; })); - REQUIRE(lua["b"](sol::types()) == 42u); + REQUIRE(lua["b"].call() == 42u); REQUIRE_NOTHROW(lua.set_function("c", [ ] { return 3.14; })); - REQUIRE(lua["c"](sol::types()) == 3.14); + REQUIRE(lua["c"].call() == 3.14); REQUIRE_NOTHROW(lua.set_function("d", [ ] { return 6.28f; })); - REQUIRE(lua["d"](sol::types()) == 6.28f); + REQUIRE(lua["d"].call() == 6.28f); REQUIRE_NOTHROW(lua.set_function("e", [ ] { return "lol"; })); - REQUIRE(lua["e"](sol::types()) == lol); + REQUIRE(lua["e"].call() == lol); REQUIRE_NOTHROW(lua.set_function("f", [ ] { return true; })); - REQUIRE(lua["f"](sol::types())); + REQUIRE(lua["f"].call()); REQUIRE_NOTHROW(lua.set_function("g", [ ] { return std::string("str"); })); - REQUIRE(lua["g"](sol::types()) == str); + REQUIRE(lua["g"].call() == str); REQUIRE_NOTHROW(lua.set_function("h", [ ] { })); - REQUIRE_NOTHROW(lua["h"](sol::types<>())); + REQUIRE_NOTHROW(lua["h"].call()); REQUIRE_NOTHROW(lua.set_function("i", [ ] { return sol::nil; })); - REQUIRE(lua["i"](sol::types()) == sol::nil); - - REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string( "heh" )); } )); - REQUIRE(lua["j"](sol::types()) == heh_tuple); + REQUIRE(lua["i"].call() == sol::nil); + REQUIRE_NOTHROW(lua.set_function("j", [ ] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); + REQUIRE((lua["j"].call() == heh_tuple)); } TEST_CASE("advanced/callLambda2", "A C++ lambda is exposed to lua and called") { From 6101865c1e9b72e382246d3eb1b4ddf415320244 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 14 Dec 2013 23:31:23 -0500 Subject: [PATCH 7/7] GCC warnings can go suck a duck. --- sol/stack.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sol/stack.hpp b/sol/stack.hpp index 821645f2..782bd98d 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -241,9 +241,14 @@ inline auto pop_call(lua_State* L, TFx&& fx, types) -> decltype(detail: return detail::ltr_pop(L, std::forward(fx), types()); } -template -void push_args(lua_State* L, Args&&... args) { +void push_args(lua_State*) { + +} + +template +void push_args(lua_State* L, Arg&& arg, Args&&... args) { using swallow = char[]; + stack::push(L, std::forward(arg)); void(swallow{'\0', (stack::push(L, std::forward(args)), '\0')... }); } } // stack