From 39e8b549fc85056334c7890c026e6a55c34c4ff3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Tue, 17 Nov 2020 16:32:24 +0100
Subject: [PATCH] Change unary operator expression builder

One now use OperatorRepository
---
 .../ASTNodeUnaryOperatorExpressionBuilder.cpp | 106 ++++--------------
 .../UnaryExpressionProcessor.hpp              |   2 +-
 src/language/utils/AffectationMangler.hpp     |   4 +-
 src/language/utils/CMakeLists.txt             |  23 ++--
 .../utils/IUnaryOperatorProcessorBuilder.hpp  |  17 +++
 src/language/utils/OperatorRepository.cpp     |  16 +++
 src/language/utils/OperatorRepository.hpp     |  23 ++++
 src/language/utils/UnaryOperatorMangler.hpp   |  32 ++++++
 .../utils/UnaryOperatorProcessorBuilder.hpp   |  24 ++++
 .../utils/UnaryOperatorRegisterForB.cpp       |  32 ++++++
 .../utils/UnaryOperatorRegisterForB.hpp       |  16 +++
 .../utils/UnaryOperatorRegisterForN.cpp       |  21 ++++
 .../utils/UnaryOperatorRegisterForN.hpp       |  15 +++
 .../utils/UnaryOperatorRegisterForR.cpp       |  20 ++++
 .../utils/UnaryOperatorRegisterForR.hpp       |  15 +++
 .../utils/UnaryOperatorRegisterForR1.cpp      |  20 ++++
 .../utils/UnaryOperatorRegisterForR1.hpp      |  15 +++
 .../utils/UnaryOperatorRegisterForR2.cpp      |  20 ++++
 .../utils/UnaryOperatorRegisterForR2.hpp      |  15 +++
 .../utils/UnaryOperatorRegisterForR3.cpp      |  20 ++++
 .../utils/UnaryOperatorRegisterForR3.hpp      |  15 +++
 .../utils/UnaryOperatorRegisterForZ.cpp       |  21 ++++
 .../utils/UnaryOperatorRegisterForZ.hpp       |  15 +++
 ..._ASTNodeUnaryOperatorExpressionBuilder.cpp |  29 +----
 24 files changed, 411 insertions(+), 125 deletions(-)
 create mode 100644 src/language/utils/IUnaryOperatorProcessorBuilder.hpp
 create mode 100644 src/language/utils/UnaryOperatorMangler.hpp
 create mode 100644 src/language/utils/UnaryOperatorProcessorBuilder.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForB.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForB.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForN.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForN.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR1.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR1.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR2.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR2.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR3.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForR3.hpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForZ.cpp
 create mode 100644 src/language/utils/UnaryOperatorRegisterForZ.hpp

diff --git a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
index 7d94c3f58..7781ebae6 100644
--- a/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/src/language/ast/ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -2,99 +2,33 @@
 
 #include <language/PEGGrammar.hpp>
 #include <language/node_processor/UnaryExpressionProcessor.hpp>
+#include <language/utils/OperatorRepository.hpp>
 #include <language/utils/ParseError.hpp>
+#include <language/utils/UnaryOperatorMangler.hpp>
 
 ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n)
 {
-  auto set_unary_operator_processor = [](ASTNode& n, const auto& operator_v) {
-    using OperatorT = std::decay_t<decltype(operator_v)>;
+  const ASTNodeDataType& data_type = n.children[0]->m_data_type;
 
-    auto set_unary_operator_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
-      using ValueT = std::decay_t<decltype(value)>;
-      switch (data_type) {
-      case ASTNodeDataType::bool_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n);
-        break;
-      }
-      case ASTNodeDataType::unsigned_int_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n);
-        break;
-      }
-      default: {
-        throw ParseError("unexpected error: invalid operand type for unary operator",
-                         std::vector{n.children[0]->begin()});
-      }
-      }
-    };
+  const std::string unary_operator_name = [&] {
+    if (n.is_type<language::unary_minus>()) {
+      return unaryOperatorMangler<language::unary_minus>(data_type);
+    } else if (n.is_type<language::unary_not>()) {
+      return unaryOperatorMangler<language::unary_not>(data_type);
+    } else {
+      throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
+    }
+  }();
 
