From 9f019ae536a75c3ec3a7ce3ce3a21022e39e2059 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Thu, 19 May 2016 17:27:12 -0400 Subject: [PATCH] Adds requires feature - Closes #90 Function name for getting the status was actually changed to status in all places... being consistent, yay --- docs/source/api/protected_function.rst | 4 +- docs/source/api/proxy.rst | 4 +- docs/source/features.rst | 16 +++---- sol/load_result.hpp | 16 +++---- sol/protected_function_result.hpp | 16 +++---- sol/state_view.hpp | 58 ++++++++++++++++++++++++++ sol/table_core.hpp | 11 ++++- sol/types.hpp | 6 +++ test_strings.cpp | 16 +++++++ 9 files changed, 117 insertions(+), 30 deletions(-) diff --git a/docs/source/api/protected_function.rst b/docs/source/api/protected_function.rst index c78057ed..cd135b86 100644 --- a/docs/source/api/protected_function.rst +++ b/docs/source/api/protected_function.rst @@ -1,7 +1,7 @@ protected_function ================== -Lua function calls that trap errors and provide error handler -------------------------------------------------------------- +Lua function calls that trap errors and provide error handling +-------------------------------------------------------------- .. code-block:: cpp diff --git a/docs/source/api/proxy.rst b/docs/source/api/proxy.rst index f67f741d..caa49d93 100644 --- a/docs/source/api/proxy.rst +++ b/docs/source/api/proxy.rst @@ -176,8 +176,8 @@ stack_proxy .. _note 1: -On Function Objects and proxies ----------------------------------- +on function objects and proxies +------------------------------- Consider the following: diff --git a/docs/source/features.rst b/docs/source/features.rst index 7ff741dd..ebd2e339 100644 --- a/docs/source/features.rst +++ b/docs/source/features.rst @@ -92,7 +92,7 @@ Explanations for a few categories are below (rest are self-explanatory). | | plain C | luawrapper | lua-intf | luabind | Selene | Sol2 | oolua | lua-api-pp | kaguya | SLB | SWIG | luacppinterface | luwra | | | | | | | | | | | | | | | | +===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+========+ -| optional | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +| optional | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | tables | ~ | ~ | ~ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✗ | ✗ | ~ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ @@ -114,11 +114,11 @@ Explanations for a few categories are below (rest are self-explanatory). +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | protected function | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ~ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ~ | +| multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | variadic/variant argument | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ~ | ~ | ✗ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| inheritance | ~ | ✔ | ~ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ✔ | ~ | ✗ | +| inheritance | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ✔ | ~ | ✗ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ @@ -126,17 +126,17 @@ Explanations for a few categories are below (rest are self-explanatory). +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | coroutines | ~ | ✗ | ~ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| no-rtti support | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ~ | +| no-rtti support | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| no-exception support | ✔ | ✗ | ✔ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✗ | +| no-exception support | ✔ | ✗ | ✔ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| Lua 5.1 | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ~ | +| Lua 5.1 | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ~ | +| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ | distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | header | +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ @@ -250,7 +250,7 @@ oolua - luwra - -* How do you store stateful functors / lambas ? Cannot find a way to support +* How do you store stateful functors / lambas? So far, no support for such. * Cannot pull functions without first leaving them on the stack: manual cleanup becomes a thing * Doesn't understand ``std::function`` conversions and the like (but with some extra code can get it to work) * Recently improved by a lot: can chain tables and such, even if performance is a bit sad for that use case diff --git a/sol/load_result.hpp b/sol/load_result.hpp index 3384df4a..9eaa7a88 100644 --- a/sol/load_result.hpp +++ b/sol/load_result.hpp @@ -72,12 +72,12 @@ namespace sol { public: load_result() = default; - load_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, load_status err = load_status::ok) : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + load_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, load_status err = load_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { } load_result(const load_result&) = default; load_result& operator=(const load_result&) = default; - load_result(load_result&& o) : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { // Must be manual, otherwise destructor will screw us // return count being 0 is enough to keep things clean // but we will be thorough @@ -87,7 +87,7 @@ namespace sol { o.popcount = 0; o.err = load_status::syntax; } - load_result& operator=(load_result&& o) { + load_result& operator=(load_result&& o) noexcept { L = o.L; index = o.index; returncount = o.returncount; @@ -104,12 +104,12 @@ namespace sol { return *this; } - load_status error() const { + load_status status() const noexcept { return err; } - bool valid() const { - return error() == load_status::ok; + bool valid() const noexcept { + return status() == load_status::ok; } template @@ -127,8 +127,8 @@ namespace sol { return call<>(std::forward(args)...); } - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; ~load_result() { stack::remove(L, index, popcount); diff --git a/sol/protected_function_result.hpp b/sol/protected_function_result.hpp index 66a05b57..f3bfdc90 100644 --- a/sol/protected_function_result.hpp +++ b/sol/protected_function_result.hpp @@ -73,12 +73,12 @@ private: public: protected_function_result() = default; - protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status err = call_status::ok): L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status err = call_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { } protected_function_result(const protected_function_result&) = default; protected_function_result& operator=(const protected_function_result&) = default; - protected_function_result(protected_function_result&& o) : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { // Must be manual, otherwise destructor will screw us // return count being 0 is enough to keep things clean // but we will be thorough @@ -88,7 +88,7 @@ public: o.popcount = 0; o.err = call_status::runtime; } - protected_function_result& operator=(protected_function_result&& o) { + protected_function_result& operator=(protected_function_result&& o) noexcept { L = o.L; index = o.index; returncount = o.returncount; @@ -105,12 +105,12 @@ public: return *this; } - call_status error() const { + call_status status() const noexcept { return err; } - bool valid() const { - return error() == call_status::ok || error() == call_status::yielded; + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; } template @@ -118,8 +118,8 @@ public: return tagged_get(types>()); } - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; ~protected_function_result() { stack::remove(L, index, popcount); diff --git a/sol/state_view.hpp b/sol/state_view.hpp index 2545270d..41646400 100644 --- a/sol/state_view.hpp +++ b/sol/state_view.hpp @@ -49,6 +49,24 @@ private: lua_State* L; table reg; global_table global; + + template + void ensure_package(const std::string& key, T&& sr) { + auto pkg = (*this)["package"]; + if (!pkg.valid()) { + pkg = create_table_with("loaded", create_table_with(key, sr)); + } + else { + auto ld = pkg["loaded"]; + if (!ld.valid()) { + ld = create_table_with(key, sr); + } + else { + ld[key] = sr; + } + } + } + public: typedef global_table::iterator iterator; typedef global_table::const_iterator const_iterator; @@ -132,11 +150,13 @@ public: case lib::ffi: #ifdef SOL_LUAJIT luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); #endif break; case lib::jit: #ifdef SOL_LUAJIT luaL_requiref(L, "jit", luaopen_jit, 1); + lua_pop(L, 1); #endif break; case lib::count: @@ -146,6 +166,44 @@ public: } } + template + object require(const std::string& key, Fx&& open_function, bool is_global_library = true) { + auto openfx = [fx = std::forward(open_function)](lua_State* L){ + typedef lua_bind_traits> traits; + return stack::call(typename traits::return_type(), typename traits::args_type(), L, fx); + }; + stack::push(L, function_args>(std::forward(openfx))); + lua_CFunction openf = stack::pop(L); + luaL_requiref(L, key.c_str(), openf, is_global_library ? 1 : 0); + object r stack::pop(L); + lua_pop(L, 1); + return r; + } + + object require_script(const std::string& key, const std::string& code) { + optional loaded = traverse_get>("package", "loaded", key); + bool ismod = loaded && !(loaded->is() && !loaded->as()); + if (ismod) + return std::move(*loaded); + script(code); + auto sr = stack::get(L); + set(key, sr); + ensure_package(key, sr); + return stack::pop(L); + } + + object require_file(const std::string& key, const std::string& file) { + auto loaded = traverse_get>("package", "loaded", key); + bool ismod = loaded && !(loaded->is() && !loaded->as()); + if (loaded) + return std::move(*loaded); + script_file(file); + auto sr = stack::get(L); + set(key, sr); + ensure_package(key, sr); + return stack::pop(L); + } + void script(const std::string& code) { if(luaL_dostring(L, code.c_str())) { lua_error(L); diff --git a/sol/table_core.hpp b/sol/table_core.hpp index b10a6e53..0bce4127 100644 --- a/sol/table_core.hpp +++ b/sol/table_core.hpp @@ -156,8 +156,15 @@ public: typedef iterator const_iterator; basic_table_core( ) noexcept : base_t( ) { } - template , meta::neg, basic_table_core>>, std::is_same, global_table>> = meta::enabler> - basic_table_core( T&& r ) noexcept : base_t( std::forward(r) ) { } + template , basic_table_core>>, std::is_base_of>> = meta::enabler> + basic_table_core( T&& r ) noexcept : base_t( std::forward(r) ) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_table>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } basic_table_core(const basic_table_core&) = default; basic_table_core(basic_table_core&&) = default; basic_table_core& operator=(const basic_table_core&) = default; diff --git a/sol/types.hpp b/sol/types.hpp index f51c983f..24aeb456 100644 --- a/sol/types.hpp +++ b/sol/types.hpp @@ -547,6 +547,12 @@ public: static const std::size_t arity = base_t::arity - meta::count_for::value; }; +template +struct is_table : std::false_type {}; + +template +struct is_table> : std::true_type {}; + template inline type type_of() { return lua_type_of>::value; diff --git a/test_strings.cpp b/test_strings.cpp index 4241aa9e..36404c95 100644 --- a/test_strings.cpp +++ b/test_strings.cpp @@ -69,3 +69,19 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") { REQUIRE(wide_to_char32 == utf32str[0]); } #endif // Shit C++ + + +TEST_CASE("state/strings", "opening strings as 'requires' clauses") { + std::string code = "return { modfunc = function () return 221 end }"; + + sol::state lua; + sol::table thingy1 = lua.require_script("thingy", code); + sol::table thingy2 = lua.require_script("thingy", code); + + int val1 = thingy1["modfunc"](); + int val2 = thingy2["modfunc"](); + REQUIRE(val1 == 221); + REQUIRE(val2 == 221); + // must have loaded the same table + REQUIRE(thingy1 == thingy2); +} \ No newline at end of file