From a49fd9c0843a5358f158ab8e1e71f77d94a9b2bf Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Mon, 9 Dec 2019 10:00:08 +0100
Subject: [PATCH] operator registering facility and int operators

---
 alib2abstraction/src/common/EvalHelper.cpp    |  45 +++
 alib2abstraction/src/common/EvalHelper.h      |   7 +
 alib2abstraction/src/common/Operators.cpp     |  17 +
 alib2abstraction/src/common/Operators.hpp     | 123 +++++++
 .../src/registration/OperatorRegistration.hpp |  72 +++++
 .../src/registry/AlgorithmRegistryInfo.hpp    |  27 +-
 .../src/registry/OperatorRegistry.cpp         | 185 +++++++++++
 .../src/registry/OperatorRegistry.hpp         | 299 ++++++++++++++++++
 alib2abstraction/src/registry/Registry.cpp    |  25 ++
 alib2abstraction/src/registry/Registry.h      |   8 +
 .../command/OperatorsIntrospectionCommand.h   |  61 ++++
 alib2cli/src/parser/Parser.cpp                |   4 +
 alib2common/src/PrimitiveRegistrator.cpp      |  43 +++
 13 files changed, 915 insertions(+), 1 deletion(-)
 create mode 100644 alib2abstraction/src/common/Operators.cpp
 create mode 100644 alib2abstraction/src/common/Operators.hpp
 create mode 100644 alib2abstraction/src/registration/OperatorRegistration.hpp
 create mode 100644 alib2abstraction/src/registry/OperatorRegistry.cpp
 create mode 100644 alib2abstraction/src/registry/OperatorRegistry.hpp
 create mode 100644 alib2cli/src/ast/command/OperatorsIntrospectionCommand.h

diff --git a/alib2abstraction/src/common/EvalHelper.cpp b/alib2abstraction/src/common/EvalHelper.cpp
index 1b8e91419b..7edb58f805 100644
--- a/alib2abstraction/src/common/EvalHelper.cpp
+++ b/alib2abstraction/src/common/EvalHelper.cpp
@@ -27,6 +27,51 @@ std::shared_ptr < abstraction::Value > EvalHelper::evalAlgorithm ( const std::st
 	}
 }
 
+std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( Operators::BinaryOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category ) {
+	ext::vector < std::string > paramTypes;
+	ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > paramTypeQualifiers;
+	for ( const std::shared_ptr < abstraction::Value > & param : params ) {
+		paramTypes.push_back ( param->getType ( ) );
+		paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) );
+	}
+
+	try {
+		return evalAbstraction ( Registry::getBinaryOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params, moves );
+	} catch ( ... ) {
+		std::throw_with_nested ( std::runtime_error ( "Evaluation of binary operator " + Operators::toString ( type ) + " failed." ) );
+	}
+}
+
+std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( Operators::PrefixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category ) {
+	ext::vector < std::string > paramTypes;
+	ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > paramTypeQualifiers;
+	for ( const std::shared_ptr < abstraction::Value > & param : params ) {
+		paramTypes.push_back ( param->getType ( ) );
+		paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) );
+	}
+
+	try {
+		return evalAbstraction ( Registry::getPrefixOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params, moves );
+	} catch ( ... ) {
+		std::throw_with_nested ( std::runtime_error ( "Evaluation of prefix operator " + Operators::toString ( type ) + " failed." ) );
+	}
+}
+
+std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( Operators::PostfixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category ) {
+	ext::vector < std::string > paramTypes;
+	ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > paramTypeQualifiers;
+	for ( const std::shared_ptr < abstraction::Value > & param : params ) {
+		paramTypes.push_back ( param->getType ( ) );
+		paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) );
+	}
+
+	try {
+		return evalAbstraction ( Registry::getPostfixOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params, moves );
+	} catch ( ... ) {
+		std::throw_with_nested ( std::runtime_error ( "Evaluation of postfix operator " + Operators::toString ( type ) + " failed." ) );
+	}
+}
+
 std::shared_ptr < abstraction::Value > EvalHelper::evalAbstraction ( std::shared_ptr < abstraction::OperationAbstraction > abstraction, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves ) {
 	unsigned i = 0;
 	ext::vector < std::shared_ptr < abstraction::Value > > casted_params;
diff --git a/alib2abstraction/src/common/EvalHelper.h b/alib2abstraction/src/common/EvalHelper.h
index b7497f7d5e..ab8a1ea871 100644
--- a/alib2abstraction/src/common/EvalHelper.h
+++ b/alib2abstraction/src/common/EvalHelper.h
@@ -12,6 +12,7 @@
 #include <alib/memory>
 #include <alib/vector>
 #include <common/AlgorithmCategories.hpp>
+#include <common/Operators.hpp>
 #include <abstraction/Value.hpp>
 
 namespace abstraction {
@@ -21,6 +22,12 @@ class EvalHelper {
 
 public:
 	static std::shared_ptr < abstraction::Value > evalAlgorithm ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
+
+	static std::shared_ptr < abstraction::Value > evalOperator ( Operators::BinaryOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
+
+	static std::shared_ptr < abstraction::Value > evalOperator ( Operators::PrefixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
+
+	static std::shared_ptr < abstraction::Value > evalOperator ( Operators::PostfixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, const std::vector < bool > & moves, AlgorithmCategories::AlgorithmCategory category );
 };
 
 } /* namespace abstraction */
diff --git a/alib2abstraction/src/common/Operators.cpp b/alib2abstraction/src/common/Operators.cpp
new file mode 100644
index 0000000000..e9ac15183f
--- /dev/null
+++ b/alib2abstraction/src/common/Operators.cpp
@@ -0,0 +1,17 @@
+#include <common/Operators.hpp>
+
+namespace abstraction {
+
+std::ostream & operator << ( std::ostream & os, Operators::BinaryOperators oper ) {
+	return os << Operators::toString ( oper );
+}
+
+std::ostream & operator << ( std::ostream & os, Operators::PrefixOperators oper ) {
+	return os << Operators::toString ( oper );
+}
+
+std::ostream & operator << ( std::ostream & os, Operators::PostfixOperators oper ) {
+	return os << Operators::toString ( oper );
+}
+
+} /* namespace abstraction */
diff --git a/alib2abstraction/src/common/Operators.hpp b/alib2abstraction/src/common/Operators.hpp
new file mode 100644
index 0000000000..4dc5401bcf
--- /dev/null
+++ b/alib2abstraction/src/common/Operators.hpp
@@ -0,0 +1,123 @@
+#ifndef _OPERATORS_HPP_
+#define _OPERATORS_HPP_
+
+#include <alib/string>
+
+namespace abstraction {
+
+class Operators {
+public:
+	enum class BinaryOperators {
+		LOGICAL_AND,
+		LOGICAL_OR,
+		BINARY_XOR,
+		BINARY_AND,
+		BINARY_OR,
+		ADD,
+		SUB,
+		MUL,
+		MOD,
+		DIV,
+		EQUALS,
+		NOT_EQUALS,
+		LESS,
+		LESS_OR_EQUAL,
+		MORE,
+		MORE_OR_EQUAL,
+		ASSIGN
+	};
+
+	enum class PrefixOperators {
+		PLUS,
+		MINUS,
+		LOGICAL_NOT,
+		BINARY_NEG,
+		INCREMENT,
+		DECREMENT
+	};
+
+	enum class PostfixOperators {
+		INCREMENT,
+		DECREMENT
+	};
+
+	static std::string toString ( BinaryOperators type ) {
+		switch ( type ) {
+		case BinaryOperators::BINARY_AND :
+			return "binary_and";
+		case BinaryOperators::BINARY_OR :
+			return "binary_or";
+		case BinaryOperators::BINARY_XOR :
+			return "binary_xor";
+		case BinaryOperators::LOGICAL_AND :
+			return "logical_and";
+		case BinaryOperators::LOGICAL_OR :
+			return "logical_or";
+		case BinaryOperators::ADD :
+			return "add";
+		case BinaryOperators::SUB :
+			return "sub";
+		case BinaryOperators::MUL :
+			return "mul";
+		case BinaryOperators::MOD :
+			return "mod";
+		case BinaryOperators::DIV :
+			return "div";
+		case BinaryOperators::EQUALS :
+			return "equals";
+		case BinaryOperators::NOT_EQUALS :
+			return "not_equals";
+		case BinaryOperators::LESS :
+			return "less";
+		case BinaryOperators::LESS_OR_EQUAL :
+			return "less_or_equal";
+		case BinaryOperators::MORE :
+			return "more";
+		case BinaryOperators::MORE_OR_EQUAL :
+			return "more_or_equal";
+		case BinaryOperators::ASSIGN :
+			return "assign";
+		}
+		throw std::invalid_argument ( "Undefined option" );
+	}
+
+	static std::string toString ( PrefixOperators type ) {
+		switch ( type ) {
+		case PrefixOperators::PLUS :
+			return "plus";
+		case PrefixOperators::MINUS :
+			return "minus";
+		case PrefixOperators::LOGICAL_NOT :
+			return "logical_not";
+		case PrefixOperators::BINARY_NEG :
+			return "binary_neg";
+		case PrefixOperators::INCREMENT :
+			return "increment";
+		case PrefixOperators::DECREMENT :
+			return "decrement";
+		}
+		throw std::invalid_argument ( "Undefined option" );
+	}
+
+	static std::string toString ( PostfixOperators type ) {
+		switch ( type ) {
+		case PostfixOperators::INCREMENT :
+			return "increment";
+		case PostfixOperators::DECREMENT :
+			return "decrement";
+		}
+		throw std::invalid_argument ( "Undefined option" );
+	}
+
+
+};
+
+std::ostream & operator << ( std::ostream & os, Operators::BinaryOperators oper );
+
+std::ostream & operator << ( std::ostream & os, Operators::PrefixOperators oper );
+
+std::ostream & operator << ( std::ostream & os, Operators::PostfixOperators oper );
+
+} /* namespace abstraction */
+
+#endif // _OPERATORS_HPP_
diff --git a/alib2abstraction/src/registration/OperatorRegistration.hpp b/alib2abstraction/src/registration/OperatorRegistration.hpp
new file mode 100644
index 0000000000..c505e42c18
--- /dev/null
+++ b/alib2abstraction/src/registration/OperatorRegistration.hpp
@@ -0,0 +1,72 @@
+#ifndef _OPERATOR_REGISTRATION_HPP_
+#define _OPERATOR_REGISTRATION_HPP_
+
+#include <alib/registration>
+
+#include <registry/OperatorRegistry.hpp>
+
+namespace registration {
+
+template < abstraction::Operators::BinaryOperators Type, class FirstParamType, class SecondParamType >
+class BinaryOperatorRegister : public ext::Register < void > {
+public:
+	template < class ReturnType >
+	BinaryOperatorRegister ( ReturnType ( * callback ) ( FirstParamType, SecondParamType ) ) : ext::Register < void > ( [ = ] ( ) {
+				abstraction::OperatorRegistry::registerBinary < ReturnType, FirstParamType, SecondParamType > ( Type, callback );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterBinary < FirstParamType, SecondParamType > ( Type );
+			} ) {
+	}
+
+	BinaryOperatorRegister ( ) : ext::Register < void > ( [ ] ( ) {
+				abstraction::OperatorRegistry::registerBinary < Type, FirstParamType, SecondParamType > ( );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterBinary < FirstParamType, SecondParamType > ( Type );
+			} ) {
+	}
+
+};
+
+template < abstraction::Operators::PrefixOperators Type, class ParamType >
+class PrefixOperatorRegister : public ext::Register < void > {
+public:
+	template < class ReturnType >
+	PrefixOperatorRegister ( ReturnType ( * callback ) ( ParamType ) ) : ext::Register < void > ( [ = ] ( ) {
+				abstraction::OperatorRegistry::registerPrefix < ReturnType, ParamType > ( Type, callback );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterBinary < ParamType > ( Type );
+			} ) {
+	}
+
+	PrefixOperatorRegister ( ) : ext::Register < void > ( [ ] ( ) {
+				abstraction::OperatorRegistry::registerPrefix < Type, ParamType > ( );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterPrefix < ParamType > ( Type );
+			} ) {
+	}
+
+};
+
+template < abstraction::Operators::PostfixOperators Type, class ParamType >
+class PostfixOperatorRegister : public ext::Register < void > {
+public:
+	template < class ReturnType >
+	PostfixOperatorRegister ( ReturnType ( * callback ) ( ParamType ) ) : ext::Register < void > ( [ = ] ( ) {
+				abstraction::OperatorRegistry::registerPostfix < ReturnType, ParamType > ( Type, callback );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterBinary < ParamType > ( Type );
+			} ) {
+	}
+
+	PostfixOperatorRegister ( ) : ext::Register < void > ( [ ] ( ) {
+				abstraction::OperatorRegistry::registerPostfix < Type, ParamType > ( );
+			}, [ ] ( ) {
+				abstraction::OperatorRegistry::unregisterPostfix < ParamType > ( Type );
+			} ) {
+	}
+
+};
+
+} /* namespace registration */
+
+#endif // _OPERATOR_REGISTRATION_HPP_
diff --git a/alib2abstraction/src/registry/AlgorithmRegistryInfo.hpp b/alib2abstraction/src/registry/AlgorithmRegistryInfo.hpp
index 1545dceb78..f9d9ccea53 100644
--- a/alib2abstraction/src/registry/AlgorithmRegistryInfo.hpp
+++ b/alib2abstraction/src/registry/AlgorithmRegistryInfo.hpp
@@ -9,7 +9,6 @@
 #define _ALGORITHM_REGISTRY_INFO_HPP_
 
 #include <alib/vector>
-#include <alib/set>
 #include <alib/pair>
 #include <alib/typeinfo>
 #include <alib/tuple>
@@ -74,6 +73,15 @@ public:
 
 		return AlgorithmBaseInfo ( category, std::move ( params ) );
 	}
+
+	template < class ... ParamTypes >
+	static AlgorithmBaseInfo operatorEntryInfo ( ) {
+		AlgorithmCategories::AlgorithmCategory category = AlgorithmCategories::AlgorithmCategory::DEFAULT;
+
+		ext::vector < ext::tuple < std::string, abstraction::ParamQualifiers::ParamQualifierSet > > params = convertTypes < ParamTypes ... > ( );
+
+		return AlgorithmBaseInfo ( category, std::move ( params ) );
+	}
 };
 
 class AlgorithmFullInfo : public AlgorithmBaseInfo {
@@ -124,6 +132,23 @@ public:
 		return AlgorithmFullInfo ( AlgorithmBaseInfo::wrapperEntryInfo < ParamTypes ... > ( ), std::move ( parameterNames ), std::move ( result ) );
 	}
 
+	template < class ReturnType, class ... ParamTypes >
+	static AlgorithmFullInfo operatorEntryInfo ( ) {
+		ext::pair < std::string, abstraction::ParamQualifiers::ParamQualifierSet > result = convertType < ReturnType > ( );
+
+		ext::vector < std::string > parameterNames;
+		if constexpr ( sizeof ... ( ParamTypes ) == 1 ) {
+			parameterNames.push_back ( "arg" );
+		} else if constexpr ( sizeof ... ( ParamTypes ) == 2 ) {
+			parameterNames.push_back ( "lhs" );
+			parameterNames.push_back ( "rhs" );
+		} else {
+			static_assert ( "Invalid number of params or operator" );
+		}
+
+		return AlgorithmFullInfo ( AlgorithmBaseInfo::operatorEntryInfo < ParamTypes ... > ( ), std::move ( parameterNames ), std::move ( result ) );
+	}
+
 };
 
 } /* namespace abstraction */
diff --git a/alib2abstraction/src/registry/OperatorRegistry.cpp b/alib2abstraction/src/registry/OperatorRegistry.cpp
new file mode 100644
index 0000000000..861198c94a
--- /dev/null
+++ b/alib2abstraction/src/registry/OperatorRegistry.cpp
@@ -0,0 +1,185 @@
+/*
+ * OperatorRegistry.cpp
+ *
+ *  Created on: 19. 8. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#include <registry/OperatorRegistry.hpp>
+#include <registry/CastRegistry.hpp>
+
+#include <alib/foreach>
+#include <alib/algorithm>
+
+#include <exception>
+
+#include <common/OverloadResolution.hpp>
+
+namespace abstraction {
+
+ext::map < Operators::BinaryOperators, ext::list < std::unique_ptr < OperatorRegistry::BinaryEntry > > > & OperatorRegistry::getBinaryEntries ( ) {
+	static ext::map < Operators::BinaryOperators, ext::list < std::unique_ptr < BinaryEntry > > > algorithmGroups;
+	return algorithmGroups;
+}
+
+bool OperatorRegistry::isRegisteredBinary ( Operators::BinaryOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getBinaryEntries ( ) [ type ];
+
+	for ( const std::unique_ptr < BinaryEntry > & entry : group )
+		if ( entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( ) )
+			return true;
+
+	return false;
+}
+
+void OperatorRegistry::registerBinaryInternal ( Operators::BinaryOperators type, std::unique_ptr < BinaryEntry > value ) {
+	if ( isRegisteredBinary ( type, value->getEntryInfo ( ) ) )
+		throw std::invalid_argument ( "Callback for operator " + Operators::toString ( type ) + " with params " + ext::to_string ( value->getEntryInfo ( ).getParams ( ) ) + " already registered." );
+
+	auto & group = getBinaryEntries ( ) [ type ];
+
+	group.insert ( group.end ( ), std::move ( value ) );
+}
+
+void OperatorRegistry::unregisterBinaryInternal ( Operators::BinaryOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getBinaryEntries ( ) [ type ];
+	auto iter = find_if ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < BinaryEntry > & entry ) {
+				return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( );
+			} );
+
+	if ( iter == group.end ( ) )
+		throw std::invalid_argument ( "Entry for operator " + Operators::toString ( type ) + " with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
+
+	group.erase ( iter );
+	if ( group.empty ( ) )
+		getBinaryEntries ( ).erase ( type );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::getBinaryAbstraction ( Operators::BinaryOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	auto & group = getBinaryEntries ( ) [ type ];
+
+	return getOverload ( group, paramTypes, paramQualifiers, category );
+}
+
+ext::list < ext::pair < Operators::BinaryOperators, AlgorithmFullInfo > > OperatorRegistry::listBinaryOverloads ( ) {
+	auto & group = getBinaryEntries ( );
+
+	ext::list < ext::pair < Operators::BinaryOperators, AlgorithmFullInfo > > res;
+	for ( const std::pair < const Operators::BinaryOperators, ext::list < std::unique_ptr < BinaryEntry > > > & overloads : group )
+		for ( const std::unique_ptr < BinaryEntry > & entry : overloads.second )
+			res.push_back ( ext::make_pair ( overloads.first, entry->getEntryInfo ( ) ) );
+
+	return res;
+}
+
+ext::map < Operators::PrefixOperators, ext::list < std::unique_ptr < OperatorRegistry::PrefixEntry > > > & OperatorRegistry::getPrefixEntries ( ) {
+	static ext::map < Operators::PrefixOperators, ext::list < std::unique_ptr < PrefixEntry > > > algorithmGroups;
+	return algorithmGroups;
+}
+
+bool OperatorRegistry::isRegisteredPrefix ( Operators::PrefixOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getPrefixEntries ( ) [ type ];
+
+	for ( const std::unique_ptr < PrefixEntry > & entry : group )
+		if ( entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( ) )
+			return true;
+
+	return false;
+}
+
+void OperatorRegistry::registerPrefixInternal ( Operators::PrefixOperators type, std::unique_ptr < PrefixEntry > value ) {
+	if ( isRegisteredPrefix ( type, value->getEntryInfo ( ) ) )
+		throw std::invalid_argument ( "Callback for operator " + Operators::toString ( type ) + " with params " + ext::to_string ( value->getEntryInfo ( ).getParams ( ) ) + " already registered." );
+
+	auto & group = getPrefixEntries ( ) [ type ];
+
+	group.insert ( group.end ( ), std::move ( value ) );
+}
+
+void OperatorRegistry::unregisterPrefixInternal ( Operators::PrefixOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getPrefixEntries ( ) [ type ];
+	auto iter = find_if ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < PrefixEntry > & entry ) {
+				return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( );
+			} );
+
+	if ( iter == group.end ( ) )
+		throw std::invalid_argument ( "Entry for operator " + Operators::toString ( type ) + " with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
+
+	group.erase ( iter );
+	if ( group.empty ( ) )
+		getPrefixEntries ( ).erase ( type );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::getPrefixAbstraction ( Operators::PrefixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	auto & group = getPrefixEntries ( ) [ type ];
+
+	return getOverload ( group, paramTypes, paramQualifiers, category );
+}
+
+ext::list < ext::pair < Operators::PrefixOperators, AlgorithmFullInfo > > OperatorRegistry::listPrefixOverloads ( ) {
+	auto & group = getPrefixEntries ( );
+
+	ext::list < ext::pair < Operators::PrefixOperators, AlgorithmFullInfo > > res;
+	for ( const std::pair < const Operators::PrefixOperators, ext::list < std::unique_ptr < PrefixEntry > > > & overloads : group )
+		for ( const std::unique_ptr < PrefixEntry > & entry : overloads.second )
+			res.push_back ( ext::make_pair ( overloads.first, entry->getEntryInfo ( ) ) );
+
+	return res;
+}
+
+ext::map < Operators::PostfixOperators, ext::list < std::unique_ptr < OperatorRegistry::PostfixEntry > > > & OperatorRegistry::getPostfixEntries ( ) {
+	static ext::map < Operators::PostfixOperators, ext::list < std::unique_ptr < PostfixEntry > > > algorithmGroups;
+	return algorithmGroups;
+}
+
+bool OperatorRegistry::isRegisteredPostfix ( Operators::PostfixOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getPostfixEntries ( ) [ type ];
+
+	for ( const std::unique_ptr < PostfixEntry > & entry : group )
+		if ( entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( ) )
+			return true;
+
+	return false;
+}
+
+void OperatorRegistry::registerPostfixInternal ( Operators::PostfixOperators type, std::unique_ptr < PostfixEntry > value ) {
+	if ( isRegisteredPostfix ( type, value->getEntryInfo ( ) ) )
+		throw std::invalid_argument ( "Callback for operator " + Operators::toString ( type ) + " with params " + ext::to_string ( value->getEntryInfo ( ).getParams ( ) ) + " already registered." );
+
+	auto & group = getPostfixEntries ( ) [ type ];
+
+	group.insert ( group.end ( ), std::move ( value ) );
+}
+
+void OperatorRegistry::unregisterPostfixInternal ( Operators::PostfixOperators type, const AlgorithmBaseInfo & entryInfo ) {
+	auto & group = getPostfixEntries ( ) [ type ];
+	auto iter = find_if ( group.begin ( ), group.end ( ), [ & ] ( const std::unique_ptr < PostfixEntry > & entry ) {
+				return entry->getEntryInfo ( ).getCategory ( ) == entryInfo.getCategory ( ) && entry->getEntryInfo ( ).getParams ( ) == entryInfo.getParams ( );
+			} );
+
+	if ( iter == group.end ( ) )
+		throw std::invalid_argument ( "Entry for operator " + Operators::toString ( type ) + " with parameters " + ext::to_string ( entryInfo.getParams ( ) ) + " not registered." );
+
+	group.erase ( iter );
+	if ( group.empty ( ) )
+		getPostfixEntries ( ).erase ( type );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::getPostfixAbstraction ( Operators::PostfixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	auto & group = getPostfixEntries ( ) [ type ];
+
+	return getOverload ( group, paramTypes, paramQualifiers, category );
+}
+
+ext::list < ext::pair < Operators::PostfixOperators, AlgorithmFullInfo > > OperatorRegistry::listPostfixOverloads ( ) {
+	auto & group = getPostfixEntries ( );
+
+	ext::list < ext::pair < Operators::PostfixOperators, AlgorithmFullInfo > > res;
+	for ( const std::pair < const Operators::PostfixOperators, ext::list < std::unique_ptr < PostfixEntry > > > & overloads : group )
+		for ( const std::unique_ptr < PostfixEntry > & entry : overloads.second )
+			res.push_back ( ext::make_pair ( overloads.first, entry->getEntryInfo ( ) ) );
+
+	return res;
+}
+
+} /* namespace abstraction */
diff --git a/alib2abstraction/src/registry/OperatorRegistry.hpp b/alib2abstraction/src/registry/OperatorRegistry.hpp
new file mode 100644
index 0000000000..cf26d5f55f
--- /dev/null
+++ b/alib2abstraction/src/registry/OperatorRegistry.hpp
@@ -0,0 +1,299 @@
+/*
+ * OperatorRegistry.hpp
+ *
+ *  Created on: 11. 7. 2017
+ *	  Author: Jan Travnicek
+ */
+
+#ifndef _OPERATOR_REGISTRY_HPP_
+#define _OPERATOR_REGISTRY_HPP_
+
+#include <alib/functional>
+#include <alib/memory>
+#include <alib/vector>
+#include <alib/list>
+#include <alib/string>
+#include <alib/set>
+#include <alib/map>
+#include <alib/typeinfo>
+
+#include <abstraction/OperationAbstraction.hpp>
+
+#include <common/ParamQualifiers.hpp>
+#include <common/AlgorithmCategories.hpp>
+#include <common/Operators.hpp>
+
+#include "AlgorithmRegistryInfo.hpp"
+#include "BaseRegistryEntry.hpp"
+
+namespace abstraction {
+
+class OperatorRegistry {
+public:
+	class BinaryEntry : public BaseRegistryEntry {
+		AlgorithmFullInfo m_entryInfo;
+
+	public:
+		BinaryEntry ( AlgorithmFullInfo entryInfo ) : m_entryInfo ( std::move ( entryInfo ) ) {
+		}
+
+		const AlgorithmFullInfo & getEntryInfo ( ) const {
+			return m_entryInfo;
+		}
+	};
+
+	class PrefixEntry : public BaseRegistryEntry {
+		AlgorithmFullInfo m_entryInfo;
+
+	public:
+		PrefixEntry ( AlgorithmFullInfo entryInfo ) : m_entryInfo ( std::move ( entryInfo ) ) {
+		}
+
+		const AlgorithmFullInfo & getEntryInfo ( ) const {
+			return m_entryInfo;
+		}
+	};
+
+	class PostfixEntry : public BaseRegistryEntry {
+		AlgorithmFullInfo m_entryInfo;
+
+	public:
+		PostfixEntry ( AlgorithmFullInfo entryInfo ) : m_entryInfo ( std::move ( entryInfo ) ) {
+		}
+
+		const AlgorithmFullInfo & getEntryInfo ( ) const {
+			return m_entryInfo;
+		}
+	};
+
+private:
+	template < class Return, class FirstParam, class SecondParam >
+	class BinaryOperator : public BinaryEntry {
+		std::function < Return ( FirstParam, SecondParam ) > m_callback;
+
+	public:
+		BinaryOperator ( std::function < Return ( FirstParam, SecondParam ) > callback ) : BinaryEntry ( AlgorithmFullInfo::operatorEntryInfo < Return, FirstParam, SecondParam > ( ) ), m_callback ( std::move ( callback ) ) {
+		}
+
+		std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
+	};
+
+	template < class Return, class Param >
+	class PrefixOperator : public PrefixEntry {
+		std::function < Return ( Param ) > m_callback;
+
+	public:
+		PrefixOperator ( std::function < Return ( Param ) > callback ) : PrefixEntry ( AlgorithmFullInfo::operatorEntryInfo < Return, Param > ( ) ), m_callback ( std::move ( callback ) ) {
+		}
+
+		std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
+	};
+
+	template < class Return, class Param >
+	class PostfixOperator : public PostfixEntry {
+		std::function < Return ( Param ) > m_callback;
+
+	public:
+		PostfixOperator ( std::function < Return ( Param ) > callback ) : PostfixEntry ( AlgorithmFullInfo::operatorEntryInfo < Return, Param > ( ) ), m_callback ( std::move ( callback ) ) {
+		}
+
+		std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
+	};
+
+	static ext::map < Operators::BinaryOperators, ext::list < std::unique_ptr < BinaryEntry > > > & getBinaryEntries ( );
+
+	static bool isRegisteredBinary ( Operators::BinaryOperators type, const AlgorithmBaseInfo & entryInfo );
+
+	static void registerBinaryInternal ( Operators::BinaryOperators type, std::unique_ptr < BinaryEntry > value );
+
+	static void unregisterBinaryInternal ( Operators::BinaryOperators type, const AlgorithmBaseInfo & entryInfo );
+
+
+
+	static ext::map < Operators::PrefixOperators, ext::list < std::unique_ptr < PrefixEntry > > > & getPrefixEntries ( );
+
+	static bool isRegisteredPrefix ( Operators::PrefixOperators type, const AlgorithmBaseInfo & entryInfo );
+
+	static void registerPrefixInternal ( Operators::PrefixOperators type, std::unique_ptr < PrefixEntry > value );
+
+	static void unregisterPrefixInternal ( Operators::PrefixOperators type, const AlgorithmBaseInfo & entryInfo );
+
+
+
+	static ext::map < Operators::PostfixOperators, ext::list < std::unique_ptr < PostfixEntry > > > & getPostfixEntries ( );
+
+	static bool isRegisteredPostfix ( Operators::PostfixOperators type, const AlgorithmBaseInfo & entryInfo );
+
+	static void registerPostfixInternal ( Operators::PostfixOperators type, std::unique_ptr < PostfixEntry > value );
+
+	static void unregisterPostfixInternal ( Operators::PostfixOperators type, const AlgorithmBaseInfo & entryInfo );
+
+public:
+	template < class FirstParam, class SecondParam >
+	static void unregisterBinary ( Operators::BinaryOperators type ) {
+		unregisterBinaryInternal ( type, AlgorithmBaseInfo::operatorEntryInfo < FirstParam, SecondParam > ( ) );
+	}
+
+	template < class Return, class FirstParam, class SecondParam >
+	static void registerBinary ( Operators::BinaryOperators type, std::function < Return ( FirstParam, SecondParam ) > func ) {
+		registerBinaryInternal ( type, std::make_unique < BinaryOperator < Return, FirstParam, SecondParam > > ( func ) );
+	}
+
+	template < Operators::BinaryOperators Type, class FirstParam, class SecondParam >
+	static void registerBinary ( ) {
+		if constexpr ( Type == Operators::BinaryOperators::LOGICAL_AND ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) && std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a && b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::LOGICAL_OR ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) || std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a || b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::BINARY_AND ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) & std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a & b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::BINARY_OR ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) | std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a | b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::BINARY_XOR ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) ^ std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a ^ b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::ADD ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) + std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a + b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::SUB ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) - std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a - b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::MUL ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) * std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a * b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::MOD ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) % std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a % b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::DIV ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) / std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a / b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::EQUALS ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) == std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a == b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::NOT_EQUALS ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) != std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a != b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::LESS ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) < std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a < b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::LESS_OR_EQUAL ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) <= std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a <= b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::MORE ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) > std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a > b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::MORE_OR_EQUAL ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) >= std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) { return a >= b; };
+			registerBinary ( Type, callback );
+		} else if constexpr ( Type == Operators::BinaryOperators::ASSIGN ) {
+			std::function < decltype ( std::declval < FirstParam > ( ) = std::declval < SecondParam > ( ) ) ( FirstParam, SecondParam ) > callback = [ ] ( FirstParam a, SecondParam b ) -> decltype ( auto ) { return a = b; };
+			registerBinary ( Type, callback );
+		} else {
+			static_assert ( "Unhandled binary operator." );
+		}
+	}
+
+	static std::shared_ptr < abstraction::OperationAbstraction > getBinaryAbstraction ( Operators::BinaryOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category );
+
+	static ext::list < ext::pair < Operators::BinaryOperators, AlgorithmFullInfo > > listBinaryOverloads ( );
+
+
+	template < class Param >
+	static void unregisterPrefix ( Operators::PrefixOperators type ) {
+		unregisterPrefixInternal ( type, AlgorithmBaseInfo::operatorEntryInfo < Param > ( ) );
+	}
+
+	template < class Return, class Param >
+	static void registerPrefix ( Operators::PrefixOperators type, std::function < Return ( Param ) > func ) {
+		registerPrefixInternal ( type, std::make_unique < PrefixOperator < Return, Param > > ( func ) );
+	}
+
+	template < Operators::PrefixOperators Type, class Param >
+	static void registerPrefix ( ) {
+		if constexpr ( Type == Operators::PrefixOperators::PLUS ) {
+			std::function < decltype ( + std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) { return + a; };
+			registerPrefix ( Type, callback );
+		} else if constexpr ( Type == Operators::PrefixOperators::MINUS ) {
+			std::function < decltype ( - std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) -> decltype ( auto ) { return - a; };
+			registerPrefix ( Type, callback );
+		} else if constexpr ( Type == Operators::PrefixOperators::LOGICAL_NOT ) {
+			std::function < decltype ( ! std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) -> decltype ( auto ) { return ! a; };
+			registerPrefix ( Type, callback );
+		} else if constexpr ( Type == Operators::PrefixOperators::BINARY_NEG ) {
+			std::function < decltype ( ~ std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) -> decltype ( auto ) { return ~ a; };
+			registerPrefix ( Type, callback );
+		} else if constexpr ( Type == Operators::PrefixOperators::INCREMENT ) {
+			std::function < decltype ( ++ std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) -> decltype ( auto ) { return ++ a; };
+			registerPrefix ( Type, callback );
+		} else if constexpr ( Type == Operators::PrefixOperators::DECREMENT ) {
+			std::function < decltype ( -- std::declval < Param > ( ) ) ( Param ) > callback = [ ] ( Param a ) -> decltype ( auto ) { return -- a; };
+			registerPrefix ( Type, callback );
+		} else {
+			static_assert ( "Unhandled prefix operator." );
+		}
+	}
+
+	static std::shared_ptr < abstraction::OperationAbstraction > getPrefixAbstraction ( Operators::PrefixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category );
+
+	static ext::list < ext::pair < Operators::PrefixOperators, AlgorithmFullInfo > > listPrefixOverloads ( );
+
+
+	template < class Param >
+	static void unregisterPostfix ( Operators::PostfixOperators type ) {
+		unregisterPostfixInternal ( type, AlgorithmBaseInfo::operatorEntryInfo < Param > ( ) );
+	}
+
+	template < class Return, class Param >
+	static void registerPostfix ( Operators::PostfixOperators type, std::function < Return ( Param ) > func ) {
+		registerPostfixInternal ( type, std::make_unique < PostfixOperator < Return, Param > > ( func ) );
+	}
+
+	template < Operators::PostfixOperators Type, class Param >
+	static void registerPostfix ( ) {
+		if constexpr ( Type == Operators::PostfixOperators::INCREMENT ) {
+			std::function < decltype ( std::declval < Param > ( ) ++ ) ( Param ) > callback = [ ] ( Param a ) { std::decay_t < Param > tmp = a; a ++; return tmp; };
+			registerPostfix ( Type, callback );
+		} else if constexpr ( Type == Operators::PostfixOperators::DECREMENT ) {
+			std::function < decltype ( std::declval < Param > ( ) -- ) ( Param ) > callback = [ ] ( Param a ) { std::decay_t < Param > tmp = a; a --; return tmp; };
+			registerPostfix ( Type, callback );
+		} else {
+			static_assert ( "Unhandled postfix operator." );
+		}
+	}
+
+	static std::shared_ptr < abstraction::OperationAbstraction > getPostfixAbstraction ( Operators::PostfixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category );
+
+	static ext::list < ext::pair < Operators::PostfixOperators, AlgorithmFullInfo > > listPostfixOverloads ( );
+
+};
+
+} /* namespace abstraction */
+
+#include <abstraction/MemberAbstraction.hpp>
+#include <abstraction/AlgorithmAbstraction.hpp>
+#include <abstraction/WrapperAbstraction.hpp>
+
+namespace abstraction {
+
+template < class Return, class FirstParam, class SecondParam >
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::BinaryOperator < Return, FirstParam, SecondParam >::getAbstraction ( ) const {
+	return std::make_shared < abstraction::AlgorithmAbstraction < Return, FirstParam, SecondParam > > ( m_callback );
+}
+
+template < class Return, class Param >
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::PrefixOperator < Return, Param >::getAbstraction ( ) const {
+	return std::make_shared < abstraction::AlgorithmAbstraction < Return, Param > > ( m_callback );
+}
+
+template < class Return, class Param >
+std::shared_ptr < abstraction::OperationAbstraction > OperatorRegistry::PostfixOperator < Return, Param >::getAbstraction ( ) const {
+	return std::make_shared < abstraction::AlgorithmAbstraction < Return, Param > > ( m_callback );
+}
+
+} /* namespace abstraction */
+
+#endif /* _OPERATOR_REGISTRY_HPP_ */
diff --git a/alib2abstraction/src/registry/Registry.cpp b/alib2abstraction/src/registry/Registry.cpp
index 8ec3c39ebb..53cec1aa42 100644
--- a/alib2abstraction/src/registry/Registry.cpp
+++ b/alib2abstraction/src/registry/Registry.cpp
@@ -12,6 +12,7 @@
 #include <registry/CastRegistry.hpp>
 #include <registry/NormalizeRegistry.hpp>
 #include <registry/ContainerRegistry.hpp>
+#include <registry/OperatorRegistry.hpp>
 
 namespace abstraction {
 
@@ -39,6 +40,18 @@ ext::list < ext::tuple < AlgorithmFullInfo, std::string > > Registry::listOverlo
 	return AlgorithmRegistry::listOverloads ( algorithm, templateParams );
 }
 
+ext::list < ext::pair < Operators::BinaryOperators, AlgorithmFullInfo > > Registry::listBinaryOperators ( ) {
+	return OperatorRegistry::listBinaryOverloads ( );
+}
+
+ext::list < ext::pair < Operators::PrefixOperators, AlgorithmFullInfo > > Registry::listPrefixOperators ( ) {
+	return OperatorRegistry::listPrefixOverloads ( );
+}
+
+ext::list < ext::pair < Operators::PostfixOperators, AlgorithmFullInfo > > Registry::listPostfixOperators ( ) {
+	return OperatorRegistry::listPostfixOverloads ( );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getContainerAbstraction ( const std::string & container, const std::string & type ) {
 	return ContainerRegistry::getAbstraction ( container, type );
 }
@@ -47,6 +60,18 @@ std::shared_ptr < abstraction::OperationAbstraction > Registry::getAlgorithmAbst
 	return AlgorithmRegistry::getAbstraction ( name, templateParams, paramTypes, paramQualifiers, category );
 }
 
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getBinaryOperatorAbstraction ( Operators::BinaryOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	return OperatorRegistry::getBinaryAbstraction ( type, paramTypes, paramQualifiers, category );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getPrefixOperatorAbstraction ( Operators::PrefixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	return OperatorRegistry::getPrefixAbstraction ( type, paramTypes, paramQualifiers, category );
+}
+
+std::shared_ptr < abstraction::OperationAbstraction > Registry::getPostfixOperatorAbstraction ( Operators::PostfixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory category ) {
+	return OperatorRegistry::getPostfixAbstraction ( type, paramTypes, paramQualifiers, category );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > Registry::getCastAbstraction ( const std::string & target, const std::string & param ) {
 	return CastRegistry::getAbstraction ( target, param );
 }
diff --git a/alib2abstraction/src/registry/Registry.h b/alib2abstraction/src/registry/Registry.h
index 6f9c89f9c8..b427158050 100644
--- a/alib2abstraction/src/registry/Registry.h
+++ b/alib2abstraction/src/registry/Registry.h
@@ -11,6 +11,7 @@
 #include <abstraction/OperationAbstraction.hpp>
 #include <common/ParamQualifiers.hpp>
 #include <common/AlgorithmCategories.hpp>
+#include <common/Operators.hpp>
 #include "AlgorithmRegistryInfo.hpp"
 
 #include <alib/pair>
@@ -30,8 +31,15 @@ public:
 
 	static ext::list < ext::tuple < AlgorithmFullInfo, std::string > > listOverloads ( const std::string & algorithm, const ext::vector < std::string > & templateParams );
 
+	static ext::list < ext::pair < Operators::BinaryOperators, AlgorithmFullInfo > > listBinaryOperators ( );
+	static ext::list < ext::pair < Operators::PrefixOperators, AlgorithmFullInfo > > listPrefixOperators ( );
+	static ext::list < ext::pair < Operators::PostfixOperators, AlgorithmFullInfo > > listPostfixOperators ( );
+
 	static std::shared_ptr < abstraction::OperationAbstraction > getContainerAbstraction ( const std::string & container, const std::string & type );
 	static std::shared_ptr < abstraction::OperationAbstraction > getAlgorithmAbstraction ( const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory );
+	static std::shared_ptr < abstraction::OperationAbstraction > getBinaryOperatorAbstraction ( Operators::BinaryOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory );
+	static std::shared_ptr < abstraction::OperationAbstraction > getPrefixOperatorAbstraction ( Operators::PrefixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory );
+	static std::shared_ptr < abstraction::OperationAbstraction > getPostfixOperatorAbstraction ( Operators::PostfixOperators type, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::ParamQualifiers::ParamQualifierSet > & paramQualifiers, AlgorithmCategories::AlgorithmCategory );
 	static std::shared_ptr < abstraction::OperationAbstraction > getCastAbstraction ( const std::string & target, const std::string & param );
 	static bool isCastNoOp ( const std::string & target, const std::string & param );
 	static std::shared_ptr < abstraction::OperationAbstraction > getNormalizeAbstraction ( const std::string & param );
diff --git a/alib2cli/src/ast/command/OperatorsIntrospectionCommand.h b/alib2cli/src/ast/command/OperatorsIntrospectionCommand.h
new file mode 100644
index 0000000000..4d69544042
--- /dev/null
+++ b/alib2cli/src/ast/command/OperatorsIntrospectionCommand.h
@@ -0,0 +1,61 @@
+#ifndef _CLI_OPERATOR_INTROSPECTION_COMMAND_H_
+#define _CLI_OPERATOR_INTROSPECTION_COMMAND_H_
+
+#include <ast/Command.h>
+#include <environment/Environment.h>
+
+namespace cli {
+
+class OperatorsIntrospectionCommand : public Command {
+	static void typePrint ( const ext::pair < std::string, abstraction::ParamQualifiers::ParamQualifierSet > & result, std::ostream & os ) {
+		if ( std::get < 1 > ( result ) && abstraction::ParamQualifiers::ParamQualifierSet::CONST )
+			os << "const ";
+
+		os << std::get < 0 > ( result );
+
+		if ( std::get < 1 > ( result ) && abstraction::ParamQualifiers::ParamQualifierSet::LREF )
+			os << " &";
+
+		if ( std::get < 1 > ( result ) && abstraction::ParamQualifiers::ParamQualifierSet::RREF )
+			os << " &&";
+	}
+
+public:
+	OperatorsIntrospectionCommand ( ) {
+	}
+
+	template < class Operators >
+	static void printOperators ( const ext::list < ext::pair < Operators, abstraction::AlgorithmFullInfo > > & overloads ) {
+		for ( const ext::pair < Operators, abstraction::AlgorithmFullInfo > & overload : overloads ) {
+
+			typePrint ( std::get < 1 > ( overload ).getNormalizedResult ( ), common::Streams::out );
+
+			common::Streams::out << " operator ";
+			common::Streams::out << abstraction::Operators::toString ( std::get < 0 > ( overload ) );
+			common::Streams::out << " (";
+
+			for ( size_t i = 0; i < std::get < 1 > ( overload ).getParams ( ).size ( ); ++ i ) {
+				if ( i != 0 )
+					common::Streams::out << ",";
+
+				common::Streams::out << " ";
+
+				typePrint ( std::get < 1 > ( overload ).getParams ( ) [ i ], common::Streams::out );
+
+				common::Streams::out << " " << std::get < 1 > ( overload ).getParamNames ( ) [ i ];
+			}
+			common::Streams::out << " )" << std::endl;
+		}
+	}
+
+	CommandResult run ( Environment & /* environment */ ) const override {
+		printOperators ( abstraction::Registry::listBinaryOperators ( ) );
+		printOperators ( abstraction::Registry::listPrefixOperators ( ) );
+		printOperators ( abstraction::Registry::listPostfixOperators ( ) );
+		return CommandResult::OK;
+	}
+};
+
+} /* namespace cli */
+
+#endif /* _CLI_OPERATOR_INTROSPECTION_COMMAND_H_ */
diff --git a/alib2cli/src/parser/Parser.cpp b/alib2cli/src/parser/Parser.cpp
index 6d6d77ba17..e793396737 100644
--- a/alib2cli/src/parser/Parser.cpp
+++ b/alib2cli/src/parser/Parser.cpp
@@ -20,6 +20,7 @@
 #include <ast/command/EOTCommand.h>
 #include <ast/command/HelpCommand.h>
 #include <ast/command/AlgorithmsIntrospectionCommand.h>
+#include <ast/command/OperatorsIntrospectionCommand.h>
 #include <ast/command/OverloadsIntrospectionCommand.h>
 #include <ast/command/DataTypesIntrospectionCommand.h>
 #include <ast/command/CastsIntrospectionCommand.h>
@@ -327,6 +328,9 @@ std::unique_ptr < Command > Parser::introspect_command ( ) {
 		}
 
 		return std::make_unique < OverloadsIntrospectionCommand > ( std::move ( param ), std::move ( templateArgs ) );
+	} else if ( check_nonreserved_kw ( "operators" ) ) {
+		match_nonreserved_kw ( "operators" );
+		return std::make_unique < OperatorsIntrospectionCommand > ( );
 	} else if ( check_nonreserved_kw ( "datatypes" ) ) {
 		match_nonreserved_kw ( "datatypes" );
 		std::unique_ptr < cli::Arg > param = optional_arg ( );
diff --git a/alib2common/src/PrimitiveRegistrator.cpp b/alib2common/src/PrimitiveRegistrator.cpp
index aafba13444..3f69a9b392 100644
--- a/alib2common/src/PrimitiveRegistrator.cpp
+++ b/alib2common/src/PrimitiveRegistrator.cpp
@@ -15,6 +15,8 @@
 #include <alib/exception>
 #include <exception/CommonException.h>
 
+#include <registration/OperatorRegistration.hpp>
+
 namespace {
 
 class PrimitiveRegistrator {
@@ -190,4 +192,45 @@ public:
 
 auto primitiveRegistrator = PrimitiveRegistrator ( );
 
+auto addInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::ADD, int, int > ( );
+auto subInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::SUB, int, int > ( );
+auto modInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::MOD, int, int > ( );
+auto mulInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::MUL, int, int > ( );
+auto divInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::DIV, int, int > ( );
+
+auto equalsInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::EQUALS, int, int > ( );
+auto notEqualsInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::NOT_EQUALS, int, int > ( );
+
+auto lessInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::LESS, int, int > ( );
+auto lessOrEqualInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::LESS_OR_EQUAL, int, int > ( );
+auto moreInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::MORE, int, int > ( );
+auto moreOrEqualInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::MORE_OR_EQUAL, int, int > ( );
+
+auto andInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::BINARY_AND, int, int > ( );
+auto orInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::BINARY_OR, int, int > ( );
+auto xorInts = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::BINARY_XOR, int, int > ( );
+
+auto plusInt = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::PLUS, int > ( );
+auto minusInt = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::MINUS, int > ( );
+
+auto negInt = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::BINARY_NEG, int > ( );
+
+auto postIncrementInt = registration::PostfixOperatorRegister < abstraction::Operators::PostfixOperators::INCREMENT, int & > ( );
+auto postDecrementInt = registration::PostfixOperatorRegister < abstraction::Operators::PostfixOperators::DECREMENT, int & > ( );
+
+auto prefixIncrementInt = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::INCREMENT, int & > ( );
+auto prefixDecrementInt = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::DECREMENT, int & > ( );
+
+auto assignInt = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::ASSIGN, int &, int > ( );
+
+
+
+auto andBools = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::LOGICAL_AND, bool, bool > ( );
+auto orBools = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::LOGICAL_OR, bool, bool > ( );
+
+auto notBools = registration::PrefixOperatorRegister < abstraction::Operators::PrefixOperators::LOGICAL_NOT, bool > ( );
+
+auto equalsBools = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::EQUALS, bool, bool > ( );
+auto notEqualsBools = registration::BinaryOperatorRegister < abstraction::Operators::BinaryOperators::NOT_EQUALS, bool, bool > ( );
+
 } /* namespace */
-- 
GitLab