Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • algorithms-library-toolkit/automata-library
  • fortmare/automata-library
  • wijnhjan/automata-library
  • zelenm14/automata-library
  • gregofi1/automata-library
  • slavim17/automata-library
6 results
Show changes
Showing
with 922 additions and 498 deletions
#pragma once
#include <ext/tuple>
#include <core/type_details.hpp>
#include <ext/typeinfo>
#include <factory/NormalizeFactory.hpp>
#include <object/AnyObject.h>
#include <object/Object.h>
#include <object/ObjectFactory.h>
namespace core {
template <typename T, typename R>
using select_second = R;
template <typename... Ts>
struct type_util<ext::tuple<Ts...>> {
static ext::tuple<Ts...> denormalize(ext::tuple<select_second<Ts, object::Object>...>&& arg)
{
return std::apply([](auto&&... elem) {
return ext::make_tuple(factory::NormalizeFactory::denormalize<Ts>(std::move(elem))...);
},
std::move(arg));
}
static ext::tuple<select_second<Ts, object::Object>...> normalize(ext::tuple<Ts...>&& arg)
{
return std::apply([](auto&&... elem) {
return ext::make_tuple(factory::NormalizeFactory::normalize<Ts>(std::move(elem))...);
},
std::move(arg));
}
static std::unique_ptr<type_details_base> type(const ext::tuple<Ts...>& arg)
{
return std::apply([](auto&... elem) {
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
(sub_types_vec.push_back(type_util<Ts>::type(elem)), ...);
return std::make_unique<type_details_template>("ext::tuple", std::move(sub_types_vec));
},
arg);
}
};
template <class... Ts>
struct type_details_retriever<ext::tuple<Ts...>> {
static std::unique_ptr<type_details_base> get()
{
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
(sub_types_vec.push_back(type_details_retriever<Ts>::get()), ...);
return std::make_unique<type_details_template>("ext::tuple", std::move(sub_types_vec));
}
};
}
#pragma once
#include <ext/unordered_map>
#include <core/type_details.hpp>
#include <ext/typeinfo>
#include <factory/NormalizeFactory.hpp>
#include <object/AnyObject.h>
#include <object/Object.h>
#include <object/ObjectFactory.h>
namespace core {
template <typename T, typename U>
struct type_util<ext::unordered_map<T, U>> {
static ext::unordered_map<T, U> denormalize(ext::unordered_map<object::Object, object::Object>&& arg)
{
ext::unordered_map<T, U> res;
for (std::pair<object::Object, object::Object>&& item : ext::make_mover(arg))
res.insert(factory::NormalizeFactory::denormalize<T>(std::move(item.first)), factory::NormalizeFactory::denormalize<U>(std::move(item.second)));
return res;
}
static ext::unordered_map<object::Object, object::Object> normalize(ext::unordered_map<T, U>&& arg)
{
ext::unordered_map<object::Object, object::Object> res;
for (std::pair<T, U>&& item : ext::make_mover(arg))
res.insert(factory::NormalizeFactory::normalize<T>(std::move(item.first)), factory::NormalizeFactory::normalize<U>(std::move(item.second)));
return res;
}
static std::unique_ptr<type_details_base> type(const ext::unordered_map<T, U>& arg)
{
core::unique_ptr_set<type_details_base> subTypes1;
core::unique_ptr_set<type_details_base> subTypes2;
for (const std::pair<const T, U>& item : arg) {
subTypes1.insert(type_util<T>::type(item.first));
subTypes2.insert(type_util<U>::type(item.second));
}
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_variant_type::make_variant(std::move(subTypes1)));
sub_types_vec.push_back(type_details_variant_type::make_variant(std::move(subTypes2)));
return std::make_unique<type_details_template>("ext::unordered_map", std::move(sub_types_vec));
}
};
template <class T, class U>
struct type_details_retriever<ext::unordered_map<T, U>> {
static std::unique_ptr<type_details_base> get()
{
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_retriever<T>::get());
sub_types_vec.push_back(type_details_retriever<U>::get());
return std::make_unique<type_details_template>("ext::unordered_map", std::move(sub_types_vec));
}
};
}
#pragma once
#include <ext/unordered_set>
#include <core/type_details.hpp>
#include <ext/typeinfo>
#include <factory/NormalizeFactory.hpp>
#include <object/AnyObject.h>
#include <object/Object.h>
#include <object/ObjectFactory.h>
namespace core {
template <typename T>
struct type_util<ext::unordered_set<T>> {
static ext::unordered_set<T> denormalize(ext::unordered_set<object::Object>&& arg)
{
ext::unordered_set<T> res;
for (object::Object&& item : ext::make_mover(arg))
res.insert(factory::NormalizeFactory::denormalize<T>(std::move(item)));
return res;
}
static ext::unordered_set<object::Object> normalize(ext::unordered_set<T>&& arg)
{
ext::unordered_set<object::Object> res;
for (T&& item : ext::make_mover(arg))
res.insert(factory::NormalizeFactory::normalize<T>(std::move(item)));
return res;
}
static std::unique_ptr<type_details_base> type(const ext::unordered_set<T>& arg)
{
core::unique_ptr_set<type_details_base> subTypes;
for (const T& item : arg)
subTypes.insert(type_util<T>::type(item));
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_variant_type::make_variant(std::move(subTypes)));
return std::make_unique<type_details_template>("ext::unordered_set", std::move(sub_types_vec));
}
};
template <class T>
struct type_details_retriever<ext::unordered_set<T>> {
static std::unique_ptr<type_details_base> get()
{
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_retriever<T>::get());
return std::make_unique<type_details_template>("ext::unordered_set", std::move(sub_types_vec));
}
};
}
#pragma once
#include <ext/variant>
#include <core/type_details.hpp>
#include <ext/typeinfo>
namespace core {
template <typename... Ts>
class type_util<ext::variant<Ts...>> {
public:
static std::unique_ptr<type_details_base> type(const ext::variant<Ts...>& arg)
{
auto visitor = []<class T>(T&& element) {
return type_util<std::decay_t<T>>::type(element);
};
return ext::visit(visitor, std::move(arg));
}
};
template <class... Ts>
struct type_details_retriever<ext::variant<Ts...>> {
static std::unique_ptr<type_details_base> get()
{
core::unique_ptr_set<type_details_base> res;
(res.insert(type_details_retriever<Ts>::get()), ...);
return std::make_unique<type_details_variant_type>(std::move(res));
}
};
}
#pragma once
#include <ext/vector>
#include <core/type_details.hpp>
#include <ext/typeinfo>
#include <factory/NormalizeFactory.hpp>
#include <object/AnyObject.h>
#include <object/Object.h>
#include <object/ObjectFactory.h>
namespace core {
template <typename T>
struct type_util<ext::vector<T>> {
static ext::vector<T> denormalize(ext::vector<object::Object>&& arg)
{
ext::vector<T> res;
for (object::Object&& item : ext::make_mover(arg))
res.push_back(factory::NormalizeFactory::denormalize<T>(std::move(item)));
return res;
}
static ext::vector<object::Object> normalize(ext::vector<T>&& arg)
{
ext::vector<object::Object> res;
for (std::conditional_t<std::is_same_v<bool, T>, T, T&&> item : ext::make_mover(arg))
res.push_back(factory::NormalizeFactory::normalize<T>(std::move(item)));
return res;
}
static std::unique_ptr<type_details_base> type(const ext::vector<T>& arg)
{
core::unique_ptr_set<type_details_base> subTypes;
for (const T& item : arg)
subTypes.insert(type_util<T>::type(item));
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_variant_type::make_variant(std::move(subTypes)));
return std::make_unique<type_details_template>("ext::vector", std::move(sub_types_vec));
}
};
template <class T>
struct type_details_retriever<ext::vector<T>> {
static std::unique_ptr<type_details_base> get()
{
std::vector<std::unique_ptr<type_details_base>> sub_types_vec;
sub_types_vec.push_back(type_details_retriever<T>::get());
return std::make_unique<type_details_template>("ext::vector", std::move(sub_types_vec));
}
};
}
#pragma once #pragma once
   
