Skip to content
Snippets Groups Projects
Commit a04286a8 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

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.
parent 45557637
No related branches found
No related tags found
1 merge request!67Feature/inline help
...@@ -50,7 +50,7 @@ parser(const std::string& filename) ...@@ -50,7 +50,7 @@ parser(const std::string& filename)
auto parse_and_execute = [](auto& input) { auto parse_and_execute = [](auto& input) {
std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input); std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input);
ASTModulesImporter{*root_node}; ASTModulesImporter module_importer{*root_node};
ASTNodeTypeCleaner<language::import_instruction>{*root_node}; ASTNodeTypeCleaner<language::import_instruction>{*root_node};
ASTSymbolTableBuilder{*root_node}; ASTSymbolTableBuilder{*root_node};
...@@ -75,7 +75,7 @@ parser(const std::string& filename) ...@@ -75,7 +75,7 @@ parser(const std::string& filename)
std::cout << "-------------------------------------------------------\n"; std::cout << "-------------------------------------------------------\n";
std::cout << rang::style::bold << "Executing AST..." << rang::style::reset << '\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; ExecutionPolicy exec_all;
root_node->execute(exec_all); root_node->execute(exec_all);
......
...@@ -37,6 +37,8 @@ ASTModulesImporter::_importAllModules(ASTNode& node) ...@@ -37,6 +37,8 @@ ASTModulesImporter::_importAllModules(ASTNode& node)
ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*root_node.m_symbol_table} ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*root_node.m_symbol_table}
{ {
Assert(root_node.is_root()); Assert(root_node.is_root());
m_module_repository.populateCoreSymbolTable(root_node, m_symbol_table);
this->_importAllModules(root_node); this->_importAllModules(root_node);
std::cout << " - loaded modules\n"; std::cout << " - loaded modules\n";
} }
...@@ -20,6 +20,12 @@ class ASTModulesImporter ...@@ -20,6 +20,12 @@ class ASTModulesImporter
void _importAllModules(ASTNode& node); void _importAllModules(ASTNode& node);
public: public:
const ModuleRepository&
moduleRepository() const
{
return m_module_repository;
}
ASTModulesImporter(ASTNode& root_node); ASTModulesImporter(ASTNode& root_node);
ASTModulesImporter(const ASTModulesImporter&) = delete; ASTModulesImporter(const ASTModulesImporter&) = delete;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
add_library(PugsLanguageModules add_library(PugsLanguageModules
BuiltinModule.cpp BuiltinModule.cpp
CoreModule.cpp
LinearSolverModule.cpp LinearSolverModule.cpp
MathModule.cpp MathModule.cpp
MeshModule.cpp MeshModule.cpp
......
#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();
}
));
}
#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
#include <language/modules/ModuleRepository.hpp> #include <language/modules/ModuleRepository.hpp>
#include <language/ast/ASTNode.hpp> #include <language/ast/ASTNode.hpp>
#include <language/modules/CoreModule.hpp>
#include <language/modules/LinearSolverModule.hpp> #include <language/modules/LinearSolverModule.hpp>
#include <language/modules/MathModule.hpp> #include <language/modules/MathModule.hpp>
#include <language/modules/MeshModule.hpp> #include <language/modules/MeshModule.hpp>
...@@ -21,6 +22,7 @@ ModuleRepository::_subscribe(std::unique_ptr<IModule> m) ...@@ -21,6 +22,7 @@ ModuleRepository::_subscribe(std::unique_ptr<IModule> m)
ModuleRepository::ModuleRepository() ModuleRepository::ModuleRepository()
{ {
this->_subscribe(std::make_unique<CoreModule>());
this->_subscribe(std::make_unique<LinearSolverModule>()); this->_subscribe(std::make_unique<LinearSolverModule>());
this->_subscribe(std::make_unique<MathModule>()); this->_subscribe(std::make_unique<MathModule>());
this->_subscribe(std::make_unique<MeshModule>()); this->_subscribe(std::make_unique<MeshModule>());
...@@ -31,22 +33,21 @@ ModuleRepository::ModuleRepository() ...@@ -31,22 +33,21 @@ ModuleRepository::ModuleRepository()
template <typename NameEmbedderMapT, typename EmbedderTableT> template <typename NameEmbedderMapT, typename EmbedderTableT>
void 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 NameEmbedderMapT& name_embedder_map,
const ASTNodeDataType& data_type, const ASTNodeDataType& data_type,
SymbolTable& symbol_table, SymbolTable& symbol_table,
EmbedderTableT& embedder_table) EmbedderTableT& embedder_table)
{ {
const std::string& module_name = module_name_node.string();
for (auto [symbol_name, embedded] : name_embedder_map) { 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) { if (not success) {
std::ostringstream error_message; std::ostringstream error_message;
error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name
<< "', it is already defined!"; << "', 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); i_symbol->attributes().setDataType(data_type);
...@@ -66,14 +67,46 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab ...@@ -66,14 +67,46 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab
if (i_module != m_module_set.end()) { if (i_module != m_module_set.end()) {
const IModule& populating_module = *i_module->second; 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, ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(), symbol_table,
symbol_table.builtinFunctionEmbedderTable()); 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, ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table,
symbol_table.typeEmbedderTable()); symbol_table.typeEmbedderTable());
} else { } else {
throw ParseError(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()}); 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();
}
...@@ -19,7 +19,8 @@ class ModuleRepository ...@@ -19,7 +19,8 @@ class ModuleRepository
void _subscribe(std::unique_ptr<IModule> a); void _subscribe(std::unique_ptr<IModule> a);
template <typename NameEmbedderMapT, typename EmbedderTableT> 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 NameEmbedderMapT& name_embedder_map,
const ASTNodeDataType& data_type, const ASTNodeDataType& data_type,
SymbolTable& symbol_table, SymbolTable& symbol_table,
...@@ -27,6 +28,9 @@ class ModuleRepository ...@@ -27,6 +28,9 @@ class ModuleRepository
public: public:
void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table); 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=(const ModuleRepository&) = delete;
const ModuleRepository& operator=(ModuleRepository&&) = delete; const ModuleRepository& operator=(ModuleRepository&&) = delete;
......
...@@ -5,22 +5,11 @@ ...@@ -5,22 +5,11 @@
#include <language/utils/ASTPrinter.hpp> #include <language/utils/ASTPrinter.hpp>
#include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp>
#include <language/utils/SymbolTable.hpp> #include <language/utils/SymbolTable.hpp>
#include <utils/PugsUtils.hpp>
#include <fstream>
UtilsModule::UtilsModule() 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)>>( this->_addBuiltinFunction("getAST", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
[]() -> std::string { []() -> std::string {
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
const ASTExecutionInfo* ASTExecutionInfo::m_current_execution_info = nullptr; 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"); Assert(m_current_execution_info == nullptr, "Can only define one ASTExecutionInfo");
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <string> #include <string>
class ModuleRepository;
class ASTNode; class ASTNode;
class ASTExecutionInfo class ASTExecutionInfo
{ {
...@@ -11,10 +12,12 @@ class ASTExecutionInfo ...@@ -11,10 +12,12 @@ class ASTExecutionInfo
const ASTNode& m_root_node; const ASTNode& m_root_node;
const ModuleRepository& m_module_repository;
// The only place where the ASTExecutionInfo can be built // The only place where the ASTExecutionInfo can be built
friend void parser(const std::string& filename); friend void parser(const std::string& filename);
ASTExecutionInfo(const ASTNode& root_node); ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_repository);
public: public:
const ASTNode& const ASTNode&
...@@ -23,6 +26,12 @@ class ASTExecutionInfo ...@@ -23,6 +26,12 @@ class ASTExecutionInfo
return m_root_node; return m_root_node;
} }
const ModuleRepository&
moduleRepository() const
{
return m_module_repository;
}
static const ASTExecutionInfo& current(); static const ASTExecutionInfo& current();
ASTExecutionInfo() = delete; ASTExecutionInfo() = delete;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment