diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 7f8cd3eb99933803d286251158dcc810f0b0c194..2e09aee48cb59acd13aecf8057b8db42ed1598dc 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable (unit_tests
   test_ExecUntilBreakOrContinue.cpp
   test_FakeProcessor.cpp
   test_ForProcessor.cpp
+  test_FunctionProcessor.cpp
   test_FunctionTable.cpp
   test_IfProcessor.cpp
   test_IncDecExpressionProcessor.cpp
diff --git a/tests/test_FunctionProcessor.cpp b/tests/test_FunctionProcessor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4e2ea79a3462f3183c193903d6d3c27f6fb8e64
--- /dev/null
+++ b/tests/test_FunctionProcessor.cpp
@@ -0,0 +1,304 @@
+#include <catch2/catch.hpp>
+
+#include <ASTNodeValueBuilder.hpp>
+
+#include <ASTBuilder.hpp>
+#include <ASTNodeDataTypeBuilder.hpp>
+
+#include <ASTNodeDeclarationToAffectationConverter.hpp>
+#include <ASTNodeTypeCleaner.hpp>
+
+#include <ASTNodeExpressionBuilder.hpp>
+
+#include <ASTNodeAffectationExpressionBuilder.hpp>
+
+#include <ASTSymbolTableBuilder.hpp>
+
+#include <ASTPrinter.hpp>
+
+#include <Demangle.hpp>
+
+#include <PEGGrammar.hpp>
+
+#include <sstream>
+
+#define CHECK_FUNCTION_EVALUATION_RESULT(data, variable_name, expected_value) \
+  {                                                                           \
+    string_input input{data, "test.pgs"};                                     \
+    auto ast = ASTBuilder::build(input);                                      \
+                                                                              \
+    ASTSymbolTableBuilder{*ast};                                              \
+    ASTNodeDataTypeBuilder{*ast};                                             \
+    ASTNodeValueBuilder{*ast};                                                \
+                                                                              \
+    ASTNodeDeclarationToAffectationConverter{*ast};                           \
+    ASTNodeTypeCleaner<language::declaration>{*ast};                          \
+    ASTNodeTypeCleaner<language::let_declaration>{*ast};                      \
+                                                                              \
+    ASTNodeExpressionBuilder{*ast};                                           \
+    ExecUntilBreakOrContinue exec_policy;                                     \
+    ast->execute(exec_policy);                                                \
+                                                                              \
+    auto symbol_table = ast->m_symbol_table;                                  \
+                                                                              \
+    using namespace TAO_PEGTL_NAMESPACE;                                      \
+    position use_position{internal::iterator{"fixture"}, "fixture"};          \
+    use_position.byte    = 10000;                                             \
+    auto [symbol, found] = symbol_table->find(variable_name, use_position);   \
+                                                                              \
+    auto attributes = symbol->attributes();                                   \
+    auto value      = std::get<decltype(expected_value)>(attributes.value()); \
+                                                                              \
+    REQUIRE(value == expected_value);                                         \
+  }
+
+TEST_CASE("FunctionProcessor", "[language]")
+{
+  SECTION("Scalar functions")
+  {
+    SECTION("-> B")
+    {
+      SECTION("B -> B")
+      {
+        SECTION("from B")
+        {
+          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);
+        }
+      }
+
+      SECTION("N -> B")
+      {
+        SECTION("from B")
+        {
+          std::string_view data = R"(
+let f : N -> B, n -> n > 2;
+B b = f(true);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
+        }
+
+        SECTION("from N")
+        {
+          std::string_view data = R"(
+let f : N -> B, n -> n > 2;
+N n = 3;
+B b = f(n);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
+        }
+
+        SECTION("from Z")
+        {
+          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);
+        }
+      }
+
+      SECTION("Z -> B")
+      {
+        SECTION("from B")
+        {
+          std::string_view data = R"(
+let f : Z -> B, z -> z-3 >= 0;
+B b = f(true);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
+        }
+
+        SECTION("from N")
+        {
+          std::string_view data = R"(
+let f : Z -> B, z -> z-3 >= 0;
+N n = 3;
+B b = f(n);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
+        }
+
+        SECTION("from Z")
+        {
+          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);
+        }
+      }
+
+      SECTION("R -> B")
+      {
+        SECTION("from B")
+        {
+          std::string_view data = R"(
+let f : R -> B, x -> x*x < 4;
+B b = f(true);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
+        }
+
+        SECTION("from N")
+        {
+          std::string_view data = R"(
+let f : R -> B, x -> x*x < 4;
+N n = 3;
+B b = f(n);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
+        }
+
+        SECTION("from Z")
+        {
+          std::string_view data = R"(
+let f : R -> B, x -> x*x < 4;
+B b = f(-2);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", false);
+        }
+
+        SECTION("from R")
+        {
+          std::string_view data = R"(
+let f : R -> B, x -> x*x < 4;
+B b = f(-1.3);
+)";
+          CHECK_FUNCTION_EVALUATION_RESULT(data, "b", true);
+        }
+      }
+    }
+
+    SECTION("-> N")
+    {
+      SECTION("from N*N")
+      {
+        std::string_view data = R"(
+let f : N*N -> N, (m,n) -> m*n;
+N n = f(2,4);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul);
+      }
+
+      SECTION("from Z*Z")
+      {
+        std::string_view data = R"(
+let f : Z*Z -> N, (p,q) -> p*q;
+N n = f(-2,-4);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "n", 8ul);
+      }
+    }
+
+    SECTION("-> Z")
+    {
+      SECTION("from N*N")
+      {
+        std::string_view data = R"(
+let f : N*N -> Z, (m,n) -> m*n;
+Z z = f(2,4);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "z", 8l);
+      }
+
+      SECTION("from Z*Z")
+      {
+        std::string_view data = R"(
+let f : Z*Z -> Z, (p,q) -> p*q;
+Z z = f(-2,4);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "z", -8l);
+      }
+
+      SECTION("from R*Z")
+      {
+        std::string_view data = R"(
+let f : R*Z -> Z, (p,q) -> p*q;
+Z z = f(-0.5,8);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "z", -4l);
+      }
+    }
+
+    SECTION("-> R")
+    {
+      SECTION("from N*R")
+      {
+        std::string_view data = R"(
+let f : N*R -> R, (n,x) -> n*x;
+R r = f(2,4.2);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{2ul * 4.2});
+      }
+
+      SECTION("from R")
+      {
+        std::string_view data = R"(
+let f : R -> R, x -> x*x-1;
+R r = f(4);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "r", double{15});
+      }
+
+      SECTION("from R using global variable")
+      {
+        std::string_view data = R"(
+R x0 = 3;
+let f : R -> R, x -> x-x0;
+R x = f(7.3);
+)";
+        CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{7.3 - 3});
+      }
+    }
+  }
+}