#include <alib/tuple> #include <ext/array>
#include <alib/array> #include <ext/tuple>
#include <alib/typeinfo> #include <ext/typeinfo>
   
#include <abstraction/OperationAbstraction.hpp> #include <abstraction/OperationAbstraction.hpp>
#include <abstraction/ValueHolderInterface.hpp> #include <abstraction/ValueHolderInterface.hpp>
...@@ -11,43 +11,46 @@ namespace abstraction { ...@@ -11,43 +11,46 @@ namespace abstraction {
   
namespace detail { namespace detail {
   
template < class ... ParamTypes, class F, class Tuple, std::size_t... I > template <class... ParamTypes, class F, class Tuple, std::size_t... I>
constexpr decltype ( auto ) apply_impl ( F && f, Tuple && t, std::index_sequence < I ... > ) { constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
return std::invoke ( std::forward < F > ( f ), abstraction::retrieveValue < ParamTypes > ( std::get < I > ( std::forward < Tuple > ( t ) ) ) ... ); {
return std::invoke(std::forward<F>(f), abstraction::retrieveValue<ParamTypes>(std::get<I>(std::forward<Tuple>(t)))...);
} }
   
} // namespace detail } // namespace detail
   
template < class ... ParamTypes, class F, class Tuple > template <class... ParamTypes, class F, class Tuple>
constexpr decltype ( auto ) apply ( F && f, Tuple && t ) { constexpr decltype(auto) apply(F&& f, Tuple&& t)
return detail::apply_impl < ParamTypes ... > ( std::forward < F > ( f ), std::forward < Tuple > ( t ), std::make_index_sequence < sizeof ... ( ParamTypes ) > { } ); {
return detail::apply_impl<ParamTypes...>(std::forward<F>(f), std::forward<Tuple>(t), std::make_index_sequence<sizeof...(ParamTypes)>{});
} }
   
template < class ... Params > template <class... Params>
static ext::type_index paramType ( unsigned index ) { static core::type_details paramType(unsigned index)
ext::type_index res ( typeid ( void ) ); {
core::type_details res = core::type_details::universal_type();
   
auto lambda = [ & ] ( auto I ) { auto lambda = [&](auto I) {
res = ext::type_index ( typeid ( std::tuple_element_t < decltype ( I )::value, std::tuple < Params ... > > ) ); res = core::type_details::get<std::decay_t<std::tuple_element_t<decltype(I)::value, std::tuple<Params...>>>>();
}; };
   
ext::constexpr_switch < sizeof ... ( Params ) > ( index, lambda ); ext::constexpr_switch<sizeof...(Params)>(index, lambda);
   
return res; return res;
} }
   
template < class ... Params > template <class... Params>
abstraction::TypeQualifiers::TypeQualifierSet paramTypeQualifiers ( unsigned index ) { abstraction::TypeQualifiers::TypeQualifierSet paramTypeQualifiers(unsigned index)
abstraction::TypeQualifiers::TypeQualifierSet res = abstraction::TypeQualifiers::TypeQualifierSet::NONE; {
abstraction::TypeQualifiers::TypeQualifierSet res = abstraction::TypeQualifiers::TypeQualifierSet::NONE;
   
auto lambda = [ & ] ( auto I ) { auto lambda = [&](auto I) {
res = abstraction::TypeQualifiers::typeQualifiers < std::tuple_element_t < decltype ( I )::value, std::tuple < Params ... > > > ( ); res = abstraction::TypeQualifiers::typeQualifiers<std::tuple_element_t<decltype(I)::value, std::tuple<Params...>>>();
}; };
   
ext::constexpr_switch < sizeof ... ( Params ) > ( index, lambda ); ext::constexpr_switch<sizeof...(Params)>(index, lambda);
   
return res; return res;
} }
   
} /* namespace abstraction */ } /* namespace abstraction */
#include <exception>
#include <algorithm> #include <algorithm>
#include <exception>
   
#include <common/AlgorithmCategories.hpp> #include <common/AlgorithmCategories.hpp>
   
namespace abstraction { namespace abstraction {
   
abstraction::AlgorithmCategories::AlgorithmCategory AlgorithmCategories::algorithmCategory ( std::string category ) { abstraction::AlgorithmCategories::AlgorithmCategory AlgorithmCategories::algorithmCategory(std::string category)
std::transform ( category.begin ( ), category.end ( ), category.begin ( ), ::tolower ); {
std::transform(category.begin(), category.end(), category.begin(), ::tolower);
   
if ( category == "default" ) if (category == "default")
return AlgorithmCategory::DEFAULT; return AlgorithmCategory::DEFAULT;
   
if ( category == "test" ) if (category == "test")
return AlgorithmCategory::TEST; return AlgorithmCategory::TEST;
   
if ( category == "student" ) if (category == "student")
return AlgorithmCategory::STUDENT; return AlgorithmCategory::STUDENT;
   
if ( category == "efficient" ) if (category == "efficient")
return AlgorithmCategory::EFFICIENT; return AlgorithmCategory::EFFICIENT;
   
if ( category == "naive" ) if (category == "naive")
return AlgorithmCategory::NAIVE; return AlgorithmCategory::NAIVE;
   
return AlgorithmCategory::NONE; return AlgorithmCategory::NONE;
} }
   
std::string AlgorithmCategories::toString ( abstraction::AlgorithmCategories::AlgorithmCategory category ) { std::string AlgorithmCategories::toString(abstraction::AlgorithmCategories::AlgorithmCategory category)
switch ( category ) { {
case abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT: switch (category) {
return "default"; case abstraction::AlgorithmCategories::AlgorithmCategory::DEFAULT:
case abstraction::AlgorithmCategories::AlgorithmCategory::TEST: return "default";
return "test"; case abstraction::AlgorithmCategories::AlgorithmCategory::TEST:
case abstraction::AlgorithmCategories::AlgorithmCategory::STUDENT: return "test";
return "student"; case abstraction::AlgorithmCategories::AlgorithmCategory::STUDENT:
case abstraction::AlgorithmCategories::AlgorithmCategory::EFFICIENT: return "student";
return "efficient"; case abstraction::AlgorithmCategories::AlgorithmCategory::EFFICIENT:
case abstraction::AlgorithmCategories::AlgorithmCategory::NAIVE: return "efficient";
return "naive"; case abstraction::AlgorithmCategories::AlgorithmCategory::NAIVE:
case abstraction::AlgorithmCategories::AlgorithmCategory::NONE: return "naive";
return "none"; case abstraction::AlgorithmCategories::AlgorithmCategory::NONE:
} return "none";
throw std::logic_error ( "Unhandled category." ); }
throw std::logic_error("Unhandled category.");
} }
   
std::ostream & operator << ( std::ostream & os, AlgorithmCategories::AlgorithmCategory category ) { std::ostream& operator<<(std::ostream& os, AlgorithmCategories::AlgorithmCategory category)
return os << AlgorithmCategories::toString ( category ); {
return os << AlgorithmCategories::toString(category);
} }
   
} /* namespace abstraction */ } /* namespace abstraction */
#pragma once #pragma once
   
#include <alib/string> #include <ext/string>
   
namespace abstraction { namespace abstraction {
   
class AlgorithmCategories { class AlgorithmCategories {
public: public:
enum class AlgorithmCategory { enum class AlgorithmCategory {
DEFAULT, DEFAULT,
TEST, TEST,
STUDENT, STUDENT,
EFFICIENT, EFFICIENT,
NAIVE, NAIVE,
NONE NONE
}; };
static AlgorithmCategory algorithmCategory ( std::string category ); static AlgorithmCategory algorithmCategory(std::string category);
static std::string toString ( AlgorithmCategory category ); static std::string toString(AlgorithmCategory category);
}; };
   
std::ostream & operator << ( std::ostream & os, AlgorithmCategories::AlgorithmCategory category ); std::ostream& operator<<(std::ostream& os, AlgorithmCategories::AlgorithmCategory category);
   
} /* namespace abstraction */ } /* namespace abstraction */
#include <common/CastHelper.h> #include <common/CastHelper.h>
   
#include <registry/Registry.h>
#include <exception> #include <exception>
#include <registry/Registry.h>
   
namespace abstraction { namespace abstraction {
   
std::shared_ptr < abstraction::Value > CastHelper::eval ( abstraction::TemporariesHolder &, const std::shared_ptr < abstraction::Value > & param, const std::string & type ) { std::shared_ptr<abstraction::Value> CastHelper::eval(abstraction::TemporariesHolder& environment, std::shared_ptr<abstraction::Value> param, const core::type_details& type)
if ( abstraction::Registry::isCastNoOp ( type, param->getType ( ) ) ) { {
return param; if (abstraction::Registry::isCastNoOp(param->getActualType(), type)) {
} return param;
}
std::unique_ptr<abstraction::OperationAbstraction> res = abstraction::Registry::getCastAbstraction(type, param->getActualType());
if (abstraction::Registry::hasDenormalize(res->getParamType(0)) && res->getParamType(0) != param->getDeclaredType()) {
std::unique_ptr<abstraction::OperationAbstraction> denormalize = abstraction::Registry::getDenormalizeAbstraction(res->getParamType(0));
denormalize->attachInput(param, 0);
param = denormalize->eval();
if (!param)
throw std::invalid_argument("Internal error in denormalization.");
environment.holdTemporary(param);
}
res->attachInput(param, 0);
   
std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( type, param->getType ( ) ); std::shared_ptr<abstraction::Value> result = res->eval();
res->attachInput ( param, 0 ); if (!result)
throw std::invalid_argument("Eval of cast to " + ext::to_string(type) + " failed.");
   
std::shared_ptr < abstraction::Value > result = res->eval ( ); if (abstraction::Registry::hasNormalize(result->getDeclaredType())) {
if ( ! result ) std::unique_ptr<abstraction::OperationAbstraction> normalize = abstraction::Registry::getNormalizeAbstraction(result->getDeclaredType());
throw std::invalid_argument ( "Eval of cast to " + type + " failed." ); normalize->attachInput(result, 0);
result = normalize->eval();
if (!result)
throw std::invalid_argument("Eval of normalize of cast to " + ext::to_string(type) + " failed.");
}
   
if ( abstraction::Registry::hasNormalize ( result->getType ( ) ) ) { environment.holdTemporary(result);
std::shared_ptr < abstraction::OperationAbstraction > normalize = abstraction::Registry::getNormalizeAbstraction ( result->getType ( ) );
normalize->attachInput ( result, 0 );
result = normalize->eval ( );
if ( ! result )
throw std::invalid_argument ( "Eval of normalize of cast to " + type + " failed." );
}
   
return result; return result;
} }
   
} /* namespace abstraction */ } /* namespace abstraction */
#pragma once #pragma once
   
#include <string>
#include <memory>
#include <abstraction/Value.hpp>
#include <abstraction/TemporariesHolder.h> #include <abstraction/TemporariesHolder.h>
#include <abstraction/Value.hpp>
#include <memory>
#include <string>
   
namespace abstraction { namespace abstraction {
   
class CastHelper { class CastHelper {
public: public:
static std::shared_ptr < abstraction::Value > eval ( abstraction::TemporariesHolder & environment, const std::shared_ptr < abstraction::Value > & param, const std::string & type ); static std::shared_ptr<abstraction::Value> eval(abstraction::TemporariesHolder& environment, std::shared_ptr<abstraction::Value> param, const core::type_details& type);
}; };
   
} /* namespace abstraction */ } /* namespace abstraction */
/*
* EvalHelper.cpp
*
* Created on: 25. 8. 2017
* Author: Jan Travnicek
*/
#include <common/EvalHelper.h> #include <common/EvalHelper.h>
   
#include <registry/Registry.h>
#include <exception>
#include <common/CastHelper.h> #include <common/CastHelper.h>
#include <exception>
#include <registry/Registry.h>
   
namespace abstraction { namespace abstraction {
   
std::shared_ptr < abstraction::Value > EvalHelper::evalAlgorithm ( abstraction::TemporariesHolder & environment, const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ) { std::shared_ptr<abstraction::Value> EvalHelper::evalAlgorithm(abstraction::TemporariesHolder& environment, const std::string& name, const ext::vector<std::string>& templateParams, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category)
ext::vector < std::string > paramTypes; {
ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > paramTypeQualifiers; ext::vector<core::type_details> paramTypes;
for ( const std::shared_ptr < abstraction::Value > & param : params ) { ext::vector<abstraction::TypeQualifiers::TypeQualifierSet> paramTypeQualifiers;
paramTypes.push_back ( param->getType ( ) ); for (const std::shared_ptr<abstraction::Value>& param : params) {
paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) ); paramTypes.push_back(param->getActualType());
} paramTypeQualifiers.push_back(param->getTypeQualifiers());
}
try {
return evalAbstraction ( environment, abstraction::Registry::getAlgorithmAbstraction ( name, templateParams, paramTypes, paramTypeQualifiers, category ), params ); try {
} catch ( const std::exception & executionException ) { return evalAbstraction(environment, abstraction::Registry::getAlgorithmAbstraction(name, templateParams, paramTypes, paramTypeQualifiers, category), params);
std::throw_with_nested ( std::runtime_error ( "Evaluation of algorithm " + name + " failed." ) ); } catch (const std::exception& executionException) {
} std::throw_with_nested(std::runtime_error("Evaluation of algorithm " + name + " failed."));
}
} }
   
std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::BinaryOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ) { std::shared_ptr<abstraction::Value> EvalHelper::evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::BinaryOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category)
ext::vector < std::string > paramTypes; {
ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > paramTypeQualifiers; ext::vector<core::type_details> paramTypes;
for ( const std::shared_ptr < abstraction::Value > & param : params ) { ext::vector<abstraction::TypeQualifiers::TypeQualifierSet> paramTypeQualifiers;
paramTypes.push_back ( param->getType ( ) ); for (const std::shared_ptr<abstraction::Value>& param : params) {
paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) ); paramTypes.push_back(param->getActualType());
} paramTypeQualifiers.push_back(param->getTypeQualifiers());
}
try {
return evalAbstraction ( environment, abstraction::Registry::getBinaryOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params ); try {
} catch ( ... ) { return evalAbstraction(environment, abstraction::Registry::getBinaryOperatorAbstraction(type, paramTypes, paramTypeQualifiers, category), params);
std::throw_with_nested ( std::runtime_error ( "Evaluation of binary operator " + abstraction::Operators::toString ( type ) + " failed." ) ); } catch (...) {
} std::throw_with_nested(std::runtime_error("Evaluation of binary operator " + abstraction::Operators::toString(type) + " failed."));
}
} }
   
std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::PrefixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ) { std::shared_ptr<abstraction::Value> EvalHelper::evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::PrefixOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category)
ext::vector < std::string > paramTypes; {
ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > paramTypeQualifiers; ext::vector<core::type_details> paramTypes;
for ( const std::shared_ptr < abstraction::Value > & param : params ) { ext::vector<abstraction::TypeQualifiers::TypeQualifierSet> paramTypeQualifiers;
paramTypes.push_back ( param->getType ( ) ); for (const std::shared_ptr<abstraction::Value>& param : params) {
paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) ); paramTypes.push_back(param->getActualType());
} paramTypeQualifiers.push_back(param->getTypeQualifiers());
}
try {
return evalAbstraction ( environment, abstraction::Registry::getPrefixOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params ); try {
} catch ( ... ) { return evalAbstraction(environment, abstraction::Registry::getPrefixOperatorAbstraction(type, paramTypes, paramTypeQualifiers, category), params);
std::throw_with_nested ( std::runtime_error ( "Evaluation of prefix operator " + abstraction::Operators::toString ( type ) + " failed." ) ); } catch (...) {
} std::throw_with_nested(std::runtime_error("Evaluation of prefix operator " + abstraction::Operators::toString(type) + " failed."));
}
} }
   
std::shared_ptr < abstraction::Value > EvalHelper::evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::PostfixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ) { std::shared_ptr<abstraction::Value> EvalHelper::evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::PostfixOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category)
ext::vector < std::string > paramTypes; {
ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > paramTypeQualifiers; ext::vector<core::type_details> paramTypes;
for ( const std::shared_ptr < abstraction::Value > & param : params ) { ext::vector<abstraction::TypeQualifiers::TypeQualifierSet> paramTypeQualifiers;
paramTypes.push_back ( param->getType ( ) ); for (const std::shared_ptr<abstraction::Value>& param : params) {
paramTypeQualifiers.push_back ( param->getTypeQualifiers ( ) ); paramTypes.push_back(param->getActualType());
} paramTypeQualifiers.push_back(param->getTypeQualifiers());
}
try {
return evalAbstraction ( environment, abstraction::Registry::getPostfixOperatorAbstraction ( type, paramTypes, paramTypeQualifiers, category ), params ); try {
} catch ( ... ) { return evalAbstraction(environment, abstraction::Registry::getPostfixOperatorAbstraction(type, paramTypes, paramTypeQualifiers, category), params);
std::throw_with_nested ( std::runtime_error ( "Evaluation of postfix operator " + abstraction::Operators::toString ( type ) + " failed." ) ); } catch (...) {
} std::throw_with_nested(std::runtime_error("Evaluation of postfix operator " + abstraction::Operators::toString(type) + " failed."));
}
} }
   
