Add lua_resumeerror
Luau has lua_resumeerror to resume a thread with the error as first value pushed to stack (basically a C API that does what coroutine.xresumr does in Pluto). It would be nice if Pluto supported resumeerror as well
Well, what coroutine.xresume does is rethrow the error, but what you're describing sounds more like a wrapper for pcall?
Well, what coroutine.xresume does is rethrow the error, but what you're describing sounds more like a wrapper for pcall?
I meant it for C side/embedder use-cases. Its very useful to be able to directly rethrow an error to a thread directly using a simple API without needing to undergo any performance loss of going through a table + lua function call in C code and resumeerror is the standard way that most Luau runtimes handle this so it'd be nice to have in Pluto as well
I mean, I don't really know how it is in LuaU, and there seems to be absolutely 0 documentation around its C API additions, but based on what you're describing, what you want is simply lua_resume from modern versions, which is what you'll have in Pluto:
lua_State* L = luaL_newstate();
luaL_openlibs(L);
auto coro = lua_newthread(L);
lua_getglobal(coro, "error");
lua_pushstring(coro, "Oh no!");
int nres;
int status = lua_resume(coro, L, 1, &nres);
if (status != LUA_OK && status != LUA_YIELD)
{
std::cout << "Coroutine had an error: " << luaL_tolstring(coro, -1, NULL) << std::endl;
}
Coroutine had an error: Oh no!
int status = lua_resume(coro, L, 1, &nres); if (status != LUA_OK && status != LUA_YIELD) { std::cout << "Coroutine had an error: " << luaL_tolstring(coro, -1, NULL) << std::endl; }
Ah hmmm... the thing lua_resumeerror in luau does well is when you pcall a coroutine that yields and is then resume error'd from C side, the pcall returns the error. E.g.
local function myAsyncCoroutine() callCCode(); return coroutine.yield()
and
local ok, err = pcall(myAsyncCoroutine)
If the C code in callCCode uses resumeerror, the error is propogated to the pcall so ok becomes false and err, the error itself.
Not sure how you'd do this with just resume though
Well, lucky for you, that is literally what coroutine.resume does:
static int luaB_coresume (lua_State *L) {
lua_State *co = getco(L);
int r;
r = auxresume(L, co, lua_gettop(L) - 1);
if (l_unlikely(r < 0)) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
}
Well, lucky for you, that is literally what
coroutine.resumedoes:static int luaB_coresume (lua_State *L) { lua_State co = getco(L); int r; r = auxresume(L, co, lua_gettop(L) - 1); if (l_unlikely(r < 0)) { lua_pushboolean(L, 0); lua_insert(L, -2); return 2; / return false + error message / } else { lua_pushboolean(L, 1); lua_insert(L, -(r + 1)); return r + 1; / return true + 'resume' returns */ } }
I realize this is closed and rather niche, but just to try explaining a second time, consider the following C/Rust pseudo code:
if some_async_op().await.is_ok() { lua_push(…) lua_resume(thread_state, numargs) } else { // here is the issue, you can’t resume the thread with a error status from C API, so it’s not possible for C/Rust code to directly propogate the error to a resume within C API }
coroutine.resume etc are lua functions/APIs. lua_resumeerror is the C API equivalent (kinda)
Yes, you can't resume the coroutine, but you can xmove the error message from the coroutine to the main thread and continue execution there. Just take a look at how lcorolib does it.
Yes, you can't resume the coroutine, but you can xmove the error message from the coroutine to the main thread and continue execution there. Just take a look at how lcorolib does it.
Not sure how this would work with pcall though. I think continuations would also solve this problem too depending on how Pluto implements continuations