From d42d87280d101abb7452b6354606d5b1fcf4f420 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 6 Feb 2022 00:18:04 +0100 Subject: [PATCH] pattern: Allow pattern function code to be executed separately --- .../hex/pattern_language/evaluator.hpp | 12 +++++++-- .../hex/pattern_language/pattern_language.hpp | 3 ++- .../source/pattern_language/evaluator.cpp | 9 ++----- .../pattern_language/pattern_language.cpp | 27 +++++++++++++++++-- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/libimhex/include/hex/pattern_language/evaluator.hpp b/lib/libimhex/include/hex/pattern_language/evaluator.hpp index 9fc1a70ca..7f9ec8b46 100644 --- a/lib/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/lib/libimhex/include/hex/pattern_language/evaluator.hpp @@ -19,13 +19,15 @@ namespace hex::prv { namespace hex::pl { - enum class DangerousFunctionPermission { + enum class DangerousFunctionPermission + { Ask, Deny, Allow }; - enum class ControlFlowStatement { + enum class ControlFlowStatement + { None, Continue, Break, @@ -230,6 +232,10 @@ namespace hex::pl { return this->m_currControlFlowStatement; } + [[nodiscard]] std::optional getMainResult() { + return this->m_mainResult; + } + private: void patternCreated(); void patternDestroyed(); @@ -254,6 +260,8 @@ namespace hex::pl { std::vector m_customFunctionDefinitions; std::vector m_stack; + std::optional m_mainResult; + std::map m_envVariables; std::map m_inVariables; std::map m_outVariables; diff --git a/lib/libimhex/include/hex/pattern_language/pattern_language.hpp b/lib/libimhex/include/hex/pattern_language/pattern_language.hpp index 198693499..0929e213f 100644 --- a/lib/libimhex/include/hex/pattern_language/pattern_language.hpp +++ b/lib/libimhex/include/hex/pattern_language/pattern_language.hpp @@ -33,8 +33,9 @@ namespace hex::pl { ~PatternLanguage(); [[nodiscard]] std::optional> parseString(const std::string &code); - [[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map &envVars = {}, const std::map &inVariables = {}); + [[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map &envVars = {}, const std::map &inVariables = {}, bool checkResult = true); [[nodiscard]] bool executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars = {}, const std::map &inVariables = {}); + [[nodiscard]] std::pair> executeFunction(prv::Provider *provider, const std::string &code); [[nodiscard]] const std::vector &getCurrentAST() const; void abort(); diff --git a/lib/libimhex/source/pattern_language/evaluator.cpp b/lib/libimhex/source/pattern_language/evaluator.cpp index 06f966d11..4af32de21 100644 --- a/lib/libimhex/source/pattern_language/evaluator.cpp +++ b/lib/libimhex/source/pattern_language/evaluator.cpp @@ -132,6 +132,7 @@ namespace hex::pl { this->m_stack.clear(); this->m_customFunctions.clear(); this->m_scopes.clear(); + this->m_mainResult.reset(); this->m_aborted = false; if (this->m_allowDangerousFunctions == DangerousFunctionPermission::Deny) @@ -192,13 +193,7 @@ namespace hex::pl { if (mainFunction.parameterCount > 0) LogConsole::abortEvaluation("main function may not accept any arguments"); - auto result = mainFunction.func(this, {}); - if (result) { - auto returnCode = Token::literalToSigned(*result); - - if (returnCode != 0) - LogConsole::abortEvaluation(hex::format("non-success value returned from main: {}", returnCode)); - } + this->m_mainResult = mainFunction.func(this, {}); } popScope(); diff --git a/lib/libimhex/source/pattern_language/pattern_language.cpp b/lib/libimhex/source/pattern_language/pattern_language.cpp index 92ab2dced..c883fc925 100644 --- a/lib/libimhex/source/pattern_language/pattern_language.cpp +++ b/lib/libimhex/source/pattern_language/pattern_language.cpp @@ -123,7 +123,7 @@ namespace hex::pl { return ast; } - bool PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map &envVars, const std::map &inVariables) { + bool PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map &envVars, const std::map &inVariables, bool checkResult) { this->m_running = true; ON_SCOPE_EXIT { this->m_running = false; }; @@ -156,6 +156,19 @@ namespace hex::pl { return false; } + if (auto mainResult = this->m_evaluator->getMainResult(); checkResult && mainResult.has_value()) { + auto returnCode = Token::literalToSigned(*mainResult); + + if (returnCode != 0) { + auto errorMessage = hex::format("non-success value returned from main: {}", returnCode); + + this->m_evaluator->getConsole().log(LogConsole::Level::Error, errorMessage); + this->m_currError = PatternLanguageError(0, errorMessage); + + return false; + } + } + this->m_patterns = std::move(patterns.value()); return true; @@ -164,7 +177,17 @@ namespace hex::pl { bool PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map &envVars, const std::map &inVariables) { File file(path, File::Mode::Read); - return this->executeString(provider, file.readString(), envVars, inVariables); + return this->executeString(provider, file.readString(), envVars, inVariables, true); + } + + std::pair> PatternLanguage::executeFunction(prv::Provider *provider, const std::string &code) { + + auto functionContent = hex::format("fn main() {{ {0} }};", code); + + auto success = this->executeString(provider, functionContent, {}, {}, false); + auto result = this->m_evaluator->getMainResult(); + + return { success, result }; } void PatternLanguage::abort() {