std::shared_ptr < abstraction::Value > EvalHelper::evalAbstraction ( abstraction::TemporariesHolder & environment, std::shared_ptr < abstraction::OperationAbstraction > abstraction, const ext::vector < std::shared_ptr < abstraction::Value > > & params ) { std::shared_ptr<abstraction::Value> EvalHelper::evalAbstraction(abstraction::TemporariesHolder& environment, std::unique_ptr<abstraction::OperationAbstraction> abstraction, const ext::vector<std::shared_ptr<abstraction::Value>>& params)
unsigned i = 0; {
ext::vector < std::shared_ptr < abstraction::Value > > casted_params; unsigned i = 0;
for ( const std::shared_ptr < abstraction::Value > & param : params ) { ext::vector<std::shared_ptr<abstraction::Value>> casted_params;
if ( abstraction->isParamTypeUniversal ( i ) || abstraction::Registry::isCastNoOp ( abstraction->getParamType ( i ), param->getType ( ) ) ) { for (std::shared_ptr<abstraction::Value> param : params) {
casted_params.push_back ( param ); param = abstraction::CastHelper::eval(environment, param, abstraction->getParamType(i));
} else {
casted_params.push_back ( abstraction::CastHelper::eval ( environment, param, abstraction->getParamType ( i ) ) ); if (abstraction::Registry::hasDenormalize(abstraction->getParamType(i)) && abstraction->getParamType(i) != param->getDeclaredType()) {
environment.holdTemporary ( casted_params.back ( ) ); std::unique_ptr<abstraction::OperationAbstraction> denormalize = abstraction::Registry::getDenormalizeAbstraction(abstraction->getParamType(i));
} denormalize->attachInput(param, 0);
++ i; param = denormalize->eval();
} if (!param)
throw std::invalid_argument("Internal error in denormalization.");
i = 0; environment.holdTemporary(param);
for ( const std::shared_ptr < abstraction::Value > & param : casted_params ) { }
abstraction->attachInput ( param, i );
++ i; casted_params.push_back(param);
} ++i;
}
std::shared_ptr < abstraction::Value > result = abstraction->eval ( );
if ( ! result ) i = 0;
throw std::invalid_argument ( "Internal error in abstraction evaluation." ); for (const std::shared_ptr<abstraction::Value>& param : casted_params) {
abstraction->attachInput(param, i);
if ( abstraction::Registry::hasNormalize ( result->getType ( ) ) ) { ++i;
std::shared_ptr < abstraction::OperationAbstraction > normalize = abstraction::Registry::getNormalizeAbstraction ( result->getType ( ) ); }
normalize->attachInput ( result, 0 );
result = normalize->eval ( ); std::shared_ptr<abstraction::Value> result = abstraction->eval();
if ( ! result ) if (!result)
throw std::invalid_argument ( "Internal error in normalization." ); throw std::invalid_argument("Internal error in abstraction evaluation.");
}
if (abstraction::Registry::hasNormalize(result->getDeclaredType()) && !abstraction::TypeQualifiers::isRef(result->getTypeQualifiers())) {
return result; std::unique_ptr<abstraction::OperationAbstraction> normalize = abstraction::Registry::getNormalizeAbstraction(result->getDeclaredType());
normalize->attachInput(result, 0);
result = normalize->eval();
if (!result)
throw std::invalid_argument("Internal error in normalization.");
}
environment.holdTemporary(result);
return result;
} }
   
} /* namespace abstraction */ } /* namespace abstraction */
/*
* EvalHelper.hpp
*
* Created on: 25. 8. 2017
* Author: Jan Travnicek
*/
#pragma once #pragma once
   
