From ac9400d4df4d8f00a70c4f513934400b2a47df37 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Thu, 23 Jan 2020 11:27:43 +0100 Subject: [PATCH] Continue introduction of R^d vectors with d in {1,2,3} These are the so-called `TinyVector` (their size is known at compilation time). On the way ASTNodeDataType has evolved from an `enum class` to a real `class` to allow the description of more complex types. In is no more just a flag. First new data is the dimension of the object. --- .../ASTNodeAffectationExpressionBuilder.cpp | 57 ++++++++++++++++++- src/language/ASTNodeDataType.cpp | 3 + src/language/ASTNodeDataType.hpp | 55 ++++++++++++++---- src/language/ASTNodeDataTypeBuilder.cpp | 12 +++- src/language/DataVariant.hpp | 19 ++++++- 5 files changed, 126 insertions(+), 20 deletions(-) diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index f0b5a93be..e30b0380a 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -5,6 +5,8 @@ #include <node_processor/AffectationProcessor.hpp> +#include <../algebra/TinyVector.hpp> + ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n) { auto set_affectation_processor = [](ASTNode& n, const auto& operator_v) { @@ -38,6 +40,28 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } }; + 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> or std::is_same_v<OperatorT, language::pluseq_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: undefined operand type for vector 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_string_data = [&](const ASTNodeDataType& data_type) { using OperatorT = std::decay_t<decltype(operator_v)>; @@ -78,8 +102,6 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode auto set_affectation_processor_for_value = [&](const ASTNodeDataType& value_type) { const ASTNodeDataType data_type = n.children[1]->m_data_type; - ASTNodeNaturalConversionChecker{n, data_type, value_type}; - switch (value_type) { case ASTNodeDataType::bool_t: { set_affectation_processor_for_data(bool{}, data_type); @@ -97,6 +119,10 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode set_affectation_processor_for_data(double{}, data_type); break; } + case ASTNodeDataType::vector_t: { + set_affectation_processor_for_vector_data(TinyVector<3>{}, data_type); + break; + } case ASTNodeDataType::string_t: { set_affectation_processor_for_string_data(data_type); break; @@ -107,6 +133,33 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } }; + 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.children.size() != n.m_data_type.dimension()) { + throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()}); + } + break; + } + default: { + throw parse_error("invalid operand for affectation", std::vector{n.children[1]->begin()}); + } + } + } else { + ASTNodeNaturalConversionChecker{n, n.children[1]->m_data_type, n.m_data_type}; + } + set_affectation_processor_for_value(n.m_data_type); }; diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp index f510344bf..9e5dc669a 100644 --- a/src/language/ASTNodeDataType.cpp +++ b/src/language/ASTNodeDataType.cpp @@ -38,6 +38,9 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::void_t: name = "void"; break; + case ASTNodeDataType::list_t: + name = "list"; + break; } return name; } diff --git a/src/language/ASTNodeDataType.hpp b/src/language/ASTNodeDataType.hpp index 214ce45df..79ae74453 100644 --- a/src/language/ASTNodeDataType.hpp +++ b/src/language/ASTNodeDataType.hpp @@ -6,19 +6,50 @@ class ASTNode; -enum class ASTNodeDataType : int32_t +class ASTNodeDataType { - undefined_t = -1, - bool_t = 0, - int_t = 1, - unsigned_int_t = 2, - double_t = 3, - vector_t = 4, - string_t = 5, - typename_t = 10, - function_t = 11, - c_function_t = 12, - void_t = std::numeric_limits<int32_t>::max() + public: + enum DataType : int32_t + { + undefined_t = -1, + bool_t = 0, + int_t = 1, + unsigned_int_t = 2, + double_t = 3, + vector_t = 4, + list_t = 5, + string_t = 6, + typename_t = 10, + function_t = 11, + c_function_t = 12, + void_t = std::numeric_limits<int32_t>::max() + }; + + private: + DataType m_data_type; + size_t m_dimension; + + public: + size_t + dimension() const + { + return m_dimension; + } + + operator DataType() const + { + return m_data_type; + } + + ASTNodeDataType& operator=(const ASTNodeDataType&) = default; + + constexpr ASTNodeDataType(DataType data_type) : m_data_type{data_type}, m_dimension{1} {} + + ASTNodeDataType(DataType data_type, size_t dimension) : m_data_type{data_type}, m_dimension{dimension} {} + + ASTNodeDataType(const ASTNodeDataType&) = default; + + ~ASTNodeDataType() = default; }; std::string dataTypeName(const ASTNodeDataType& data_type); diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index ad39a0183..b7e349374 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -38,7 +38,12 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo } else if (type_node.is_type<language::R_set>()) { data_type = ASTNodeDataType::double_t; } else if (type_node.is_type<language::vector_type>()) { - data_type = ASTNodeDataType::vector_t; + ASTNode& dimension_node = *type_node.children[1]; + if (not dimension_node.is_type<language::integer>()) { + throw parse_error("unexpected non integer constant dimension", dimension_node.begin()); + } + const size_t dimension = std::stol(dimension_node.string()); + data_type = ASTNodeDataType{ASTNodeDataType::vector_t, dimension}; } else if (type_node.is_type<language::string_type>()) { data_type = ASTNodeDataType::string_t; } @@ -387,9 +392,10 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } else if (n.is_type<language::B_set>() or n.is_type<language::Z_set>() or n.is_type<language::N_set>() or n.is_type<language::R_set>() or n.is_type<language::string_type>()) { n.m_data_type = ASTNodeDataType::typename_t; - } else if (n.is_type<language::name_list>() or n.is_type<language::expression_list>() or - n.is_type<language::function_argument_list>()) { + } else if (n.is_type<language::name_list>() or n.is_type<language::function_argument_list>()) { n.m_data_type = ASTNodeDataType::void_t; + } else if (n.is_type<language::expression_list>()) { + n.m_data_type = ASTNodeDataType::list_t; } } } diff --git a/src/language/DataVariant.hpp b/src/language/DataVariant.hpp index 9c19870f5..54abc6692 100644 --- a/src/language/DataVariant.hpp +++ b/src/language/DataVariant.hpp @@ -5,11 +5,22 @@ #include <variant> #include <vector> +#include <../algebra/TinyVector.hpp> + #include <PugsAssert.hpp> class AggregateDataVariant; -using DataVariant = std::variant<std::monostate, bool, uint64_t, int64_t, double, std::string, AggregateDataVariant>; +using DataVariant = std::variant<std::monostate, + bool, + uint64_t, + int64_t, + double, + std::string, + AggregateDataVariant, + TinyVector<1>, + TinyVector<2>, + TinyVector<3>>; class AggregateDataVariant // LCOV_EXCL_LINE { @@ -60,14 +71,16 @@ class AggregateDataVariant // LCOV_EXCL_LINE } PUGS_INLINE - DataVariant& operator[](size_t i) + DataVariant& + operator[](size_t i) { Assert(i < m_data_vector.size()); return m_data_vector[i]; } PUGS_INLINE - const DataVariant& operator[](size_t i) const + const DataVariant& + operator[](size_t i) const { Assert(i < m_data_vector.size()); return m_data_vector[i]; -- GitLab