Skip to content
Snippets Groups Projects
Commit 9c4b6da7 authored by Tomáš Pecka's avatar Tomáš Pecka
Browse files

Merge branch 'master' of gitlab.fit.cvut.cz:algorithms-library-toolkit/automata-library

* 'master' of gitlab.fit.cvut.cz:algorithms-library-toolkit/automata-library:
  move type independent code to cpp file
  delete not needed imports
  remove not needed class specialisation
  prepare getAbstraction for qualifiers support
parents be896d2e 7a398a06
No related branches found
No related tags found
No related merge requests found
Pipeline #
/*
* AlgorithmRegistry.cpp
*
* Created on: 19. 8. 2017
* Author: Jan Travnicek
*/
#include <abstraction/AlgorithmRegistry.hpp>
#include <abstraction/CastRegistry.hpp>
#include <foreach>
namespace abstraction {
std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, bool & downcast, bool & normalize ) {
auto group = getEntries ( ).find ( name );
if ( group == getEntries ( ).end ( ) )
throw exception::CommonException ( "Entry " + name + " not available" );
auto incompatibleLambda = [ ] ( const ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > & compatibility ) {
return std::get < 0 > ( compatibility ) == MatchType::INCOMPATIBLE;
};
auto castLambda = [ ] ( const ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > & compatibility ) {
return std::get < 0 > ( compatibility ) == MatchType::CAST;
};
auto exactLambda = [ ] ( const ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > & compatibility ) {
return std::get < 0 > ( compatibility ) == MatchType::EXACT;
};
// determine how one can actually map what we have ( paramTypes ) as params to what is available as overloads ( group->second )
std::vector < std::pair < ext::vector < ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > > compatibilityData;
for ( const std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > & entry : group->second ) {
if ( entry.first.size ( ) != paramTypes.size ( ) )
continue;
ext::vector < ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > > compatibilityVector;
for ( unsigned i = 0; i < paramTypes.size ( ); ++ i ) {
MatchType matchType;
if ( entry.first [ i ].first == paramTypes [ i ] ) {
matchType = MatchType::EXACT;
} else if ( abstraction::CastRegistry::castAvailable ( entry.first [ i ].first, paramTypes [ i ] ) ) {
matchType = MatchType::CAST;
} else {
matchType = MatchType::INCOMPATIBLE;
}
compatibilityVector.push_back ( ext::make_tuple ( matchType, entry.first [ i ].first, entry.first [ i ].second ) );
}
// clear incompatibilities are fitered out
if ( std::none_of ( compatibilityVector.begin ( ), compatibilityVector.end ( ), incompatibleLambda ) )
compatibilityData.push_back ( std::make_pair ( std::move ( compatibilityVector ), entry.second ) );
}
// remaining compatible overloads are examined per parameter and the best option is remembered as overload index that achieved it
ext::vector < ext::set < unsigned > > winnerList;
for ( unsigned i = 0; i < paramTypes.size ( ); ++ i ) {
ext::set < unsigned > best;
unsigned overload = 0;
for ( const std::pair < ext::vector < ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > & data : compatibilityData ) {
if ( exactLambda ( data.first [ i ] ) )
best.insert ( overload );
++ overload;
}
if ( best.size ( ) > 0 ) {
winnerList.push_back ( std::move ( best ) );
continue;
}
overload = 0;
for ( const std::pair < ext::vector < ext::tuple < MatchType, std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > & data : compatibilityData ) {
if ( castLambda ( data.first [ i ] ) )
best.insert ( overload );
++ overload;
}
winnerList.push_back ( std::move ( best ) );
}
// intersection of everything together finds indexes which are better or of the same quality for all params over all overloads
ext::set < unsigned > winner { ext::sequence < unsigned > ( 0 ).begin ( ), ext::sequence < unsigned > ( compatibilityData.size ( ) ).end ( ) };
for ( const std::set < unsigned > & best : winnerList ) {
ext::set < unsigned > filtered;
std::set_intersection ( winner.begin ( ), winner.end ( ), best.begin ( ), best.end ( ), std::inserter ( filtered, filtered.end ( ) ) );
winner = std::move ( filtered );
}
// if there is a sinle winner, return it
std::shared_ptr < Entry > best;
if ( winner.size ( ) == 1 ) {
best = compatibilityData [ * winner.begin ( ) ].second;
} else if ( winner.size ( ) > 1 ) {
std::stringstream ss;
ss << paramTypes;
throw exception::CommonException ( "Entry overload " + ss.str ( ) + " ambiguous." );
} else {
std::stringstream ss;
ss << paramTypes;
throw exception::CommonException ( "Entry overload " + ss.str ( ) + " not available." );
}
downcast = best->getDowncast ( );
normalize = best->getNormalize ( );
return best->getAbstraction ( );
}
std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes ) {
bool downcast;
bool normalize;
return getAbstraction ( name, paramTypes, downcast, normalize );
}
void AlgorithmRegistry::listGroup ( const std::string & group ) {
for ( const std::pair < const std::string, ext::vector < std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > > > & entry : getEntries ( ) ) {
if ( entry.first.find ( group ) == 0 ) //found at the begining
std::cout << entry.first << std::endl;
}
}
void AlgorithmRegistry::listOverloads ( const std::string & algorithm ) {
auto group = getEntries ( ).find ( algorithm );
if ( group == getEntries ( ).end ( ) )
throw exception::CommonException ( "Entry " + algorithm + " not available" );
for ( const std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > & overloads : group->second ) {
for ( const std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > & param : overloads.first ) {
if ( param.second.count ( abstraction::ParamQualifiers::ParamQualifier::CONST ) )
std::cout << "const ";
std::cout << param.first;
if ( param.second.count ( abstraction::ParamQualifiers::ParamQualifier::LREF ) )
std::cout << " &";
if ( param.second.count ( abstraction::ParamQualifiers::ParamQualifier::RREF ) )
std::cout << " &";
std::cout << ", ";
}
std::cout << std::endl;
}
}
void AlgorithmRegistry::list ( ) {
for ( const std::pair < const std::string, ext::vector < std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > > > & entry : getEntries ( ) ) {
std::cout << entry.first << std::endl;
}
}
} /* namespace abstraction */
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
   
