replace to nf7:yield() from a custom type of Node::Lambda in Lua script

This commit is contained in:
2022-08-27 00:26:10 +09:00
parent 2e25e6d14c
commit a703ba3bbc
6 changed files with 51 additions and 87 deletions

View File

@@ -368,43 +368,6 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
lua_setmetatable(L, -2);
}
void PushNodeLambda(lua_State* L,
const std::shared_ptr<nf7::Node::Lambda>& callee,
const std::weak_ptr<nf7::Node::Lambda>& caller) noexcept {
constexpr auto kTypeName = "nf7::Node::Lambda";
struct Data {
std::shared_ptr<nf7::Node::Lambda> callee;
std::weak_ptr<nf7::Node::Lambda> caller;
};
new (lua_newuserdata(L, sizeof(Data))) Data { .callee = callee, .caller = caller };
if (luaL_newmetatable(L, kTypeName)) {
lua_pushcfunction(L, [](auto L) {
const auto& d = *reinterpret_cast<Data*>(luaL_checkudata(L, 1, kTypeName));
auto caller = d.caller.lock();
if (!caller) return luaL_error(L, "caller expired");
std::string n = luaL_checkstring(L, 2);
auto v = nf7::luajit::CheckValue(L, 3);
auto callee = d.callee;
callee->env().ExecSub(callee, [callee, caller, n = std::move(n), v = std::move(v)]() {
callee->Handle(n, v, caller);
});
return 0;
});
lua_setfield(L, -2, "__call");
lua_pushcfunction(L, [](auto L) {
reinterpret_cast<Data*>(luaL_checkudata(L, 1, kTypeName))->~Data();
return 0;
});
lua_setfield(L, -2, "__gc");
}
lua_setmetatable(L, -2);
}
std::optional<nf7::Value> ToValue(lua_State* L, int idx) noexcept {
if (lua_isnoneornil(L, idx)) {

View File

@@ -9,7 +9,6 @@
#include <lua.hpp>
#include "common/node.hh"
#include "common/value.hh"
@@ -20,9 +19,6 @@ void PushImmEnv(lua_State*) noexcept;
void PushValue(lua_State*, const nf7::Value&) noexcept;
void PushVector(lua_State*, const nf7::Value::ConstVector&) noexcept;
void PushMutableVector(lua_State*, std::vector<uint8_t>&&) noexcept;
void PushNodeLambda(lua_State*,
const std::shared_ptr<nf7::Node::Lambda>& callee,
const std::weak_ptr<nf7::Node::Lambda>& caller) noexcept;
std::optional<nf7::Value> ToValue(lua_State*, int) noexcept;
std::optional<nf7::Value::ConstVector> ToVector(lua_State*, int) noexcept;

View File

@@ -147,9 +147,6 @@ static void PushMeta(lua_State* L) noexcept {
// nf7:yield(results...)
lua_pushcfunction(L, [](auto L) {
auto th = Thread::GetPtr(L, 1);
th->ExecResume(L);
th->ExpectYield(L);
return lua_yield(L, lua_gettop(L)-1);
});
lua_setfield(L, -2, "yield");

View File

@@ -5,6 +5,7 @@
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
@@ -17,6 +18,7 @@
#include "common/logger_ref.hh"
#include "common/luajit.hh"
#include "common/luajit_ref.hh"
#include "common/node.hh"
namespace nf7::luajit {
@@ -40,9 +42,14 @@ class Thread final : public std::enable_shared_from_this<Thread> {
// Creates a handler to finalize a promise.
template <typename T>
static Handler CreatePromiseHandler(
static inline Handler CreatePromiseHandler(
nf7::Future<T>::Promise& pro, std::function<T(lua_State*)>&&) noexcept;
// Creates a handler to emit yielded value to Node::Lambda.
static inline Handler CreateNodeLambdaHandler(
const std::shared_ptr<nf7::Node::Lambda>& caller,
const std::shared_ptr<nf7::Node::Lambda>& callee) noexcept;
// must be called on luajit thread
static std::shared_ptr<Thread> GetPtr(lua_State* L, int idx) {
auto th = CheckWeakPtr<Thread>(L, idx, kTypeName);
@@ -176,4 +183,42 @@ Thread::Handler Thread::CreatePromiseHandler(
};
}
Thread::Handler Thread::CreateNodeLambdaHandler(
const std::shared_ptr<nf7::Node::Lambda>& caller,
const std::shared_ptr<nf7::Node::Lambda>& callee) noexcept {
return [caller, callee](auto& th, auto L) {
switch (th.state()) {
case nf7::luajit::Thread::kPaused:
switch (lua_gettop(L)) {
case 0:
th.ExecResume(L);
return;
case 2: {
auto k = luaL_checkstring(L, 1);
auto v = nf7::luajit::CheckValue(L, 2);
caller->env().ExecSub(
caller, [caller, callee, k = std::string {k}, v = std::move(v)]() {
caller->Handle(k, v, callee);
});
} return;
default:
if (auto log = th.logger()) {
log->Warn("invalid use of yield, nf7:yield() or nf7:yield(name, value)");
}
th.Resume(L, 0);
return;
}
case nf7::luajit::Thread::kFinished:
return;
default:
if (auto log = th.logger()) {
log->Warn(std::string {"luajit execution error: "}+lua_tostring(L, -1));
}
return;
}
};
}
} // namespace nf7::luajit