diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp
index b958907ab7f9d2c1e5f1852cd27977ec404a7e5b..936236d1c3dd1fd3e25c739fc7edc53e287293c4 100644
--- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp
+++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp
@@ -3,64 +3,73 @@
 
 #include <SymbolTable.hpp>
 
+#include <ASTNodeDataTypeFlattener.hpp>
+
 #include <node_processor/CFunctionProcessor.hpp>
 
-PUGS_INLINE std::unique_ptr<INodeProcessor>
-ASTNodeCFunctionExpressionBuilder::_getArgumentProcessor(const ASTNodeDataType& parameter_type, ASTNode& argument_node)
+PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter>
+ASTNodeCFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeDataType& parameter_type,
+                                                         const ASTNodeSubDataType& argument_node_sub_data_type,
+                                                         const size_t argument_number)
 {
-  auto get_function_argument_processor_for = [&](const auto& parameter_v) -> std::unique_ptr<INodeProcessor> {
+  auto get_function_argument_converter_for =
+    [&](const auto& parameter_v) -> std::unique_ptr<IFunctionArgumentConverter> {
     using ParameterT = std::decay_t<decltype(parameter_v)>;
-    switch (argument_node.m_data_type) {
+    switch (argument_node_sub_data_type.m_data_type) {
     case ASTNodeDataType::bool_t: {
-      return std::make_unique<CFunctionArgumentProcessor<ParameterT, bool>>(argument_node);
+      return std::make_unique<FunctionArgumentConverter<ParameterT, bool>>(argument_number);
     }
     case ASTNodeDataType::unsigned_int_t: {
-      return std::make_unique<CFunctionArgumentProcessor<ParameterT, uint64_t>>(argument_node);
+      return std::make_unique<FunctionArgumentConverter<ParameterT, uint64_t>>(argument_number);
     }
     case ASTNodeDataType::int_t: {
-      return std::make_unique<CFunctionArgumentProcessor<ParameterT, int64_t>>(argument_node);
+      return std::make_unique<FunctionArgumentConverter<ParameterT, int64_t>>(argument_number);
     }
     case ASTNodeDataType::double_t: {
-      return std::make_unique<CFunctionArgumentProcessor<ParameterT, double>>(argument_node);
+      return std::make_unique<FunctionArgumentConverter<ParameterT, double>>(argument_number);
     }
     default: {
-      throw parse_error("invalid argument type for function", std::vector{argument_node.begin()});
+      throw parse_error("invalid argument type for function",
+                        std::vector{argument_node_sub_data_type.m_parent_node.begin()});
     }
     }
   };
 
-  auto get_function_argument_processor_for_argument_type = [&]() {
+  auto get_function_argument_converter_for_argument_type = [&]() {
     switch (parameter_type) {
     case ASTNodeDataType::bool_t: {
-      return get_function_argument_processor_for(bool{});
+      return get_function_argument_converter_for(bool{});
     }
     case ASTNodeDataType::unsigned_int_t: {
-      return get_function_argument_processor_for(uint64_t{});
+      return get_function_argument_converter_for(uint64_t{});
     }
     case ASTNodeDataType::int_t: {
-      return get_function_argument_processor_for(int64_t{});
+      return get_function_argument_converter_for(int64_t{});
     }
     case ASTNodeDataType::double_t: {
-      return get_function_argument_processor_for(double{});
+      return get_function_argument_converter_for(double{});
     }
     default: {
-      throw parse_error("unexpected error: undefined parameter type for function", std::vector{argument_node.begin()});
+      throw parse_error("unexpected error: undefined parameter type for function",
+                        std::vector{argument_node_sub_data_type.m_parent_node.begin()});
     }
     }
   };
 
-  return get_function_argument_processor_for_argument_type();
+  return get_function_argument_converter_for_argument_type();
 }
 
 PUGS_INLINE
 void
-ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list,
-                                                           const size_t argument_number,
-                                                           ASTNode& argument_node,
-                                                           CFunctionProcessor& c_function_processor)
+ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(
+  const std::vector<ASTNodeDataType>& parameter_type_list,
+  const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list,
+  const size_t argument_number,
+  CFunctionProcessor& c_function_processor)
 {
-  c_function_processor.addArgumentProcessor(
-    this->_getArgumentProcessor(parameter_type_list[argument_number], argument_node));
+  c_function_processor.addArgumentConverter(this->_getArgumentConverter(parameter_type_list[argument_number],
+                                                                        flattened_datatype_list[argument_number],
+                                                                        argument_number));
 }
 
 PUGS_INLINE
@@ -71,9 +80,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS
 {
   ASTNode& argument_nodes = *node.children[1];
 
-  const size_t arguments_number =
-    argument_nodes.is_type<language::function_argument_list>() ? argument_nodes.children.size() : 1;
+  ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list;
+  ASTNodeDataTypeFlattener{argument_nodes, flattened_datatype_list};
 
+  const size_t arguments_number  = flattened_datatype_list.size();
   const size_t parameters_number = parameter_type_list.size();
 
   if (arguments_number != parameters_number) {
@@ -85,11 +95,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS
 
   if (arguments_number > 1) {
     for (size_t i = 0; i < arguments_number; ++i) {
-      ASTNode& argument_node = *argument_nodes.children[i];
-      this->_storeArgumentProcessor(parameter_type_list, i, argument_node, c_function_processor);
+      this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, i, c_function_processor);
     }
   } else {
-    this->_storeArgumentProcessor(parameter_type_list, 0, argument_nodes, c_function_processor);
+    this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, 0, c_function_processor);
   }
 }
 
@@ -106,7 +115,8 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no
 
   std::vector<ASTNodeDataType> c_function_parameter_type_list = c_function_embedder->getParameterDataTypes();
 
-  std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>();
+  ASTNode& argument_nodes              = *node.children[1];
+  std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>(argument_nodes);
 
   this->_buildArgumentProcessors(c_function_parameter_type_list, node, *c_function_processor);
 
diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.hpp b/src/language/ASTNodeCFunctionExpressionBuilder.hpp
index db4533bdb16dbe4ce332476ac1d768ccf43097eb..267e4223868eed72c63dd7c19b7f0c1f75ffb6fb 100644
--- a/src/language/ASTNodeCFunctionExpressionBuilder.hpp
+++ b/src/language/ASTNodeCFunctionExpressionBuilder.hpp
@@ -4,18 +4,23 @@
 #include <ASTNode.hpp>
 #include <node_processor/INodeProcessor.hpp>
 
+#include <ASTNodeDataTypeFlattener.hpp>
+
 class CFunctionProcessor;
+class IFunctionArgumentConverter;
 
 class ASTNodeCFunctionExpressionBuilder
 {
  private:
-  PUGS_INLINE std::unique_ptr<INodeProcessor> _getArgumentProcessor(const ASTNodeDataType& parameter_type,
-                                                                    ASTNode& argument_node);
+  PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter> _getArgumentConverter(
+    const ASTNodeDataType& parameter_type,
+    const ASTNodeSubDataType& argument_node_sub_data_type,
+    const size_t argument_number);
 
   PUGS_INLINE
   void _storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list,
+                               const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list,
                                const size_t argument_number,
-                               ASTNode& argument_node,
                                CFunctionProcessor& c_function_processor);
 
   PUGS_INLINE
diff --git a/src/language/node_processor/CFunctionProcessor.hpp b/src/language/node_processor/CFunctionProcessor.hpp
index 5c5f3c82be16563435fb4e8485c4502f53b941cc..e41eb2ca456fab00138cb0df4b6b279c04be6124 100644
--- a/src/language/node_processor/CFunctionProcessor.hpp
+++ b/src/language/node_processor/CFunctionProcessor.hpp
@@ -7,25 +7,7 @@
 
 #include <CFunctionEmbedder.hpp>
 
-template <typename ExpectedValueType, typename ProvidedValueType>
-class CFunctionArgumentProcessor final : public INodeProcessor
-{
- private:
-  ASTNode& m_provided_value_node;
-
- public:
-  DataVariant
-  execute(ExecutionPolicy& exec_policy)
-  {
-    if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) {
-      return m_provided_value_node.execute(exec_policy);
-    } else {
-      return static_cast<ExpectedValueType>(std::get<ProvidedValueType>(m_provided_value_node.execute(exec_policy)));
-    }
-  }
-
-  CFunctionArgumentProcessor(ASTNode& provided_value_node) : m_provided_value_node{provided_value_node} {}
-};
+#include <node_processor/FunctionArgumentConverter.hpp>
 
 class CFunctionExpressionProcessor final : public INodeProcessor
 {
@@ -47,15 +29,17 @@ class CFunctionExpressionProcessor final : public INodeProcessor
 class CFunctionProcessor : public INodeProcessor
 {
  private:
+  ASTNode& m_argument_node;
+
   std::unique_ptr<INodeProcessor> m_function_expression_processor;
 
-  std::vector<std::unique_ptr<INodeProcessor>> m_argument_processors;
+  std::vector<std::unique_ptr<IFunctionArgumentConverter>> m_argument_converters;
 
  public:
   void
-  addArgumentProcessor(std::unique_ptr<INodeProcessor>&& argument_processor)
+  addArgumentConverter(std::unique_ptr<IFunctionArgumentConverter>&& argument_converter)
   {
-    m_argument_processors.emplace_back(std::move(argument_processor));
+    m_argument_converters.emplace_back(std::move(argument_converter));
   }
 
   void
@@ -69,17 +53,22 @@ class CFunctionProcessor : public INodeProcessor
   {
     ExecutionPolicy context_exec_policy{exec_policy,
                                         ExecutionPolicy::Context{-1, std::make_shared<ExecutionPolicy::Context::Values>(
-                                                                       m_argument_processors.size())}};
-    auto& argument_values = context_exec_policy.currentContext();
+                                                                       m_argument_converters.size())}};
+    if (m_argument_converters.size() == 1) {
+      m_argument_converters[0]->convert(context_exec_policy, m_argument_node.execute(context_exec_policy));
+    } else {
+      AggregateDataVariant argument_values{
+        std::get<AggregateDataVariant>(m_argument_node.execute(context_exec_policy))};
 
-    for (size_t i = 0; i < argument_values.size(); ++i) {
-      argument_values[i] = m_argument_processors[i]->execute(context_exec_policy);
+      for (size_t i = 0; i < m_argument_converters.size(); ++i) {
+        m_argument_converters[i]->convert(context_exec_policy, std::move(argument_values[i]));
+      }
     }
 
     return m_function_expression_processor->execute(context_exec_policy);
   }
 
-  CFunctionProcessor() = default;
+  CFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {}
 };
 
 #endif   // CFUNCTION_PROCESSOR_HPP