#include <exception/CommonException.h> #include <exception/CommonException.h>
#include <abstraction/OperationAbstraction.hpp> #include <abstraction/OperationAbstraction.hpp>
#include <abstraction/CastRegistry.hpp>
#include <abstraction/common/ParamQualifiers.hpp>
   
namespace abstraction { namespace abstraction {
   
...@@ -50,19 +51,8 @@ class AlgorithmRegistry { ...@@ -50,19 +51,8 @@ class AlgorithmRegistry {
virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override; virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
}; };
   
template < class Return, class ... Params > static ext::map < std::string, ext::vector < std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > > > & getEntries ( ) {
class EntryImpl < Return *, Params ... > : public Entry { static ext::map < std::string, ext::vector < std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > > > algorithmGroups;
std::function < Return * ( Params ... ) > m_callback;
public:
EntryImpl ( std::function < Return * ( Params ... ) > callback, bool downcast, bool normalize ) : Entry ( downcast, normalize ), m_callback ( callback ) {
}
virtual std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( ) const override;
};
static ext::map < std::string, ext::map < ext::vector < std::string >, std::unique_ptr < Entry > > > & getEntries ( ) {
static ext::map < std::string, ext::map < ext::vector < std::string >, std::unique_ptr < Entry > > > algorithmGroups;
return algorithmGroups; return algorithmGroups;
}; };
   
...@@ -76,93 +66,27 @@ public: ...@@ -76,93 +66,27 @@ public:
static void registerAlgorithm ( ReturnType ( * callback ) ( ParamTypes ... ), bool downcast, bool normalize ) { static void registerAlgorithm ( ReturnType ( * callback ) ( ParamTypes ... ), bool downcast, bool normalize ) {
std::string algorithm = ext::to_string < Algo > ( ); std::string algorithm = ext::to_string < Algo > ( );
   
ext::vector < std::string > params; ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > > params;
( void ) std::initializer_list < int > { ( params.push_back ( ext::to_string < typename std::decay < ParamTypes >::type > ( ) ), 0 ) ... }; ( void ) std::initializer_list < int > { ( params.push_back ( std::make_pair ( ext::to_string < typename std::decay < ParamTypes >::type > ( ), abstraction::ParamQualifiers::paramQualifiers < ParamTypes > ( ) ) ), 0 ) ... };
if ( ! getEntries ( ) [ algorithm ].insert ( std::make_pair ( params, std::unique_ptr < Entry > ( new EntryImpl < ReturnType, ParamTypes ... > ( callback, downcast, normalize ) ) ) ).second )
throw ::exception::CommonException ( "Callback for " + algorithm + " already registered." );
}
   
static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, bool & downcast, bool & normalize ) { auto & group = getEntries ( ) [ algorithm ];
auto group = getEntries ( ).find ( name ); for ( const std::pair < ext::vector < std::pair < std::string, ext::set < abstraction::ParamQualifiers::ParamQualifier > > >, std::shared_ptr < Entry > > & entry : group )
if ( group == getEntries ( ).end ( ) ) if ( entry.first == params )
throw exception::CommonException ( "Entry " + name + " not available" ); throw exception::CommonException ( "Callback for " + algorithm + " already registered." );
auto overload = group->second.find ( paramTypes );
if ( overload == group->second.end ( ) ) {
std::vector < std::pair < std::vector < MatchType >, std::map < ext::vector < std::string >, std::unique_ptr < Entry > >::iterator > > compatibilityData;
for ( auto iter = group->second.begin ( ); iter != group->second.end ( ); ++ iter ) {
if ( iter->first.size ( ) != paramTypes.size ( ) )
continue;
std::vector < MatchType > compatibilityVector;
for ( unsigned i = 0; i < paramTypes.size ( ); ++ i ) {
if ( iter->first [ i ] == paramTypes [ i ] ) {
compatibilityVector.push_back ( MatchType::EXACT );
} else if ( abstraction::CastRegistry::castAvailable ( iter->first [ i ], paramTypes [ i ] ) ) {
compatibilityVector.push_back ( MatchType::CAST );
} else {
compatibilityVector.push_back ( MatchType::INCOMPATIBLE );
}
}
if ( std::none_of ( compatibilityVector.begin(), compatibilityVector.end(), [] ( MatchType & matchType ) { return matchType == MatchType::INCOMPATIBLE; } ) ) {
compatibilityData.push_back ( std::make_pair ( std::move ( compatibilityVector ), iter ) );
}
}
if ( compatibilityData.size ( ) == 1 ) {
overload = compatibilityData [ 0 ].second;
} else if ( compatibilityData.size ( ) > 1 ) {
std::stringstream ss;
ss << paramTypes;
throw exception::CommonException ( "Entry overload " + ss.str ( ) + " ambiguous." );
}
}
if ( overload == group->second.end ( ) ) {
std::stringstream ss;
ss << paramTypes;
   
throw exception::CommonException ( "Entry overload " + ss.str ( ) + " not available." ); auto entryValue = std::make_pair ( params, std::shared_ptr < Entry > ( new EntryImpl < ReturnType, ParamTypes ... > ( callback, downcast, normalize ) ) );
} group.push_back ( std::move ( entryValue ) );
downcast = overload->second->getDowncast ( );
normalize = overload->second->getNormalize ( );
return overload->second->getAbstraction ( );
} }
   
static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes ) { static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes, bool & downcast, bool & normalize );
bool downcast;
bool normalize;
return getAbstraction ( name, paramTypes, downcast, normalize );
}
   
