pattern: Allow pattern function code to be executed separately
This commit is contained in:
parent
b8026398e0
commit
d42d87280d
@ -19,13 +19,15 @@ namespace hex::prv {
|
|||||||
|
|
||||||
namespace hex::pl {
|
namespace hex::pl {
|
||||||
|
|
||||||
enum class DangerousFunctionPermission {
|
enum class DangerousFunctionPermission
|
||||||
|
{
|
||||||
Ask,
|
Ask,
|
||||||
Deny,
|
Deny,
|
||||||
Allow
|
Allow
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ControlFlowStatement {
|
enum class ControlFlowStatement
|
||||||
|
{
|
||||||
None,
|
None,
|
||||||
Continue,
|
Continue,
|
||||||
Break,
|
Break,
|
||||||
@ -230,6 +232,10 @@ namespace hex::pl {
|
|||||||
return this->m_currControlFlowStatement;
|
return this->m_currControlFlowStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<Token::Literal> getMainResult() {
|
||||||
|
return this->m_mainResult;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void patternCreated();
|
void patternCreated();
|
||||||
void patternDestroyed();
|
void patternDestroyed();
|
||||||
@ -254,6 +260,8 @@ namespace hex::pl {
|
|||||||
std::vector<ASTNode *> m_customFunctionDefinitions;
|
std::vector<ASTNode *> m_customFunctionDefinitions;
|
||||||
std::vector<Token::Literal> m_stack;
|
std::vector<Token::Literal> m_stack;
|
||||||
|
|
||||||
|
std::optional<Token::Literal> m_mainResult;
|
||||||
|
|
||||||
std::map<std::string, Token::Literal> m_envVariables;
|
std::map<std::string, Token::Literal> m_envVariables;
|
||||||
std::map<std::string, Token::Literal> m_inVariables;
|
std::map<std::string, Token::Literal> m_inVariables;
|
||||||
std::map<std::string, size_t> m_outVariables;
|
std::map<std::string, size_t> m_outVariables;
|
||||||
|
@ -33,8 +33,9 @@ namespace hex::pl {
|
|||||||
~PatternLanguage();
|
~PatternLanguage();
|
||||||
|
|
||||||
[[nodiscard]] std::optional<std::vector<ASTNode *>> parseString(const std::string &code);
|
[[nodiscard]] std::optional<std::vector<ASTNode *>> parseString(const std::string &code);
|
||||||
[[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {});
|
[[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {}, bool checkResult = true);
|
||||||
[[nodiscard]] bool executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {});
|
[[nodiscard]] bool executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {});
|
||||||
|
[[nodiscard]] std::pair<bool, std::optional<Token::Literal>> executeFunction(prv::Provider *provider, const std::string &code);
|
||||||
[[nodiscard]] const std::vector<ASTNode *> &getCurrentAST() const;
|
[[nodiscard]] const std::vector<ASTNode *> &getCurrentAST() const;
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
|
@ -132,6 +132,7 @@ namespace hex::pl {
|
|||||||
this->m_stack.clear();
|
this->m_stack.clear();
|
||||||
this->m_customFunctions.clear();
|
this->m_customFunctions.clear();
|
||||||
this->m_scopes.clear();
|
this->m_scopes.clear();
|
||||||
|
this->m_mainResult.reset();
|
||||||
this->m_aborted = false;
|
this->m_aborted = false;
|
||||||
|
|
||||||
if (this->m_allowDangerousFunctions == DangerousFunctionPermission::Deny)
|
if (this->m_allowDangerousFunctions == DangerousFunctionPermission::Deny)
|
||||||
@ -192,13 +193,7 @@ namespace hex::pl {
|
|||||||
if (mainFunction.parameterCount > 0)
|
if (mainFunction.parameterCount > 0)
|
||||||
LogConsole::abortEvaluation("main function may not accept any arguments");
|
LogConsole::abortEvaluation("main function may not accept any arguments");
|
||||||
|
|
||||||
auto result = mainFunction.func(this, {});
|
this->m_mainResult = mainFunction.func(this, {});
|
||||||
if (result) {
|
|
||||||
auto returnCode = Token::literalToSigned(*result);
|
|
||||||
|
|
||||||
if (returnCode != 0)
|
|
||||||
LogConsole::abortEvaluation(hex::format("non-success value returned from main: {}", returnCode));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
popScope();
|
popScope();
|
||||||
|
@ -123,7 +123,7 @@ namespace hex::pl {
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables) {
|
bool PatternLanguage::executeString(prv::Provider *provider, const std::string &code, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables, bool checkResult) {
|
||||||
this->m_running = true;
|
this->m_running = true;
|
||||||
ON_SCOPE_EXIT { this->m_running = false; };
|
ON_SCOPE_EXIT { this->m_running = false; };
|
||||||
|
|
||||||
@ -156,6 +156,19 @@ namespace hex::pl {
|
|||||||
return false;
|
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());
|
this->m_patterns = std::move(patterns.value());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -164,7 +177,17 @@ namespace hex::pl {
|
|||||||
bool PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables) {
|
bool PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables) {
|
||||||
File file(path, File::Mode::Read);
|
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<bool, std::optional<Token::Literal>> 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() {
|
void PatternLanguage::abort() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user