Select Git revision
INodeProcessor.hpp
ASTNodeAffectationExpressionBuilder.cpp 9.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>>) {
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;
}
}
}
throw parse_error("invalid operand value", std::vector{n.children[1]->begin()});
}
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("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("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("invalid operand", std::vector{n.children[1]->begin()});
}
}
} else {
throw parse_error("invalid operator 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;
}
// 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("unexpected error: undefined operator type", std::vector{n.children[0]->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;
}
default: {
throw parse_error("unexpected error: unexpected vector dimension", std::vector{n.begin()});
}
}
break;
}
case ASTNodeDataType::string_t: {
set_affectation_processor_for_string_data(data_type);
break;
}
default: {
throw parse_error("unexpected error: undefined value type for affectation", std::vector{n.begin()});
}
}
};
if (n.m_data_type == ASTNodeDataType::vector_t) {
// Only real data are considered
const ASTNode& data_node = *n.children[1];
switch (data_node.m_data_type) {
case ASTNodeDataType::list_t: {
if (data_node.children.size() != n.m_data_type.dimension()) {
throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()});
}
for (const auto& child : data_node.children) {
ASTNodeNaturalConversionChecker{n, child->m_data_type, ASTNodeDataType::double_t};
}
break;
}
case ASTNodeDataType::vector_t: {
if (data_node.m_data_type.dimension() != n.m_data_type.dimension()) {
throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()});
}
break;
}
default: {
}
}
} else {
ASTNodeNaturalConversionChecker{n, n.children[1]->m_data_type, 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()});
}
}