#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()}); } }