From 1338f2ae198652a00b919383b15a086819491ebb Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 18 Nov 2019 18:38:00 +0100 Subject: [PATCH] Continue compound type management Declarations are now allowed, however, affections require a bit of work. --- src/language/ASTNodeDataTypeBuilder.cpp | 82 ++++++++++++------- src/language/ASTNodeDataTypeBuilder.hpp | 4 +- src/language/ASTNodeDataVariant.hpp | 43 ++++++++-- .../ASTSymbolInitializationChecker.cpp | 16 ++-- src/language/ASTSymbolTableBuilder.cpp | 29 +++++-- src/language/PEGGrammar.hpp | 3 +- 6 files changed, 126 insertions(+), 51 deletions(-) diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index e110ee46c..73a423032 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -6,8 +6,56 @@ #include <CFunctionEmbedder.hpp> +ASTNodeDataType +ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNode& name_node) const +{ + ASTNodeDataType data_type{ASTNodeDataType::undefined_t}; + if (type_node.is_type<language::type_expression>()) { + if (type_node.children.size() != name_node.children.size()) { + std::ostringstream message; + message << "number of product spaces (" << type_node.children.size() << ") " << rang::fgB::yellow + << type_node.string() << rang::style::reset << rang::style::bold << " differs from number of variables (" + << name_node.children.size() << ") " << rang::fgB::yellow << name_node.string() << rang::style::reset + << std::ends; + throw parse_error(message.str(), name_node.begin()); + } + + for (size_t i = 0; i < type_node.children.size(); ++i) { + auto& sub_type_node = *type_node.children[i]; + auto& sub_name_node = *name_node.children[i]; + _buildDeclarationNodeDataTypes(sub_type_node, sub_name_node); + } + data_type = ASTNodeDataType::typename_t; + } else { + if (type_node.is_type<language::B_set>()) { + data_type = ASTNodeDataType::bool_t; + } else if (type_node.is_type<language::Z_set>()) { + data_type = ASTNodeDataType::int_t; + } else if (type_node.is_type<language::N_set>()) { + data_type = ASTNodeDataType::unsigned_int_t; + } else if (type_node.is_type<language::R_set>()) { + data_type = ASTNodeDataType::double_t; + } else if (type_node.is_type<language::string_type>()) { + data_type = ASTNodeDataType::string_t; + } + + Assert(name_node.is_type<language::name>()); + name_node.m_data_type = data_type; + const std::string& symbol = name_node.string(); + + std::shared_ptr<SymbolTable>& symbol_table = name_node.m_symbol_table; + + auto [i_symbol, found] = symbol_table->find(symbol, name_node.begin()); + Assert(found); + i_symbol->attributes().setDataType(data_type); + } + + Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE + return data_type; +} + void -ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) +ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const { if (n.is_type<language::block>() or n.is_type<language::for_statement>()) { for (auto& child : n.children) { @@ -33,33 +81,10 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) n.m_data_type = ASTNodeDataType::void_t; } else if (n.is_type<language::declaration>()) { auto& type_node = *(n.children[0]); - ASTNodeDataType data_type{ASTNodeDataType::undefined_t}; - if (type_node.is_type<language::B_set>()) { - data_type = ASTNodeDataType::bool_t; - } else if (type_node.is_type<language::Z_set>()) { - data_type = ASTNodeDataType::int_t; - } else if (type_node.is_type<language::N_set>()) { - data_type = ASTNodeDataType::unsigned_int_t; - } else if (type_node.is_type<language::R_set>()) { - data_type = ASTNodeDataType::double_t; - } else if (type_node.is_type<language::string_type>()) { - data_type = ASTNodeDataType::string_t; - } else if (type_node.is_type<language::type_expression>()) { - data_type = ASTNodeDataType::typename_t; - } - - Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE + auto& name_node = *(n.children[1]); - type_node.m_data_type = ASTNodeDataType::typename_t; - n.children[1]->m_data_type = data_type; - const std::string& symbol = n.children[1]->string(); - - std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table; - - auto [i_symbol, found] = symbol_table->find(symbol, n.children[1]->begin()); - Assert(found); - i_symbol->attributes().setDataType(data_type); - n.m_data_type = data_type; + type_node.m_data_type = _buildDeclarationNodeDataTypes(type_node, name_node); + n.m_data_type = type_node.m_data_type; } else if (n.is_type<language::let_declaration>()) { n.children[0]->m_data_type = ASTNodeDataType::function_t; @@ -91,8 +116,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) if (nb_parameter_domains != nb_parameter_names) { std::ostringstream message; - message << "Compound data type deduction is not yet implemented\n" - << "note: number of product spaces (" << nb_parameter_domains << ") " << rang::fgB::yellow + message << "note: number of product spaces (" << nb_parameter_domains << ") " << rang::fgB::yellow << parameters_domain_node.string() << rang::style::reset << rang::style::bold << " differs from number of variables (" << nb_parameter_names << ") " << rang::fgB::yellow << parameters_name_node.string() << rang::style::reset << std::ends; diff --git a/src/language/ASTNodeDataTypeBuilder.hpp b/src/language/ASTNodeDataTypeBuilder.hpp index 126c8d442..ccec5e057 100644 --- a/src/language/ASTNodeDataTypeBuilder.hpp +++ b/src/language/ASTNodeDataTypeBuilder.hpp @@ -6,7 +6,9 @@ class ASTNodeDataTypeBuilder { private: - void _buildNodeDataTypes(ASTNode& node); + ASTNodeDataType _buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNode& name_node) const; + + void _buildNodeDataTypes(ASTNode& node) const; public: ASTNodeDataTypeBuilder(ASTNode& root_node); diff --git a/src/language/ASTNodeDataVariant.hpp b/src/language/ASTNodeDataVariant.hpp index 46f4d1658..96d940229 100644 --- a/src/language/ASTNodeDataVariant.hpp +++ b/src/language/ASTNodeDataVariant.hpp @@ -4,20 +4,53 @@ #include <variant> #include <vector> -struct CompoundDataVariant; +#include <PugsAssert.hpp> + +class CompoundDataVariant; using ASTNodeDataVariant = std::variant<std::monostate, bool, uint64_t, int64_t, double, std::string, CompoundDataVariant>; -struct CompoundDataVariant +class CompoundDataVariant { + private: std::vector<ASTNodeDataVariant> m_data_vector; - friend std::ostream& - operator<<(std::ostream& os, const CompoundDataVariant&) + + std::ostream& + _printComponent(std::ostream& os, const ASTNodeDataVariant& value) const { - os << " *CompoundDataVariant* "; + std::visit( + [&](auto&& v) { + if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::monostate>) { + os << " -- "; + } else { + os << v; + } + }, + value); return os; } + + std::ostream& + _print(std::ostream& os) const + { + Assert(m_data_vector.size() > 0, "unexpected compound data size"); + os << '('; + this->_printComponent(os, m_data_vector[0]); + for (size_t i = 1; i < m_data_vector.size(); ++i) { + os << ", "; + this->_printComponent(os, m_data_vector[i]); + } + os << ')'; + return os; + } + + public: + friend std::ostream& + operator<<(std::ostream& os, const CompoundDataVariant& compound) + { + return compound._print(os); + } }; #endif // AST_NODE_DATA_VARIANT_HPP diff --git a/src/language/ASTSymbolInitializationChecker.cpp b/src/language/ASTSymbolInitializationChecker.cpp index f6ccf5524..0698b6fad 100644 --- a/src/language/ASTSymbolInitializationChecker.cpp +++ b/src/language/ASTSymbolInitializationChecker.cpp @@ -8,12 +8,16 @@ void ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) { if (node.is_type<language::declaration>()) { - const std::string& symbol = node.children[1]->string(); - auto [i_symbol, found] = node.m_symbol_table->find(symbol, node.children[1]->begin()); - Assert(found, "unexpected error, should have been detected through declaration checking"); - if (node.children.size() == 3) { - this->_checkSymbolInitialization(*node.children[2]); - i_symbol->attributes().setIsInitialized(); + if (node.children[1]->is_type<language::name>()) { + const std::string& symbol = node.children[1]->string(); + auto [i_symbol, found] = node.m_symbol_table->find(symbol, node.children[1]->begin()); + Assert(found, "unexpected error, should have been detected through declaration checking"); + if (node.children.size() == 3) { + this->_checkSymbolInitialization(*node.children[2]); + i_symbol->attributes().setIsInitialized(); + } + } else { + std::cerr << __FILE__ << ':' << __LINE__ << ": '" << node.children[1]->name() << "' NIY!\n"; } } else if (node.is_type<language::let_declaration>()) { const std::string& symbol = node.children[0]->string(); diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp index 87a549c02..d78100060 100644 --- a/src/language/ASTSymbolTableBuilder.cpp +++ b/src/language/ASTSymbolTableBuilder.cpp @@ -38,15 +38,26 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> n.m_symbol_table = symbol_table; if (n.has_content()) { if (n.is_type<language::declaration>()) { - const std::string& symbol = n.children[1]->string(); - auto [i_symbol, success] = symbol_table->add(symbol, n.children[1]->begin()); - if (not success) { - std::ostringstream error_message; - error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!"; - throw parse_error(error_message.str(), std::vector{n.begin()}); + auto register_symbol = [&](const ASTNode& argument_node) { + auto [i_symbol, success] = symbol_table->add(argument_node.string(), argument_node.begin()); + if (not success) { + std::ostringstream error_message; + error_message << "symbol '" << rang::fg::red << argument_node.string() << rang::fg::reset + << "' was already defined!"; + throw parse_error(error_message.str(), std::vector{argument_node.begin()}); + } + }; + + if (n.children[1]->is_type<language::name>()) { + register_symbol(*n.children[1]); + } else { // treats the case of list of parameters + Assert(n.children[1]->is_type<language::name_list>()); + for (auto& child : n.children[1]->children) { + register_symbol(*child); + } } } else if (n.is_type<language::function_definition>()) { - auto register_symbol = [&](const ASTNode& argument_node) { + auto register_and_initialize_symbol = [&](const ASTNode& argument_node) { auto [i_symbol, success] = symbol_table->add(argument_node.string(), argument_node.begin()); if (not success) { std::ostringstream error_message; @@ -59,11 +70,11 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> }; if (n.children[0]->is_type<language::name>()) { - register_symbol(*n.children[0]); + register_and_initialize_symbol(*n.children[0]); } else { // treats the case of list of parameters Assert(n.children[0]->is_type<language::name_list>()); for (auto& child : n.children[0]->children) { - register_symbol(*child); + register_and_initialize_symbol(*child); } } } else if (n.is_type<language::name>()) { diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index f3d245ecd..b44f873c0 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -213,7 +213,8 @@ struct affect_op : sor< eq_op, multiplyeq_op, divideeq_op, pluseq_op, minuseq_op struct affectation : seq< NAME , if_must< affect_op, sor< expression_list, expression > > >{}; -struct declaration : if_must< type_expression, NAME, opt< if_must< seq< one< '=' >, ignored >, sor< expression_list, expression > > > >{}; +struct name_list; +struct declaration : if_must< type_expression, sor< NAME, name_list>, opt< if_must< seq< one< '=' >, ignored >, sor< expression_list, expression > > > >{}; struct type_mapping : seq< type_expression, RIGHT_ARROW, type_expression >{}; -- GitLab