From b7bf9f92c61c313c6b29936339eba058bfebcd79 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Tue, 14 Jan 2020 18:46:01 +0100
Subject: [PATCH] Disallow function arguments non natural implicit conversions

Related to issue #16
---
 .../ASTNodeFunctionExpressionBuilder.cpp      |   4 +
 .../test_ASTNodeFunctionExpressionBuilder.cpp | 111 +++++++++---------
 tests/test_FunctionProcessor.cpp              |  46 --------
 3 files changed, 60 insertions(+), 101 deletions(-)

diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp
index 156811f78..188af8305 100644
--- a/src/language/ASTNodeFunctionExpressionBuilder.cpp
+++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp
@@ -5,6 +5,7 @@
 #include <SymbolTable.hpp>
 
 #include <ASTNodeDataTypeFlattener.hpp>
+#include <ASTNodeNaturalConversionChecker.hpp>
 
 #include <node_processor/FunctionProcessor.hpp>
 
@@ -15,6 +16,9 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy
 {
   const size_t parameter_id = std::get<size_t>(parameter_symbol.attributes().value());
 
+  ASTNodeNaturalConversionChecker{node_sub_data_type.m_parent_node, node_sub_data_type.m_data_type,
+                                  parameter_symbol.attributes().dataType()};
+
   auto get_function_argument_converter_for =
     [&](const auto& parameter_v) -> std::unique_ptr<IFunctionArgumentConverter> {
     using ParameterT = std::decay_t<decltype(parameter_v)>;
diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp
index c45708ddd..4393ee9dd 100644
--- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp
+++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp
@@ -102,59 +102,6 @@ not_v(true);
 
         CHECK_AST(data, result);
       }
-
-      SECTION("N parameter")
-      {
-        std::string_view data = R"(
-let not_v : B -> B, a -> not a;
-N n = 1;
-not_v(n);
-)";
-
-        std::string_view result = R"(
-(root:ASTNodeListProcessor)
- `-(language::function_evaluation:FunctionProcessor)
-     +-(language::name:not_v:NameProcessor)
-     `-(language::name:n:NameProcessor)
-)";
-
-        CHECK_AST(data, result);
-      }
-
-      SECTION("Z parameter")
-      {
-        std::string_view data = R"(
-let not_v : B -> B, a -> not a;
-not_v(-1);
-)";
-
-        std::string_view result = R"(
-(root:ASTNodeListProcessor)
- `-(language::function_evaluation:FunctionProcessor)
-     +-(language::name:not_v:NameProcessor)
-     `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>)
-         `-(language::integer:1:ValueProcessor)
-)";
-
-        CHECK_AST(data, result);
-      }
-
-      SECTION("R parameter")
-      {
-        std::string_view data = R"(
-let not_v : B -> B, a -> not a;
-not_v(1.3);
-)";
-
-        std::string_view result = R"(
-(root:ASTNodeListProcessor)
- `-(language::function_evaluation:FunctionProcessor)
-     +-(language::name:not_v:NameProcessor)
-     `-(language::real:1.3:ValueProcessor)
-)";
-
-        CHECK_AST(data, result);
-      }
     }
 
     SECTION("N argument")
@@ -215,14 +162,14 @@ test(2.1);
     {
       std::string_view data = R"(
 let test : N -> N, n -> n+2;
-test(2.1);
+test(2);
 )";
 
       std::string_view result = R"(
 (root:ASTNodeListProcessor)
  `-(language::function_evaluation:FunctionProcessor)
      +-(language::name:test:NameProcessor)
-     `-(language::real:2.1:ValueProcessor)
+     `-(language::integer:2:ValueProcessor)
 )";
 
       CHECK_AST(data, result);
@@ -416,5 +363,59 @@ bad_conv(2);
 
       CHECK_AST_THROWS_WITH(data, std::string{"invalid string conversion"});
     }
+
+    SECTION("invalid argument implicit conversion")
+    {
+      SECTION("N -> B")
+      {
+        std::string_view data = R"(
+let negate : B -> B, b -> not b;
+N n = 2;
+negate(n);
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"});
+      }
+
+      SECTION("Z -> B")
+      {
+        std::string_view data = R"(
+let negate : B -> B, b -> not b;
+negate(3-4);
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"});
+      }
+
+      SECTION("R -> B")
+      {
+        std::string_view data = R"(
+let negate : B -> B, b -> not b;
+negate(3.24);
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"});
+      }
+
+      SECTION("R -> N")
+      {
+        std::string_view data = R"(
+let next : N -> N, n -> n+1;
+next(3.24);
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"});
+      }
+
+      SECTION("R -> Z")
+      {
+        std::string_view data = R"(
+let prev : Z -> Z, z -> z-1;
+prev(3 + .24);
+)";
+
+        CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"});
+      }
+    }
   }
 }
diff --git a/tests/test_FunctionProcessor.cpp b/tests/test_FunctionProcessor.cpp
index c28b196ef..be13e0315 100644
--- a/tests/test_FunctionProcessor.cpp
+++ b/tests/test_FunctionProcessor.cpp
@@ -67,34 +67,6 @@ TEST_CASE("FunctionProcessor", "[language]")
           std::string_view data = R"(
 let f : B -> B, b -> not b;
 B b = f(true);
-)";
-          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
-        }
-
-        SECTION("from N")
-        {
-          std::string_view data = R"(
-let f : B -> B, b -> not b;
-N n = 2;
-B b = f(n);
-)";
-          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
-        }
-
-        SECTION("from Z")
-        {
-          std::string_view data = R"(
-let f : B -> B, b -> not b;
-B b = f(0);
-)";
-          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
-        }
-
-        SECTION("from R")
-        {
-          std::string_view data = R"(
-let f : B -> B, b -> not b;
-B b = f(0.3);
 )";
           CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
         }
@@ -126,15 +98,6 @@ B b = f(n);
           std::string_view data = R"(
 let f : N -> B, (n) -> (n > 2);
 B b = f(2);
-)";
-          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
-        }
-
-        SECTION("from R")
-        {
-          std::string_view data = R"(
-let f : N -> B, n -> n > 2;
-B b = f(2.3);
 )";
           CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
         }
@@ -166,15 +129,6 @@ B b = f(n);
           std::string_view data = R"(
 let f : Z -> B, z -> (z-3 >= 0);
 B b = f(2);
-)";
-          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
-        }
-
-        SECTION("from R")
-        {
-          std::string_view data = R"(
-let f : Z -> B, (z) -> z-3 > 0;
-B b = f(3.3);
 )";
           CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
         }
-- 
GitLab