From a90a1a776eae1fdc90c1fbb66cf058f690345c4a Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Wed, 10 Jul 2024 20:28:51 -0400 Subject: [PATCH] Add a `NamedOperator` facility to Alepha. This permits naming operators via an enhanced enum and then looking them up. This is a useful component for quick scripting language functionalities. --- Utility/CMakeLists.txt | 1 + Utility/NamedOperator.h | 64 +++++++++++++++++++++++ Utility/NamedOperator.test/0.cc | 31 +++++++++++ Utility/NamedOperator.test/CMakeLists.txt | 1 + 4 files changed, 97 insertions(+) create mode 100644 Utility/NamedOperator.h create mode 100644 Utility/NamedOperator.test/0.cc create mode 100644 Utility/NamedOperator.test/CMakeLists.txt diff --git a/Utility/CMakeLists.txt b/Utility/CMakeLists.txt index 2c1bf06..6d3634f 100644 --- a/Utility/CMakeLists.txt +++ b/Utility/CMakeLists.txt @@ -4,3 +4,4 @@ target_sources( alepha PRIVATE add_subdirectory( derived_pointer_cast.test ) add_subdirectory( print_number.test ) +add_subdirectory( NamedOperator.test ) diff --git a/Utility/NamedOperator.h b/Utility/NamedOperator.h new file mode 100644 index 0000000..5d7f848 --- /dev/null +++ b/Utility/NamedOperator.h @@ -0,0 +1,64 @@ +static_assert( __cplusplus > 2023'00 ); + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace Alepha::Hydrogen::Utility ::detail:: NamedOperator_m +{ + inline namespace exports + { + using OperatorName= Enum + < + "add"_value, + "sub"_value, + "mul"_value, + "mod"_value, + "idiv"_value + >; + + } + + struct comparator + { + constexpr auto + operator () ( const OperatorName &lhs, const OperatorName &rhs ) const + { + return lhs.get_index() < rhs.get_index(); + } + }; + + namespace exports + { + template< typename Type > + auto + getOperatorMap() + { + std::map< OperatorName, std::function< Type ( Type, Type ) >, comparator > rv + { + { "add"_value, std::plus<>{} }, + { "sub"_value, std::minus<>{} }, + { "mul"_value, std::multiplies<>{} }, + { "mod"_value, std::modulus<>{} }, + }; + + if constexpr( std::is_integral_v< Type > ) + { + rv[ "idiv"_value ]= std::divides<>{}; + } + + return rv; + }; + } +} + +namespace Alepha::Hydrogen::Utility::inline exports::inline NamedOperator_m +{ + using namespace detail::NamedOperator_m::exports; +} diff --git a/Utility/NamedOperator.test/0.cc b/Utility/NamedOperator.test/0.cc new file mode 100644 index 0000000..5fe2c0c --- /dev/null +++ b/Utility/NamedOperator.test/0.cc @@ -0,0 +1,31 @@ +static_assert( __cplusplus > 2023'00 ); + +#include "../NamedOperator.h" + +#include +#include + +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + using namespace Alepha::Utility::NamedOperator_m; + using namespace Alepha::literals::enum_literals; + + "Does the named operator system have the expected basic functionality?"_test <= TableTest + < + []( const int lhs, const OperatorName name, const int rhs ) + { + return getOperatorMap< int >().at( name )( lhs, rhs ); + } + > + ::Cases + { + { "addition", { 1, "add"_value, 1 }, 2 }, + { "subtraction", { 1, "sub"_value, 1 }, 0 }, + { "multiplication", { 5, "mul"_value, 5 }, 25 }, + { "modulus", { 9, "mod"_value, 5 }, 4 }, + { "division", { 5, "idiv"_value, 3 }, 1 }, + }; +}; diff --git a/Utility/NamedOperator.test/CMakeLists.txt b/Utility/NamedOperator.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Utility/NamedOperator.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )