From a6823ea7d9319509b17078aa14d97a6cbc3706cd Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Fri, 20 Sep 2019 12:10:51 +0200 Subject: [PATCH] Fix function domains and arguments definition Symbol table is now populated correctly. It remains the case of `` let g : R*N -> R, x -> x; `` where `x` is a complex type. It produces a clean error message and this development is postponed to a far(?) future since it will require compound types management (or at least heterogeneous arrays) --- src/language/ASTNodeDataTypeBuilder.cpp | 71 ++++++++++++++++++------- src/language/ASTSymbolTableBuilder.cpp | 28 +++++++--- src/language/PugsParser.cpp | 1 + 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index 11a812465..42a2f698e 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -56,6 +56,13 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) n.children[1]->children[0]->m_data_type = ASTNodeDataType::typename_t; n.children[1]->children[1]->m_data_type = ASTNodeDataType::typename_t; + // build types for compound types + for (auto& child : n.children[1]->children[0]->children) { + this->_buildNodeDataTypes(*child); + } + for (auto& child : n.children[1]->children[1]->children) { + this->_buildNodeDataTypes(*child); + } { // Function data type const std::string& symbol = n.children[0]->string(); @@ -66,30 +73,51 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) Assert(found); i_symbol->second.setDataType(n.children[0]->m_data_type); } - auto& type_node = *(n.children[1]->children[0]); - ASTNodeDataType data_type{ASTNodeDataType::undefined_t}; - if (type_node.is<language::B_set>()) { - data_type = ASTNodeDataType::bool_t; - } else if (type_node.is<language::Z_set>()) { - data_type = ASTNodeDataType::int_t; - } else if (type_node.is<language::N_set>()) { - data_type = ASTNodeDataType::unsigned_int_t; - } else if (type_node.is<language::R_set>()) { - data_type = ASTNodeDataType::double_t; - } else if (type_node.is<language::string_type>()) { - data_type = ASTNodeDataType::string_t; + + if (n.children[1]->children[0]->children.size() != n.children[2]->children[0]->children.size()) { + std::ostringstream message; + message << "Compound data type deduction is not yet implemented\n" + << "note: number of product spaces (" << n.children[1]->children[0]->children.size() << ") " + << rang::fgB::yellow << n.children[1]->children[0]->string() << rang::style::reset + << " differs from number of variables (" << n.children[2]->children[0]->children.size() << ") " + << rang::fgB::yellow << n.children[2]->children[0]->string() << rang::style::reset << std::ends; + throw parse_error(message.str(), n.children[0]->begin()); } - Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE + auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) { + ASTNodeDataType data_type{ASTNodeDataType::undefined_t}; + if (type_node.is<language::B_set>()) { + data_type = ASTNodeDataType::bool_t; + } else if (type_node.is<language::Z_set>()) { + data_type = ASTNodeDataType::int_t; + } else if (type_node.is<language::N_set>()) { + data_type = ASTNodeDataType::unsigned_int_t; + } else if (type_node.is<language::R_set>()) { + data_type = ASTNodeDataType::double_t; + } else if (type_node.is<language::string_type>()) { + data_type = ASTNodeDataType::string_t; + } + + Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE + + symbol_node.m_data_type = data_type; + const std::string& symbol = symbol_node.string(); - n.children[2]->children[0]->m_data_type = data_type; - const std::string& symbol = n.children[2]->children[0]->string(); + std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table; - std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table; + auto [i_symbol, found] = symbol_table->find(symbol, symbol_node.begin()); + Assert(found); + i_symbol->second.setDataType(data_type); + }; + + if (n.children[1]->children[0]->children.size() == 0) { + simple_type_allocator(*n.children[1]->children[0], *n.children[2]->children[0]); + } else { + for (size_t i = 0; i < n.children[1]->children[0]->children.size(); ++i) { + simple_type_allocator(*n.children[1]->children[0]->children[i], *n.children[2]->children[0]->children[i]); + } + } - auto [i_symbol, found] = symbol_table->find(symbol, n.children[2]->children[0]->begin()); - Assert(found); - i_symbol->second.setDataType(data_type); n.m_data_type = ASTNodeDataType::void_t; } else if (n.is<language::name>()) { std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table; @@ -173,6 +201,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) } else if (n.is<language::function_evaluation>()) { std::cout << rang::fgB::red << "returned type of function evaluation is incorrect" << rang::style::reset << "\n"; n.m_data_type = ASTNodeDataType::double_t; + } else if (n.is<language::B_set>() or n.is<language::Z_set>() or n.is<language::N_set>() or + n.is<language::R_set>() or n.is<language::string_type>()) { + n.m_data_type = ASTNodeDataType::typename_t; + } else if (n.is<language::name_list>() or n.is<language::expression_list>()) { + n.m_data_type = ASTNodeDataType::void_t; } } } diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp index 8bbb6cf6d..3d0ad6942 100644 --- a/src/language/ASTSymbolTableBuilder.cpp +++ b/src/language/ASTSymbolTableBuilder.cpp @@ -22,7 +22,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> auto [i_symbol, success] = symbol_table->add(symbol, n.children[0]->begin()); if (not success) { std::ostringstream error_message; - error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!"; + error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!"; throw parse_error(error_message.str(), std::vector{n.begin()}); } @@ -37,16 +37,28 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> 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!"; + error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!"; throw parse_error(error_message.str(), std::vector{n.begin()}); } } else if (n.is<language::function_definition>()) { - const std::string& symbol = n.children[0]->string(); - auto [i_symbol, success] = symbol_table->add(symbol, n.children[0]->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 std::string& symbol) { + auto [i_symbol, success] = symbol_table->add(symbol, n.children[0]->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()}); + } + // Symbols will be initialized at call + i_symbol->second.setIsInitialized(); + }; + + if (n.children[0]->is<language::name>()) { + register_symbol(n.children[0]->string()); + } else { // treats the case of list of parameters + Assert(n.children[0]->is<language::name_list>()); + for (auto& child : n.children[0]->children) { + register_symbol(child->string()); + } } } else if (n.is<language::name>()) { auto [i_symbol, found] = symbol_table->find(n.string(), n.begin()); diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index 13c16e223..1b40aa888 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -57,6 +57,7 @@ parser(const std::string& filename) ASTSymbolInitializationChecker{*root_node}; ASTNodeDataTypeBuilder{*root_node}; + { std::string dot_filename{"parse_tree.dot"}; std::ofstream fout(dot_filename); -- GitLab