static void listGroup ( const std::string & group ) { static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & name, const ext::vector < std::string > & paramTypes );
for ( const std::pair < const std::string, ext::map < ext::vector < std::string >, std::unique_ptr < Entry > > > & entry : getEntries ( ) ) {
if ( entry.first.find ( group ) == 0 ) //found at the begining
std::cout << entry.first << std::endl;
}
}
   
static void listOverloads ( const std::string & algorithm ) { static void listGroup ( const std::string & group );
auto group = getEntries ( ).find ( algorithm );
if ( group == getEntries ( ).end ( ) )
throw exception::CommonException ( "Entry " + algorithm + " not available" );
   
for ( const std::pair < const ext::vector < std::string >, std::unique_ptr < Entry > > & overloads : group->second ) { static void listOverloads ( const std::string & algorithm );
for ( const std::string & param : overloads.first ) {
std::cout << param << " " << std::endl;
}
}
}
   
static void list ( ) { static void list ( );
for ( const std::pair < const std::string, ext::map < ext::vector < std::string >, std::unique_ptr < Entry > > > & entry : getEntries ( ) ) {
std::cout << entry.first << std::endl;
}
}
}; };
   
} /* namespace abstraction */ } /* namespace abstraction */
...@@ -176,11 +100,6 @@ std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::EntryIm ...@@ -176,11 +100,6 @@ std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::EntryIm
return std::make_shared < abstraction::AlgorithmAbstraction < Return, Params ... > > ( m_callback ); return std::make_shared < abstraction::AlgorithmAbstraction < Return, Params ... > > ( m_callback );
} }
   
template < class Return, class ... Params >
std::shared_ptr < abstraction::OperationAbstraction > AlgorithmRegistry::EntryImpl < Return *, Params ... >::getAbstraction ( ) const {
return std::make_shared < abstraction::AlgorithmAbstraction < Return *, Params ... > > ( m_callback );
}
} /* namespace abstraction */ } /* namespace abstraction */
   
#endif /* _ALGORITHM_REGISTRY_HPP_ */ #endif /* _ALGORITHM_REGISTRY_HPP_ */
#ifndef _PARAM_QUALIFIERS_HPP_
#define _PARAM_QUALIFIERS_HPP_
#include <set>
#include <type_traits>
namespace abstraction {
class ParamQualifiers {
public:
enum class ParamQualifier {
CONST,
LREF,
RREF,
};
template < class Param >
static ext::set < ParamQualifier > paramQualifiers ( ) {
ext::set < ParamQualifier > res;
if ( std::is_lvalue_reference < Param >::value )
res.insert ( ParamQualifier::LREF );
if ( std::is_rvalue_reference < Param >::value )
res.insert ( ParamQualifier::RREF );
if ( std::is_const < typename std::remove_reference < Param >::type >::value )
res.insert ( ParamQualifier::CONST );
return res;
}
};
} /* namespace abstraction */
#endif // _PARAM_QUALIFIERS_HPP_
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#include <core/multipleDispatch.hpp> #include <core/multipleDispatch.hpp>
   
#include <abstraction/AlgorithmRegistry.hpp> #include <abstraction/AlgorithmRegistry.hpp>
#include <abstraction/NormalizeRegistry.hpp>
#include <abstraction/DowncastRegistry.hpp>
   
#include <registration/NormalizationRegistration.hpp> #include <registration/NormalizationRegistration.hpp>
   
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment