Age | Commit message (Collapse) | Author |
|
Lua scripts floater
|
|
Our std::strings are UTF-8 encoded, so conversion from std::string to
std::filesystem::path must use UTF-8 decoding. The native Windows
std::filesystem::path constructor and assignment operator accepting
std::string use "native narrow encoding," which mangles path strings
containing UTF-8 encoded non-ASCII characters.
fsyspath's std::string constructor and assignment operator explicitly engage
std::filesystem::u8path() to handle encoding. u8path() is deprecated in C++20,
but once we adapt fsyspath's conversion to C++20 conventions, consuming code
need not be modified.
|
|
|
|
Make LLRequireResolver capture std::filesystem::path instances, instead of
std::strings, for the path to resolve and the source directory. Store the
running script's containing directory instead of calling parent_path() over
and over.
Demote Lua LL.post_on() logging to DEBUG level instead of INFO.
|
|
|
|
|
|
Push throwing Lua errors down into LLRequireResolver::findModule() and
findModuleImpl() so their callers don't have to handle the error case. That
eliminates finishrequire().
require() itself now only retrieves (and pops) the passed module name and
calls LLRequireResolver::resolveRequire() to do the actual work.
resolveRequire() is now void. It only instantiates LLRequireResolver and calls
its findModule().
findModule() is now also void. It's guaranteed to either push the loaded Lua
module or throw a Lua error. In particular, when findPathImpl() cannot find
the specified module, findModule() throws an error. That replaces
ModuleStatus::NotFound.
Since std::filesystem::path::append() aka operator/() detects when its right
operand is absolute and, in that case, discards the left operand, we no longer
need resolveAndStoreDefaultPaths(): we can just invoke that operation inline.
When findModule() pushes _MODULES on the Lua stack, it uses LuaRemover (below)
to ensure that _MODULES is removed again no matter how findModules() exits.
findModuleImpl() now accepts the candidate pathname as its argument. That
eliminates mAbsolutePath.
findModuleImpl() now returns only bool: true means the module was found and
loaded and pushed on the Lua stack, false means not found and nothing was
pushed; no return means an error was reported.
Push running a newly found module's source file down into findModuleImpl().
That eliminates the distinction between Cached and FileRead, which obviates
ModuleStatus: a bool return means either "previously cached" or "we read it,
compiled it, loaded it and ran it." That also eliminates the need to store the
module's textual content in mSourceCode.
Similarly, once loading the module succeeds, findModuleImpl() caches it in
_MODULES right away. That eliminates ResolvedRequire since we need not pass
the full pathname of the found module (or its contents) back up through the
call chain.
Move require() code that runs the new module into private runModule() method,
called by findModuleImpl() in the not-cached case. runModule() is the only
remaining method that can push either a string error message or the desired
module, because of its funny stack manipulations. That means the check for a
string error message on the stack top can move down to findModuleImpl().
Add LuaRemover class to ensure that on exit from some particular C++ block,
the specified Lua stack entry will definitely be removed. This is different
from LuaPopper in that it engages lua_remove() rather than lua_pop().
Also ditch obsolete await_event() Lua entry point.
|
|
|
|
|
|
Break out for LLLUAmanager consumers the promise/future semantics of
waitScriptFile() and waitScriptLine(). startScriptMumble() uses
runScriptMumble() to launch a coroutine to run the specified Lua script or
chunk, providing an internal adapter callback to set a promise on completion.
It then returns to its caller the future obtained from that promise. This
allows a caller to call startScriptMumble(), run in parallel with the Lua
coroutine for a while and then call get() on the returned future to wait for
results.
waitScriptMumble() is then trivially implemented using startScriptMumble().
Fix runScriptLine()'s logic to abbreviate the passed Lua chunk for use as the
description. We were erroneously assigning back through a string_view of the
parameter, which overwrote a temporary string in the argument list.
With Lua 5.4, listen_events() tried to discover the main "thread" (Lua
coroutine) associated with the current lua_State so we could call async
callbacks on that thread. Luau doesn't seem to provide that feature, so run
callbacks on whichever thread calls listen_events().
Reinstate original multi-argument lua_print_msg(), tweaked to avoid the Lua
5.4 lua_rotate() function, which is missing from Luau.
|
|
Add LuaState::expr() that evaluates a Lua snippet and reports back any result
(or error) left on the stack.
Add LLLUAmanager::runScriptFile() and runScriptLine() overloads that accept a
callback with an (int count, LLSD result) signature. The count disambiguates
(error, no result, one result, array of results). Also add overloads that accept
an existing LuaState instance. Also add waitScriptFile() and waitScriptLine()
methods that pause the calling coroutine until the Lua script completes, and
return its results.
Instead of giving LuaState a description to use for all subsequent checkLua()
calls, remove description from its constructor and data members. Move to
expr() and checkLua() parameters: we want a description specific to each
operation, rather than for the LuaState as a whole. This prepares for
persistent LuaState instances.
For now, the existing script_finished_fn semantics remain: the callback will
be called only when the LuaState is destroyed. This may need to change as we
migrate towards longer-lasting LuaState instances.
Make lua_function(name) macro append suffixes to the name for both the
LuaFunction subclass declaration and the instance declaration. This allows
publishing a lua_function() name such as sleep(), which already has a
different C++ declaration.
Move the Lua sleep() entry point to a standalone lua_function(sleep), instead
of a lambda in the body of runScriptFile().
|
|
The first test runs a Lua script that calls post_on(), listen_events() and
await_event() to engage in LLEventPump handshakes with the test program.
Make llluamanager.cpp testable by putting LL_TEST conditionals around lots of
viewer-internals headers and the lua_function definitions that engage them.
Since LuaListener::connect() is called by its constructor, make it a static
method that explicitly accepts the lua_State* (instead of finding it as
mState). Add that parameter to its two existing calls.
Add a debug log message when LuaListener is destroyed. This surfaced the need
to pass a no-op deleter when listen_events() constructs a LuaListener::ptr_t.
When compiled for LL_TEST, make LuaListener::mReplyPump an
LLEventLogProxyFor<LLEventStream> instead of a plain LLEventStream.
For debugging purposes, add a type string "LLEventLogProxy" for
LLEventPumps::make(). A make() call with this type will return an
LLEventLogProxyFor<LLEventStream>.
|
|
|
|
|
|
|