Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 369cb617 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

[WIP] SCRIPT: Begin the module validation process

parent 9b0d033e
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!16Add a way to execute a Lua file with Vivy in a click-click way
#include "CRTPLuaScriptObject.hh"
#include "lua.hpp"
#include <QFileInfo>
#include <QString>
using namespace Vivy::Script;
......@@ -64,15 +66,12 @@ int
ModuleDeclaration::setImports(lua_State *const L) noexcept
{
auto *const self = ModuleDeclaration::CHECK(L, 1);
auto *const context = LuaContext::getContext(L);
IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool {
IterateOverArray(L, 2, [self, L]() noexcept -> bool {
std::string import(CHECK_STRING_VIEW(L, -1));
Utils::trim(import);
self->importNames.emplace_back(import);
err(context) << "Add import " << import << " for module " << self->moduleName << "\n";
return false; // Value was not popped from stack!
});
err(context) << "Imports done!\n";
LUA_RETURN_NOTHING(L);
}
......@@ -80,15 +79,12 @@ int
ModuleDeclaration::setOptions(lua_State *const L) noexcept
{
auto *const self = ModuleDeclaration::CHECK(L, 1);
auto *const context = LuaContext::getContext(L);
IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool {
IterateOverArray(L, 2, [self, L]() noexcept -> bool {
OptionDeclaration *const opt = OptionDeclaration::CHECK(L, -1);
self->moduleOptions.emplace_back(opt);
err(context) << "Add option for module " << self->moduleName << "\n";
self->addUserValue(L, 1); // Tie the opt to the module
return true; // The value was popped from the stack
});
err(context) << "Options done!\n";
LUA_RETURN_NOTHING(L);
}
......@@ -96,15 +92,12 @@ int
ModuleDeclaration::setFunctions(lua_State *const L) noexcept
{
auto *const self = ModuleDeclaration::CHECK(L, 1);
auto *const context = LuaContext::getContext(L);
IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool {
IterateOverArray(L, 2, [self, L]() noexcept -> bool {
FunctionDeclaration *const fun = FunctionDeclaration::CHECK(L, -1);
self->moduleFunctions.emplace_back(fun);
err(context) << "Add function " << fun->name << " to module " << self->moduleName << "\n";
self->addUserValue(L, 1); // Tie the function to the module
return true; // The value was popped from the stack
});
err(context) << "Functions done!\n";
LUA_RETURN_NOTHING(L);
}
......@@ -112,15 +105,12 @@ int
ModuleDeclaration::setJobs(lua_State *const L) noexcept
{
auto *const self = ModuleDeclaration::CHECK(L, 1);
auto *const context = LuaContext::getContext(L);
IterateOverArray(L, 2, [&context, self, L]() noexcept -> bool {
IterateOverArray(L, 2, [self, L]() noexcept -> bool {
JobDeclaration *const job = JobDeclaration::CHECK(L, -1);
self->moduleJobs.emplace_back(job);
err(context) << "Add job " << job->name << " to module " << self->moduleName << "\n";
self->addUserValue(L, 1); // Tie the job to the module
return true; // The value was popped from the stack
});
err(context) << "Jobs done!\n";
LUA_RETURN_NOTHING(L);
}
......@@ -129,12 +119,66 @@ ModuleDeclaration::pushToRuntime(lua_State *const L) noexcept
{
ModuleDeclaration *const self = CHECK(L, 1);
auto *const context = LuaContext::getContext(L);
Utils::uniqAndSort<std::string>(self->importNames);
if (self->validateModule(L)) {
err(context) << "Register module \"" << self->moduleName << "\" in the runtime!\n";
lua_settop(L, 1);
context->registerModuleDeclaration(self);
if (context->registerModuleDeclaration(self) == LuaContext::Code::Error)
context->setFailed("Failed to register module " + self->moduleName);
}
else
context->setFailed("Module " + self->moduleName + " is invalid");
LUA_RETURN_NOTHING(L);
}
bool
ModuleDeclaration::validateModule(lua_State *const L) const noexcept
{
auto *const context = LuaContext::getContext(L);
// Minimal module file
if (moduleName.empty() || authorName.empty() || implementationFile.empty()) {
context->setFailed("The module does not have the minimal required information");
return false;
}
// Implementation file exists, relative to the .module file
{
QString moduleFile = context->getCurrentLuaFile().c_str();
QFileInfo moduleInfo(moduleFile);
QFileInfo fileInfo(moduleInfo.absoluteDir(), implementationFile.c_str());
if (!fileInfo.exists()) {
context->setFailed("The module " + moduleName +
" does not have a valid implementation file");
return false;
}
}
// Imports
{
std::vector<std::string> usedImports{};
const auto getUsedImports = [&usedImports](auto vectorOfPtr) noexcept -> void {
for (const auto *ptr : vectorOfPtr) {
if (!ptr->parentScript.empty())
usedImports.emplace_back(ptr->parentScript);
}
};
getUsedImports(moduleJobs);
getUsedImports(moduleFunctions);
Utils::uniqAndSort<std::string>(usedImports);
std::vector<std::string> unusedImports =
Utils::sortedSetDifference(usedImports, importNames);
}
return true;
}
// OptionDeclaration
int
......
......@@ -251,6 +251,8 @@ script_class (ModuleDeclaration) {
// Will be resolved later
std::vector<std::string> importNames{};
bool validateModule(lua_State *const) const noexcept;
public:
std::string moduleName{};
std::string authorName{};
......
......@@ -41,10 +41,12 @@ LuaContext::~LuaContext() noexcept
void
LuaContext::loadPackagedFile(const QString &url) noexcept
{
currentFile = url.toStdString();
QFile libVivy(url);
if (!libVivy.open(QIODevice::ReadOnly | QIODevice::Text))
qFatal("FATA -> failed to find packaged Vivy file %s", url.toStdString().c_str());
loadString(libVivy.readAll().toStdString().c_str());
currentFile = "";
}
LuaContext *
......@@ -95,11 +97,15 @@ LuaContext::loadString(const char *str) noexcept
LuaContext::Code
LuaContext::loadFile(const char *file) noexcept
{
currentFile = file;
if (luaL_loadfile(L, file) != LUA_OK) {
err(this) << "Error loading file " << file << ": " << getLastError().toStdString() << "\n";
currentFile = "";
return Code::Error;
}
return exec();
auto rc = exec();
currentFile = "";
return rc;
}
QString
......@@ -166,3 +172,30 @@ LuaContext::getAllModuleName() const noexcept
moduleNames.emplace_back(name);
return moduleNames;
}
void
LuaContext::setFailed(const std::string &msg) noexcept
{
failureString = msg;
streamErr << "LuaContext is now in failure state: " << msg;
}
bool
LuaContext::isFailed() const noexcept
{
return failureString.empty();
}
const std::string &
LuaContext::getFailureDescription() const noexcept
{
return failureString;
}
const std::string &
LuaContext::getCurrentLuaFile() const
{
if (currentFile.empty())
throw std::logic_error("Not called when a file is being evaluated");
return currentFile;
}
......@@ -23,6 +23,8 @@ namespace Vivy::Script
// New Lua script instance
class LuaContext final {
lua_State *L{ nullptr };
std::string failureString{};
std::string currentFile{};
std::map<const std::string_view, const int> modules = {};
static inline std::map<const lua_State *const, LuaContext *const> contextList = {};
......@@ -55,9 +57,15 @@ public:
// Returns the module or `nullptr` if not found.
const ModuleDeclaration *getModule(const std::string_view) const noexcept;
const std::vector<std::string_view> getAllModuleName() const noexcept;
void setFailed(const std::string &) noexcept;
bool isFailed() const noexcept;
const std::string &getFailureDescription() const noexcept;
// Makes only sens when called from within loadFile and loadPackagedFile
const std::string &getCurrentLuaFile() const;
private:
// Exec all loaded strings and files
Code exec() noexcept;
......
......@@ -64,3 +64,9 @@ ScriptStore::getLoadedModules() const noexcept
else
return {};
}
const Script::ModuleDeclaration *
ScriptStore::getModule(const std::string_view str) const noexcept
{
return luaContext->getModule(str);
}
......@@ -7,6 +7,7 @@
namespace Vivy::Script
{
class LuaContext;
class ModuleDeclaration;
}
namespace Vivy
......@@ -30,6 +31,7 @@ public:
// Get modules from scripts
const std::vector<std::string_view> getLoadedModules() const noexcept;
const Script::ModuleDeclaration *getModule(const std::string_view) const noexcept;
private:
std::unique_ptr<Script::LuaContext> luaContext{ nullptr };
......
......@@ -18,6 +18,7 @@ VivyCli::exec() noexcept
scriptStore.executeScript(selectedDoc->getUuid());
for (const auto &str : scriptStore.getLoadedModules()) {
std::cout << "Module " << str << " was loaded!\n";
const auto *mod = scriptStore.getModule(str);
}
return 0;
}
......@@ -3,14 +3,6 @@ custom_opt = DeclareOption { option1 = false }
time_opt = DeclareOption { preTime = -900, postTime = 300, }
color_opt = DeclareOption { color1 = Vivy:newColor("#314159") }
job1 = DeclareJob { "set_retime", options = { time_opt } }
job2 = DeclareJob { "demultiply_syllabes" }
job3 = ImportJob { "utils", "color_after_read_3", options = { color_opt } }
fun1 = DeclareFunction { "tripleCopySyl" }
fun2 = DeclareFunction { "printFoo" }
fun3 = ImportFunction { "utils", "prettyPrint" }
DeclareModule {
name = "sample-spec",
description = "Sample script used for the specification proposition",
......@@ -19,6 +11,14 @@ DeclareModule {
revision = "rev-1254",
imports = { "utils" },
options = { custom_opt, time_opt, color_opt },
functions = { fun1, fun2, fun3 },
jobs = { job1, job2, job3 },
functions = {
DeclareFunction { "tripleCopySyl" },
DeclareFunction { "printFoo" },
ImportFunction { "utils", "prettyPrint" },
},
jobs = {
DeclareJob { "set_retime", options = { time_opt } },
DeclareJob { "demultiply_syllabes" },
ImportJob { "utils", "color_after_read_3", options = { color_opt } },
},
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter