diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp
index 839404a00966c0e61c4d892d303c432f5713f996..f70b8010524899c858795733ca77588d730d899c 100644
--- a/src/language/ASTNodeExpressionBuilder.cpp
+++ b/src/language/ASTNodeExpressionBuilder.cpp
@@ -2,6 +2,7 @@
 
 #include <ASTNodeAffectationExpressionBuilder.hpp>
 #include <ASTNodeBinaryOperatorExpressionBuilder.hpp>
+#include <ASTNodeFunctionExpressionBuilder.hpp>
 #include <ASTNodeIncDecExpressionBuilder.hpp>
 #include <ASTNodeUnaryOperatorExpressionBuilder.hpp>
 
@@ -11,7 +12,6 @@
 #include <node_processor/DoWhileProcessor.hpp>
 #include <node_processor/FakeProcessor.hpp>
 #include <node_processor/ForProcessor.hpp>
-#include <node_processor/FunctionProcessor.hpp>
 #include <node_processor/IfProcessor.hpp>
 #include <node_processor/NameProcessor.hpp>
 #include <node_processor/OStreamProcessor.hpp>
@@ -32,7 +32,7 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n)
     n.m_node_processor = std::make_unique<FakeProcessor>();
 
   } else if (n.is<language::function_evaluation>()) {
-    n.m_node_processor = std::make_unique<FunctionProcessor>(n);
+    ASTNodeFunctionExpressionBuilder{n};
 
   } else if (n.is<language::real>()) {
     n.m_node_processor = std::make_unique<FakeProcessor>();
diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3238d45ba078254f801bff0120ab2bf1ef8124d
--- /dev/null
+++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp
@@ -0,0 +1,76 @@
+#include <ASTNodeFunctionExpressionBuilder.hpp>
+#include <PEGGrammar.hpp>
+
+#include <FunctionTable.hpp>
+#include <SymbolTable.hpp>
+
+#include <node_processor/FunctionProcessor.hpp>
+
+ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node)
+{
+  auto [i_symbol, found] = node.m_symbol_table->find(node.children[0]->string(), node.begin());
+  Assert(found);
+  uint64_t function_id = std::get<uint64_t>(i_symbol->attributes().value());
+
+  FunctionDescriptor& function_descriptor = node.m_symbol_table->functionTable()[function_id];
+
+#warning compute the right value type
+  const ASTNodeDataType return_value_type     = ASTNodeDataType::double_t;
+  const ASTNodeDataType expression_value_type = function_descriptor.definitionNode().children[1]->m_data_type;
+
+  auto set_function_processor = [&](ASTNode& node) {
+    auto set_function_processor_for_expression_value = [&](const auto& return_v) {
+      using ReturnT = std::decay_t<decltype(return_v)>;
+      switch (expression_value_type) {
+      case ASTNodeDataType::bool_t: {
+        node.m_node_processor = std::make_unique<FunctionProcessor<ReturnT, bool>>(node);
+        break;
+      }
+      case ASTNodeDataType::unsigned_int_t: {
+        node.m_node_processor = std::make_unique<FunctionProcessor<ReturnT, uint64_t>>(node);
+        break;
+      }
+      case ASTNodeDataType::int_t: {
+        node.m_node_processor = std::make_unique<FunctionProcessor<ReturnT, int64_t>>(node);
+        break;
+      }
+      case ASTNodeDataType::double_t: {
+        node.m_node_processor = std::make_unique<FunctionProcessor<ReturnT, double>>(node);
+        break;
+      }
+      default: {
+        throw parse_error("unexpected error: undefined expression value type for function",
+                          std::vector{node.children[1]->begin()});
+      }
+      }
+    };
+
+    auto set_function_processor_for_value = [&]() {
+      switch (return_value_type) {
+      case ASTNodeDataType::bool_t: {
+        set_function_processor_for_expression_value(bool{});
+        break;
+      }
+      case ASTNodeDataType::unsigned_int_t: {
+        set_function_processor_for_expression_value(uint64_t{});
+        break;
+      }
+      case ASTNodeDataType::int_t: {
+        set_function_processor_for_expression_value(int64_t{});
+        break;
+      }
+      case ASTNodeDataType::double_t: {
+        set_function_processor_for_expression_value(double{});
+        break;
+      }
+      default: {
+        throw parse_error("unexpected error: undefined return type for function", std::vector{node.begin()});
+      }
+      }
+    };
+
+    set_function_processor_for_value();
+  };
+
+  set_function_processor(node);
+}
diff --git a/src/language/ASTNodeFunctionExpressionBuilder.hpp b/src/language/ASTNodeFunctionExpressionBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..adf3cb48d7b21091289de28297ca2c786f1a6a5e
--- /dev/null
+++ b/src/language/ASTNodeFunctionExpressionBuilder.hpp
@@ -0,0 +1,11 @@
+#ifndef AST_NODE_FUNCTION_EXPRESSION_BUILDER_HPP
+#define AST_NODE_FUNCTION_EXPRESSION_BUILDER_HPP
+
+#include <ASTNode.hpp>
+
+struct ASTNodeFunctionExpressionBuilder
+{
+  ASTNodeFunctionExpressionBuilder(ASTNode& node);
+};
+
+#endif   // AST_NODE_FUNCTION_EXPRESSION_BUILDER_HPP
diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt
index ab42c18cc035467baa7bb3dcccc72d55d53d51a0..1e6777998f93cd2de07d1e416413d2725ae44a0c 100644
--- a/src/language/CMakeLists.txt
+++ b/src/language/CMakeLists.txt
@@ -18,6 +18,7 @@ add_library(
   ASTNodeDeclarationCleaner.cpp
   ASTNodeEmptyBlockCleaner.cpp
   ASTNodeExpressionBuilder.cpp
+  ASTNodeFunctionExpressionBuilder.cpp
   ASTNodeIncDecExpressionBuilder.cpp
   ASTNodeJumpPlacementChecker.cpp
   ASTNodeUnaryOperatorExpressionBuilder.cpp
diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp
index 4527b0b6ebe3dd337b43f71ce7b88a1025d94038..57394f993d26322eb0fc6c8590bcbfaa8c8bc1d5 100644
--- a/src/language/node_processor/FunctionProcessor.hpp
+++ b/src/language/node_processor/FunctionProcessor.hpp
@@ -6,8 +6,11 @@
 
 #include <PEGGrammar.hpp>
 
+#include <ASTPrinter.hpp>
+
 #include <node_processor/INodeProcessor.hpp>
 
+template <typename ReturnType, typename ExpressionValueType>
 class FunctionProcessor final : public INodeProcessor
 {
  private:
@@ -15,9 +18,8 @@ class FunctionProcessor final : public INodeProcessor
 
   FunctionDescriptor& m_function_descriptor;
 
- public:
   void
-  execute(ExecUntilBreakOrContinue& exec_policy)
+  _executeArguments(ExecUntilBreakOrContinue& exec_policy)
   {
     // Compute arguments values
     ASTNode& arguments_values = *m_node.children[1];
@@ -33,15 +35,31 @@ class FunctionProcessor final : public INodeProcessor
       auto [i_symbol, found] = arguments.m_symbol_table->find(arguments.string(), arguments.begin());
       Assert(found);
 
-      i_symbol->attributes().value() = arguments_values.m_value;
+      if (i_symbol->attributes().dataType() == arguments_values.m_data_type) {
+        i_symbol->attributes().value() = arguments_values.m_value;
+      } else {
+        throw parse_error("argument type conversion not implemented yet!", arguments_values.begin());
+      }
     } else {
-      throw parse_error("argument list not implemented yet!", definition_node.children[0]->begin());
+      throw parse_error("argument list not implemented yet!", arguments_values.begin());
     }
+  }
 
+ public:
+  void
+  execute(ExecUntilBreakOrContinue& exec_policy)
+  {
+    this->_executeArguments(exec_policy);
+
+    ASTNode& definition_node     = m_function_descriptor.definitionNode();
     ASTNode& function_expression = *definition_node.children[1];
     function_expression.execute(exec_policy);
 
-    m_node.m_value = function_expression.m_value;
+    if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) {
+      m_node.m_value = function_expression.m_value;
+    } else {
+      m_node.m_value = static_cast<ReturnType>(std::get<ExpressionValueType>(function_expression.m_value));
+    }
   }
 
   FunctionProcessor(ASTNode& node)