Select Git revision
test_ASTNodeIncDecExpressionBuilder.cpp
ASTNodeListAffectationExpressionBuilder.cpp 8.04 KiB
#include <ASTNodeListAffectationExpressionBuilder.hpp>
#include <PEGGrammar.hpp>
#include <node_processor/AffectationProcessor.hpp>
#include <ASTNodeDataTypeFlattener.hpp>
#include <ASTNodeNaturalConversionChecker.hpp>
template <typename OperatorT>
void
ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor(
const ASTNodeSubDataType& rhs_node_sub_data_type,
ASTNode& value_node,
std::unique_ptr<ListAffectationProcessor<OperatorT>>& list_affectation_processor)
{
auto add_affectation_processor_for_data = [&](const auto& value, const ASTNodeSubDataType& node_sub_data_type) {
using ValueT = std::decay_t<decltype(value)>;
switch (node_sub_data_type.m_data_type) {
case ASTNodeDataType::bool_t: {
list_affectation_processor->template add<ValueT, bool>(value_node);
break;
}
case ASTNodeDataType::unsigned_int_t: {
list_affectation_processor->template add<ValueT, uint64_t>(value_node);
break;
}
case ASTNodeDataType::int_t: {
list_affectation_processor->template add<ValueT, int64_t>(value_node);
break;
}
case ASTNodeDataType::double_t: {
list_affectation_processor->template add<ValueT, double>(value_node);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: invalid operand type for affectation",
std::vector{node_sub_data_type.m_parent_node.begin()});
}
// LCOV_EXCL_STOP
}
};
auto add_affectation_processor_for_vector_data = [&](const auto& value,
const ASTNodeSubDataType& node_sub_data_type) {
using ValueT = std::decay_t<decltype(value)>;
if constexpr (std::is_same_v<ValueT, TinyVector<1>>) {
if ((node_sub_data_type.m_data_type == ASTNodeDataType::vector_t) and
(node_sub_data_type.m_data_type.dimension() == value.dimension())) {
list_affectation_processor->template add<ValueT, ValueT>(value_node);
} else {
add_affectation_processor_for_data(value, node_sub_data_type);
}
} else if constexpr (std::is_same_v<ValueT, TinyVector<2>> or std::is_same_v<ValueT, TinyVector<3>>) {
if ((node_sub_data_type.m_data_type == ASTNodeDataType::vector_t) and
(node_sub_data_type.m_data_type.dimension() == value.dimension())) {
list_affectation_processor->template add<ValueT, ValueT>(value_node);
} else if (node_sub_data_type.m_parent_node.is_type<language::integer>()) {
if (std::stoi(node_sub_data_type.m_parent_node.string()) == 0) {
list_affectation_processor->template add<ValueT, ZeroType>(value_node);
} else {
throw parse_error("invalid operand value", std::vector{node_sub_data_type.m_parent_node.begin()});
}
} else {
throw parse_error("invalid dimension", std::vector{node_sub_data_type.m_parent_node.begin()});
}
} else {
throw parse_error("unexpected error: invalid value type");
}
};
auto add_affectation_processor_for_string_data = [&](const ASTNodeSubDataType& node_sub_data_type) {
if constexpr (std::is_same_v<OperatorT, language::eq_op>) {
switch (node_sub_data_type.m_data_type) {
case ASTNodeDataType::bool_t: {
list_affectation_processor->template add<std::string, bool>(value_node);
break;
}
case ASTNodeDataType::unsigned_int_t: {
list_affectation_processor->template add<std::string, uint64_t>(value_node);
break;
}
case ASTNodeDataType::int_t: {
list_affectation_processor->template add<std::string, int64_t>(value_node);
break;
}
case ASTNodeDataType::double_t: {
list_affectation_processor->template add<std::string, double>(value_node);
break;
}
case ASTNodeDataType::string_t: {
list_affectation_processor->template add<std::string, std::string>(value_node);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("invalid operand type for string affectation",
std::vector{node_sub_data_type.m_parent_node.begin()});
}
// LCOV_EXCL_STOP
}
} else {
throw parse_error("unexpected error: undefined operator type for string affectation",
std::vector{m_node.begin()});
}
};
auto add_affectation_processor_for_value = [&](const ASTNodeDataType& value_type,
const ASTNodeSubDataType& node_sub_data_type) {
switch (value_type) {
case ASTNodeDataType::bool_t: {
add_affectation_processor_for_data(bool{}, node_sub_data_type);
break;
}
case ASTNodeDataType::unsigned_int_t: {
add_affectation_processor_for_data(uint64_t{}, node_sub_data_type);
break;
}
case ASTNodeDataType::int_t: {
add_affectation_processor_for_data(int64_t{}, node_sub_data_type);
break;
}
case ASTNodeDataType::double_t: {
add_affectation_processor_for_data(double{}, node_sub_data_type);
break;
}
case ASTNodeDataType::vector_t: {
switch (value_type.dimension()) {
case 1: {
add_affectation_processor_for_vector_data(TinyVector<1>{}, node_sub_data_type);
break;
}
case 2: {
add_affectation_processor_for_vector_data(TinyVector<2>{}, node_sub_data_type);
break;
}
case 3: {
add_affectation_processor_for_vector_data(TinyVector<3>{}, node_sub_data_type);
break;
}
default: {
throw parse_error("invalid dimension", std::vector{value_node.begin()});
}
}
break;
}
case ASTNodeDataType::string_t: {
add_affectation_processor_for_string_data(node_sub_data_type);
break;
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined value type for tuple affectation",
std::vector{value_node.begin()});
}
// LCOV_EXCL_STOP
}
};
if ((value_node.m_data_type != rhs_node_sub_data_type.m_data_type) and
(value_node.m_data_type == ASTNodeDataType::vector_t) and (value_node.m_data_type.dimension() == 1)) {
ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, ASTNodeDataType::double_t};
} else {
ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, value_node.m_data_type};
}
add_affectation_processor_for_value(value_node.m_data_type, rhs_node_sub_data_type);
}
template <typename OperatorT>
void
ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor()
{
Assert(m_node.children[1]->is_type<language::expression_list>() or
m_node.children[1]->is_type<language::function_evaluation>());
ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_rhs_data_type_list;
ASTNodeDataTypeFlattener{*m_node.children[1], flattened_rhs_data_type_list};
ASTNode& name_list_node = *m_node.children[0];
if (name_list_node.children.size() != flattened_rhs_data_type_list.size()) {
throw parse_error("incompatible list sizes in affectation", std::vector{m_node.begin()});
}
using ListAffectationProcessorT = ListAffectationProcessor<OperatorT>;
std::unique_ptr list_affectation_processor = std::make_unique<ListAffectationProcessorT>(m_node);
for (size_t i = 0; i < name_list_node.children.size(); ++i) {
ASTNode& name_node = *name_list_node.children[i];
this->_buildAffectationProcessor(flattened_rhs_data_type_list[i], name_node, list_affectation_processor);
}
m_node.m_node_processor = std::move(list_affectation_processor);
}
ASTNodeListAffectationExpressionBuilder::ASTNodeListAffectationExpressionBuilder(ASTNode& node) : m_node(node)
{
if (node.children[1]->is_type<language::expression_list>() or
node.children[1]->is_type<language::function_evaluation>()) {
if (node.is_type<language::eq_op>()) {
this->_buildListAffectationProcessor<language::eq_op>();
} else {
throw parse_error("undefined affectation operator for tuples", std::vector{node.begin()});
}
} else {
throw parse_error("invalid right hand side in tuple affectation", std::vector{node.children[1]->begin()});
}
}