From a04286a83e3320caf90701cd71190248f3aa82f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Tue, 10 Nov 2020 14:38:07 +0100 Subject: [PATCH] Add the CoreModule This is a special module that is *always* imported For this first version of the module we have three functions: getAvailableModules() -> string which returns the list of available pugs modules getPugsVersion() -> string getPugsBuildInfo() -> string which are moved from the 'utils' module There is no need to use `import core` in the preamble of a pugs script file. --- src/language/PugsParser.cpp | 4 +- src/language/ast/ASTModulesImporter.cpp | 2 + src/language/ast/ASTModulesImporter.hpp | 6 +++ src/language/modules/CMakeLists.txt | 1 + src/language/modules/CoreModule.cpp | 33 ++++++++++++++++ src/language/modules/CoreModule.hpp | 19 +++++++++ src/language/modules/ModuleRepository.cpp | 47 +++++++++++++++++++---- src/language/modules/ModuleRepository.hpp | 6 ++- src/language/modules/UtilsModule.cpp | 15 +------- src/language/utils/ASTExecutionInfo.cpp | 3 +- src/language/utils/ASTExecutionInfo.hpp | 11 +++++- 11 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 src/language/modules/CoreModule.cpp create mode 100644 src/language/modules/CoreModule.hpp diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index 0294206b7..ed00e3032 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -50,7 +50,7 @@ parser(const std::string& filename) auto parse_and_execute = [](auto& input) { std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input); - ASTModulesImporter{*root_node}; + ASTModulesImporter module_importer{*root_node}; ASTNodeTypeCleaner<language::import_instruction>{*root_node}; ASTSymbolTableBuilder{*root_node}; @@ -75,7 +75,7 @@ parser(const std::string& filename) std::cout << "-------------------------------------------------------\n"; std::cout << rang::style::bold << "Executing AST..." << rang::style::reset << '\n'; - ASTExecutionInfo execution_info{*root_node}; + ASTExecutionInfo execution_info{*root_node, module_importer.moduleRepository()}; ExecutionPolicy exec_all; root_node->execute(exec_all); diff --git a/src/language/ast/ASTModulesImporter.cpp b/src/language/ast/ASTModulesImporter.cpp index 197f9dcdd..5ef3b5804 100644 --- a/src/language/ast/ASTModulesImporter.cpp +++ b/src/language/ast/ASTModulesImporter.cpp @@ -37,6 +37,8 @@ ASTModulesImporter::_importAllModules(ASTNode& node) ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*root_node.m_symbol_table} { Assert(root_node.is_root()); + m_module_repository.populateCoreSymbolTable(root_node, m_symbol_table); + this->_importAllModules(root_node); std::cout << " - loaded modules\n"; } diff --git a/src/language/ast/ASTModulesImporter.hpp b/src/language/ast/ASTModulesImporter.hpp index 2b8c081fd..566155c4a 100644 --- a/src/language/ast/ASTModulesImporter.hpp +++ b/src/language/ast/ASTModulesImporter.hpp @@ -20,6 +20,12 @@ class ASTModulesImporter void _importAllModules(ASTNode& node); public: + const ModuleRepository& + moduleRepository() const + { + return m_module_repository; + } + ASTModulesImporter(ASTNode& root_node); ASTModulesImporter(const ASTModulesImporter&) = delete; diff --git a/src/language/modules/CMakeLists.txt b/src/language/modules/CMakeLists.txt index cd4c99bd8..020727478 100644 --- a/src/language/modules/CMakeLists.txt +++ b/src/language/modules/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(PugsLanguageModules BuiltinModule.cpp + CoreModule.cpp LinearSolverModule.cpp MathModule.cpp MeshModule.cpp diff --git a/src/language/modules/CoreModule.cpp b/src/language/modules/CoreModule.cpp new file mode 100644 index 000000000..c9a214306 --- /dev/null +++ b/src/language/modules/CoreModule.cpp @@ -0,0 +1,33 @@ +#include <language/modules/CoreModule.hpp> + +#include <language/modules/CoreModule.hpp> +#include <language/modules/ModuleRepository.hpp> +#include <language/utils/ASTExecutionInfo.hpp> +#include <language/utils/BuiltinFunctionEmbedder.hpp> +#include <utils/PugsUtils.hpp> + +CoreModule::CoreModule() +{ + this->_addBuiltinFunction("getPugsVersion", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>( + + []() -> std::string { return pugsVersion(); } + + )); + + this->_addBuiltinFunction("getPugsBuildInfo", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>( + + []() -> std::string { return pugsBuildInfo(); } + + )); + + this->_addBuiltinFunction("getAvailableModules", std::make_shared<BuiltinFunctionEmbedder<std::string()>>( + + []() -> std::string { + const ModuleRepository& repository = + ASTExecutionInfo::current().moduleRepository(); + + return repository.getAvailableModules(); + } + + )); +} diff --git a/src/language/modules/CoreModule.hpp b/src/language/modules/CoreModule.hpp new file mode 100644 index 000000000..963719be2 --- /dev/null +++ b/src/language/modules/CoreModule.hpp @@ -0,0 +1,19 @@ +#ifndef CORE_MODULE_HPP +#define CORE_MODULE_HPP + +#include <language/modules/BuiltinModule.hpp> + +class CoreModule : public BuiltinModule +{ + public: + std::string_view + name() const final + { + return "core"; + } + + CoreModule(); + ~CoreModule() = default; +}; + +#endif // CORE_MODULE_HPP diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp index 83d44b23e..1fff5dda8 100644 --- a/src/language/modules/ModuleRepository.cpp +++ b/src/language/modules/ModuleRepository.cpp @@ -1,6 +1,7 @@ #include <language/modules/ModuleRepository.hpp> #include <language/ast/ASTNode.hpp> +#include <language/modules/CoreModule.hpp> #include <language/modules/LinearSolverModule.hpp> #include <language/modules/MathModule.hpp> #include <language/modules/MeshModule.hpp> @@ -21,6 +22,7 @@ ModuleRepository::_subscribe(std::unique_ptr<IModule> m) ModuleRepository::ModuleRepository() { + this->_subscribe(std::make_unique<CoreModule>()); this->_subscribe(std::make_unique<LinearSolverModule>()); this->_subscribe(std::make_unique<MathModule>()); this->_subscribe(std::make_unique<MeshModule>()); @@ -31,22 +33,21 @@ ModuleRepository::ModuleRepository() template <typename NameEmbedderMapT, typename EmbedderTableT> void -ModuleRepository::_populateEmbedderTableT(const ASTNode& module_name_node, +ModuleRepository::_populateEmbedderTableT(const ASTNode& module_node, + const std::string& module_name, const NameEmbedderMapT& name_embedder_map, const ASTNodeDataType& data_type, SymbolTable& symbol_table, EmbedderTableT& embedder_table) { - const std::string& module_name = module_name_node.string(); - for (auto [symbol_name, embedded] : name_embedder_map) { - auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin()); + auto [i_symbol, success] = symbol_table.add(symbol_name, module_node.begin()); if (not success) { std::ostringstream error_message; error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name << "', it is already defined!"; - throw ParseError(error_message.str(), module_name_node.begin()); + throw ParseError(error_message.str(), module_node.begin()); } i_symbol->attributes().setDataType(data_type); @@ -66,14 +67,46 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab if (i_module != m_module_set.end()) { const IModule& populating_module = *i_module->second; - this->_populateEmbedderTableT(module_name_node, populating_module.getNameBuiltinFunctionMap(), + this->_populateEmbedderTableT(module_name_node, module_name, populating_module.getNameBuiltinFunctionMap(), ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(), symbol_table, symbol_table.builtinFunctionEmbedderTable()); - this->_populateEmbedderTableT(module_name_node, populating_module.getNameTypeMap(), + this->_populateEmbedderTableT(module_name_node, module_name, populating_module.getNameTypeMap(), ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table, symbol_table.typeEmbedderTable()); } else { throw ParseError(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()}); } } + +void +ModuleRepository::populateCoreSymbolTable(const ASTNode& root_node, SymbolTable& symbol_table) +{ + const std::string& module_name = "core"; + + auto i_module = m_module_set.find(module_name); + if (i_module != m_module_set.end()) { + const IModule& populating_module = *i_module->second; + + this->_populateEmbedderTableT(root_node, module_name, populating_module.getNameBuiltinFunctionMap(), + ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(), symbol_table, + symbol_table.builtinFunctionEmbedderTable()); + + this->_populateEmbedderTableT(root_node, module_name, populating_module.getNameTypeMap(), + ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table, + symbol_table.typeEmbedderTable()); + } else { + throw ParseError(std::string{"could not find module "} + module_name, std::vector{root_node.begin()}); + } +} + +std::string +ModuleRepository::getAvailableModules() const +{ + std::stringstream os; + os << rang::fgB::yellow << "Available modules" << rang::style::reset << '\n'; + for (auto& [name, i_module] : m_module_set) { + os << " " << rang::fg::green << name << rang::style::reset << '\n'; + } + return os.str(); +} diff --git a/src/language/modules/ModuleRepository.hpp b/src/language/modules/ModuleRepository.hpp index f928a1552..b6983eb54 100644 --- a/src/language/modules/ModuleRepository.hpp +++ b/src/language/modules/ModuleRepository.hpp @@ -19,7 +19,8 @@ class ModuleRepository void _subscribe(std::unique_ptr<IModule> a); template <typename NameEmbedderMapT, typename EmbedderTableT> - void _populateEmbedderTableT(const ASTNode& module_name_node, + void _populateEmbedderTableT(const ASTNode& module_node, + const std::string& module_name, const NameEmbedderMapT& name_embedder_map, const ASTNodeDataType& data_type, SymbolTable& symbol_table, @@ -27,6 +28,9 @@ class ModuleRepository public: void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table); + void populateCoreSymbolTable(const ASTNode& root_node, SymbolTable& symbol_table); + + std::string getAvailableModules() const; const ModuleRepository& operator=(const ModuleRepository&) = delete; const ModuleRepository& operator=(ModuleRepository&&) = delete; diff --git a/src/language/modules/UtilsModule.cpp b/src/language/modules/UtilsModule.cpp index 90845af9a..8b2271158 100644 --- a/src/language/modules/UtilsModule.cpp +++ b/src/language/modules/UtilsModule.cpp @@ -5,22 +5,11 @@ #include <language/utils/ASTPrinter.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/SymbolTable.hpp> -#include <utils/PugsUtils.hpp> + +#include <fstream> UtilsModule::UtilsModule() { - this->_addBuiltinFunction("getPugsVersion", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>( - - []() -> std::string { return pugsVersion(); } - - )); - - this->_addBuiltinFunction("getPugsBuildInfo", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>( - - []() -> std::string { return pugsBuildInfo(); } - - )); - this->_addBuiltinFunction("getAST", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>( []() -> std::string { diff --git a/src/language/utils/ASTExecutionInfo.cpp b/src/language/utils/ASTExecutionInfo.cpp index c0327d501..6015b6a8f 100644 --- a/src/language/utils/ASTExecutionInfo.cpp +++ b/src/language/utils/ASTExecutionInfo.cpp @@ -4,7 +4,8 @@ const ASTExecutionInfo* ASTExecutionInfo::m_current_execution_info = nullptr; -ASTExecutionInfo::ASTExecutionInfo(const ASTNode& root_node) : m_root_node(root_node) +ASTExecutionInfo::ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_repository) + : m_root_node{root_node}, m_module_repository{module_repository} { Assert(m_current_execution_info == nullptr, "Can only define one ASTExecutionInfo"); diff --git a/src/language/utils/ASTExecutionInfo.hpp b/src/language/utils/ASTExecutionInfo.hpp index 90baa8a6f..96fc874ce 100644 --- a/src/language/utils/ASTExecutionInfo.hpp +++ b/src/language/utils/ASTExecutionInfo.hpp @@ -3,6 +3,7 @@ #include <string> +class ModuleRepository; class ASTNode; class ASTExecutionInfo { @@ -11,10 +12,12 @@ class ASTExecutionInfo const ASTNode& m_root_node; + const ModuleRepository& m_module_repository; + // The only place where the ASTExecutionInfo can be built friend void parser(const std::string& filename); - ASTExecutionInfo(const ASTNode& root_node); + ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_repository); public: const ASTNode& @@ -23,6 +26,12 @@ class ASTExecutionInfo return m_root_node; } + const ModuleRepository& + moduleRepository() const + { + return m_module_repository; + } + static const ASTExecutionInfo& current(); ASTExecutionInfo() = delete; -- GitLab