-    auto set_unary_operator_processor_for_value = [&](const ASTNodeDataType& value_type) {
-      const ASTNodeDataType data_type = n.children[0]->m_data_type;
-      switch (value_type) {
-      case ASTNodeDataType::bool_t: {
-        set_unary_operator_processor_for_data(bool{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::int_t: {
-        set_unary_operator_processor_for_data(int64_t{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::double_t: {
-        set_unary_operator_processor_for_data(double{}, data_type);
-        break;
-      }
-      case ASTNodeDataType::vector_t: {
-        if constexpr (std::is_same_v<OperatorT, language::unary_minus>) {
-          switch (data_type.dimension()) {
-          case 1: {
-            using ValueT       = TinyVector<1>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-          case 2: {
-            using ValueT       = TinyVector<2>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-          case 3: {
-            using ValueT       = TinyVector<3>;
-            n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
-            break;
-          }
-            // LCOV_EXCL_START
-          default: {
-            throw ParseError("unexpected error: invalid vector dimension", std::vector{n.begin()});
-          }
-            // LCOV_EXCL_STOP
-          }
-        } else {
-          // LCOV_EXCL_START
-          throw ParseError("unexpected error: invalid unary operator for vector data", std::vector{n.begin()});
-          // LCOV_EXCL_STOP
-        }
-        break;
-      }
-      default: {
-        throw ParseError("undefined value type for unary operator", std::vector{n.begin()});
-      }
-      }
-    };
+  const auto& optional_processor_builder = OperatorRepository::instance().getUnaryProcessorBuilder(unary_operator_name);
 
-    set_unary_operator_processor_for_value(n.m_data_type);
-  };
-
-  if (n.is_type<language::unary_minus>()) {
-    set_unary_operator_processor(n, language::unary_minus{});
-  } else if (n.is_type<language::unary_not>()) {
-    set_unary_operator_processor(n, language::unary_not{});
+  if (optional_processor_builder.has_value()) {
+    n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
   } else {
-    throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
+    std::ostringstream error_message;
+    error_message << "undefined unary operator type: ";
+    error_message << rang::fgB::red << unary_operator_name << rang::fg::reset;
+
+    throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
   }
 }
diff --git a/src/language/node_processor/UnaryExpressionProcessor.hpp b/src/language/node_processor/UnaryExpressionProcessor.hpp
index c99c7f2dd..055e3a028 100644
--- a/src/language/node_processor/UnaryExpressionProcessor.hpp
+++ b/src/language/node_processor/UnaryExpressionProcessor.hpp
@@ -2,8 +2,8 @@
 #define UNARY_EXPRESSION_PROCESSOR_HPP
 
 #include <language/PEGGrammar.hpp>
+#include <language/ast/ASTNode.hpp>
 #include <language/node_processor/INodeProcessor.hpp>
-#include <language/utils/SymbolTable.hpp>
 
 template <typename Op>
 struct UnaryOp;
diff --git a/src/language/utils/AffectationMangler.hpp b/src/language/utils/AffectationMangler.hpp
index b128da936..85aaab35b 100644
--- a/src/language/utils/AffectationMangler.hpp
+++ b/src/language/utils/AffectationMangler.hpp
@@ -33,9 +33,7 @@ affectationMangler(const ASTNodeDataType& lhs, const ASTNodeDataType& rhs)
     } else if constexpr (std::is_same_v<language::minuseq_op, AffectationOperatorT>) {
       return "-=";
     } else {
-      // LCOV_EXCL_START
-      throw UnexpectedError("undefined affectation operator");
-      // LCOV_EXCL_STOP
+      static_assert(std::is_same_v<language::eq_op, AffectationOperatorT>, "undefined affectation operator");
     }
   }();
 
diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt
index aee593608..e44c4f664 100644
--- a/src/language/utils/CMakeLists.txt
+++ b/src/language/utils/CMakeLists.txt
@@ -1,14 +1,14 @@
 # ------------------- Source files --------------------
 
 add_library(PugsLanguageUtils
-  AffectationRegisterForB
-  AffectationRegisterForN
-  AffectationRegisterForR
-  AffectationRegisterForR1
-  AffectationRegisterForR2
-  AffectationRegisterForR3
-  AffectationRegisterForString
-  AffectationRegisterForZ
+  AffectationRegisterForB.cpp
+  AffectationRegisterForN.cpp
+  AffectationRegisterForR.cpp
+  AffectationRegisterForR1.cpp
+  AffectationRegisterForR2.cpp
+  AffectationRegisterForR3.cpp
+  AffectationRegisterForString.cpp
+  AffectationRegisterForZ.cpp
   ASTDotPrinter.cpp
   ASTExecutionInfo.cpp
   ASTNodeDataType.cpp
@@ -16,6 +16,13 @@ add_library(PugsLanguageUtils
   DataVariant.cpp
   EmbeddedData.cpp
   OperatorRepository.cpp
+  UnaryOperatorRegisterForB.cpp
+  UnaryOperatorRegisterForN.cpp
+  UnaryOperatorRegisterForR.cpp
+  UnaryOperatorRegisterForR1.cpp
+  UnaryOperatorRegisterForR2.cpp
+  UnaryOperatorRegisterForR3.cpp
+  UnaryOperatorRegisterForZ.cpp
   )
 
 
diff --git a/src/language/utils/IUnaryOperatorProcessorBuilder.hpp b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
new file mode 100644
index 000000000..7aca7c2c2
--- /dev/null
+++ b/src/language/utils/IUnaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,17 @@
+#ifndef I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+class ASTNode;
+class INodeProcessor;
+
+#include <memory>
+
+class IUnaryOperatorProcessorBuilder
+{
+ public:
+  virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
+
+  virtual ~IUnaryOperatorProcessorBuilder() = default;
+};
+
+#endif   // I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/OperatorRepository.cpp b/src/language/utils/OperatorRepository.cpp
index cbd520dd4..8bfcda61f 100644
--- a/src/language/utils/OperatorRepository.cpp
+++ b/src/language/utils/OperatorRepository.cpp
@@ -9,6 +9,13 @@
 #include <language/utils/AffectationRegisterForR3.hpp>
 #include <language/utils/AffectationRegisterForString.hpp>
 #include <language/utils/AffectationRegisterForZ.hpp>
+#include <language/utils/UnaryOperatorRegisterForB.hpp>
+#include <language/utils/UnaryOperatorRegisterForN.hpp>
+#include <language/utils/UnaryOperatorRegisterForR.hpp>
+#include <language/utils/UnaryOperatorRegisterForR1.hpp>
+#include <language/utils/UnaryOperatorRegisterForR2.hpp>
+#include <language/utils/UnaryOperatorRegisterForR3.hpp>
+#include <language/utils/UnaryOperatorRegisterForZ.hpp>
 
 #include <utils/PugsAssert.hpp>
 
@@ -18,6 +25,7 @@ void
 OperatorRepository::reset()
 {
   m_affectation_builder_list.clear();
+  m_unary_operator_builder_list.clear();
   this->_initialize();
 }
 
@@ -48,4 +56,12 @@ OperatorRepository::_initialize()
   AffectationRegisterForR2{};
   AffectationRegisterForR3{};
   AffectationRegisterForString{};
+
+  UnaryOperatorRegisterForB{};
+  UnaryOperatorRegisterForN{};
+  UnaryOperatorRegisterForZ{};
+  UnaryOperatorRegisterForR{};
+  UnaryOperatorRegisterForR1{};
+  UnaryOperatorRegisterForR2{};
+  UnaryOperatorRegisterForR3{};
 }
diff --git a/src/language/utils/OperatorRepository.hpp b/src/language/utils/OperatorRepository.hpp
index 509410d98..7cc0ae241 100644
--- a/src/language/utils/OperatorRepository.hpp
+++ b/src/language/utils/OperatorRepository.hpp
@@ -5,6 +5,8 @@
 #include <language/utils/ASTNodeDataType.hpp>
 #include <language/utils/AffectationMangler.hpp>
 #include <language/utils/IAffectationProcessorBuilder.hpp>
+#include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
+#include <language/utils/UnaryOperatorMangler.hpp>
 
 #include <utils/Exceptions.hpp>
 
@@ -14,6 +16,7 @@ class OperatorRepository
 {
  private:
   std::unordered_map<std::string, std::shared_ptr<const IAffectationProcessorBuilder>> m_affectation_builder_list;
+  std::unordered_map<std::string, std::shared_ptr<const IUnaryOperatorProcessorBuilder>> m_unary_operator_builder_list;
 
   void _initialize();
 
@@ -32,6 +35,16 @@ class OperatorRepository
     }
   }
 
+  template <typename OperatorTypeT, typename UnaryProcessorBuilderT>
+  void
+  addUnaryOperator(const ASTNodeDataType& operand, const std::shared_ptr<UnaryProcessorBuilderT>& processor_builder)
+  {
+    const std::string unary_operator_type_name = unaryOperatorMangler<OperatorTypeT>(operand);
+    if (not m_unary_operator_builder_list.try_emplace(unary_operator_type_name, processor_builder).second) {
+      throw UnexpectedError(unary_operator_type_name + " has already an entry");
+    }
+  }
+
   std::optional<std::shared_ptr<const IAffectationProcessorBuilder>>
   getAffectationProcessorBuilder(const std::string& affectation_name) const
   {
@@ -42,6 +55,16 @@ class OperatorRepository
     return {};
   }
 
+  std::optional<std::shared_ptr<const IUnaryOperatorProcessorBuilder>>
+  getUnaryProcessorBuilder(const std::string& affectation_name) const
+  {
+    auto&& processor_builder = m_unary_operator_builder_list.find(affectation_name);
+    if (processor_builder != m_unary_operator_builder_list.end()) {
+      return processor_builder->second;
+    }
+    return {};
+  }
+
   static void create();
 
   PUGS_INLINE
diff --git a/src/language/utils/UnaryOperatorMangler.hpp b/src/language/utils/UnaryOperatorMangler.hpp
new file mode 100644
index 000000000..380eb6fa0
--- /dev/null
+++ b/src/language/utils/UnaryOperatorMangler.hpp
@@ -0,0 +1,32 @@
+#ifndef UNARY_OPERATOR_MANGLER_HPP
+#define UNARY_OPERATOR_MANGLER_HPP
+
+#include <language/utils/ASTNodeDataType.hpp>
+#include <utils/Exceptions.hpp>
+
+#include <string>
+
+namespace language
+{
+struct unary_minus;
+struct unary_not;
+}   // namespace language
+
+template <typename UnaryOperatorT>
+std::string
+unaryOperatorMangler(const ASTNodeDataType& operand)
+{
+  const std::string operator_name = [] {
+    if constexpr (std::is_same_v<language::unary_minus, UnaryOperatorT>) {
+      return "-";
+    } else if constexpr (std::is_same_v<language::unary_not, UnaryOperatorT>) {
+      return "not";
+    } else {
+      static_assert(std::is_same_v<language::unary_minus, UnaryOperatorT>, "undefined unary operator");
+    }
+  }();
+
+  return operator_name + " " + dataTypeName(operand);
+}
+
+#endif   // UNARY_OPERATOR_MANGLER_HPP
diff --git a/src/language/utils/UnaryOperatorProcessorBuilder.hpp b/src/language/utils/UnaryOperatorProcessorBuilder.hpp
new file mode 100644
index 000000000..a4a3a22a4
--- /dev/null
+++ b/src/language/utils/UnaryOperatorProcessorBuilder.hpp
@@ -0,0 +1,24 @@
+#ifndef UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+#define UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
+
+#include <algebra/TinyVector.hpp>
+#include <language/PEGGrammar.hpp>
+#include <language/node_processor/UnaryExpressionProcessor.hpp>
+#include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
+
+#include <type_traits>
+
+template <typename OperatorT, typename ValueT, typename DataT>
+class UnaryOperatorProcessorBuilder final : public IUnaryOperatorProcessorBuilder
+{
+ public:
+  UnaryOperatorProcessorBuilder() = default;
+
+  std::unique_ptr<INodeProcessor>
+  getNodeProcessor(ASTNode& node) const
+  {
+    return std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, DataT>>(node);
+  }
+};
+
+#endif   // UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForB.cpp b/src/language/utils/UnaryOperatorRegisterForB.cpp
new file mode 100644
index 000000000..33173e82b
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForB.cpp
@@ -0,0 +1,32 @@
+#include <language/utils/UnaryOperatorRegisterForB.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForB::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, bool>>());
+}
+
+void
+UnaryOperatorRegisterForB::_register_unary_not()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
+
+  repository.addUnaryOperator<
+    language::unary_not>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_not, bool, bool>>());
+}
+
+UnaryOperatorRegisterForB::UnaryOperatorRegisterForB()
+{
+  this->_register_unary_minus();
+  this->_register_unary_not();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForB.hpp b/src/language/utils/UnaryOperatorRegisterForB.hpp
new file mode 100644
index 000000000..8d05dcd0a
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForB.hpp
@@ -0,0 +1,16 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_B_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_B_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForB
+{
+ private:
+  void _register_unary_minus();
+  void _register_unary_not();
+
+ public:
+  UnaryOperatorRegisterForB();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_B_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForN.cpp b/src/language/utils/UnaryOperatorRegisterForN.cpp
new file mode 100644
index 000000000..baed0e43e
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForN.cpp
@@ -0,0 +1,21 @@
+#include <language/utils/UnaryOperatorRegisterForN.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForN::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(N,
+                           std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, uint64_t>>());
+}
+
+UnaryOperatorRegisterForN::UnaryOperatorRegisterForN()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForN.hpp b/src/language/utils/UnaryOperatorRegisterForN.hpp
new file mode 100644
index 000000000..331c3b0b0
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForN.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_N_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_N_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForN
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForN();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_N_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForR.cpp b/src/language/utils/UnaryOperatorRegisterForR.cpp
new file mode 100644
index 000000000..c0c60a31f
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR.cpp
@@ -0,0 +1,20 @@
+#include <language/utils/UnaryOperatorRegisterForR.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForR::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(R, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, double, double>>());
+}
+
+UnaryOperatorRegisterForR::UnaryOperatorRegisterForR()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForR.hpp b/src/language/utils/UnaryOperatorRegisterForR.hpp
new file mode 100644
index 000000000..53edd6af1
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_R_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_R_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForR
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForR();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_R_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForR1.cpp b/src/language/utils/UnaryOperatorRegisterForR1.cpp
new file mode 100644
index 000000000..b225d2eea
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR1.cpp
@@ -0,0 +1,20 @@
+#include <language/utils/UnaryOperatorRegisterForR1.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForR1::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R1 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
+
+  repository.addUnaryOperator<language::unary_minus>(R1, std::make_shared<UnaryOperatorProcessorBuilder<
+                                                           language::unary_minus, TinyVector<1>, TinyVector<1>>>());
+}
+
+UnaryOperatorRegisterForR1::UnaryOperatorRegisterForR1()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForR1.hpp b/src/language/utils/UnaryOperatorRegisterForR1.hpp
new file mode 100644
index 000000000..4ce6b3de8
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR1.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_R1_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_R1_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForR1
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForR1();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_R1_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForR2.cpp b/src/language/utils/UnaryOperatorRegisterForR2.cpp
new file mode 100644
index 000000000..14b61630f
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR2.cpp
@@ -0,0 +1,20 @@
+#include <language/utils/UnaryOperatorRegisterForR2.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForR2::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R2 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
+
+  repository.addUnaryOperator<language::unary_minus>(R2, std::make_shared<UnaryOperatorProcessorBuilder<
+                                                           language::unary_minus, TinyVector<2>, TinyVector<2>>>());
+}
+
+UnaryOperatorRegisterForR2::UnaryOperatorRegisterForR2()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForR2.hpp b/src/language/utils/UnaryOperatorRegisterForR2.hpp
new file mode 100644
index 000000000..9b80db026
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR2.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_R2_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_R2_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForR2
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForR2();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_R2_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForR3.cpp b/src/language/utils/UnaryOperatorRegisterForR3.cpp
new file mode 100644
index 000000000..d288e5eef
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR3.cpp
@@ -0,0 +1,20 @@
+#include <language/utils/UnaryOperatorRegisterForR3.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForR3::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto R3 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
+
+  repository.addUnaryOperator<language::unary_minus>(R3, std::make_shared<UnaryOperatorProcessorBuilder<
+                                                           language::unary_minus, TinyVector<3>, TinyVector<3>>>());
+}
+
+UnaryOperatorRegisterForR3::UnaryOperatorRegisterForR3()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForR3.hpp b/src/language/utils/UnaryOperatorRegisterForR3.hpp
new file mode 100644
index 000000000..4c03d46ce
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForR3.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_R3_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_R3_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForR3
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForR3();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_R3_HPP
diff --git a/src/language/utils/UnaryOperatorRegisterForZ.cpp b/src/language/utils/UnaryOperatorRegisterForZ.cpp
new file mode 100644
index 000000000..89e0b4972
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForZ.cpp
@@ -0,0 +1,21 @@
+#include <language/utils/UnaryOperatorRegisterForZ.hpp>
+
+#include <language/utils/OperatorRepository.hpp>
+#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
+
+void
+UnaryOperatorRegisterForZ::_register_unary_minus()
+{
+  OperatorRepository& repository = OperatorRepository::instance();
+
+  auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>();
+
+  repository.addUnaryOperator<
+    language::unary_minus>(Z,
+                           std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, int64_t>>());
+}
+
+UnaryOperatorRegisterForZ::UnaryOperatorRegisterForZ()
+{
+  this->_register_unary_minus();
+}
diff --git a/src/language/utils/UnaryOperatorRegisterForZ.hpp b/src/language/utils/UnaryOperatorRegisterForZ.hpp
new file mode 100644
index 000000000..c4b3e0015
--- /dev/null
+++ b/src/language/utils/UnaryOperatorRegisterForZ.hpp
@@ -0,0 +1,15 @@
+#ifndef UNARY_OPERATOR_REGISTER_FOR_Z_HPP
+#define UNARY_OPERATOR_REGISTER_FOR_Z_HPP
+
+#include <language/utils/OperatorRepository.hpp>
+
+class UnaryOperatorRegisterForZ
+{
+ private:
+  void _register_unary_minus();
+
+ public:
+  UnaryOperatorRegisterForZ();
+};
+
+#endif   // UNARY_OPERATOR_REGISTER_FOR_Z_HPP
diff --git a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
index cc31b5670..96290c449 100644
--- a/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
+++ b/tests/test_ASTNodeUnaryOperatorExpressionBuilder.cpp
@@ -191,27 +191,13 @@ not b;
 
   SECTION("Errors")
   {
-    SECTION("Invalid unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "unexpected error: undefined unary operator");
-    }
-
-    SECTION("Invalid unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "unexpected error: undefined unary operator");
-    }
-
     SECTION("Invalid value type for unary minus")
     {
       auto ast = std::make_unique<ASTNode>();
       ast->set_type<language::unary_minus>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined value type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined unary operator type: - undefined");
     }
 
     SECTION("errors")
@@ -228,18 +214,7 @@ not b;
       ast->set_type<language::unary_not>();
       ast->children.emplace_back(std::make_unique<ASTNode>());
 
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined value type for unary operator");
-    }
-
-    SECTION("Invalid data type for unary operator")
-    {
-      auto ast = std::make_unique<ASTNode>();
-      ast->set_type<language::unary_minus>();
-      ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::int_t>();
-      ast->children.emplace_back(std::make_unique<ASTNode>());
-
-      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast},
-                          "unexpected error: invalid operand type for unary operator");
+      REQUIRE_THROWS_WITH(ASTNodeUnaryOperatorExpressionBuilder{*ast}, "undefined unary operator type: not undefined");
     }
   }
 }
-- 
GitLab