diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index 427e084e87ae89de498558fff98b7c246b1d4a68..ed00e3032b5efddcbfbd21124836f737889041e3 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -14,6 +14,7 @@ #include <language/ast/ASTSymbolInitializationChecker.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ASTDotPrinter.hpp> +#include <language/utils/ASTExecutionInfo.hpp> #include <language/utils/ASTPrinter.hpp> #include <language/utils/SymbolTable.hpp> #include <utils/PugsAssert.hpp> @@ -32,8 +33,6 @@ #include <unordered_map> #include <variant> -const std::unique_ptr<ASTNode>* p_root_node = nullptr; - void parser(const std::string& filename) { @@ -50,9 +49,8 @@ parser(const std::string& filename) auto parse_and_execute = [](auto& input) { std::unique_ptr<ASTNode> root_node = ASTBuilder::build(input); - p_root_node = &root_node; - ASTModulesImporter{*root_node}; + ASTModulesImporter module_importer{*root_node}; ASTNodeTypeCleaner<language::import_instruction>{*root_node}; ASTSymbolTableBuilder{*root_node}; @@ -77,11 +75,12 @@ parser(const std::string& filename) std::cout << "-------------------------------------------------------\n"; std::cout << rang::style::bold << "Executing AST..." << rang::style::reset << '\n'; + ASTExecutionInfo execution_info{*root_node, module_importer.moduleRepository()}; + ExecutionPolicy exec_all; root_node->execute(exec_all); root_node->m_symbol_table->clearValues(); - p_root_node = nullptr; }; if (not SignalManager::pauseOnError()) { diff --git a/src/language/ast/ASTModulesImporter.cpp b/src/language/ast/ASTModulesImporter.cpp index 197f9dcdd33a7e268a550cea12464567ff0f93b5..d52b964a8a670ca3af3d0bcd0f3223798e2502c3 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.populateMandatorySymbolTable(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 2b8c081fdee5ef48dd9594a79ceeca13e52fdedc..566155c4a19ecd00f0b049a29030c0036f212d8a 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/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp index ce2bbcc60182e0fe025d4836ee43fe0cb6d37a59..1f0847f865a6972e7865f4b50601898ab5930616 100644 --- a/src/language/ast/ASTNodeDataType.cpp +++ b/src/language/ast/ASTNodeDataType.cpp @@ -84,6 +84,24 @@ dataTypeName(const ASTNodeDataType& data_type) return name; } +std::string +dataTypeName(const std::vector<ASTNodeDataType>& data_type_vector) +{ + if (data_type_vector.size() == 0) { + return dataTypeName(ASTNodeDataType::build<ASTNodeDataType::void_t>()); + } else if (data_type_vector.size() == 1) { + return dataTypeName(data_type_vector[0]); + } else { + std::ostringstream os; + os << '(' << dataTypeName(data_type_vector[0]); + for (size_t i = 1; i < data_type_vector.size(); ++i) { + os << ',' << dataTypeName(data_type_vector[i]); + } + os << ')'; + return os.str(); + } +} + ASTNodeDataType dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& data_type_2) { diff --git a/src/language/ast/ASTNodeDataType.hpp b/src/language/ast/ASTNodeDataType.hpp index 98dfaecf8dc06da4b0b42090fe9ea9bd411ddc50..951aff6e4d070e4747f5eb3f5a5fcc93f8ba5b8e 100644 --- a/src/language/ast/ASTNodeDataType.hpp +++ b/src/language/ast/ASTNodeDataType.hpp @@ -14,6 +14,8 @@ class ASTNodeDataType; ASTNodeDataType getVectorDataType(const ASTNode& type_node); +std::string dataTypeName(const std::vector<ASTNodeDataType>& data_type_vector); + std::string dataTypeName(const ASTNodeDataType& data_type); ASTNodeDataType dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTNodeDataType& data_type_2); diff --git a/src/language/modules/BuiltinModule.cpp b/src/language/modules/BuiltinModule.cpp index 0ab7911394a9ebb81454c3381a380ea4aca9c03e..22d23f8033604698f44ea18e42c63e9ba48ba345 100644 --- a/src/language/modules/BuiltinModule.cpp +++ b/src/language/modules/BuiltinModule.cpp @@ -6,6 +6,8 @@ #include <memory> +BuiltinModule::BuiltinModule(bool is_mandatory) : m_is_mandatory{is_mandatory} {} + void BuiltinModule::_addBuiltinFunction(const std::string& name, std::shared_ptr<IBuiltinFunctionEmbedder> builtin_function_embedder) diff --git a/src/language/modules/BuiltinModule.hpp b/src/language/modules/BuiltinModule.hpp index bf8743c9e5a9913dd6939e3d6cbe18495bccc27e..6ea3ee56ae6f4b8c3cbfd86ede3370a638d0bff4 100644 --- a/src/language/modules/BuiltinModule.hpp +++ b/src/language/modules/BuiltinModule.hpp @@ -18,7 +18,15 @@ class BuiltinModule : public IModule void _addTypeDescriptor(const ASTNodeDataType& type); + const bool m_is_mandatory; + public: + bool + isMandatory() const final + { + return m_is_mandatory; + } + const NameBuiltinFunctionMap& getNameBuiltinFunctionMap() const final { @@ -31,7 +39,7 @@ class BuiltinModule : public IModule return m_name_type_map; } - BuiltinModule() = default; + BuiltinModule(bool is_mandatory = false); ~BuiltinModule() = default; }; diff --git a/src/language/modules/CMakeLists.txt b/src/language/modules/CMakeLists.txt index cd4c99bd8fb9d8e354706020a4077bf0c8234057..020727478c5e64bac9ec0a780a0cfb80541fb28a 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 0000000000000000000000000000000000000000..14a9548238c91682aac53850a6cdf6f36b4d9e93 --- /dev/null +++ b/src/language/modules/CoreModule.cpp @@ -0,0 +1,44 @@ +#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() : BuiltinModule(true) +{ + 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(); + } + + )); + + this->_addBuiltinFunction("getModuleInfo", std::make_shared<BuiltinFunctionEmbedder<std::string(const std::string&)>>( + + [](const std::string& module_name) -> std::string { + const ModuleRepository& repository = + ASTExecutionInfo::current().moduleRepository(); + + return repository.getModuleInfo(module_name); + } + + )); +} diff --git a/src/language/modules/CoreModule.hpp b/src/language/modules/CoreModule.hpp new file mode 100644 index 0000000000000000000000000000000000000000..963719be2bce1b841fe9cee05db5b957ad53ba2b --- /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/IModule.hpp b/src/language/modules/IModule.hpp index b839ed496d8d032f660a6d21c484c7ca342c5f98..48e4b15360de922a83025921d1058095cc205d89 100644 --- a/src/language/modules/IModule.hpp +++ b/src/language/modules/IModule.hpp @@ -19,6 +19,8 @@ class IModule IModule(IModule&&) = default; IModule& operator=(IModule&&) = default; + virtual bool isMandatory() const = 0; + virtual const NameBuiltinFunctionMap& getNameBuiltinFunctionMap() const = 0; virtual const NameTypeMap& getNameTypeMap() const = 0; diff --git a/src/language/modules/ModuleRepository.cpp b/src/language/modules/ModuleRepository.cpp index 83d44b23ee90423f495144216f5244a9b40db482..abb5d527d4858f86ff3a25e68f4d666c2da8193b 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> @@ -10,8 +11,11 @@ #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/ParseError.hpp> #include <language/utils/SymbolTable.hpp> +#include <language/utils/TypeDescriptor.hpp> #include <utils/PugsAssert.hpp> +#include <algorithm> + void ModuleRepository::_subscribe(std::unique_ptr<IModule> m) { @@ -21,6 +25,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 +36,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 +70,83 @@ 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::populateMandatorySymbolTable(const ASTNode& root_node, SymbolTable& symbol_table) +{ + for (auto&& [module_name, i_module] : m_module_set) { + if (i_module->isMandatory()) { + this->_populateEmbedderTableT(root_node, module_name, i_module->getNameBuiltinFunctionMap(), + ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(), symbol_table, + symbol_table.builtinFunctionEmbedderTable()); + + this->_populateEmbedderTableT(root_node, module_name, i_module->getNameTypeMap(), + ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>(), symbol_table, + symbol_table.typeEmbedderTable()); + } + } +} + +std::string +ModuleRepository::getAvailableModules() const +{ + std::stringstream os; + os << rang::fgB::yellow << "Available modules" << rang::fg::blue << " [modules tagged with a " << rang::style::reset + << rang::style::bold << '*' << rang::style::reset << rang::fg::blue << " are automatically imported]" + << rang::style::reset << '\n'; + for (auto& [name, i_module] : m_module_set) { + if (i_module->isMandatory()) { + os << rang::style::bold << " *" << rang::style::reset; + } else { + os << " "; + } + os << rang::fgB::green << name << rang::style::reset << '\n'; + } + + return os.str(); +} + +std::string +ModuleRepository::getModuleInfo(const std::string& module_name) const +{ + std::stringstream os; + auto i_module = m_module_set.find(module_name); + if (i_module != m_module_set.end()) { + os << rang::fgB::yellow << "Module '" << rang::fgB::blue << module_name << rang::fgB::yellow << "' provides" + << rang::style::reset << '\n'; + const auto& builtin_function_map = i_module->second->getNameBuiltinFunctionMap(); + if (builtin_function_map.size() > 0) { + os << " functions\n"; + for (auto& [name, function] : builtin_function_map) { + os << " " << rang::fgB::green << name << rang::style::reset << ": "; + os << dataTypeName(function->getParameterDataTypes()); + os << rang::fgB::yellow << " -> " << rang::style::reset; + os << dataTypeName(function->getReturnDataType()) << '\n'; + } + } + + const auto& builtin_type_map = i_module->second->getNameTypeMap(); + if (builtin_type_map.size() > 0) { + os << " types\n"; + for (auto& [name, descriptor] : builtin_type_map) { + os << " " << rang::fgB::green << name << rang::style::reset << '\n'; + } + } + + } else { + throw NormalError(std::string{"could not find module "} + module_name); + } + + return os.str(); +} diff --git a/src/language/modules/ModuleRepository.hpp b/src/language/modules/ModuleRepository.hpp index f928a1552563612ed77434e4295a2d31fb2969c1..c224f6491521ad9757ad5253011604e863a10503 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,10 @@ class ModuleRepository public: void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table); + void populateMandatorySymbolTable(const ASTNode& root_node, SymbolTable& symbol_table); + + std::string getAvailableModules() const; + std::string getModuleInfo(const std::string& module_name) 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 8c688e20768b5499549f88334deab4f2ac85a7a9..8b2271158c1548d05b39c379782abb3cc4754d66 100644 --- a/src/language/modules/UtilsModule.cpp +++ b/src/language/modules/UtilsModule.cpp @@ -1,35 +1,22 @@ #include <language/modules/UtilsModule.hpp> #include <language/utils/ASTDotPrinter.hpp> +#include <language/utils/ASTExecutionInfo.hpp> #include <language/utils/ASTPrinter.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/SymbolTable.hpp> -#include <utils/PugsUtils.hpp> -extern const std::unique_ptr<ASTNode>* p_root_node; +#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 { - Assert(p_root_node != nullptr, "unable to find AST's root node"); + const auto& root_node = ASTExecutionInfo::current().rootNode(); - const auto& root_node = *p_root_node; std::ostringstream os; - os << ASTPrinter{*root_node}; + os << ASTPrinter{root_node}; return os.str(); } @@ -39,9 +26,7 @@ UtilsModule::UtilsModule() this->_addBuiltinFunction("saveASTDot", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>( [](const std::string& dot_filename) -> void { - Assert(p_root_node != nullptr, "unable to find AST's root node"); - - const auto& root_node = *p_root_node; + const auto& root_node = ASTExecutionInfo::current().rootNode(); std::ofstream fout(dot_filename); @@ -51,7 +36,7 @@ UtilsModule::UtilsModule() throw NormalError(os.str()); } - ASTDotPrinter dot_printer{*root_node}; + ASTDotPrinter dot_printer{root_node}; fout << dot_printer; if (not fout) { diff --git a/src/language/utils/ASTExecutionInfo.cpp b/src/language/utils/ASTExecutionInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6015b6a8f03625d436916224566725eaa7a18e2d --- /dev/null +++ b/src/language/utils/ASTExecutionInfo.cpp @@ -0,0 +1,25 @@ +#include <language/utils/ASTExecutionInfo.hpp> + +#include <language/ast/ASTNode.hpp> + +const ASTExecutionInfo* ASTExecutionInfo::m_current_execution_info = nullptr; + +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"); + + m_current_execution_info = this; +} + +const ASTExecutionInfo& +ASTExecutionInfo::current() +{ + Assert(m_current_execution_info != nullptr, "ASTExecutionInfo is not defined!"); + return *m_current_execution_info; +} + +ASTExecutionInfo::~ASTExecutionInfo() +{ + m_current_execution_info = nullptr; +} diff --git a/src/language/utils/ASTExecutionInfo.hpp b/src/language/utils/ASTExecutionInfo.hpp new file mode 100644 index 0000000000000000000000000000000000000000..da4b817428c2ea00e8c089e14de2049c4faae4af --- /dev/null +++ b/src/language/utils/ASTExecutionInfo.hpp @@ -0,0 +1,44 @@ +#ifndef AST_EXECUTION_INFO_HPP +#define AST_EXECUTION_INFO_HPP + +#include <string> + +class ModuleRepository; +class ASTNode; +class ASTExecutionInfo +{ + private: + static const ASTExecutionInfo* m_current_execution_info; + + 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); + // also allowed for testing + friend void test_ASTExecutionInfo(const ASTNode&, const ModuleRepository&); + + ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_repository); + + public: + const ASTNode& + rootNode() const + { + return m_root_node; + } + + const ModuleRepository& + moduleRepository() const + { + return m_module_repository; + } + + static const ASTExecutionInfo& current(); + + ASTExecutionInfo() = delete; + + ~ASTExecutionInfo(); +}; + +#endif // AST_EXECUTION_INFO_HPP diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index 6a8216a9ca62a440c7eb84111cbb87d26ae6b1d3..1cb991d6c6d19a18579d3c0802a6ea032891d5c2 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(PugsLanguageUtils ASTDotPrinter.cpp + ASTExecutionInfo.cpp ASTPrinter.cpp DataVariant.cpp EmbeddedData.cpp diff --git a/tests/test_ASTModulesImporter.cpp b/tests/test_ASTModulesImporter.cpp index 42638d918a362516b53a0f05772096b477f943b4..a3a4e3d7a6bd6bfc7d624b9d1ee4a9d69e34b876 100644 --- a/tests/test_ASTModulesImporter.cpp +++ b/tests/test_ASTModulesImporter.cpp @@ -4,11 +4,22 @@ #include <language/ast/ASTModulesImporter.hpp> #include <language/ast/ASTNodeExpressionBuilder.hpp> #include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/utils/ASTExecutionInfo.hpp> #include <language/utils/ASTPrinter.hpp> #include <language/utils/SymbolTable.hpp> #include <pegtl/string_input.hpp> +inline void +test_ASTExecutionInfo(const ASTNode& root_node, const ModuleRepository& module_repository) +{ + ASTExecutionInfo execution_info{root_node, module_repository}; + REQUIRE(&root_node == &execution_info.rootNode()); + REQUIRE(&module_repository == &execution_info.moduleRepository()); + + REQUIRE(&ASTExecutionInfo::current() == &execution_info); +} + #define CHECK_AST(data, expected_output) \ { \ static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ @@ -17,10 +28,13 @@ string_input input{data, "test.pgs"}; \ auto ast = ASTBuilder::build(input); \ \ - ASTModulesImporter{*ast}; \ + ASTModulesImporter importer{*ast}; \ ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ \ ASTNodeExpressionBuilder{*ast}; \ + const auto& module_repository = importer.moduleRepository(); \ + test_ASTExecutionInfo(*ast, module_repository); \ + \ ExecutionPolicy exec_policy; \ ast->execute(exec_policy); \ \ diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp index 21f5c08bfbe6399b8d5a27ea2c33b56e84f78232..3d4ea9b6954363cdd9007679e425d5f4f4c74c36 100644 --- a/tests/test_ASTNodeDataType.cpp +++ b/tests/test_ASTNodeDataType.cpp @@ -31,6 +31,9 @@ TEST_CASE("ASTNodeDataType", "[language]") const ASTNodeDataType list_dt = ASTNodeDataType::build<ASTNodeDataType::list_t>(type_list); + const ASTNodeDataType empty_list_dt = + ASTNodeDataType::build<ASTNodeDataType::list_t>(std::vector<std::shared_ptr<const ASTNodeDataType>>{}); + SECTION("dataTypeName") { REQUIRE(dataTypeName(undefined_dt) == "undefined"); @@ -44,6 +47,7 @@ TEST_CASE("ASTNodeDataType", "[language]") REQUIRE(dataTypeName(function_dt) == "function"); REQUIRE(dataTypeName(builtin_function_dt) == "builtin_function"); REQUIRE(dataTypeName(list_dt) == "list(R*Z)"); + REQUIRE(dataTypeName(empty_list_dt) == "list(void)"); REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)) == "tuple(B)"); REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt)) == "tuple(N)"); REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)) == "tuple(Z)"); @@ -57,6 +61,10 @@ TEST_CASE("ASTNodeDataType", "[language]") REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)) == "R^1"); REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)) == "R^2"); REQUIRE(dataTypeName(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)) == "R^3"); + + REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{}) == "void"); + REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{bool_dt}) == "B"); + REQUIRE(dataTypeName(std::vector<ASTNodeDataType>{bool_dt, unsigned_int_dt}) == "(B,N)"); } SECTION("promotion")