/* * 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::TypeQualifiers::TypeQualifierSet > & typeQualifiers, AlgorithmCategories::AlgorithmCategory category ) { auto & group = getBinaryEntries ( ) [ type ]; return getOverload ( group, paramTypes, typeQualifiers, 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::TypeQualifiers::TypeQualifierSet > & typeQualifiers, AlgorithmCategories::AlgorithmCategory category ) { auto & group = getPrefixEntries ( ) [ type ]; return getOverload ( group, paramTypes, typeQualifiers, 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::TypeQualifiers::TypeQualifierSet > & typeQualifiers, AlgorithmCategories::AlgorithmCategory category ) { auto & group = getPostfixEntries ( ) [ type ]; return getOverload ( group, paramTypes, typeQualifiers, 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 */