From 85c8ff9264bf98af4c8f3c6dc29e513ff19705f1 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 28 Oct 2019 12:27:23 +0100
Subject: [PATCH] Forbid function with string arguments and add related tests

---
 src/language/ASTNodeDataTypeBuilder.cpp | 12 ++---
 tests/test_ASTNodeDataTypeBuilder.cpp   | 70 ++++++++++++++++++-------
 2 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp
index a42a8d0a8..a96d31461 100644
--- a/src/language/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ASTNodeDataTypeBuilder.cpp
@@ -108,11 +108,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
             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(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
+          if (data_type == ASTNodeDataType::undefined_t) {
+            throw parse_error("invalid parameter type", type_node.begin());
+          }
 
           symbol_node.m_data_type   = data_type;
           const std::string& symbol = symbol_node.string();
@@ -256,12 +256,12 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
             data_type = ASTNodeDataType::unsigned_int_t;
           } else if (image_domain_node.is_type<language::R_set>()) {
             data_type = ASTNodeDataType::double_t;
-          } else if (image_domain_node.is_type<language::string_type>()) {
-            data_type = ASTNodeDataType::string_t;
           }
         }
 
-        Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
+        if (data_type == ASTNodeDataType::undefined_t) {
+          throw parse_error("invalid return type", image_domain_node.begin());
+        }
 
         n.m_data_type = data_type;
       } else if (n.children[0]->m_data_type == ASTNodeDataType::c_function_t) {
diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp
index b0c23f29e..60214915d 100644
--- a/tests/test_ASTNodeDataTypeBuilder.cpp
+++ b/tests/test_ASTNodeDataTypeBuilder.cpp
@@ -134,6 +134,21 @@ let substract : R*R -> R, (x,y) -> x-y;
         CHECK_AST(data, result);
       }
 
+      SECTION("multiple values")
+      {
+        std::string_view data = R"(
+let square : R -> R*R, x -> (x,x*x);
+)";
+
+        std::string_view result = R"(
+(root:void)
+ `-(language::let_declaration:void)
+     `-(language::name:square:function)
+)";
+
+        CHECK_AST(data, result);
+      }
+
       SECTION("name -> expression")
       {
         std::string_view data = R"(
@@ -197,61 +212,52 @@ let f : R -> R, (x) -> (x+1);
 
     SECTION("Z-functions")
     {
-      SECTION("name -> expression")
-      {
-        std::string_view data = R"(
+      std::string_view data = R"(
 let f : Z -> Z, z -> z-1;
 )";
 
-        std::string_view result = R"(
+      std::string_view result = R"(
 (root:void)
  `-(language::let_declaration:void)
      `-(language::name:f:function)
 )";
 
-        CHECK_AST(data, result);
-      }
+      CHECK_AST(data, result);
     }
 
     SECTION("N-functions")
     {
-      SECTION("name -> expression")
-      {
-        std::string_view data = R"(
+      std::string_view data = R"(
 let f : N -> N, x -> (x+1)/2;
 )";
 
-        std::string_view result = R"(
+      std::string_view result = R"(
 (root:void)
  `-(language::let_declaration:void)
      `-(language::name:f:function)
 )";
 
-        CHECK_AST(data, result);
-      }
+      CHECK_AST(data, result);
     }
 
     SECTION("B-functions")
     {
-      SECTION("name -> expression")
-      {
-        std::string_view data = R"(
+      std::string_view data = R"(
 let f : N*B -> B, (n,b) -> (n>3) and b;
 )";
 
-        std::string_view result = R"(
+      std::string_view result = R"(
 (root:void)
  `-(language::let_declaration:void)
      `-(language::name:f:function)
 )";
 
-        CHECK_AST(data, result);
-      }
+      CHECK_AST(data, result);
     }
 
     SECTION("errors")
     {
-      SECTION("wring parameter number")
+      SECTION("wrong parameter number")
       {
         std::string_view data = R"(
 let f : R*Z -> B, x -> 3;
@@ -263,7 +269,7 @@ let f : R*Z -> B, x -> 3;
         REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
       }
 
-      SECTION("wring parameter number 2")
+      SECTION("wrong parameter number 2")
       {
         std::string_view data = R"(
 let f : R -> B, (x,y) -> 3;
@@ -274,6 +280,30 @@ let f : R -> B, (x,y) -> 3;
 
         REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
       }
+
+      SECTION("invalid parameter type")
+      {
+        std::string_view data = R"(
+let f : string -> N, s -> 3;
+)";
+        string_input input{data, "test.pgs"};
+        auto ast = ASTBuilder::build(input);
+        ASTSymbolTableBuilder{*ast};
+
+        REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
+      }
+
+      SECTION("invalid parameter type 2")
+      {
+        std::string_view data = R"(
+let f : N*string -> N, (i,s) -> i;
+)";
+        string_input input{data, "test.pgs"};
+        auto ast = ASTBuilder::build(input);
+        ASTSymbolTableBuilder{*ast};
+
+        REQUIRE_THROWS_AS(ASTNodeDataTypeBuilder{*ast}, parse_error);
+      }
     }
   }
 
-- 
GitLab