From db7a20bd5ec9c005e6223e1f45ecbb1447675895 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Sat, 6 Jan 2024 12:44:41 +0100 Subject: [PATCH] Add exit function in core module. This function allow to interrupt the script execution. The parameter exit code is returned by pugs when leaving. --- doc/userdoc.org | 7 ++++++- src/language/PugsParser.cpp | 10 ++++++++-- src/language/modules/CoreModule.cpp | 16 ++++++++++++++++ src/language/utils/Exit.hpp | 29 +++++++++++++++++++++++++++++ src/main.cpp | 4 +++- src/utils/ExecutionStatManager.hpp | 15 +++++++++++++++ 6 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/language/utils/Exit.hpp diff --git a/doc/userdoc.org b/doc/userdoc.org index b50768b07..eaac7da46 100644 --- a/doc/userdoc.org +++ b/doc/userdoc.org @@ -2540,11 +2540,16 @@ to files for instance) as we will see below. **** ~core~ provided functions +***** ~exit: Z -> void~ + +This function interrupts the execution of the script. The integer (~Z~) +value is the code that is returned when ~pugs~ exits. + ***** ~getAvailableModules: void -> string~ This function that is used in the preamble of this section is a function that returns a ~string~ that contains the list of modules that -are available in the current version of pugs. +are available in the current version of ~pugs~. ***** ~getModuleInfo: string -> string~ diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index fbf7b60a2..603367fd6 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -17,9 +17,11 @@ #include <language/utils/ASTDotPrinter.hpp> #include <language/utils/ASTExecutionInfo.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/Exit.hpp> #include <language/utils/OperatorRepository.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/ConsoleManager.hpp> +#include <utils/ExecutionStatManager.hpp> #include <utils/PugsAssert.hpp> #include <utils/PugsUtils.hpp> #include <utils/SignalManager.hpp> @@ -89,8 +91,12 @@ parser(const std::string& filename) ASTExecutionInfo execution_info{*root_node, module_importer.moduleRepository()}; ExecutionPolicy exec_all; - root_node->execute(exec_all); - + try { + root_node->execute(exec_all); + } + catch (language::Exit& e) { + ExecutionStatManager::getInstance().setExitCode(e.code()); + } root_node->m_symbol_table->clearValues(); OperatorRepository::destroy(); diff --git a/src/language/modules/CoreModule.cpp b/src/language/modules/CoreModule.cpp index ff07fc9da..e9be93f3c 100644 --- a/src/language/modules/CoreModule.cpp +++ b/src/language/modules/CoreModule.cpp @@ -19,6 +19,7 @@ #include <language/utils/BinaryOperatorRegisterForString.hpp> #include <language/utils/BinaryOperatorRegisterForZ.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <language/utils/Exit.hpp> #include <language/utils/IncDecOperatorRegisterForN.hpp> #include <language/utils/IncDecOperatorRegisterForZ.hpp> #include <language/utils/OFStream.hpp> @@ -95,6 +96,21 @@ CoreModule::CoreModule() : BuiltinModule(true) )); + this->_addBuiltinFunction("exit", std::function( + + [](const int64_t& exit_code) -> void { + const auto& location = ASTBacktrace::getInstance().sourceLocation(); + std::cout << "\n** " << rang::fgB::yellow << "exit" << rang::fg::reset + << " explicitly called with code " << rang::fgB::cyan << exit_code + << rang::fg::reset << "\n from " << rang::style::underline + << location.filename() << rang::style::reset << ':' + << rang::fgB::yellow << location.line() << rang::fg::reset << '\n'; + + throw language::Exit(exit_code); + } + + )); + this->_addNameValue("cout", ast_node_data_type_from<std::shared_ptr<const OStream>>, EmbeddedData{std::make_shared<DataHandler<const OStream>>(std::make_shared<OStream>(std::cout))}); diff --git a/src/language/utils/Exit.hpp b/src/language/utils/Exit.hpp new file mode 100644 index 000000000..ec24402e8 --- /dev/null +++ b/src/language/utils/Exit.hpp @@ -0,0 +1,29 @@ +#ifndef EXIT_HPP +#define EXIT_HPP + +namespace language +{ + +class Exit +{ + private: + int m_code = 0; + + public: + int + code() const + { + return m_code; + } + + Exit(int code) : m_code{code} {} + + Exit(const Exit&) = default; + Exit(Exit&&) = default; + + ~Exit() = default; +}; + +} // namespace language + +#endif // EXIT_HPP diff --git a/src/main.cpp b/src/main.cpp index 7ee38e518..7d0112c80 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,7 +42,9 @@ main(int argc, char* argv[]) finalize(); ParallelChecker::destroy(); + + int return_code = ExecutionStatManager::getInstance().exitCode(); ExecutionStatManager::destroy(); - return 0; + return return_code; } diff --git a/src/utils/ExecutionStatManager.hpp b/src/utils/ExecutionStatManager.hpp index 6f7c33356..3738492a1 100644 --- a/src/utils/ExecutionStatManager.hpp +++ b/src/utils/ExecutionStatManager.hpp @@ -11,6 +11,7 @@ class ExecutionStatManager Timer m_elapse_time; bool m_do_print = true; + int m_exit_code = 0; std::string _prettyPrintTime(double seconds) const; @@ -38,6 +39,20 @@ class ExecutionStatManager m_do_print = do_print; } + PUGS_INLINE + int + exitCode() const + { + return m_exit_code; + } + + PUGS_INLINE + void + setExitCode(int exit_code) + { + m_exit_code = exit_code; + } + PUGS_INLINE static ExecutionStatManager& getInstance() -- GitLab