#include <alib/string> #include <abstraction/TemporariesHolder.h>
#include <alib/memory> #include <abstraction/Value.hpp>
#include <alib/vector>
#include <common/AlgorithmCategories.hpp> #include <common/AlgorithmCategories.hpp>
#include <common/Operators.hpp> #include <common/Operators.hpp>
#include <abstraction/Value.hpp> #include <ext/memory>
#include <abstraction/TemporariesHolder.h> #include <ext/string>
#include <ext/vector>
   
namespace abstraction { namespace abstraction {
   
class EvalHelper { class EvalHelper {
static std::shared_ptr < abstraction::Value > evalAbstraction ( abstraction::TemporariesHolder & environment, std::shared_ptr < abstraction::OperationAbstraction > abstraction, const ext::vector < std::shared_ptr < abstraction::Value > > & params );
public: public:
static std::shared_ptr < abstraction::Value > evalAlgorithm ( abstraction::TemporariesHolder & environment, const std::string & name, const ext::vector < std::string > & templateParams, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ); static std::shared_ptr<abstraction::Value> evalAbstraction(abstraction::TemporariesHolder& environment, std::unique_ptr<abstraction::OperationAbstraction> abstraction, const ext::vector<std::shared_ptr<abstraction::Value>>& params);
   
static std::shared_ptr < abstraction::Value > evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::BinaryOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ); static std::shared_ptr<abstraction::Value> evalAlgorithm(abstraction::TemporariesHolder& environment, const std::string& name, const ext::vector<std::string>& templateParams, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category);
   
static std::shared_ptr < abstraction::Value > evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::PrefixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ); static std::shared_ptr<abstraction::Value> evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::BinaryOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category);
   
static std::shared_ptr < abstraction::Value > evalOperator ( abstraction::TemporariesHolder & environment, abstraction::Operators::PostfixOperators type, const ext::vector < std::shared_ptr < abstraction::Value > > & params, abstraction::AlgorithmCategories::AlgorithmCategory category ); static std::shared_ptr<abstraction::Value> evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::PrefixOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category);
static std::shared_ptr<abstraction::Value> evalOperator(abstraction::TemporariesHolder& environment, abstraction::Operators::PostfixOperators type, const ext::vector<std::shared_ptr<abstraction::Value>>& params, abstraction::AlgorithmCategories::AlgorithmCategory category);
}; };
   
} /* namespace abstraction */ } /* namespace abstraction */
...@@ -2,16 +2,19 @@ ...@@ -2,16 +2,19 @@
   
namespace abstraction { namespace abstraction {
   
std::ostream & operator << ( std::ostream & os, Operators::BinaryOperators oper ) { std::ostream& operator<<(std::ostream& os, Operators::BinaryOperators oper)
return os << Operators::toString ( oper ); {
return os << Operators::toString(oper);
} }
   
std::ostream & operator << ( std::ostream & os, Operators::PrefixOperators oper ) { std::ostream& operator<<(std::ostream& os, Operators::PrefixOperators oper)
return os << Operators::toString ( oper ); {
return os << Operators::toString(oper);
} }
   
std::ostream & operator << ( std::ostream & os, Operators::PostfixOperators oper ) { std::ostream& operator<<(std::ostream& os, Operators::PostfixOperators oper)
return os << Operators::toString ( oper ); {
return os << Operators::toString(oper);
} }
   
} /* namespace abstraction */ } /* namespace abstraction */
#pragma once #pragma once
   
#include <alib/string> #include <ext/string>
   
namespace abstraction { namespace abstraction {
   
class Operators { class Operators {
public: public:
enum class BinaryOperators { enum class BinaryOperators {
LOGICAL_AND, LOGICAL_AND,
LOGICAL_OR, LOGICAL_OR,
BINARY_XOR, BINARY_XOR,
BINARY_AND, BINARY_AND,
BINARY_OR, BINARY_OR,
ADD, ADD,
SUB, SUB,
MUL, MUL,
MOD, MOD,
DIV, DIV,
EQUALS, EQUALS,
NOT_EQUALS, NOT_EQUALS,
LESS, LESS,
LESS_OR_EQUAL, LESS_OR_EQUAL,
MORE, MORE,
MORE_OR_EQUAL, MORE_OR_EQUAL,
ASSIGN ASSIGN
}; };
   
enum class PrefixOperators { enum class PrefixOperators {
PLUS, PLUS,
MINUS, MINUS,
LOGICAL_NOT, LOGICAL_NOT,
BINARY_NEG, BINARY_NEG,
INCREMENT, INCREMENT,
DECREMENT DECREMENT
}; };
   
enum class PostfixOperators { enum class PostfixOperators {
INCREMENT, INCREMENT,
DECREMENT DECREMENT
}; };
   
static std::string toString ( BinaryOperators type ) { static std::string toString(BinaryOperators type)
switch ( type ) { {
case BinaryOperators::BINARY_AND : switch (type) {
return "binary_and"; case BinaryOperators::BINARY_AND:
case BinaryOperators::BINARY_OR : return "binary_and";
return "binary_or"; case BinaryOperators::BINARY_OR:
case BinaryOperators::BINARY_XOR : return "binary_or";
return "binary_xor"; case BinaryOperators::BINARY_XOR:
case BinaryOperators::LOGICAL_AND : return "binary_xor";
return "logical_and"; case BinaryOperators::LOGICAL_AND:
case BinaryOperators::LOGICAL_OR : return "logical_and";
return "logical_or"; case BinaryOperators::LOGICAL_OR:
case BinaryOperators::ADD : return "logical_or";
return "add"; case BinaryOperators::ADD:
case BinaryOperators::SUB : return "add";
return "sub"; case BinaryOperators::SUB:
case BinaryOperators::MUL : return "sub";
return "mul"; case BinaryOperators::MUL:
case BinaryOperators::MOD : return "mul";
return "mod"; case BinaryOperators::MOD:
case BinaryOperators::DIV : return "mod";
return "div"; case BinaryOperators::DIV:
case BinaryOperators::EQUALS : return "div";
return "equals"; case BinaryOperators::EQUALS:
case BinaryOperators::NOT_EQUALS : return "equals";
return "not_equals"; case BinaryOperators::NOT_EQUALS:
case BinaryOperators::LESS : return "not_equals";
return "less"; case BinaryOperators::LESS:
case BinaryOperators::LESS_OR_EQUAL : return "less";
return "less_or_equal"; case BinaryOperators::LESS_OR_EQUAL:
case BinaryOperators::MORE : return "less_or_equal";
return "more"; case BinaryOperators::MORE:
case BinaryOperators::MORE_OR_EQUAL : return "more";
return "more_or_equal"; case BinaryOperators::MORE_OR_EQUAL:
case BinaryOperators::ASSIGN : return "more_or_equal";
return "assign"; case BinaryOperators::ASSIGN:
} return "assign";
throw std::invalid_argument ( "Undefined option" ); }
} 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" );
}
   
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::BinaryOperators oper);
   
std::ostream & operator << ( std::ostream & os, Operators::PrefixOperators oper ); std::ostream& operator<<(std::ostream& os, Operators::PrefixOperators oper);
   
std::ostream & operator << ( std::ostream & os, Operators::PostfixOperators oper ); std::ostream& operator<<(std::ostream& os, Operators::PostfixOperators oper);
   
} /* namespace abstraction */ } /* namespace abstraction */
#include <common/OverloadResolution.hpp>
#include <registry/AlgorithmRegistry.hpp>
#include <registry/CastRegistry.hpp>
#include <registry/OperatorRegistry.hpp>
#include <ext/foreach>
namespace abstraction {
template <class Entry>
std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<Entry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>&, AlgorithmCategories::AlgorithmCategory category)
{
enum class MatchType {
EXACT,
CAST,
INCOMPATIBLE
};
auto incompatibleLambda = [](MatchType compatibility) {
return compatibility == MatchType::INCOMPATIBLE;
};
// determine how one can actually map what we have ( paramTypes ) as params to what is available as overloads ( overloads )
std::vector<std::pair<ext::vector<MatchType>, Entry*>> compatibilityData;
for (const std::unique_ptr<Entry>& entry : overloads) {
if (entry->getEntryInfo().getCategory() != category && AlgorithmCategories::AlgorithmCategory::NONE != category)
continue;
if (entry->getEntryInfo().getParams().size() != paramTypes.size())
continue;
ext::vector<MatchType> compatibilityVector;
for (size_t i = 0; i < paramTypes.size(); ++i) {
MatchType matchType;
if (paramTypes[i].compatible_with(std::get<0>(entry->getEntryInfo().getParams()[i])) || core::type_details::universal_type().compatible_with(std::get<0>(entry->getEntryInfo().getParams()[i]))) {
matchType = MatchType::EXACT;
} else if (abstraction::CastRegistry::castAvailable(std::get<0>(entry->getEntryInfo().getParams()[i]), paramTypes[i], true)) {
matchType = MatchType::CAST;
} else {
matchType = MatchType::INCOMPATIBLE;
}
compatibilityVector.push_back(matchType);
}
// clear incompatibilities are fitered out
if (std::none_of(compatibilityVector.begin(), compatibilityVector.end(), incompatibleLambda))
compatibilityData.emplace_back(std::move(compatibilityVector), entry.get());
}
for (auto iter = compatibilityData.begin(); iter != compatibilityData.end();) {
const auto& formalArgumentsLike = iter->second->getEntryInfo().getParams();
auto compatibilityCheck = [&](const auto& compatibilityDataEntry) {
if (compatibilityDataEntry.second == iter->second)
return false;
const auto& actualArgumentsLike = compatibilityDataEntry.second->getEntryInfo().getParams();
for (size_t i = 0; i < actualArgumentsLike.size(); ++i)
if (!std::get<0>(actualArgumentsLike[i]).compatible_with(std::get<0>(formalArgumentsLike[i])))
return false;
return true;
};
if (std::any_of(compatibilityData.begin(), compatibilityData.end(), compatibilityCheck))
iter = compatibilityData.erase(iter);
else
++iter;
}
// 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 (size_t i = 0; i < paramTypes.size(); ++i) {
ext::set<unsigned> best;
unsigned overload = 0;
for (const std::pair<ext::vector<MatchType>, Entry*>& data : compatibilityData) {
if (data.first[i] == MatchType::EXACT)
best.insert(overload);
++overload;
}
if (!best.empty()) {
winnerList.push_back(std::move(best));
continue;
}
overload = 0;
for (const std::pair<ext::vector<MatchType>, Entry*>& data : compatibilityData) {
if (data.first[i] == MatchType::CAST)
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 ext::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
if (winner.size() == 1) {
return compatibilityData[*winner.begin()].second->getAbstraction();
} else if (winner.size() > 1) {
// throw std::invalid_argument ( "Entry overload " + ext::to_string ( paramTypes ) + " ambiguous." ); FIXME make better overload select algorithm
return compatibilityData[*std::next(winner.begin())].second->getAbstraction(); // FIXME terrible hack to get to const variant of get on datastructures...
/* if(common::GlobalData::verbose)
common::Streams::err << "Entry overload " + ss.str ( ) + " ambiguous. First selected." << std::endl;*/
} else {
throw std::invalid_argument("Entry overload not found");
}
}
template std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<OperatorRegistry::BinaryEntry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>& typeQualifiers, AlgorithmCategories::AlgorithmCategory category);
template std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<OperatorRegistry::PrefixEntry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>& typeQualifiers, AlgorithmCategories::AlgorithmCategory category);
template std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<OperatorRegistry::PostfixEntry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>& typeQualifiers, AlgorithmCategories::AlgorithmCategory category);
template std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<AlgorithmRegistry::Entry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>& typeQualifiers, AlgorithmCategories::AlgorithmCategory category);
} /* namespace abstraction */
#pragma once #pragma once
   
