Select Git revision
ASTNodeAffectationExpressionBuilder.cpp
ASTNodeAffectationExpressionBuilder.cpp 11.92 KiB
#include <ASTNodeAffectationExpressionBuilder.hpp>
#include <PEGGrammar.hpp>
#include <ASTNodeNaturalConversionChecker.hpp>
#include <node_processor/AffectationProcessor.hpp>
#include <../algebra/TinyVector.hpp>
ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n)
{
auto set_affectation_processor = [](ASTNode& n, const auto& operator_v) {
auto set_affectation_processor_for_data = [&](const auto& value, const ASTNodeDataType& data_type) {
using OperatorT = std::decay_t<decltype(operator_v)>;
using ValueT = std::decay_t<decltype(value)>;
switch (data_type) {
case ASTNodeDataType::bool_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
break;
}
case ASTNodeDataType::unsigned_int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
case ASTNodeDataType::int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
break;
}
case ASTNodeDataType::double_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined operand type for affectation",
std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
};
auto set_affectation_processor_for_vector_data = [&](const auto& value, const ASTNodeDataType& data_type) {
using OperatorT = std::decay_t<decltype(operator_v)>;
using ValueT = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
switch (data_type) {
case ASTNodeDataType::vector_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
case ASTNodeDataType::list_t: {
n.m_node_processor = std::make_unique<AffectationFromListProcessor<OperatorT, ValueT>>(n);
break;
}
case ASTNodeDataType::bool_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
break;
}
}
case ASTNodeDataType::unsigned_int_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
}
case ASTNodeDataType::int_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
if (n.children[1]->is_type<language::integer>()) {
if (std::stoi(n.children[1]->string()) == 0) {
n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n);
break;
}
}
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
break;
} else if (n.children[1]->is_type<language::integer>()) {
if (std::stoi(n.children[1]->string()) == 0) {
n.m_node_processor = std::make_unique<AffectationFromZeroProcessor<ValueT>>(n);
break;
}
}
// LCOV_EXCL_START
throw parse_error("unexpected error: invalid integral value", std::vector{n.children[1]->begin()});
// LCOV_EXCL_STOP
}
case ASTNodeDataType::double_t: {
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
break;
}
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: invalid operand type", std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else if constexpr (std::is_same_v<OperatorT, language::pluseq_op> or
std::is_same_v<OperatorT, language::minuseq_op>) {
switch (data_type) {
case ASTNodeDataType::vector_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, ValueT>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: invalid operand type", std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else if constexpr (std::is_same_v<OperatorT, language::multiplyeq_op>) {
switch (data_type) {
case ASTNodeDataType::bool_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, bool>>(n);
break;
}
case ASTNodeDataType::unsigned_int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, uint64_t>>(n);
break;
}
case ASTNodeDataType::int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, int64_t>>(n);
break;
}
case ASTNodeDataType::double_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, ValueT, double>>(n);
break;
}
default: {
throw parse_error("expecting scalar operand type", std::vector{n.children[1]->begin()});
}
}
} else {
throw parse_error("invalid affectation operator for " + dataTypeName(n.m_data_type), std::vector{n.begin()});
}
};
auto set_affectation_processor_for_string_data = [&](const ASTNodeDataType& data_type) {
using OperatorT = std::decay_t<decltype(operator_v)>;
if constexpr (std::is_same_v<OperatorT, language::eq_op> or std::is_same_v<OperatorT, language::pluseq_op>) {
switch (data_type) {
case ASTNodeDataType::bool_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, bool>>(n);
break;
}
case ASTNodeDataType::unsigned_int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, uint64_t>>(n);
break;
}
case ASTNodeDataType::int_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, int64_t>>(n);
break;
}
case ASTNodeDataType::double_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, double>>(n);
break;
}
case ASTNodeDataType::string_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, std::string>>(n);
break;
}
case ASTNodeDataType::vector_t: {
switch (data_type.dimension()) {
case 1: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<1>>>(n);
break;
}
case 2: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<2>>>(n);
break;
}
case 3: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, std::string, TinyVector<3>>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: invalid vector dimension for string affectation",
std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined operand type for string affectation",
std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else {
throw parse_error("invalid operator for string affectation", std::vector{n.begin()});
}
};
auto set_affectation_processor_for_embedded_data = [&](const ASTNodeDataType& data_type) {
using OperatorT = std::decay_t<decltype(operator_v)>;
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
switch (data_type) {
case ASTNodeDataType::type_id_t: {
n.m_node_processor = std::make_unique<AffectationProcessor<OperatorT, EmbeddedData, EmbeddedData>>(n);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined operand type for string affectation",
std::vector{n.children[1]->begin()});
}
// LCOV_EXCL_STOP
}
} else {
throw parse_error("invalid operator for '" + data_type.typeName() + "' affectation", std::vector{n.begin()});
}
};
auto set_affectation_processor_for_value = [&](const ASTNodeDataType& value_type) {
const ASTNodeDataType data_type = n.children[1]->m_data_type;
switch (value_type) {
case ASTNodeDataType::bool_t: {
set_affectation_processor_for_data(bool{}, data_type);
break;
}
case ASTNodeDataType::unsigned_int_t: {
set_affectation_processor_for_data(uint64_t{}, data_type);
break;
}
case ASTNodeDataType::int_t: {
set_affectation_processor_for_data(int64_t{}, data_type);
break;
}
case ASTNodeDataType::double_t: {
set_affectation_processor_for_data(double{}, data_type);
break;
}
case ASTNodeDataType::vector_t: {
switch (value_type.dimension()) {
case 1: {
set_affectation_processor_for_vector_data(TinyVector<1>{}, data_type);
break;
}
case 2: {
set_affectation_processor_for_vector_data(TinyVector<2>{}, data_type);
break;
}
case 3: {
set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: unexpected vector dimension", std::vector{n.begin()});
}
// LCOV_EXCL_STOP
}
break;
}
case ASTNodeDataType::string_t: {
set_affectation_processor_for_string_data(data_type);
break;
}
case ASTNodeDataType::type_id_t: {
set_affectation_processor_for_embedded_data(data_type);
break;
}
default: {
throw parse_error("unexpected error: undefined value type for affectation", std::vector{n.begin()});
}
}
};
using OperatorT = std::decay_t<decltype(operator_v)>;
// Special treatment dedicated to R^1 to be able to initialize them
if (((n.m_data_type != n.children[1]->m_data_type) and (n.m_data_type == ASTNodeDataType::vector_t) and
(n.m_data_type.dimension() == 1)) or
// Special treatment for R^d vectors and operator *=
((n.m_data_type == ASTNodeDataType::vector_t) and (n.children[1]->m_data_type != ASTNodeDataType::vector_t) and
std::is_same_v<OperatorT, language::multiplyeq_op>)) {
ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::double_t};
} else {
ASTNodeNaturalConversionChecker{*n.children[1], n.m_data_type};
}
set_affectation_processor_for_value(n.m_data_type);
};
if (n.is_type<language::eq_op>()) {
set_affectation_processor(n, language::eq_op{});
} else if (n.is_type<language::multiplyeq_op>()) {
set_affectation_processor(n, language::multiplyeq_op{});
} else if (n.is_type<language::divideeq_op>()) {
set_affectation_processor(n, language::divideeq_op{});
} else if (n.is_type<language::pluseq_op>()) {
set_affectation_processor(n, language::pluseq_op{});
} else if (n.is_type<language::minuseq_op>()) {
set_affectation_processor(n, language::minuseq_op{});
} else {
throw parse_error("unexpected error: undefined affectation operator", std::vector{n.begin()});
}
}