diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 24841d797529750ba2adc6664c278a56c615fdd2..44e30ec2e11fba9db2701268d582089f9cb839f4 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -203,7 +203,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const if (nb_parameter_domains != nb_parameter_names) { std::ostringstream message; - message << "note: number of product spaces (" << nb_parameter_domains << ") " << rang::fgB::yellow + message << "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; @@ -255,7 +255,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const std::ostringstream message; message << "expecting " << image_type.dimension() << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; - throw ParseError(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_expression_node.begin()); } } else if (image_domain_node.is_type<language::matrix_type>()) { ASTNodeDataType image_type = getMatrixDataType(image_domain_node); @@ -263,7 +263,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const std::ostringstream message; message << "expecting " << image_type.nbRows() * image_type.nbColumns() << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; - throw ParseError(message.str(), image_domain_node.begin()); + throw ParseError(message.str(), image_expression_node.begin()); } } else { std::ostringstream message; @@ -290,8 +290,26 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } else if (symbol_table->has(n.string(), n.begin())) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>(); } else { + // LCOV_EXCL_START throw UnexpectedError("could not find symbol " + n.string()); + // LCOV_EXCL_STOP } + } else if (n.is_type<language::type_name_id>()) { + const std::string& type_name_id = n.string(); + + auto& symbol_table = *n.m_symbol_table; + + const auto [i_type_symbol, found] = symbol_table.find(type_name_id, n.begin()); + if (not found) { + throw ParseError("undefined type identifier", std::vector{n.begin()}); + } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { + std::ostringstream os; + os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" + << dataTypeName(i_type_symbol->attributes().dataType()) << '\''; + throw ParseError(os.str(), std::vector{n.begin()}); + } + + n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id); } } for (auto& child : n.children) { @@ -339,22 +357,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const value_type = getMatrixDataType(image_node); } else if (image_node.is_type<language::string_type>()) { value_type = ASTNodeDataType::build<ASTNodeDataType::string_t>(); - } else if (image_node.is_type<language::type_name_id>()) { - const std::string& type_name_id = image_node.string(); - - auto& symbol_table = *image_node.m_symbol_table; - - const auto [i_type_symbol, found] = symbol_table.find(type_name_id, image_node.begin()); - if (not found) { - throw ParseError("undefined type identifier", std::vector{image_node.begin()}); - } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { - std::ostringstream os; - os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" - << dataTypeName(i_type_symbol->attributes().dataType()) << '\''; - throw ParseError(os.str(), std::vector{image_node.begin()}); - } - - value_type = ASTNodeDataType::build<ASTNodeDataType::type_id_t>(type_name_id); } // LCOV_EXCL_START diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 79e01aef9a34ab2324c0c731e1a2079d3e985d99..be1f60db863ce2af4df25bad45ce41be0121eb35 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -392,7 +392,7 @@ let (x,y) : R; SECTION("invalid R-list -> R^d") { std::string_view data = R"( -let square : R -> R^3, x -> (x, x*x); +let square : R -> R^3, x -> (x, 2); )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -999,7 +999,8 @@ let f : R*Z -> B, x -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "number of product spaces (2) R*Z differs from number of variables (1) x"); } SECTION("wrong parameter number 2") @@ -1011,7 +1012,8 @@ let f : R -> B, (x,y) -> 3; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "number of product spaces (1) R differs from number of variables (2) (x,y) "); } SECTION("wrong image size") @@ -1052,6 +1054,58 @@ let f : R -> R^2x2, x -> (x, 2*x, 2); REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "expecting 4 scalar expressions or an R^2x2, found 3 scalar expressions"); } + + SECTION("undefined type identifier") + { + std::string_view data = R"( +let x:X; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("undefined type identifier") + { + std::string_view data = R"( +let X:R, X = 3; +let x:X; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'X' was previously defined as a 'R'"); + } + + SECTION("undefined image type identifier") + { + std::string_view data = R"( +let f: R -> X, x -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined type identifier"); + } + + SECTION("invalid image type identifier") + { + std::string_view data = R"( +let X: R, X = 3; +let f: R -> X, x -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "invalid type identifier, 'X' was previously defined as a 'R'"); + } } } @@ -1277,7 +1331,8 @@ not_a_function(2,3); auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid function call\n" + "note: 'not_a_function' (type: R) is not a function!"); } } } @@ -1732,7 +1787,7 @@ if ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -1818,7 +1873,7 @@ while ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -1904,7 +1959,7 @@ do 1; while ("string"); TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid implicit conversion: string -> B"); } } @@ -2223,7 +2278,8 @@ true xor false; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; auto ast = ASTBuilder::build(input); ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, ParseError); + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "undefined binary operator\n" + "note: incompatible operand types Z and string"); } } }