diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/lua_function.cpp | 37 | ||||
-rw-r--r-- | indra/llcommon/lua_function.h | 30 |
2 files changed, 53 insertions, 14 deletions
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp index f6db4eafe1..5466e0058e 100644 --- a/indra/llcommon/lua_function.cpp +++ b/indra/llcommon/lua_function.cpp @@ -407,8 +407,7 @@ void lua_pushllsd(lua_State* L, const LLSD& data) } } -LuaState::LuaState(const std::string_view& desc, script_finished_fn cb): - mDesc(desc), +LuaState::LuaState(script_finished_fn cb): mCallback(cb), mState(luaL_newstate()) { @@ -450,19 +449,49 @@ LuaState::~LuaState() } } -bool LuaState::checkLua(int r) +bool LuaState::checkLua(const std::string& desc, int r) { if (r != LUA_OK) { mError = lua_tostring(mState, -1); lua_pop(mState, 1); - LL_WARNS() << mDesc << ": " << mError << LL_ENDL; + LL_WARNS() << desc << ": " << mError << LL_ENDL; return false; } return true; } +std::pair<int, LLSD> LuaState::expr(const std::string& desc, const std::string& text) +{ + if (! checkLua(desc, lluau::dostring(mState, desc, text))) + return { -1, mError }; + + // here we believe there was no error -- did the Lua fragment leave + // anything on the stack? + std::pair<int, LLSD> result{ lua_gettop(mState), {} }; + if (! result.first) + return result; + + // aha, at least one entry on the stack! + if (result.first == 1) + { + result.second = lua_tollsd(mState, 1); + // pop the result we claimed + lua_settop(mState, 0); + return result; + } + + // multiple entries on the stack + for (int index = 1; index <= result.first; ++index) + { + result.second.append(lua_tollsd(mState, index)); + } + // pop everything + lua_settop(mState, 0); + return result; +} + LuaPopper::~LuaPopper() { diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h index e2bd58e80a..ea9f2ebdf8 100644 --- a/indra/llcommon/lua_function.h +++ b/indra/llcommon/lua_function.h @@ -17,6 +17,7 @@ #include "luau/luaconf.h" #include "luau/lualib.h" #include "stringize.h" +#include <utility> // std::pair #define lua_register(L, n, f) (lua_pushcfunction(L, (f), n), lua_setglobal(L, (n))) #define lua_rawlen lua_objlen @@ -55,19 +56,28 @@ class LuaState public: typedef std::function<void(std::string msg)> script_finished_fn; - LuaState(const std::string_view& desc, script_finished_fn cb); + LuaState(script_finished_fn cb={}); LuaState(const LuaState&) = delete; LuaState& operator=(const LuaState&) = delete; ~LuaState(); - bool checkLua(int r); + bool checkLua(const std::string& desc, int r); + + // expr() is for when we want to capture any results left on the stack + // by a Lua expression, possibly including multiple return values. + // int < 0 means error, and LLSD::asString() is the error message. + // int == 0 with LLSD::isUndefined() means the Lua expression returned no + // results. + // int == 1 means the Lua expression returned one result. + // int > 1 with LLSD::isArray() means the Lua expression returned + // multiple results, represented as the entries of the array. + std::pair<int, LLSD> expr(const std::string& desc, const std::string& text); operator lua_State*() const { return mState; } private: - std::string mDesc; script_finished_fn mCallback; lua_State* mState; std::string mError; @@ -129,13 +139,13 @@ private: * call() method definition header, to be followed by a method body enclosed * in curly braces as usual. */ -#define lua_function(name) \ -static struct name##_ : public LuaFunction \ -{ \ - name##_(): LuaFunction(#name, &call) {} \ - static int call(lua_State* L); \ -} name; \ -int name##_::call(lua_State* L) +#define lua_function(name) \ +static struct name##_luadecl : public LuaFunction \ +{ \ + name##_luadecl(): LuaFunction(#name, &call) {} \ + static int call(lua_State* L); \ +} name##_luadef; \ +int name##_luadecl::call(lua_State* L) // { // ... supply method body here, referencing 'L' ... // } |