Skip to content
Snippets Groups Projects
Commit 39e8b549 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Change unary operator expression builder

One now use OperatorRepository
parent 46f9c3d9
No related branches found
No related tags found
1 merge request!70Feature/language reduce static
Showing
with 358 additions and 98 deletions
......@@ -2,99 +2,33 @@
#include <language/PEGGrammar.hpp>
#include <language/node_processor/UnaryExpressionProcessor.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/ParseError.hpp>
#include <language/utils/UnaryOperatorMangler.hpp>
ASTNodeUnaryOperatorExpressionBuilder::ASTNodeUnaryOperatorExpressionBuilder(ASTNode& n)
{
auto set_unary_operator_processor = [](ASTNode& n, const auto& operator_v) {
using OperatorT = std::decay_t<decltype(operator_v)>;
const ASTNodeDataType& data_type = n.children[0]->m_data_type;
auto set_unary_operator_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
using ValueT = std::decay_t<decltype(value)>;
switch (data_type) {
case ASTNodeDataType::bool_t: {
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, bool>>(n);
break;
}
case ASTNodeDataType::unsigned_int_t: {
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
case ASTNodeDataType::int_t: {
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, int64_t>>(n);
break;
}
case ASTNodeDataType::double_t: {
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, double>>(n);
break;
}
default: {
throw ParseError("unexpected error: invalid operand type for unary operator",
std::vector{n.children[0]->begin()});
}
}
};
auto set_unary_operator_processor_for_value = [&](const ASTNodeDataType& value_type) {
const ASTNodeDataType data_type = n.children[0]->m_data_type;
switch (value_type) {
case ASTNodeDataType::bool_t: {
set_unary_operator_processor_for_data(bool{}, data_type);
break;
}
case ASTNodeDataType::int_t: {
set_unary_operator_processor_for_data(int64_t{}, data_type);
break;
}
case ASTNodeDataType::double_t: {
set_unary_operator_processor_for_data(double{}, data_type);
break;
}
case ASTNodeDataType::vector_t: {
if constexpr (std::is_same_v<OperatorT, language::unary_minus>) {
switch (data_type.dimension()) {
case 1: {
using ValueT = TinyVector<1>;
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
case 2: {
using ValueT = TinyVector<2>;
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
case 3: {
using ValueT = TinyVector<3>;
n.m_node_processor = std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw ParseError("unexpected error: invalid vector dimension", std::vector{n.begin()});
}
// LCOV_EXCL_STOP
}
const std::string unary_operator_name = [&] {
if (n.is_type<language::unary_minus>()) {
return unaryOperatorMangler<language::unary_minus>(data_type);
} else if (n.is_type<language::unary_not>()) {
return unaryOperatorMangler<language::unary_not>(data_type);
} else {
// LCOV_EXCL_START
throw ParseError("unexpected error: invalid unary operator for vector data", std::vector{n.begin()});
// LCOV_EXCL_STOP
}
break;
}
default: {
throw ParseError("undefined value type for unary operator", std::vector{n.begin()});
}
throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
}
};
}();
set_unary_operator_processor_for_value(n.m_data_type);
};
const auto& optional_processor_builder = OperatorRepository::instance().getUnaryProcessorBuilder(unary_operator_name);
if (n.is_type<language::unary_minus>()) {
set_unary_operator_processor(n, language::unary_minus{});
} else if (n.is_type<language::unary_not>()) {
set_unary_operator_processor(n, language::unary_not{});
if (optional_processor_builder.has_value()) {
n.m_node_processor = optional_processor_builder.value()->getNodeProcessor(n);
} else {
throw ParseError("unexpected error: undefined unary operator", std::vector{n.begin()});
std::ostringstream error_message;
error_message << "undefined unary operator type: ";
error_message << rang::fgB::red << unary_operator_name << rang::fg::reset;
throw ParseError(error_message.str(), std::vector{n.children[0]->begin()});
}
}
......@@ -2,8 +2,8 @@
#define UNARY_EXPRESSION_PROCESSOR_HPP
#include <language/PEGGrammar.hpp>
#include <language/ast/ASTNode.hpp>
#include <language/node_processor/INodeProcessor.hpp>
#include <language/utils/SymbolTable.hpp>
template <typename Op>
struct UnaryOp;
......
......@@ -33,9 +33,7 @@ affectationMangler(const ASTNodeDataType& lhs, const ASTNodeDataType& rhs)
} else if constexpr (std::is_same_v<language::minuseq_op, AffectationOperatorT>) {
return "-=";
} else {
// LCOV_EXCL_START
throw UnexpectedError("undefined affectation operator");
// LCOV_EXCL_STOP
static_assert(std::is_same_v<language::eq_op, AffectationOperatorT>, "undefined affectation operator");
}
}();
......
# ------------------- Source files --------------------
add_library(PugsLanguageUtils
AffectationRegisterForB
AffectationRegisterForN
AffectationRegisterForR
AffectationRegisterForR1
AffectationRegisterForR2
AffectationRegisterForR3
AffectationRegisterForString
AffectationRegisterForZ
AffectationRegisterForB.cpp
AffectationRegisterForN.cpp
AffectationRegisterForR.cpp
AffectationRegisterForR1.cpp
AffectationRegisterForR2.cpp
AffectationRegisterForR3.cpp
AffectationRegisterForString.cpp
AffectationRegisterForZ.cpp
ASTDotPrinter.cpp
ASTExecutionInfo.cpp
ASTNodeDataType.cpp
......@@ -16,6 +16,13 @@ add_library(PugsLanguageUtils
DataVariant.cpp
EmbeddedData.cpp
OperatorRepository.cpp
UnaryOperatorRegisterForB.cpp
UnaryOperatorRegisterForN.cpp
UnaryOperatorRegisterForR.cpp
UnaryOperatorRegisterForR1.cpp
UnaryOperatorRegisterForR2.cpp
UnaryOperatorRegisterForR3.cpp
UnaryOperatorRegisterForZ.cpp
)
......
#ifndef I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
#define I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
class ASTNode;
class INodeProcessor;
#include <memory>
class IUnaryOperatorProcessorBuilder
{
public:
virtual std::unique_ptr<INodeProcessor> getNodeProcessor(ASTNode& node) const = 0;
virtual ~IUnaryOperatorProcessorBuilder() = default;
};
#endif // I_UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
......@@ -9,6 +9,13 @@
#include <language/utils/AffectationRegisterForR3.hpp>
#include <language/utils/AffectationRegisterForString.hpp>
#include <language/utils/AffectationRegisterForZ.hpp>
#include <language/utils/UnaryOperatorRegisterForB.hpp>
#include <language/utils/UnaryOperatorRegisterForN.hpp>
#include <language/utils/UnaryOperatorRegisterForR.hpp>
#include <language/utils/UnaryOperatorRegisterForR1.hpp>
#include <language/utils/UnaryOperatorRegisterForR2.hpp>
#include <language/utils/UnaryOperatorRegisterForR3.hpp>
#include <language/utils/UnaryOperatorRegisterForZ.hpp>
#include <utils/PugsAssert.hpp>
......@@ -18,6 +25,7 @@ void
OperatorRepository::reset()
{
m_affectation_builder_list.clear();
m_unary_operator_builder_list.clear();
this->_initialize();
}
......@@ -48,4 +56,12 @@ OperatorRepository::_initialize()
AffectationRegisterForR2{};
AffectationRegisterForR3{};
AffectationRegisterForString{};
UnaryOperatorRegisterForB{};
UnaryOperatorRegisterForN{};
UnaryOperatorRegisterForZ{};
UnaryOperatorRegisterForR{};
UnaryOperatorRegisterForR1{};
UnaryOperatorRegisterForR2{};
UnaryOperatorRegisterForR3{};
}
......@@ -5,6 +5,8 @@
#include <language/utils/ASTNodeDataType.hpp>
#include <language/utils/AffectationMangler.hpp>
#include <language/utils/IAffectationProcessorBuilder.hpp>
#include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
#include <language/utils/UnaryOperatorMangler.hpp>
#include <utils/Exceptions.hpp>
......@@ -14,6 +16,7 @@ class OperatorRepository
{
private:
std::unordered_map<std::string, std::shared_ptr<const IAffectationProcessorBuilder>> m_affectation_builder_list;
std::unordered_map<std::string, std::shared_ptr<const IUnaryOperatorProcessorBuilder>> m_unary_operator_builder_list;
void _initialize();
......@@ -32,6 +35,16 @@ class OperatorRepository
}
}
template <typename OperatorTypeT, typename UnaryProcessorBuilderT>
void
addUnaryOperator(const ASTNodeDataType& operand, const std::shared_ptr<UnaryProcessorBuilderT>& processor_builder)
{
const std::string unary_operator_type_name = unaryOperatorMangler<OperatorTypeT>(operand);
if (not m_unary_operator_builder_list.try_emplace(unary_operator_type_name, processor_builder).second) {
throw UnexpectedError(unary_operator_type_name + " has already an entry");
}
}
std::optional<std::shared_ptr<const IAffectationProcessorBuilder>>
getAffectationProcessorBuilder(const std::string& affectation_name) const
{
......@@ -42,6 +55,16 @@ class OperatorRepository
return {};
}
std::optional<std::shared_ptr<const IUnaryOperatorProcessorBuilder>>
getUnaryProcessorBuilder(const std::string& affectation_name) const
{
auto&& processor_builder = m_unary_operator_builder_list.find(affectation_name);
if (processor_builder != m_unary_operator_builder_list.end()) {
return processor_builder->second;
}
return {};
}
static void create();
PUGS_INLINE
......
#ifndef UNARY_OPERATOR_MANGLER_HPP
#define UNARY_OPERATOR_MANGLER_HPP
#include <language/utils/ASTNodeDataType.hpp>
#include <utils/Exceptions.hpp>
#include <string>
namespace language
{
struct unary_minus;
struct unary_not;
} // namespace language
template <typename UnaryOperatorT>
std::string
unaryOperatorMangler(const ASTNodeDataType& operand)
{
const std::string operator_name = [] {
if constexpr (std::is_same_v<language::unary_minus, UnaryOperatorT>) {
return "-";
} else if constexpr (std::is_same_v<language::unary_not, UnaryOperatorT>) {
return "not";
} else {
static_assert(std::is_same_v<language::unary_minus, UnaryOperatorT>, "undefined unary operator");
}
}();
return operator_name + " " + dataTypeName(operand);
}
#endif // UNARY_OPERATOR_MANGLER_HPP
#ifndef UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
#define UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
#include <algebra/TinyVector.hpp>
#include <language/PEGGrammar.hpp>
#include <language/node_processor/UnaryExpressionProcessor.hpp>
#include <language/utils/IUnaryOperatorProcessorBuilder.hpp>
#include <type_traits>
template <typename OperatorT, typename ValueT, typename DataT>
class UnaryOperatorProcessorBuilder final : public IUnaryOperatorProcessorBuilder
{
public:
UnaryOperatorProcessorBuilder() = default;
std::unique_ptr<INodeProcessor>
getNodeProcessor(ASTNode& node) const
{
return std::make_unique<UnaryExpressionProcessor<OperatorT, ValueT, DataT>>(node);
}
};
#endif // UNARY_OPERATOR_PROCESSOR_BUILDER_HPP
#include <language/utils/UnaryOperatorRegisterForB.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForB::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
repository.addUnaryOperator<
language::unary_minus>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, bool>>());
}
void
UnaryOperatorRegisterForB::_register_unary_not()
{
OperatorRepository& repository = OperatorRepository::instance();
auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
repository.addUnaryOperator<
language::unary_not>(B, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_not, bool, bool>>());
}
UnaryOperatorRegisterForB::UnaryOperatorRegisterForB()
{
this->_register_unary_minus();
this->_register_unary_not();
}
#ifndef UNARY_OPERATOR_REGISTER_FOR_B_HPP
#define UNARY_OPERATOR_REGISTER_FOR_B_HPP
#include <language/utils/OperatorRepository.hpp>
class UnaryOperatorRegisterForB
{
private:
void _register_unary_minus();
void _register_unary_not();
public:
UnaryOperatorRegisterForB();
};
#endif // UNARY_OPERATOR_REGISTER_FOR_B_HPP
#include <language/utils/UnaryOperatorRegisterForN.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForN::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
repository.addUnaryOperator<
language::unary_minus>(N,
std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, int64_t, uint64_t>>());
}
UnaryOperatorRegisterForN::UnaryOperatorRegisterForN()
{
this->_register_unary_minus();
}
#ifndef UNARY_OPERATOR_REGISTER_FOR_N_HPP
#define UNARY_OPERATOR_REGISTER_FOR_N_HPP
#include <language/utils/OperatorRepository.hpp>
class UnaryOperatorRegisterForN
{
private:
void _register_unary_minus();
public:
UnaryOperatorRegisterForN();
};
#endif // UNARY_OPERATOR_REGISTER_FOR_N_HPP
#include <language/utils/UnaryOperatorRegisterForR.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForR::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>();
repository.addUnaryOperator<
language::unary_minus>(R, std::make_shared<UnaryOperatorProcessorBuilder<language::unary_minus, double, double>>());
}
UnaryOperatorRegisterForR::UnaryOperatorRegisterForR()
{
this->_register_unary_minus();
}
#ifndef UNARY_OPERATOR_REGISTER_FOR_R_HPP
#define UNARY_OPERATOR_REGISTER_FOR_R_HPP
#include <language/utils/OperatorRepository.hpp>
class UnaryOperatorRegisterForR
{
private:
void _register_unary_minus();
public:
UnaryOperatorRegisterForR();
};
#endif // UNARY_OPERATOR_REGISTER_FOR_R_HPP
#include <language/utils/UnaryOperatorRegisterForR1.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForR1::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto R1 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
repository.addUnaryOperator<language::unary_minus>(R1, std::make_shared<UnaryOperatorProcessorBuilder<
language::unary_minus, TinyVector<1>, TinyVector<1>>>());
}
UnaryOperatorRegisterForR1::UnaryOperatorRegisterForR1()
{
this->_register_unary_minus();
}
#ifndef UNARY_OPERATOR_REGISTER_FOR_R1_HPP
#define UNARY_OPERATOR_REGISTER_FOR_R1_HPP
#include <language/utils/OperatorRepository.hpp>
class UnaryOperatorRegisterForR1
{
private:
void _register_unary_minus();
public:
UnaryOperatorRegisterForR1();
};
#endif // UNARY_OPERATOR_REGISTER_FOR_R1_HPP
#include <language/utils/UnaryOperatorRegisterForR2.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForR2::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto R2 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
repository.addUnaryOperator<language::unary_minus>(R2, std::make_shared<UnaryOperatorProcessorBuilder<
language::unary_minus, TinyVector<2>, TinyVector<2>>>());
}
UnaryOperatorRegisterForR2::UnaryOperatorRegisterForR2()
{
this->_register_unary_minus();
}
#ifndef UNARY_OPERATOR_REGISTER_FOR_R2_HPP
#define UNARY_OPERATOR_REGISTER_FOR_R2_HPP
#include <language/utils/OperatorRepository.hpp>
class UnaryOperatorRegisterForR2
{
private:
void _register_unary_minus();
public:
UnaryOperatorRegisterForR2();
};
#endif // UNARY_OPERATOR_REGISTER_FOR_R2_HPP
#include <language/utils/UnaryOperatorRegisterForR3.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <language/utils/UnaryOperatorProcessorBuilder.hpp>
void
UnaryOperatorRegisterForR3::_register_unary_minus()
{
OperatorRepository& repository = OperatorRepository::instance();
auto R3 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
repository.addUnaryOperator<language::unary_minus>(R3, std::make_shared<UnaryOperatorProcessorBuilder<
language::unary_minus, TinyVector<3>, TinyVector<3>>>());
}
UnaryOperatorRegisterForR3::UnaryOperatorRegisterForR3()
{
this->_register_unary_minus();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment