diff --git a/alib2abstraction/src/common/EvalHelper.cpp b/alib2abstraction/src/common/EvalHelper.cpp index 1b8e91419b285ccd39c3bccced0e8082ba3e9398..7edb58f8058e72176b46c7560de9c6c91a983a44 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 b7497f7d5e46ba605967e196ac9471173df64ae1..ab8a1ea8710ee0610ab4e550436e6fe20497e604 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 0000000000000000000000000000000000000000..e9ac15183fee7316d0723607fb49302c1f723a66 --- /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 0000000000000000000000000000000000000000..4dc5401bcf2db0f68517fe2a13026a5a0566fde6 --- /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 0000000000000000000000000000000000000000..c505e42c1871fd1e915ecf206cb0d6d6e2714845 --- /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 1545dceb78c17da1dfaa1e9b7b1bf48e2ac55050..f9d9ccea5365cc2e16e5806c832eac904f6946cf 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 0000000000000000000000000000000000000000..861198c94a80db2f2ca07f5af2d8652e3c279630 --- /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 0000000000000000000000000000000000000000..cf26d5f55fc2739439c5ceace55581b211a767c6 --- /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 8ec3c39ebbfb3ad192738438e6d1e95331e2e601..53cec1aa4231333a568d5530db333a2db30c3e39 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 6f9c89f9c83ca16b11b15fcacda6b16bc0fa63de..b42715805011d35032f36b6d7d0d4114401a74e8 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 0000000000000000000000000000000000000000..4d69544042ee6db9ec01485820feffebb1b7bcd7 --- /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 6d6d77ba179f970e41dbf7a125dc242c659b20d4..e7933967378585e74f90cec84c39ffd898e4d10a 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 aafba13444e2bcbcfe77c1e9d543e8d91f90b527..3f69a9b392d65a713ad7c6577e573c059ff29184 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 */