diff options
Diffstat (limited to 'Sluift/Lua')
-rw-r--r-- | Sluift/Lua/Check.cpp | 66 | ||||
-rw-r--r-- | Sluift/Lua/Check.h | 29 | ||||
-rw-r--r-- | Sluift/Lua/Debug.h | 28 | ||||
-rw-r--r-- | Sluift/Lua/Exception.cpp | 15 | ||||
-rw-r--r-- | Sluift/Lua/Exception.h | 22 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.cpp | 16 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistration.h | 43 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.cpp | 58 | ||||
-rw-r--r-- | Sluift/Lua/FunctionRegistry.h | 47 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.cpp | 199 | ||||
-rw-r--r-- | Sluift/Lua/LuaUtils.h | 43 | ||||
-rw-r--r-- | Sluift/Lua/Value.cpp | 9 | ||||
-rw-r--r-- | Sluift/Lua/Value.h | 28 |
13 files changed, 599 insertions, 4 deletions
diff --git a/Sluift/Lua/Check.cpp b/Sluift/Lua/Check.cpp new file mode 100644 index 0000000..a9b8f02 --- /dev/null +++ b/Sluift/Lua/Check.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Lua/Check.h> + +#include <boost/numeric/conversion/cast.hpp> +#include <iostream> +#include <sstream> +#include <lua.hpp> + +#include <Sluift/Lua/Exception.h> +#include <Swiften/Base/ByteArray.h> + +using namespace Swift; + + +static std::string getArgTypeError(lua_State* L, int arg, int tag) { + std::ostringstream s; + s << "Arg " << arg << ": expected " << lua_typename(L, tag) << ", got " << luaL_typename(L, arg); + return s.str(); +} + +void Lua::checkType(lua_State* L, int arg, int type) { + if (lua_type(L, arg) != type) { + throw Lua::Exception(getArgTypeError(L, arg, type)); + } +} + +int Lua::checkIntNumber(lua_State* L, int arg) { + if (!lua_isnumber(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TNUMBER)); + } + return boost::numeric_cast<int>(lua_tonumber(L, arg)); +} + +std::string Lua::checkString(lua_State* L, int arg) { + const char *s = lua_tolstring(L, arg, NULL); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return std::string(s); +} + +ByteArray Lua::checkByteArray(lua_State* L, int arg) { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return createByteArray(s, len); +} + +void* Lua::checkUserDataRaw(lua_State* L, int arg) { + void* userData = lua_touserdata(L, arg); + if (!userData) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + if (!lua_getmetatable(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + lua_pop(L, 1); + return userData; +} diff --git a/Sluift/Lua/Check.h b/Sluift/Lua/Check.h new file mode 100644 index 0000000..c22751b --- /dev/null +++ b/Sluift/Lua/Check.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013-2014 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/ByteArray.h> + +struct lua_State; + +namespace Swift { + namespace Lua { + void checkType(lua_State* L, int arg, int type); + int checkIntNumber(lua_State* L, int arg); + std::string checkString(lua_State* L, int arg); + ByteArray checkByteArray(lua_State* L, int arg); + + void* checkUserDataRaw(lua_State* L, int arg); + + template<typename T> + T** checkUserData(lua_State* L, int arg) { + return reinterpret_cast<T**>(checkUserDataRaw(L, arg)); + } + } +} diff --git a/Sluift/Lua/Debug.h b/Sluift/Lua/Debug.h new file mode 100644 index 0000000..8e86b89 --- /dev/null +++ b/Sluift/Lua/Debug.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <lua.hpp> +#include <iostream> + +namespace Swift { + namespace Lua { + inline void dumpStack(lua_State *L) { + for (int i = 1; i <= lua_gettop(L); i++) { + int type = lua_type(L, i); + std::cout << i << ": [" << lua_typename(L, type) << "] "; + switch (type) { + case LUA_TSTRING: std::cout << lua_tostring(L, i); break; + case LUA_TNUMBER: std::cout << lua_tonumber(L, i); break; + case LUA_TBOOLEAN: std::cout << lua_toboolean(L, i); break; + default: break; + } + std::cout << std::endl; + } + } + } +} diff --git a/Sluift/Lua/Exception.cpp b/Sluift/Lua/Exception.cpp new file mode 100644 index 0000000..889c931 --- /dev/null +++ b/Sluift/Lua/Exception.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Lua/Exception.h> + +using namespace Swift::Lua; + +Exception::Exception(const std::string& what) : std::runtime_error(what) { +} + +Exception::~Exception() SWIFTEN_NOEXCEPT { +} diff --git a/Sluift/Lua/Exception.h b/Sluift/Lua/Exception.h new file mode 100644 index 0000000..a68b925 --- /dev/null +++ b/Sluift/Lua/Exception.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013-2014 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <stdexcept> +#include <Swiften/Base/API.h> + +namespace Swift { + namespace Lua { + class Exception : public std::runtime_error { + public: + Exception(const std::string& what); + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Exception) + virtual ~Exception() SWIFTEN_NOEXCEPT; + }; + } +} + diff --git a/Sluift/Lua/FunctionRegistration.cpp b/Sluift/Lua/FunctionRegistration.cpp new file mode 100644 index 0000000..ddfa1f0 --- /dev/null +++ b/Sluift/Lua/FunctionRegistration.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Lua/FunctionRegistration.h> + +using namespace Swift::Lua; + +FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type, const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + FunctionRegistry::getInstance().addFunction(name, function, type, helpDescription, helpParameters, helpOptions); +} + +FunctionRegistration::~FunctionRegistration() { +} diff --git a/Sluift/Lua/FunctionRegistration.h b/Sluift/Lua/FunctionRegistration.h new file mode 100644 index 0000000..74269e2 --- /dev/null +++ b/Sluift/Lua/FunctionRegistration.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/Override.h> +#include <Swiften/Base/API.h> +#include <Sluift/Lua/FunctionRegistry.h> +#include <lua.hpp> +#include <string> + +namespace Swift { + namespace Lua { + class FunctionRegistration { + public: + FunctionRegistration( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + ~FunctionRegistration(); + }; + } +} + + +#define SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS) \ + static int TYPE##_##NAME(lua_State* L); \ + static int TYPE##_##NAME##_wrapper(lua_State* L); \ + static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS); \ + static int TYPE##_##NAME##_wrapper(lua_State* L) { \ + try { \ + return TYPE ## _ ## NAME (L); \ + } \ + catch (const std::exception& e) { \ + return luaL_error(L, e.what()); \ + } \ + } \ + static int TYPE ## _ ## NAME (lua_State* L) + +#define SLUIFT_LUA_FUNCTION(TYPE, NAME) \ + SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, "", "", "") diff --git a/Sluift/Lua/FunctionRegistry.cpp b/Sluift/Lua/FunctionRegistry.cpp new file mode 100644 index 0000000..df24d9c --- /dev/null +++ b/Sluift/Lua/FunctionRegistry.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Lua/FunctionRegistry.h> + +#include <Swiften/Base/foreach.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/globals.h> + +using namespace Swift::Lua; + +FunctionRegistry::FunctionRegistry() { +} + +FunctionRegistry::~FunctionRegistry() { +} + +FunctionRegistry& FunctionRegistry::getInstance() { + static FunctionRegistry instance; + return instance; +} + +void FunctionRegistry::addFunction( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + Registration registration; + registration.name = name; + registration.function = function; + registration.type = type; + registration.helpDescription = helpDescription; + registration.helpParameters = helpParameters; + registration.helpOptions = helpOptions; + registrations.push_back(registration); +} + +void FunctionRegistry::createFunctionTable(lua_State* L, const std::string& type) { + lua_newtable(L); + addFunctionsToTable(L, type); +} + +void FunctionRegistry::addFunctionsToTable(lua_State* L, const std::string& type) { + foreach(const Registration& registration, registrations) { + if (registration.type == type) { + lua_pushcclosure(L, registration.function, 0); + if (!registration.helpDescription.empty()) { + Lua::registerHelp(L, -1, registration.helpDescription, registration.helpParameters, registration.helpOptions); + } + else { + Lua::registerExtraHelp(L, -1, registration.type + "." + registration.name); + } + lua_setfield(L, -2, registration.name.c_str()); + } + } +} diff --git a/Sluift/Lua/FunctionRegistry.h b/Sluift/Lua/FunctionRegistry.h new file mode 100644 index 0000000..b20108d --- /dev/null +++ b/Sluift/Lua/FunctionRegistry.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/Override.h> +#include <lua.hpp> +#include <string> +#include <vector> + +namespace Swift { + namespace Lua { + class FunctionRegistry { + public: + ~FunctionRegistry(); + static FunctionRegistry& getInstance(); + + void addFunction(const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + + void createFunctionTable(lua_State* L, const std::string& type); + + /** + * Adds the functions to the table on the top of the stack. + */ + void addFunctionsToTable(lua_State* L, const std::string& type); + + private: + FunctionRegistry(); + + + private: + struct Registration { + std::string name; + lua_CFunction function; + std::string type; + std::string helpDescription; + std::string helpParameters; + std::string helpOptions; + }; + std::vector<Registration> registrations; + }; + } +} diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp new file mode 100644 index 0000000..9ea5cba --- /dev/null +++ b/Sluift/Lua/LuaUtils.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Sluift/Lua/LuaUtils.h> + +#include <lua.hpp> + +#include <boost/scope_exit.hpp> +#include <Sluift/Lua/Exception.h> +#include <iostream> +#include <cassert> +#include <sstream> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <Sluift/globals.h> + +using namespace Swift::Lua; + +static const std::string INDENT = " "; + +void Swift::Lua::registerTableToString(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_tostring"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerTableEquals(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_equals"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerGetByTypeIndex(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_get_by_type_index"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +boost::optional<std::string> Swift::Lua::getStringField(lua_State* L, int index, const std::string& field) { + lua_getfield(L, index, field.c_str()); + // Seems to generate warnings with some versions of CLang that i can't turn off. + // Leaving the more elegant code here, hoping we can re-enable it later (newer boost? c++11?). + // The same applies to the other get*Field functions. + //BOOST_SCOPE_EXIT(&L) { lua_pop(L,1); } BOOST_SCOPE_EXIT_END + //return lua_isstring(L, -1) ? std::string(lua_tostring(L, -1)) : boost::optional<std::string>(); + + boost::optional<std::string> result; + if (lua_isstring(L, -1)) { + result = std::string(lua_tostring(L, -1)); + } + lua_pop(L, 1); + return result; +} + +boost::optional<bool> Swift::Lua::getBooleanField(lua_State* L, int index, const std::string& field) { + lua_getfield(L, index, field.c_str()); + boost::optional<bool> result; + if (lua_isboolean(L, -1)) { + result = lua_toboolean(L, -1); + } + lua_pop(L, 1); + return result; +} + +boost::optional<int> Swift::Lua::getIntField(lua_State* L, int index, const std::string& field) { + lua_getfield(L, index, field.c_str()); + boost::optional<int> result; + if (lua_isnumber(L, -1)) { + result = boost::numeric_cast<int>(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void Swift::Lua::registerHelp(lua_State* L, int index, const std::string& description, const std::string& parameters, const std::string& options) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_help"); + lua_pushvalue(L, index); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (!parameters.empty()) { + std::istringstream s(parameters); + lua_newtable(L); + int i = 1; + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_createtable(L, 2, 0); + lua_pushstring(L, key.c_str()); + lua_rawseti(L, -2, 1); + lua_pushstring(L, value.c_str()); + lua_rawseti(L, -2, 2); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "parameters"); + } + if (!options.empty()) { + std::istringstream s(options); + lua_newtable(L); + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_pushstring(L, value.c_str()); + lua_setfield(L, -2, key.c_str()); + } + lua_setfield(L, -2, "options"); + } + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerClassHelp(lua_State* L, const std::string& name, const std::string& description) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_class_help"); + lua_pushstring(L, name.c_str()); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerExtraHelp(lua_State* L, int index, const std::string& name) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "extra_help"); + lua_getfield(L, -1, name.c_str()); + if (!lua_isnil(L, -1)) { + lua_getfield(L, -3, "register_help"); + lua_pushvalue(L, index); + lua_pushvalue(L, -3); + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + } + lua_pop(L, 3); +} + +void Swift::Lua::pushStringArray(lua_State* L, const std::vector<std::string>& strings) { + lua_createtable(L, boost::numeric_cast<int>(strings.size()), 0); + for (size_t i = 0; i < strings.size(); ++i) { + lua_pushstring(L, strings[i].c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } +} diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h new file mode 100644 index 0000000..ed4fcc1 --- /dev/null +++ b/Sluift/Lua/LuaUtils.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <lua.hpp> +#include <boost/optional.hpp> +#include <string> +#include <vector> + +#if LUA_VERSION_NUM < 502 +#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) +#endif + +namespace Swift { + namespace Lua { + /** + * Can be used as __tostring metamethod on a table. + */ + int convertTableToString(lua_State* L); + + void registerTableToString(lua_State* L, int index); + void registerTableEquals(lua_State* L, int index); + void registerGetByTypeIndex(lua_State* L, int index); + void registerHelp(lua_State* L, int index, + const std::string& description, const std::string& parameters, const std::string& options); + void registerClassHelp(lua_State* L, const std::string& name, const std::string& description); + void registerExtraHelp(lua_State* L, int index, const std::string& name); + + inline int absoluteOffset(lua_State* L, int index) { + return index > 0 ? index : lua_gettop(L) + index + 1; + } + + boost::optional<std::string> getStringField(lua_State* L, int index, const std::string&); + boost::optional<bool> getBooleanField(lua_State* L, int index, const std::string&); + boost::optional<int> getIntField(lua_State* L, int index, const std::string&); + + void pushStringArray(lua_State* L, const std::vector<std::string>& strings); + } +} diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp index 3164ec6..4f8078e 100644 --- a/Sluift/Lua/Value.cpp +++ b/Sluift/Lua/Value.cpp @@ -7,6 +7,9 @@ #include "Value.h" +extern "C" { #include <lualib.h> +} #include <boost/variant/apply_visitor.hpp> +#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/foreach.h> @@ -36,13 +39,13 @@ namespace { void operator()(const std::vector<Value>& values) const { - lua_createtable(state, values.size(), 0); + lua_createtable(state, boost::numeric_cast<int>(values.size()), 0); for(size_t i = 0; i < values.size(); ++i) { boost::apply_visitor(PushVisitor(state), values[i]); - lua_rawseti(state, -2, i + 1); + lua_rawseti(state, -2, boost::numeric_cast<int>(i + 1)); } } void operator()(const std::map<std::string, boost::shared_ptr<Value> >& table) const { - lua_createtable(state, 0, table.size()); + lua_createtable(state, 0, boost::numeric_cast<int>(table.size())); for(std::map<std::string, boost::shared_ptr<Value> >::const_iterator i = table.begin(); i != table.end(); ++i) { boost::apply_visitor(PushVisitor(state), *i->second); diff --git a/Sluift/Lua/Value.h b/Sluift/Lua/Value.h index 7b10cd2..55aa347 100644 --- a/Sluift/Lua/Value.h +++ b/Sluift/Lua/Value.h @@ -1,4 +1,4 @@ /* - * Copyright (c) 2011 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. @@ -12,4 +12,5 @@ #include <boost/variant.hpp> #include <boost/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> struct lua_State; @@ -29,4 +30,29 @@ namespace Swift { typedef std::map<std::string, boost::shared_ptr<Value> > Table; + typedef std::vector<Value> Array; + + inline boost::shared_ptr<Value> nilRef() { + return boost::make_shared<Value>(Nil()); + } + + inline boost::shared_ptr<Value> valueRef(const std::string& value) { + return boost::make_shared<Value>(value); + } + + inline boost::shared_ptr<Value> intRef(int value) { + return boost::make_shared<Value>(value); + } + + inline boost::shared_ptr<Value> boolRef(bool value) { + return boost::make_shared<Value>(value); + } + + inline boost::shared_ptr<Value> valueRef(const Table& table) { + return boost::make_shared<Value>(table); + } + + inline boost::shared_ptr<Value> valueRef(const Array& array) { + return boost::make_shared<Value>(array); + } void pushValue(lua_State* state, const Value& value); |