rename NodeRootSelectLambda -> NodeRootLambda

and improve common/luajit.hh
This commit is contained in:
falsycat 2022-09-30 17:11:06 +09:00
parent 7d696cfbd9
commit f96188ef14
8 changed files with 340 additions and 327 deletions

View File

@ -107,7 +107,7 @@ target_sources(nf7
common/nfile_watcher.hh
common/node.hh
common/node_link_store.hh
common/node_root_select_lambda.hh
common/node_root_lambda.hh
common/ptr_selector.hh
common/queue.hh
common/ring_buffer.hh

View File

@ -13,12 +13,11 @@
#include "common/logger.hh"
#include "common/logger_ref.hh"
#include "common/luajit_thread.hh"
#include "common/luajit_std.hh"
namespace nf7::luajit {
static void PushStd(lua_State* L) noexcept;
// buffer <-> lua value conversion
template <typename T>
static size_t PushArrayFromBytes(
@ -29,25 +28,6 @@ template <typename T>
static size_t ToBytes(lua_State* L, uint8_t* ptr, uint8_t* end);
void PushGlobalTable(lua_State* L) noexcept {
if (luaL_newmetatable(L, "nf7::luajit::PushGlobalTable")) {
PushStd(L);
lua_setfield(L, -2, "std");
}
}
void PushImmEnv(lua_State* L) noexcept {
if (luaL_newmetatable(L, "nf7::luajit::PushImmEnv")) {
lua_createtable(L, 0, 0);
PushGlobalTable(L);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, [](auto L) { return luaL_error(L, "global is immutable"); });
lua_setfield(L, -2, "__newindex");
lua_setmetatable(L, -2);
}
}
void PushValue(lua_State* L, const nf7::Value& v) noexcept {
new (lua_newuserdata(L, sizeof(v))) nf7::Value(v);
@ -102,14 +82,60 @@ void PushValue(lua_State* L, const nf7::Value& v) noexcept {
}
lua_setmetatable(L, -2);
}
std::optional<nf7::Value> ToValue(lua_State* L, int idx) noexcept {
if (lua_isnoneornil(L, idx)) {
return nf7::Value {nf7::Value::Pulse {}};
}
if (lua_isnumber(L, idx)) {
const double n = lua_tonumber(L, idx);
return nf7::Value {n};
}
if (lua_isboolean(L, idx)) {
return nf7::Value {bool {!!lua_toboolean(L, idx)}};
}
if (lua_isstring(L, idx)) {
size_t len;
const char* str = lua_tolstring(L, idx, &len);
return nf7::Value {std::string {str, len}};
}
if (auto vec = ToVector(L, idx)) {
return nf7::Value {std::move(*vec)};
}
if (auto vec = ToMutableVector(L, idx)) {
return nf7::Value {std::move(*vec)};
}
if (lua_istable(L, idx)) {
std::vector<nf7::Value::TuplePair> tup;
lua_pushnil(L);
while (lua_next(L, idx)) {
std::string name = "";
if (lua_isstring(L, -2)) {
name = lua_tostring(L, -2);
}
auto val = ToValue(L, -1);
if (!val) return std::nullopt;
tup.push_back({std::move(name), std::move(*val)});
lua_pop(L, 1);
}
return nf7::Value {std::move(tup)};
}
if (auto val = ToRef<nf7::Value>(L, idx, "nf7::Value")) {
return *val;
}
return std::nullopt;
}
void PushVector(lua_State* L, const nf7::Value::ConstVector& v) noexcept {
assert(v);
static const char* kTypeName = "nf7::Value::ConstVector";
using T = nf7::Value::ConstVector;
assert(v != nullptr);
new (lua_newuserdata(L, sizeof(v))) nf7::Value::ConstVector(v);
if (luaL_newmetatable(L, "nf7::Value::ConstVector")) {
if (luaL_newmetatable(L, kTypeName)) {
lua_createtable(L, 0, 0);
lua_pushcfunction(L, [](auto L) {
const auto& v = CheckRef<nf7::Value::ConstVector>(L, 1, "nf7::Value::ConstVector");
const auto& v = CheckRef<T>(L, 1, kTypeName);
const auto offset = luaL_checkinteger(L, 2);
if (offset < 0) {
return luaL_error(L, "negative offset");
@ -189,14 +215,14 @@ void PushVector(lua_State* L, const nf7::Value::ConstVector& v) noexcept {
lua_setfield(L, -2, "get");
lua_pushcfunction(L, [](auto L) {
const auto& v = CheckRef<nf7::Value::ConstVector>(L, 1, "nf7::Value::ConstVector");
const auto& v = CheckRef<T>(L, 1, kTypeName);
lua_pushlstring(L, reinterpret_cast<const char*>(v->data()), v->size());
return 1;
});
lua_setfield(L, -2, "str");
lua_pushcfunction(L, [](auto L) {
const auto& v = CheckRef<nf7::Value::ConstVector>(L, 1, "nf7::Value::ConstVector");
const auto& v = CheckRef<T>(L, 1, kTypeName);
lua_pushinteger(L, static_cast<lua_Integer>(v->size()));
return 1;
});
@ -204,20 +230,23 @@ void PushVector(lua_State* L, const nf7::Value::ConstVector& v) noexcept {
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, [](auto L) {
CheckRef<nf7::Value::ConstVector>(L, 1, "nf7::Value::ConstVector").~shared_ptr();
CheckRef<T>(L, 1, kTypeName).~shared_ptr();
return 0;
});
lua_setfield(L, -2, "__gc");
}
lua_setmetatable(L, -2);
}
void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
new (lua_newuserdata(L, sizeof(v))) std::vector<uint8_t>(std::move(v));
if (luaL_newmetatable(L, "nf7::Value::MutableVector")) {
void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
constexpr const char* kTypeName = "nf7::Value::MutableVector";
using T = std::vector<uint8_t>;
new (lua_newuserdata(L, sizeof(v))) T(std::move(v));
if (luaL_newmetatable(L, kTypeName)) {
lua_createtable(L, 0, 0);
lua_pushcfunction(L, [](auto L) {
auto& v = CheckRef<std::vector<uint8_t>>(L, 1, "nf7::Value::MutableVector");
auto& v = CheckRef<T>(L, 1, kTypeName);
const lua_Integer offset = luaL_checkinteger(L, 2);
if (offset < 0) return luaL_error(L, "negative offset");
@ -261,7 +290,7 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
lua_setfield(L, -2, "set");
lua_pushcfunction(L, [](auto L) {
auto& v = CheckRef<std::vector<uint8_t>>(L, 1, "nf7::Value::MutableVector");
auto& v = CheckRef<T>(L, 1, kTypeName);
const lua_Integer size = luaL_checkinteger(L, 2);
if (size < 0) return luaL_error(L, "negative size");
v.resize(static_cast<size_t>(size));
@ -270,10 +299,10 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
lua_setfield(L, -2, "resize");
lua_pushcfunction(L, [](auto L) {
auto& dst = CheckRef<std::vector<uint8_t>>(L, 1, "nf7::Value::MutableVector");
auto& dst = CheckRef<T>(L, 1, kTypeName);
const auto dst_off = luaL_checkinteger(L, 2);
const std::vector<uint8_t>* src;
const T* src;
if (const auto& v = ToVector(L, 3)) {
src = &**v;
} else if (const auto& mv = ToMutableVector(L, 3)) {
@ -302,23 +331,25 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, [](auto L) {
CheckRef<std::vector<uint8_t>>(L, 1, "nf7::Value::MutableVector").~vector();
CheckRef<T>(L, 1, kTypeName).~vector();
return 0;
});
lua_setfield(L, -2, "__gc");
}
lua_setmetatable(L, -2);
}
void PushNodeRootSelectLambda(
lua_State* L, const std::shared_ptr<nf7::NodeRootSelectLambda>& la) noexcept {
void PushNodeRootLambda(
lua_State* L, const std::shared_ptr<nf7::NodeRootLambda>& la) noexcept {
constexpr const char* kTypeName = "nf7::NodeRootLambda";
assert(la);
using T = std::shared_ptr<nf7::NodeRootSelectLambda>;
using T = std::shared_ptr<nf7::NodeRootLambda>;
new (lua_newuserdata(L, sizeof(T))) T {la};
if (luaL_newmetatable(L, "nf7::NodeRootSelectLambda")) {
if (luaL_newmetatable(L, kTypeName)) {
lua_pushcfunction(L, [](auto L) {
CheckRef<T>(L, 1, "nf7::NodeRootSelectLambda").~T();
CheckRef<T>(L, 1, kTypeName).~T();
return 0;
});
lua_setfield(L, -2, "__gc");
@ -327,205 +358,24 @@ void PushNodeRootSelectLambda(
}
std::optional<nf7::Value> ToValue(lua_State* L, int idx) noexcept {
if (lua_isnoneornil(L, idx)) {
return nf7::Value {nf7::Value::Pulse {}};
void PushGlobalTable(lua_State* L) noexcept {
if (luaL_newmetatable(L, "nf7::luajit::GlobalTable")) {
PushStdTable(L);
lua_setfield(L, -2, "std");
}
if (lua_isnumber(L, idx)) {
const double n = lua_tonumber(L, idx);
return nf7::Value {n};
}
if (lua_isboolean(L, idx)) {
return nf7::Value {bool {!!lua_toboolean(L, idx)}};
}
if (lua_isstring(L, idx)) {
size_t len;
const char* str = lua_tolstring(L, idx, &len);
return nf7::Value {std::string {str, len}};
}
if (auto vec = ToVector(L, idx)) {
return nf7::Value {std::move(*vec)};
}
if (auto vec = ToMutableVector(L, idx)) {
return nf7::Value {std::move(*vec)};
}
if (lua_istable(L, idx)) {
std::vector<nf7::Value::TuplePair> tup;
lua_pushnil(L);
while (lua_next(L, idx)) {
std::string name = "";
if (lua_isstring(L, -2)) {
name = lua_tostring(L, -2);
}
auto val = ToValue(L, -1);
if (!val) return std::nullopt;
tup.push_back({std::move(name), std::move(*val)});
lua_pop(L, 1);
}
void PushImmEnv(lua_State* L) noexcept {
if (luaL_newmetatable(L, "nf7::luajit::ImmEnv")) {
lua_createtable(L, 0, 0);
{
PushGlobalTable(L);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, [](auto L) { return luaL_error(L, "global is immutable"); });
lua_setfield(L, -2, "__newindex");
}
return nf7::Value {std::move(tup)};
lua_setmetatable(L, -2);
}
if (auto val = ToRef<nf7::Value>(L, idx, "nf7::Value")) {
return *val;
}
return std::nullopt;
}
std::optional<nf7::Value::ConstVector> ToVector(lua_State* L, int idx) noexcept {
auto ptr = ToRef<nf7::Value::ConstVector>(L, idx, "nf7::Value::ConstVector");
if (!ptr) return std::nullopt;
return *ptr;
}
std::optional<std::vector<uint8_t>> ToMutableVector(lua_State* L, int idx) noexcept {
auto ptr = ToRef<std::vector<uint8_t>>(L, idx, "nf7::Value::MutableVector");
if (!ptr) return std::nullopt;
return std::move(*ptr);
}
static void PushStd(lua_State* L) noexcept {
lua_newuserdata(L, 0);
lua_createtable(L, 0, 0);
lua_createtable(L, 0, 0);
{
// ---- lua lib ----
// assert(expr[, msg])
lua_pushcfunction(L, [](auto L) {
if (lua_toboolean(L, 1)) {
return 0;
}
if (lua_gettop(L) >= 2) {
return luaL_error(L, lua_tostring(L, 2));
} else {
return luaL_error(L, "assertion failure");
}
});
lua_setfield(L, -2, "assert");
// error(msg)
lua_pushcfunction(L, [](auto L) {
return luaL_error(L, luaL_checkstring(L, 1));
});
lua_setfield(L, -2, "error");
// load(str)
lua_pushcfunction(L, [](auto L) {
if (0 != luaL_loadstring(L, luaL_checkstring(L, 1))) {
return luaL_error(L, "lua.load error: %s", lua_tostring(L, -1));
}
return 1;
});
lua_setfield(L, -2, "load");
// pcall(func, args...) -> success, result
lua_pushcfunction(L, [](auto L) {
if (0 == lua_pcall(L, lua_gettop(L)-1, LUA_MULTRET, 0)) {
lua_pushboolean(L, true);
lua_insert(L, 1);
return lua_gettop(L);
} else {
lua_pushboolean(L, false);
lua_insert(L, 1);
return 2;
}
});
lua_setfield(L, -2, "pcall");
// ---- math lib ----
// sin(theta)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::sin(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "sin");
// cos(theta)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::cos(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "cos");
// tan(slope)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::tan(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "tan");
// ---- table lib ----
// meta(table, meta_table)
lua_pushcfunction(L, [](auto L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
});
lua_setfield(L, -2, "meta");
// ---- time lib ----
// now()
lua_pushcfunction(L, [](auto L) {
const auto now = nf7::Env::Clock::now().time_since_epoch();
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now);
lua_pushnumber(L, static_cast<double>(ms.count())/1000.);
return 1;
});
lua_setfield(L, -2, "now");
// ---- value lib ----
// value(entity) -> value
lua_pushcfunction(L, [](auto L) {
if (lua_isstring(L, 2)) {
const auto type = std::string_view {lua_tostring(L, 2)};
if (type == "integer" || type == "int") {
PushValue(L, static_cast<nf7::Value::Integer>(luaL_checkinteger(L, 1)));
} else {
return luaL_error(L, "unknown type specifier: %s", type);
}
} else {
PushValue(L, CheckValue(L, 1));
}
return 1;
});
lua_setfield(L, -2, "value");
// mvector(vector or mutable vector) -> mutable vector
lua_pushcfunction(L, [](auto L) {
if (auto imm = ToVector(L, 1)) {
if (imm->use_count() == 1) {
PushMutableVector(L, std::move(const_cast<std::vector<uint8_t>&>(**imm)));
} else {
PushMutableVector(L, std::vector<uint8_t> {**imm});
}
return 1;
} else if (auto mut = ToMutableVector(L, 1)) {
PushMutableVector(L, std::vector<uint8_t> {*mut});
return 1;
} else {
PushMutableVector(L, {});
return 1;
}
});
lua_setfield(L, -2, "mvector");
// ---- bit manip ----
luaL_openlibs(L);
luaL_loadstring(L, "return require(\"bit\")");
lua_call(L, 0, 1);
lua_setfield(L, -2, "bit");
}
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
}

View File

@ -9,25 +9,84 @@
#include <lua.hpp>
#include "common/node_root_select_lambda.hh"
#include "common/node_root_lambda.hh"
#include "common/value.hh"
namespace nf7::luajit {
void PushGlobalTable(lua_State*) noexcept;
void PushImmEnv(lua_State*) noexcept;
// ---- utility
inline bool MatchMetaName(lua_State* L, int idx, const char* type) noexcept {
if (0 == lua_getmetatable(L, idx)) {
return false;
}
luaL_getmetatable(L, type);
const bool ret = lua_rawequal(L, -1, -2);
lua_pop(L, 2);
return ret;
}
template <typename T, typename... Args>
inline T& NewUserData(lua_State* L, Args&&... args) noexcept {
return *(new (lua_newuserdata(L, sizeof(T))) T(std::forward<Args>(args)...));
}
// ---- reference conversion
template <typename T>
inline T* ToRef(lua_State* L, int idx, const char* type) noexcept {
return MatchMetaName(L, idx, type)? reinterpret_cast<T*>(lua_touserdata(L, idx)): nullptr;
}
template <typename T>
inline T& CheckRef(lua_State* L, int idx, const char* type) {
return *reinterpret_cast<T*>(luaL_checkudata(L, idx, type));
}
// ---- Value conversion
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 PushNodeRootSelectLambda(
lua_State*, const std::shared_ptr<nf7::NodeRootSelectLambda>&) noexcept;
std::optional<nf7::Value> ToValue(lua_State*, int) noexcept;
std::optional<nf7::Value::ConstVector> ToVector(lua_State*, int) noexcept;
std::optional<std::vector<uint8_t>> ToMutableVector(lua_State*, int) noexcept;
inline nf7::Value CheckValue(lua_State* L, int idx) {
auto v = ToValue(L, idx);
if (!v) luaL_error(L, "expected nf7::Value");
return std::move(*v);
}
void PushVector(lua_State*, const nf7::Value::ConstVector&) noexcept;
inline std::optional<nf7::Value::ConstVector> ToVector(lua_State* L, int idx) noexcept {
auto ptr = ToRef<nf7::Value::ConstVector>(L, idx, "nf7::Value::ConstVector");
if (!ptr) return std::nullopt;
return *ptr;
}
void PushMutableVector(lua_State*, std::vector<uint8_t>&&) noexcept;
inline std::optional<std::vector<uint8_t>> ToMutableVector(lua_State* L, int idx) noexcept {
auto ptr = ToRef<std::vector<uint8_t>>(L, idx, "nf7::Value::MutableVector");
if (!ptr) return std::nullopt;
return std::move(*ptr);
}
void PushNodeRootLambda(
lua_State*, const std::shared_ptr<nf7::NodeRootLambda>&) noexcept;
inline const std::shared_ptr<nf7::NodeRootLambda>& CheckNodeRootLambda(lua_State* L, int idx) {
return CheckRef<std::shared_ptr<nf7::NodeRootLambda>>(L, idx, "nf7::NodeRootLambda");
}
inline void ToStringList(lua_State* L, int idx, std::vector<std::string>& v) noexcept {
const size_t n = lua_objlen(L, idx);
v.clear();
v.reserve(n);
for (int i = 1; i <= static_cast<int>(n); ++i) {
lua_rawgeti(L, idx, i);
if (auto str = lua_tostring(L, -1)) {
v.push_back(str);
}
lua_pop(L, 1);
}
}
// ---- overloaded Push function for template
template <typename T>
void Push(lua_State* L, T v) noexcept {
if constexpr (std::is_integral<T>::value) {
@ -55,10 +114,11 @@ inline void Push(lua_State* L, const std::vector<uint8_t>& v) noexcept {
inline void Push(lua_State* L, std::vector<uint8_t>&& v) noexcept {
luajit::PushMutableVector(L, std::move(v));
}
inline void Push(lua_State* L, const std::shared_ptr<nf7::NodeRootSelectLambda>& la) noexcept {
luajit::PushNodeRootSelectLambda(L, la);
inline void Push(lua_State* L, const std::shared_ptr<nf7::NodeRootLambda>& la) noexcept {
luajit::PushNodeRootLambda(L, la);
}
// pushes all args and returns a number of them
inline int PushAll(lua_State*) noexcept {
return 0;
}
@ -73,68 +133,8 @@ int PushAll(lua_State* L, T v, Args&&... args) noexcept {
}
template <typename T>
inline void PushWeakPtr(lua_State* L, const std::weak_ptr<T>& wptr) noexcept {
new (lua_newuserdata(L, sizeof(wptr))) std::weak_ptr<T>(wptr);
}
template <typename T>
inline void PushWeakPtrDeleter(lua_State* L, const std::weak_ptr<T>& = {}) noexcept {
lua_pushcfunction(L, [](auto L) {
reinterpret_cast<std::weak_ptr<T>*>(lua_touserdata(L, 1))->~weak_ptr();
return 0;
});
}
inline bool MatchMetaName(lua_State* L, int idx, const char* type) noexcept {
if (0 == lua_getmetatable(L, idx)) {
return false;
}
luaL_getmetatable(L, type);
const bool ret = lua_rawequal(L, -1, -2);
lua_pop(L, 2);
return ret;
}
template <typename T>
inline T* ToRef(lua_State* L, int idx, const char* type) noexcept {
return MatchMetaName(L, idx, type)? reinterpret_cast<T*>(lua_touserdata(L, idx)): nullptr;
}
template <typename T>
inline std::shared_ptr<T> CheckWeakPtr(lua_State* L, int idx, const char* type) {
auto ptr = reinterpret_cast<std::weak_ptr<T>*>(luaL_checkudata(L, idx, type));
if (auto ret = ptr->lock()) {
return ret;
} else {
luaL_error(L, "object expired: %s", typeid(T).name());
return nullptr;
}
}
template <typename T>
inline T& CheckRef(lua_State* L, int idx, const char* type) {
return *reinterpret_cast<T*>(luaL_checkudata(L, idx, type));
}
inline const std::shared_ptr<nf7::NodeRootSelectLambda>& CheckNodeRootSelectLambda(
lua_State* L, int idx) {
return CheckRef<std::shared_ptr<nf7::NodeRootSelectLambda>>(
L, idx, "nf7::NodeRootSelectLambda");
}
inline nf7::Value CheckValue(lua_State* L, int idx) {
auto v = ToValue(L, idx);
if (!v) luaL_error(L, "expected nf7::Value");
return std::move(*v);
}
inline void ToStringList(lua_State* L, std::vector<std::string>& v, int idx) {
const size_t n = lua_objlen(L, idx);
v.clear();
v.reserve(n);
for (int i = 1; i <= static_cast<int>(n); ++i) {
lua_rawgeti(L, idx, i);
if (auto str = lua_tostring(L, -1)) {
v.push_back(str);
}
lua_pop(L, 1);
}
}
// ---- global table
void PushGlobalTable(lua_State*) noexcept;
void PushImmEnv(lua_State*) noexcept;
} // namespace nf7

155
common/luajit_std.hh Normal file
View File

@ -0,0 +1,155 @@
#include <lua.hpp>
#include "common/luajit.hh"
namespace nf7::luajit {
inline void PushStdTable(lua_State* L) noexcept {
lua_newuserdata(L, 0);
lua_createtable(L, 0, 0);
lua_createtable(L, 0, 0);
{
// ---- lua lib ----
// assert(expr[, msg])
lua_pushcfunction(L, [](auto L) {
if (lua_toboolean(L, 1)) {
return 0;
}
if (lua_gettop(L) >= 2) {
return luaL_error(L, lua_tostring(L, 2));
} else {
return luaL_error(L, "assertion failure");
}
});
lua_setfield(L, -2, "assert");
// error(msg)
lua_pushcfunction(L, [](auto L) {
return luaL_error(L, luaL_checkstring(L, 1));
});
lua_setfield(L, -2, "error");
// load(str)
lua_pushcfunction(L, [](auto L) {
if (0 != luaL_loadstring(L, luaL_checkstring(L, 1))) {
return luaL_error(L, "lua.load error: %s", lua_tostring(L, -1));
}
return 1;
});
lua_setfield(L, -2, "load");
// pcall(func, args...) -> success, result
lua_pushcfunction(L, [](auto L) {
if (0 == lua_pcall(L, lua_gettop(L)-1, LUA_MULTRET, 0)) {
lua_pushboolean(L, true);
lua_insert(L, 1);
return lua_gettop(L);
} else {
lua_pushboolean(L, false);
lua_insert(L, 1);
return 2;
}
});
lua_setfield(L, -2, "pcall");
// ---- math lib ----
// sin(theta)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::sin(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "sin");
// cos(theta)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::cos(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "cos");
// tan(theta)
lua_pushcfunction(L, [](auto L) {
lua_pushnumber(L, std::tan(luaL_checknumber(L, 1)));
return 1;
});
lua_setfield(L, -2, "tan");
// ---- table lib ----
// meta(table, meta_table)
lua_pushcfunction(L, [](auto L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
});
lua_setfield(L, -2, "meta");
// ---- time lib ----
// now()
lua_pushcfunction(L, [](auto L) {
const auto now = nf7::Env::Clock::now().time_since_epoch();
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now);
lua_pushnumber(L, static_cast<double>(ms.count())/1000.);
return 1;
});
lua_setfield(L, -2, "now");
// ---- value lib ----
// value(entity) -> value
lua_pushcfunction(L, [](auto L) {
if (lua_isstring(L, 2)) {
const auto type = std::string_view {lua_tostring(L, 2)};
if (type == "integer" || type == "int") {
PushValue(L, static_cast<nf7::Value::Integer>(luaL_checkinteger(L, 1)));
} else {
return luaL_error(L, "unknown type specifier: %s", type);
}
} else {
PushValue(L, CheckValue(L, 1));
}
return 1;
});
lua_setfield(L, -2, "value");
// mvector(vector or mutable vector) -> mutable vector
lua_pushcfunction(L, [](auto L) {
if (auto imm = ToVector(L, 1)) {
if (imm->use_count() == 1) {
PushMutableVector(L, std::move(const_cast<std::vector<uint8_t>&>(**imm)));
} else {
PushMutableVector(L, std::vector<uint8_t> {**imm});
}
return 1;
} else if (auto mut = ToMutableVector(L, 1)) {
PushMutableVector(L, std::vector<uint8_t> {*mut});
return 1;
} else {
PushMutableVector(L, {});
return 1;
}
});
lua_setfield(L, -2, "mvector");
// ---- bit manip ----
luaL_openlibs(L);
luaL_loadstring(L, "return require(\"bit\")");
lua_call(L, 0, 1);
lua_setfield(L, -2, "bit");
}
lua_setfield(L, -2, "__index");
lua_setmetatable(L, -2);
}
} // namespace nf7::luajit

View File

@ -6,7 +6,7 @@
#include <unordered_set>
#include "common/node.hh"
#include "common/node_root_select_lambda.hh"
#include "common/node_root_lambda.hh"
namespace nf7::luajit {
@ -42,7 +42,7 @@ void Thread::Resume(lua_State* L, int narg) noexcept {
// set global table
PushGlobalTable(L);
PushWeakPtr(L, weak_from_this());
NewUserData<std::weak_ptr<Thread>>(L, weak_from_this());
PushMeta(L);
lua_setmetatable(L, -2);
lua_setfield(L, -2, "nf7");
@ -120,7 +120,10 @@ Thread::Handler Thread::CreateNodeLambdaHandler(
static void PushMeta(lua_State* L) noexcept {
if (luaL_newmetatable(L, Thread::kTypeName)) {
PushWeakPtrDeleter<Thread>(L);
lua_pushcfunction(L, [](auto L) {
CheckRef<std::weak_ptr<Thread>>(L, 1, Thread::kTypeName).~weak_ptr();
return 0;
});
lua_setfield(L, -2, "__gc");
lua_createtable(L, 0, 0);
@ -164,7 +167,7 @@ static void PushMeta(lua_State* L) noexcept {
auto& f = th->env().GetFileOrThrow(static_cast<nf7::File::Id>(id));
if (iface == "node") {
th->ExecResume(
L, nf7::NodeRootSelectLambda::Create(
L, nf7::NodeRootLambda::Create(
th->ctx(), f.template interfaceOrThrow<nf7::Node>()));
} else {
throw nf7::Exception {"unknown interface: "+iface};
@ -193,7 +196,7 @@ static void PushMeta(lua_State* L) noexcept {
// nf7:send(obj, params...)
lua_pushcfunction(L, [](auto L) {
auto th = Thread::GetPtr(L, 1);
auto la = luajit::CheckNodeRootSelectLambda(L, 2);
auto la = luajit::CheckNodeRootLambda(L, 2);
la->ExecSend(luaL_checkstring(L, 3), luajit::CheckValue(L, 4));
return 0;
});
@ -202,7 +205,7 @@ static void PushMeta(lua_State* L) noexcept {
// nf7:recv(obj, params...)
lua_pushcfunction(L, [](auto L) {
auto th = Thread::GetPtr(L, 1);
auto la = luajit::CheckNodeRootSelectLambda(L, 2);
auto la = luajit::CheckNodeRootLambda(L, 2);
std::unordered_set<std::string> names;
if (lua_istable(L, 3)) {

View File

@ -49,9 +49,14 @@ class Thread final : public std::enable_shared_from_this<Thread> {
// must be called on luajit thread
static std::shared_ptr<Thread> GetPtr(lua_State* L, int idx) {
auto th = CheckWeakPtr<Thread>(L, idx, kTypeName);
th->EnsureActive(L);
return th;
auto th = CheckRef<std::weak_ptr<Thread>>(L, idx, kTypeName).lock();
if (th) {
th->EnsureActive(L);
return th;
} else {
luaL_error(L, "thread expired");
return nullptr;
}
}
Thread() = delete;

View File

@ -19,14 +19,14 @@
namespace nf7 {
class NodeRootSelectLambda : public nf7::Node::Lambda,
public std::enable_shared_from_this<NodeRootSelectLambda> {
class NodeRootLambda : public nf7::Node::Lambda,
public std::enable_shared_from_this<NodeRootLambda> {
public:
using Pair = std::pair<std::string, nf7::Value>;
static std::shared_ptr<NodeRootSelectLambda> Create(
static std::shared_ptr<NodeRootLambda> Create(
const std::shared_ptr<nf7::Context>& ctx, nf7::Node& n) noexcept {
auto ret = std::make_shared<NodeRootSelectLambda>(ctx->env(), ctx->initiator(), ctx);
auto ret = std::make_shared<NodeRootLambda>(ctx->env(), ctx->initiator(), ctx);
ret->target_ = n.CreateLambda(ret);
return ret;
}

View File

@ -232,14 +232,14 @@ nf7::Future<std::shared_ptr<LuaNode::Meta>> LuaNode::Build() noexcept {
auto ret = std::make_shared<Meta>();
lua_getfield(L, 1, "inputs");
nf7::luajit::ToStringList(L, ret->inputs, -1);
nf7::luajit::ToStringList(L, -1, ret->inputs);
if (nf7::util::Uniq(ret->inputs) > 0) {
throw nf7::Exception {"duplicated inputs"};
}
lua_pop(L, 1);
lua_getfield(L, 1, "outputs");
nf7::luajit::ToStringList(L, ret->outputs, -1);
nf7::luajit::ToStringList(L, -1, ret->outputs);
if (nf7::util::Uniq(ret->outputs)) {
throw nf7::Exception {"duplicated outputs"};
}