diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp
index 11a81246597b4b979d21f250343587ec346b1093..42a2f698e2fdb4e57b2c4510ceb87a10b319bcb9 100644
--- a/src/language/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ASTNodeDataTypeBuilder.cpp
@@ -56,6 +56,13 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
 
         n.children[1]->children[0]->m_data_type = ASTNodeDataType::typename_t;
         n.children[1]->children[1]->m_data_type = ASTNodeDataType::typename_t;
+        // build types for compound types
+        for (auto& child : n.children[1]->children[0]->children) {
+          this->_buildNodeDataTypes(*child);
+        }
+        for (auto& child : n.children[1]->children[1]->children) {
+          this->_buildNodeDataTypes(*child);
+        }
 
         {   // Function data type
           const std::string& symbol = n.children[0]->string();
@@ -66,30 +73,51 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
           Assert(found);
           i_symbol->second.setDataType(n.children[0]->m_data_type);
         }
-        auto& type_node = *(n.children[1]->children[0]);
-        ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
-        if (type_node.is<language::B_set>()) {
-          data_type = ASTNodeDataType::bool_t;
-        } else if (type_node.is<language::Z_set>()) {
-          data_type = ASTNodeDataType::int_t;
-        } else if (type_node.is<language::N_set>()) {
-          data_type = ASTNodeDataType::unsigned_int_t;
-        } else if (type_node.is<language::R_set>()) {
-          data_type = ASTNodeDataType::double_t;
-        } else if (type_node.is<language::string_type>()) {
-          data_type = ASTNodeDataType::string_t;
+
+        if (n.children[1]->children[0]->children.size() != n.children[2]->children[0]->children.size()) {
+          std::ostringstream message;
+          message << "Compound data type deduction is not yet implemented\n"
+                  << "note: number of product spaces (" << n.children[1]->children[0]->children.size() << ") "
+                  << rang::fgB::yellow << n.children[1]->children[0]->string() << rang::style::reset
+                  << " differs  from number of variables (" << n.children[2]->children[0]->children.size() << ") "
+                  << rang::fgB::yellow << n.children[2]->children[0]->string() << rang::style::reset << std::ends;
+          throw parse_error(message.str(), n.children[0]->begin());
         }
 
-        Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
+        auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) {
+          ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
+          if (type_node.is<language::B_set>()) {
+            data_type = ASTNodeDataType::bool_t;
+          } else if (type_node.is<language::Z_set>()) {
+            data_type = ASTNodeDataType::int_t;
+          } else if (type_node.is<language::N_set>()) {
+            data_type = ASTNodeDataType::unsigned_int_t;
+          } else if (type_node.is<language::R_set>()) {
+            data_type = ASTNodeDataType::double_t;
+          } else if (type_node.is<language::string_type>()) {
+            data_type = ASTNodeDataType::string_t;
+          }
+
+          Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
+
+          symbol_node.m_data_type   = data_type;
+          const std::string& symbol = symbol_node.string();
 
-        n.children[2]->children[0]->m_data_type = data_type;
-        const std::string& symbol               = n.children[2]->children[0]->string();
+          std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
 
-        std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
+          auto [i_symbol, found] = symbol_table->find(symbol, symbol_node.begin());
+          Assert(found);
+          i_symbol->second.setDataType(data_type);
+        };
+
+        if (n.children[1]->children[0]->children.size() == 0) {
+          simple_type_allocator(*n.children[1]->children[0], *n.children[2]->children[0]);
+        } else {
+          for (size_t i = 0; i < n.children[1]->children[0]->children.size(); ++i) {
+            simple_type_allocator(*n.children[1]->children[0]->children[i], *n.children[2]->children[0]->children[i]);
+          }
+        }
 
-        auto [i_symbol, found] = symbol_table->find(symbol, n.children[2]->children[0]->begin());
-        Assert(found);
-        i_symbol->second.setDataType(data_type);
         n.m_data_type = ASTNodeDataType::void_t;
       } else if (n.is<language::name>()) {
         std::shared_ptr<SymbolTable>& symbol_table = n.m_symbol_table;
@@ -173,6 +201,11 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
     } else if (n.is<language::function_evaluation>()) {
       std::cout << rang::fgB::red << "returned type of function evaluation is incorrect" << rang::style::reset << "\n";
       n.m_data_type = ASTNodeDataType::double_t;
+    } else if (n.is<language::B_set>() or n.is<language::Z_set>() or n.is<language::N_set>() or
+               n.is<language::R_set>() or n.is<language::string_type>()) {
+      n.m_data_type = ASTNodeDataType::typename_t;
+    } else if (n.is<language::name_list>() or n.is<language::expression_list>()) {
+      n.m_data_type = ASTNodeDataType::void_t;
     }
   }
 }
diff --git a/src/language/ASTSymbolTableBuilder.cpp b/src/language/ASTSymbolTableBuilder.cpp
index 8bbb6cf6d7002a23b4e74d5c8647f186f6c2ead0..3d0ad6942073f98366549cc6bc0e5ef70680be1d 100644
--- a/src/language/ASTSymbolTableBuilder.cpp
+++ b/src/language/ASTSymbolTableBuilder.cpp
@@ -22,7 +22,7 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable>
     auto [i_symbol, success]           = symbol_table->add(symbol, n.children[0]->begin());
     if (not success) {
       std::ostringstream error_message;
-      error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!";
+      error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!";
       throw parse_error(error_message.str(), std::vector{n.begin()});
     }
 
@@ -37,16 +37,28 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable>
         auto [i_symbol, success]  = symbol_table->add(symbol, n.children[1]->begin());
         if (not success) {
           std::ostringstream error_message;
-          error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!";
+          error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!";
           throw parse_error(error_message.str(), std::vector{n.begin()});
         }
       } else if (n.is<language::function_definition>()) {
-        const std::string& symbol = n.children[0]->string();
-        auto [i_symbol, success]  = symbol_table->add(symbol, n.children[0]->begin());
-        if (not success) {
-          std::ostringstream error_message;
-          error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << '\'' << " was already defined!";
-          throw parse_error(error_message.str(), std::vector{n.begin()});
+        auto register_symbol = [&](const std::string& symbol) {
+          auto [i_symbol, success] = symbol_table->add(symbol, n.children[0]->begin());
+          if (not success) {
+            std::ostringstream error_message;
+            error_message << "symbol '" << rang::fg::red << symbol << rang::fg::reset << "' was already defined!";
+            throw parse_error(error_message.str(), std::vector{n.begin()});
+          }
+          // Symbols will be initialized at call
+          i_symbol->second.setIsInitialized();
+        };
+
+        if (n.children[0]->is<language::name>()) {
+          register_symbol(n.children[0]->string());
+        } else {   // treats the case of list of parameters
+          Assert(n.children[0]->is<language::name_list>());
+          for (auto& child : n.children[0]->children) {
+            register_symbol(child->string());
+          }
         }
       } else if (n.is<language::name>()) {
         auto [i_symbol, found] = symbol_table->find(n.string(), n.begin());
diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp
index 13c16e22362cd19bde2f883fe4738295d7363511..1b40aa888b052f6be4c3c2c004e145abb55726e4 100644
--- a/src/language/PugsParser.cpp
+++ b/src/language/PugsParser.cpp
@@ -57,6 +57,7 @@ parser(const std::string& filename)
     ASTSymbolInitializationChecker{*root_node};
 
     ASTNodeDataTypeBuilder{*root_node};
+
     {
       std::string dot_filename{"parse_tree.dot"};
       std::ofstream fout(dot_filename);