#include <alib/list>
#include <common/AlgorithmCategories.hpp> #include <common/AlgorithmCategories.hpp>
#include <ext/list>
   
namespace abstraction { #include <abstraction/OperationAbstraction.hpp>
template < class Entry >
std::shared_ptr < abstraction::OperationAbstraction > getOverload ( const ext::list < std::unique_ptr < Entry > > & overloads, const ext::vector < std::string > & paramTypes, const ext::vector < abstraction::TypeQualifiers::TypeQualifierSet > &, AlgorithmCategories::AlgorithmCategory category ) {
enum class MatchType {
EXACT,
CAST,
INCOMPATIBLE
};
auto incompatibleLambda = [ ] ( MatchType compatibility ) {
return compatibility == MatchType::INCOMPATIBLE;
};
// determine how one can actually map what we have ( paramTypes ) as params to what is available as overloads ( overloads )
std::vector < std::pair < ext::vector < MatchType >, Entry * > > compatibilityData;
for ( const std::unique_ptr < Entry > & entry : overloads ) {
if ( entry->getEntryInfo ( ).getCategory ( ) != category && AlgorithmCategories::AlgorithmCategory::NONE != category )
continue;
if ( entry->getEntryInfo ( ).getParams ( ).size ( ) != paramTypes.size ( ) )
continue;
ext::vector < MatchType > compatibilityVector;
for ( size_t i = 0; i < paramTypes.size ( ); ++ i ) {
MatchType matchType;
if ( std::get < 0 > ( entry->getEntryInfo ( ).getParams ( ) [ i ] ) == paramTypes [ i ] || std::get < 0 > ( entry->getEntryInfo ( ).getParams ( ) [ i ] ) == "auto" ) {
matchType = MatchType::EXACT;
} else if ( abstraction::CastRegistry::castAvailable ( std::get < 0 > ( entry->getEntryInfo ( ).getParams ( ) [ i ] ), paramTypes [ i ], true ) ) {
matchType = MatchType::CAST;
} else {
matchType = MatchType::INCOMPATIBLE;
}
compatibilityVector.push_back ( matchType );
}
// clear incompatibilities are fitered out
if ( std::none_of ( compatibilityVector.begin ( ), compatibilityVector.end ( ), incompatibleLambda ) )
compatibilityData.emplace_back ( std::move ( compatibilityVector ), entry.get ( ) );
}
// 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 ( size_t i = 0; i < paramTypes.size ( ); ++ i ) {
ext::set < unsigned > best;
   
unsigned overload = 0; namespace abstraction {
for ( const std::pair < ext::vector < MatchType >, Entry * > & data : compatibilityData ) {
if ( data.first [ i ] == MatchType::EXACT )
best.insert ( overload );
++ overload;
}
if ( !best.empty ( ) ) {
winnerList.push_back ( std::move ( best ) );
continue;
}
overload = 0;
for ( const std::pair < ext::vector < MatchType >, Entry * > & data : compatibilityData ) {
if ( data.first [ i ] == MatchType::CAST )
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 ext::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
if ( winner.size ( ) == 1 ) {
return compatibilityData [ * winner.begin ( ) ].second->getAbstraction ( );
} else if ( winner.size ( ) > 1 ) {
// throw std::invalid_argument ( "Entry overload " + ext::to_string ( paramTypes ) + " ambiguous." ); FIXME make better overload select algorithm
return compatibilityData [ * std::next ( winner.begin ( ) ) ].second->getAbstraction ( ); // FIXME terrible hack to get to const variant of get on datastructures...
   
/* if(common::GlobalData::verbose) template <class Entry>
common::Streams::err << "Entry overload " + ss.str ( ) + " ambiguous. First selected." << std::endl;*/ std::unique_ptr<abstraction::OperationAbstraction> getOverload(const ext::list<std::unique_ptr<Entry>>& overloads, const ext::vector<core::type_details>& paramTypes, const ext::vector<abstraction::TypeQualifiers::TypeQualifierSet>&, AlgorithmCategories::AlgorithmCategory category);
} else {
throw std::invalid_argument ( "Entry overload not found" );
}
}
   
} /* namespace abstraction */ } /* namespace abstraction */
This diff is collapsed.
This diff is collapsed.