Skip to content
Snippets Groups Projects
Commit c841b1d8 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Check return datatype at function declaration

Also add a bunch of tests for function declaration and evaluation
parent 85c8ff92
No related branches found
No related tags found
1 merge request!37Feature/language
......@@ -146,6 +146,31 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
this->_buildNodeDataTypes(*child);
}
auto check_image_type = [&](const ASTNode& image_node) {
ASTNodeDataType value_type{ASTNodeDataType::undefined_t};
if (image_node.is_type<language::B_set>()) {
value_type = ASTNodeDataType::bool_t;
} else if (image_node.is_type<language::Z_set>()) {
value_type = ASTNodeDataType::int_t;
} else if (image_node.is_type<language::N_set>()) {
value_type = ASTNodeDataType::unsigned_int_t;
} else if (image_node.is_type<language::R_set>()) {
value_type = ASTNodeDataType::double_t;
}
if (value_type == ASTNodeDataType::undefined_t) {
throw parse_error("invalid value type", image_node.begin());
}
};
if (image_domain_node.children.size() == 0) {
check_image_type(image_domain_node);
} else {
for (size_t i = 0; i < image_domain_node.children.size(); ++i) {
check_image_type(*image_domain_node.children[i]);
}
}
n.m_data_type = ASTNodeDataType::void_t;
} else if (n.is_type<language::name>()) {
std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
......@@ -245,7 +270,6 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
if (image_domain_node.children.size() > 0) {
std::ostringstream message;
throw parse_error("compound data type is not implemented yet", image_domain_node.begin());
} else {
if (image_domain_node.is_type<language::B_set>()) {
......@@ -259,9 +283,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
}
}
if (data_type == ASTNodeDataType::undefined_t) {
throw parse_error("invalid return type", image_domain_node.begin());
}
Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE
n.m_data_type = data_type;
} else if (n.children[0]->m_data_type == ASTNodeDataType::c_function_t) {
......
......@@ -63,5 +63,5 @@ ASTNodeValueBuilder::ASTNodeValueBuilder(ASTNode& node)
this->_buildNodeValue(function_expression);
}
std::cout << " - build node data types\n";
std::cout << " - build node values\n";
}
......@@ -304,6 +304,164 @@ let f : N*string -> N, (i,s) -> i;
REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
}
SECTION("invalid return type")
{
std::string_view data = R"(
let f : R -> string, x -> "foo";
)";
string_input input{data, "test.pgs"};
auto ast = ASTBuilder::build(input);
ASTSymbolTableBuilder{*ast};
REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
}
SECTION("invalid return type 2")
{
std::string_view data = R"(
let f : R -> N*string, x -> (2,"foo");
)";
string_input input{data, "test.pgs"};
auto ast = ASTBuilder::build(input);
ASTSymbolTableBuilder{*ast};
REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
}
}
}
SECTION("function evaluation")
{
SECTION("R-functions")
{
SECTION("single argument")
{
std::string_view data = R"(
let incr : R -> R, x -> x+1;
R x = incr(3);
)";
std::string_view result = R"(
(root:void)
+-(language::let_declaration:void)
| `-(language::name:incr:function)
`-(language::declaration:R)
+-(language::R_set:typename)
+-(language::name:x:R)
`-(language::function_evaluation:R)
+-(language::name:incr:function)
`-(language::integer:3:Z)
)";
CHECK_AST(data, result);
}
SECTION("multiple variable")
{
std::string_view data = R"(
let substract : R*R -> R, (x,y) -> x-y;
R diff = substract(3,2);
)";
std::string_view result = R"(
(root:void)
+-(language::let_declaration:void)
| `-(language::name:substract:function)
`-(language::declaration:R)
+-(language::R_set:typename)
+-(language::name:diff:R)
`-(language::function_evaluation:R)
+-(language::name:substract:function)
`-(language::function_argument_list:void)
+-(language::integer:3:Z)
`-(language::integer:2:Z)
)";
CHECK_AST(data, result);
}
}
SECTION("Z-functions")
{
std::string_view data = R"(
let incr : Z -> Z, z -> z+1;
Z z = incr(3);
)";
std::string_view result = R"(
(root:void)
+-(language::let_declaration:void)
| `-(language::name:incr:function)
`-(language::declaration:Z)
+-(language::Z_set:typename)
+-(language::name:z:Z)
`-(language::function_evaluation:Z)
+-(language::name:incr:function)
`-(language::integer:3:Z)
)";
CHECK_AST(data, result);
}
SECTION("N-functions")
{
std::string_view data = R"(
let double : N -> N, n -> 2*n;
N n = double(3);
)";
std::string_view result = R"(
(root:void)
+-(language::let_declaration:void)
| `-(language::name:double:function)
`-(language::declaration:N)
+-(language::N_set:typename)
+-(language::name:n:N)
`-(language::function_evaluation:N)
+-(language::name:double:function)
`-(language::integer:3:Z)
)";
CHECK_AST(data, result);
}
SECTION("B-functions")
{
std::string_view data = R"(
let greater_than_2 : R -> B, x -> x>2;
B b = greater_than_2(3);
)";
std::string_view result = R"(
(root:void)
+-(language::let_declaration:void)
| `-(language::name:greater_than_2:function)
`-(language::declaration:B)
+-(language::B_set:typename)
+-(language::name:b:B)
`-(language::function_evaluation:B)
+-(language::name:greater_than_2:function)
`-(language::integer:3:Z)
)";
CHECK_AST(data, result);
}
SECTION("errors")
{
SECTION("not a function")
{
std::string_view data = R"(
R not_a_function = 3;
not_a_function(2,3);
)";
string_input input{data, "test.pgs"};
auto ast = ASTBuilder::build(input);
ASTSymbolTableBuilder{*ast};
REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment