init project

This commit is contained in:
Timofey Khoruzhii 2023-04-16 00:23:12 +03:00
commit 821ea7eed0
16 changed files with 950 additions and 0 deletions

154
src/lua/loader.cpp Normal file
View file

@ -0,0 +1,154 @@
#include <cstdlib>
#include <iostream>
#include <lua/loader.hpp>
#include <stdexcept>
LuaLoader::LuaLoader() : L(luaL_newstate()) {
luaL_openlibs(L);
AddLuaPath("./?.lua");
AddCPath("./?.so");
AddCPath("./?.dylib");
}
void LuaLoader::AddLuaPath(const std::string& new_path) {
lua_getglobal(L, "package");
lua_getfield(L, -1, "path");
lua_pushstring(L, (std::string(";") + new_path).data());
lua_concat(L, 2);
lua_setfield(L, -2, "path");
lua_pop(L, 1);
}
void LuaLoader::AddCPath(const std::string& new_path) {
lua_getglobal(L, "package");
lua_getfield(L, -1, "cpath");
lua_pushstring(L, (std::string(";") + new_path).data());
lua_concat(L, 2);
lua_setfield(L, -2, "cpath");
lua_pop(L, 1);
}
void LuaLoader::LoadImpl(const std::string& name) {
lua_getglobal(L, "require");
lua_pushstring(L, name.data());
if (lua_pcall(L, 1, 1, 0) != LUA_OK) {
std::cerr << "Error call script: " << name.data() << std::endl;
std::cerr << lua_tostring(L, -1) << std::endl;
throw std::logic_error("Error call script: " + name);
}
ParseRequire();
ParseImport();
}
void LuaLoader::LoadToGlobal(const std::string& name) {
LoadImpl(name);
lua_setglobal(L, name.data());
}
std::vector<std::string> LuaLoader::GetListScripts(const std::string& lua_module) const {
std::vector<std::string> result;
lua_getglobal(L, lua_module.data());
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
continue;
}
lua_pop(L, 1);
result.push_back(lua_tostring(L, -1));
}
lua_pop(L, 1);
return result;
}
void LuaLoader::ForEachByStringArray(std::function<void(const std::string&)> callback) {
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
return;
}
if (lua_isstring(L, -1)) {
callback(lua_tostring(L, -1));
lua_pop(L, 1);
return;
} else if (lua_istable(L, -1)) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
if (!lua_isstring(L, -1)) {
throw std::logic_error("Error in for each by string array");
}
callback(lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_pop(L, 1);
return;
}
throw std::logic_error("Error in parse requires ");
}
void LuaLoader::ParseRequire() {
if (!lua_istable(L, -1)) {
return;
}
lua_getfield(L, -1, "require");
ForEachByStringArray(
[this](const std::string& new_module_name) { LoadToGlobal(new_module_name); });
}
void LuaLoader::Import(const std::string& name, const std::string& field, int table) {
LoadImpl(name);
lua_getfield(L, -1, field.data());
lua_setfield(L, table, field.data());
lua_pop(L, 1);
}
void LuaLoader::ParseImport() {
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return;
}
lua_getfield(L, -1, "import");
ForEachByStringArray([this, table = lua_absindex(L, -2)](const std::string& new_module_name) {
int dot_position = new_module_name.find(".");
if (dot_position == std::string::npos) {
throw std::logic_error("Can't find dot in import");
}
Import(new_module_name.substr(0, dot_position), new_module_name.substr(dot_position + 1),
table);
});
}
void LuaLoader::Call(const std::string& lua_module, const std::string& function) {
lua_getglobal(L, lua_module.data());
lua_getfield(L, -1, function.data());
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
std::cout << "Error in call " << lua_module << "." << function << std::endl;
std::cerr << lua_tostring(L, -1) << std::endl;
throw std::logic_error("Error in call " + lua_module + "." + function);
}
lua_pop(L, 1);
}
LuaLoader::~LuaLoader() {
lua_close(L);
}