diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index 1fe2d74b067718ad1425309f838fed1a9dfc9464..68bb5a9203f71eb27d7e64a0eb17d0440e7edf9a 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -142,9 +142,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const data_type = ASTNodeDataType::string_t; } + // LCOV_EXCL_START if (data_type == ASTNodeDataType::undefined_t) { throw parse_error("invalid parameter type", type_node.begin()); } + // LCOV_EXCL_STOP symbol_node.m_data_type = data_type; const std::string& symbol = symbol_node.string(); @@ -207,9 +209,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const value_type = ASTNodeDataType::string_t; } + // LCOV_EXCL_START if (value_type == ASTNodeDataType::undefined_t) { throw parse_error("invalid value type", image_node.begin()); } + // LCOV_EXCL_STOP }; if (image_domain_node.children.size() == 0) { diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 3fecc130b0daf20e177e3c9fe61aecb947ebb280..8e297e78b60c433a3f1748a32338be859c548f27 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -115,6 +115,77 @@ false; CHECK_AST(data, result); } + SECTION("compound") + { + SECTION("declaration") + { + std::string_view data = R"( +R*B*N*string (x,b,n,s); +)"; + + std::string_view result = R"( +(root:void) + `-(language::declaration:typename) + +-(language::type_expression:typename) + | +-(language::R_set:typename) + | +-(language::B_set:typename) + | +-(language::N_set:typename) + | `-(language::string_type:typename) + `-(language::name_list:void) + +-(language::name:x:R) + +-(language::name:b:B) + +-(language::name:n:N) + `-(language::name:s:string) +)"; + + CHECK_AST(data, result); + } + + SECTION("errors") + { + SECTION("too many variables") + { + std::string_view data = R"( +R*B*N*string (x,b,n,s,t); +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "number of product spaces (4) R*B*N*string differs from " + "number of variables (5) (x,b,n,s,t)"); + } + + SECTION("too few variables") + { + std::string_view data = R"( +R*B*N*string (x,b,n); +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "number of product spaces (4) R*B*N*string differs from " + "number of variables (3) (x,b,n)"); + } + + SECTION("unexpected variable list") + { + std::string_view data = R"( +R (x,y); +)"; + + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "unexpected variable list for scalar space"); + } + } + } + SECTION("let declaration") { SECTION("R-functions") @@ -255,6 +326,21 @@ let f : N*B -> B, (n,b) -> (n>3) and b; CHECK_AST(data, result); } + SECTION("string-functions") + { + std::string_view data = R"( +let cat : string*N -> string, (s,n) -> s+n; +)"; + + std::string_view result = R"( +(root:void) + `-(language::let_declaration:void) + `-(language::name:cat:function) +)"; + + CHECK_AST(data, result); + } + SECTION("errors") { SECTION("wrong parameter number") @@ -280,6 +366,19 @@ let f : R -> B, (x,y) -> 3; REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error); } + + SECTION("wrong image size") + { + std::string_view data = R"( +let f : R*Z -> B, (x,z) -> (3, x); +)"; + string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, + "note: number of image spaces (1) B differs from number of expressions (2) (3, x)"); + } } } @@ -356,7 +455,7 @@ Z z = incr(3); CHECK_AST(data, result); } - SECTION("N-functions") + SECTION("N-function") { std::string_view data = R"( let double : N -> N, n -> 2*n; @@ -378,7 +477,7 @@ N n = double(3); CHECK_AST(data, result); } - SECTION("B-functions") + SECTION("B-function") { std::string_view data = R"( let greater_than_2 : R -> B, x -> x>2; @@ -400,6 +499,56 @@ B b = greater_than_2(3); CHECK_AST(data, result); } + SECTION("string-function") + { + std::string_view data = R"( +let cat : string*string -> string, (s,t) -> s+t; +string s = cat("foo", "bar"); +)"; + + std::string_view result = R"( +(root:void) + +-(language::let_declaration:void) + | `-(language::name:cat:function) + `-(language::declaration:string) + +-(language::string_type:typename) + +-(language::name:s:string) + `-(language::function_evaluation:string) + +-(language::name:cat:function) + `-(language::function_argument_list:void) + +-(language::literal:"foo":string) + `-(language::literal:"bar":string) +)"; + + CHECK_AST(data, result); + } + + SECTION("compound return function") + { + std::string_view data = R"( +let x_x2 : R -> R*R, x -> (x,x*x); +R*R (x,x2) = x_x2(3); +)"; + + std::string_view result = R"( +(root:void) + +-(language::let_declaration:void) + | `-(language::name:x_x2:function) + `-(language::declaration:typename) + +-(language::type_expression:typename) + | +-(language::R_set:typename) + | `-(language::R_set:typename) + +-(language::name_list:void) + | +-(language::name:x:R) + | `-(language::name:x2:R) + `-(language::function_evaluation:typename) + +-(language::name:x_x2:function) + `-(language::integer:3:Z) +)"; + + CHECK_AST(data, result); + } + SECTION("errors") { SECTION("not a function")