diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index 0635f1b32b12d29bbbaa85273d6c49d92aba12ca..c92a2855dfe968c1f56145cee00559708c1eefbf 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -36,6 +36,24 @@ class [[nodiscard]] TinyMatrix } public: + PUGS_INLINE + constexpr size_t dimension() const + { + return N * N; + } + + PUGS_INLINE + constexpr size_t nbRows() const + { + return N; + } + + PUGS_INLINE + constexpr size_t nbColumns() const + { + return N; + } + PUGS_INLINE constexpr TinyMatrix operator-() const { diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 553a2797c8cf227ab88d4b977f9f727b671a4c7a..20ec81befa009efd926820b0a6333be0cc48dc5e 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -75,11 +75,12 @@ struct string_type : TAO_PEGTL_KEYWORD("string") {}; struct scalar_type : sor< B_set, R_set, Z_set, N_set >{}; struct vector_type : seq< R_set, ignored, one< '^' >, ignored, integer >{}; +struct matrix_type : seq< R_set, ignored, one< '^' >, ignored, integer, ignored, one< 'x' >, ignored, integer >{}; struct basic_type : sor< scalar_type, string_type >{}; struct type_name_id; -struct simple_type_specifier : sor< vector_type, basic_type, type_name_id >{}; +struct simple_type_specifier : sor< matrix_type, vector_type, basic_type, type_name_id >{}; struct tuple_type_specifier : sor<try_catch< open_parent, simple_type_specifier, ignored, close_parent >, // non matching braces management diff --git a/src/language/ast/ASTBuilder.cpp b/src/language/ast/ASTBuilder.cpp index 35d787354c37e5b1dbc3f176548fb4725d924cbb..f9e3edceb480b01c608997e31c82fb133b8e7c35 100644 --- a/src/language/ast/ASTBuilder.cpp +++ b/src/language/ast/ASTBuilder.cpp @@ -247,6 +247,7 @@ using selector = parse_tree::selector< language::type_name_id, language::tuple_expression, language::vector_type, + language::matrix_type, language::string_type, language::cout_kw, language::cerr_kw, diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index 6e712e3d84c0eb6d52064fdfecabd9dd6f9016db..037bd767fc1064aab5b0848497749860b89a7350 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -30,16 +30,16 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } }(); - // Special treatment dedicated to R^1 to be able to initialize them - if (((target_data_type != source_data_type) and (target_data_type == ASTNodeDataType::vector_t) and - (target_data_type.dimension() == 1)) or - // Special treatment for R^d vectors and operator *= - ((target_data_type == ASTNodeDataType::vector_t) and (source_data_type != ASTNodeDataType::vector_t) and - n.is_type<language::multiplyeq_op>())) { - ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::build<ASTNodeDataType::double_t>()}; - } else { - ASTNodeNaturalConversionChecker{*n.children[1], target_data_type}; - } + // // Special treatment dedicated to R^1 to be able to initialize them + // if (((target_data_type != source_data_type) and (target_data_type == ASTNodeDataType::vector_t) and + // (target_data_type.dimension() == 1)) or + // // Special treatment for R^d vectors and operator *= + // ((target_data_type == ASTNodeDataType::vector_t) and (source_data_type != ASTNodeDataType::vector_t) and + // n.is_type<language::multiplyeq_op>())) { + // ASTNodeNaturalConversionChecker{*n.children[1], ASTNodeDataType::build<ASTNodeDataType::double_t>()}; + // } else { + // ASTNodeNaturalConversionChecker{*n.children[1], target_data_type}; + // } const auto& optional_processor_builder = OperatorRepository::instance().getAffectationProcessorBuilder(affectation_name); diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 7c93b50527bbae5c352d62159e40d0eba3bb7aad..f6fe085672ad9e6fa0443bd113f343c2e3603dae 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -41,6 +41,8 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>(); } else if (type_node.is_type<language::vector_type>()) { data_type = getVectorDataType(type_node); + } else if (type_node.is_type<language::matrix_type>()) { + data_type = getMatrixDataType(type_node); } else if (type_node.is_type<language::tuple_type_specifier>()) { const auto& content_node = type_node.children[0]; diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp index cf1ccdabf1cffa0e2256ed17e13dca6717229fc9..eca854ac598856af53b7f3fd2e76e8bd8e0c3895 100644 --- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp @@ -82,6 +82,48 @@ ASTNodeNaturalConversionChecker<RToR1Conversion>::_checkIsNaturalExpressionConve this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); } } + } else if (target_data_type == ASTNodeDataType::matrix_t) { + switch (data_type) { + case ASTNodeDataType::list_t: { + const auto& content_type_list = data_type.contentTypeList(); + if (content_type_list.size() != (target_data_type.nbRows() * target_data_type.nbColumns())) { + throw ParseError("incompatible dimensions in affectation", std::vector{node.begin()}); + } + + Assert(content_type_list.size() == node.children.size()); + for (size_t i = 0; i < content_type_list.size(); ++i) { + const auto& child_type = *content_type_list[i]; + const auto& child_node = *node.children[i]; + Assert(child_type == child_node.m_data_type); + this->_checkIsNaturalExpressionConversion(child_node, child_type, + ASTNodeDataType::build<ASTNodeDataType::double_t>()); + } + + break; + } + case ASTNodeDataType::matrix_t: { + if ((data_type.nbRows() != target_data_type.nbRows()) or + (data_type.nbColumns() != target_data_type.nbColumns())) { + std::ostringstream error_message; + error_message << "invalid implicit conversion: "; + error_message << rang::fgB::red << dataTypeName(data_type) << " -> " << dataTypeName(target_data_type) + << rang::fg::reset; + throw ParseError(error_message.str(), std::vector{node.begin()}); + } + break; + } + case ASTNodeDataType::int_t: { + if (node.is_type<language::integer>()) { + if (std::stoi(node.string()) == 0) { + break; + } + } + [[fallthrough]]; + } + default: { + this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + } + } } else if (target_data_type == ASTNodeDataType::tuple_t) { const ASTNodeDataType& target_content_type = target_data_type.contentType(); if (node.m_data_type == ASTNodeDataType::tuple_t) { diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 88d4488365427aecbffd48abf9e37a3b08e55707..85251f8446b73f2947decc15b1857db13f2386f7 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -391,6 +391,55 @@ class AffectationToTinyVectorFromListProcessor final : public INodeProcessor } }; +template <typename OperatorT, typename ValueT> +class AffectationToTinyMatrixFromListProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + DataVariant* m_lhs; + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + AggregateDataVariant children_values = std::get<AggregateDataVariant>(m_node.children[1]->execute(exec_policy)); + + static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to vectors"); + + ValueT v; + for (size_t i = 0, l = 0; i < v.nbRows(); ++i) { + for (size_t j = 0; j < v.nbColumns(); ++j, ++l) { + std::visit( + [&](auto&& child_value) { + using T = std::decay_t<decltype(child_value)>; + if constexpr (std::is_same_v<T, bool> or std::is_same_v<T, uint64_t> or std::is_same_v<T, int64_t> or + std::is_same_v<T, double>) { + v(i, j) = child_value; + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + // LCOV_EXCL_STOP + } + }, + children_values[l]); + } + } + + *m_lhs = v; + return {}; + } + + AffectationToTinyMatrixFromListProcessor(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + + m_lhs = &i_symbol->attributes().value(); + } +}; + template <typename ValueT> class AffectationToTupleProcessor final : public INodeProcessor { diff --git a/src/language/utils/ASTNodeDataType.cpp b/src/language/utils/ASTNodeDataType.cpp index 02a352ac3d0f7435c89445d4113b037bd0f54c2c..81f3fc81caba045ca4ae719ddfa21c09c1c8fc98 100644 --- a/src/language/utils/ASTNodeDataType.cpp +++ b/src/language/utils/ASTNodeDataType.cpp @@ -16,9 +16,42 @@ getVectorDataType(const ASTNode& type_node) throw ParseError("unexpected non integer constant dimension", dimension_node.begin()); } const size_t dimension = std::stol(dimension_node.string()); + if (not(dimension > 0 and dimension <= 3)) { + throw ParseError("invalid dimension (must be 1, 2 or 3)", dimension_node.begin()); + } return ASTNodeDataType::build<ASTNodeDataType::vector_t>(dimension); } +ASTNodeDataType +getMatrixDataType(const ASTNode& type_node) +{ + if (not(type_node.is_type<language::matrix_type>() and (type_node.children.size() == 3))) { + throw ParseError("unexpected node type", type_node.begin()); + } + + ASTNode& dimension0_node = *type_node.children[1]; + if (not dimension0_node.is_type<language::integer>()) { + throw ParseError("unexpected non integer constant dimension", dimension0_node.begin()); + } + const size_t dimension0 = std::stol(dimension0_node.string()); + + ASTNode& dimension1_node = *type_node.children[2]; + if (not dimension1_node.is_type<language::integer>()) { + throw ParseError("unexpected non integer constant dimension", dimension1_node.begin()); + } + const size_t dimension1 = std::stol(dimension1_node.string()); + + if (dimension0 != dimension1) { + throw ParseError("only square matrices are supported", type_node.begin()); + } + + if (not(dimension0 > 0 and dimension0 <= 3)) { + throw ParseError("invalid dimension (must be 1, 2 or 3)", dimension0_node.begin()); + } + + return ASTNodeDataType::build<ASTNodeDataType::matrix_t>(dimension0, dimension1); +} + std::string dataTypeName(const ASTNodeDataType& data_type) { @@ -42,6 +75,9 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::vector_t: name = "R^" + std::to_string(data_type.dimension()); break; + case ASTNodeDataType::matrix_t: + name = "R^" + std::to_string(data_type.nbRows()) + "x" + std::to_string(data_type.nbColumns()); + break; case ASTNodeDataType::tuple_t: name = "tuple(" + dataTypeName(data_type.contentType()) + ')'; break; @@ -129,6 +165,9 @@ isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& tar return (data_type.nameOfTypeId() == target_data_type.nameOfTypeId()); } else if (data_type == ASTNodeDataType::vector_t) { return (data_type.dimension() == target_data_type.dimension()); + } else if (data_type == ASTNodeDataType::matrix_t) { + return ((data_type.nbRows() == target_data_type.nbRows()) and + (data_type.nbColumns() == target_data_type.nbColumns())); } else { return true; } diff --git a/src/language/utils/ASTNodeDataType.hpp b/src/language/utils/ASTNodeDataType.hpp index 951aff6e4d070e4747f5eb3f5a5fcc93f8ba5b8e..c31c9e15b6e8df0055aa4854bb7ede0a73318abd 100644 --- a/src/language/utils/ASTNodeDataType.hpp +++ b/src/language/utils/ASTNodeDataType.hpp @@ -14,6 +14,8 @@ class ASTNodeDataType; ASTNodeDataType getVectorDataType(const ASTNode& type_node); +ASTNodeDataType getMatrixDataType(const ASTNode& type_node); + std::string dataTypeName(const std::vector<ASTNodeDataType>& data_type_vector); std::string dataTypeName(const ASTNodeDataType& data_type); @@ -33,9 +35,10 @@ class ASTNodeDataType unsigned_int_t = 2, double_t = 3, vector_t = 4, - tuple_t = 5, - list_t = 6, - string_t = 7, + matrix_t = 5, + tuple_t = 6, + list_t = 7, + string_t = 8, typename_t = 10, type_name_id_t = 11, type_id_t = 21, @@ -49,6 +52,7 @@ class ASTNodeDataType using DataTypeDetails = std::variant<std::monostate, size_t, + std::array<size_t, 2>, std::string, std::shared_ptr<const ASTNodeDataType>, std::vector<std::shared_ptr<const ASTNodeDataType>>>; @@ -64,6 +68,22 @@ class ASTNodeDataType return std::get<size_t>(m_details); } + PUGS_INLINE + size_t + nbRows() const + { + Assert(std::holds_alternative<std::array<size_t, 2>>(m_details)); + return std::get<std::array<size_t, 2>>(m_details)[0]; + } + + PUGS_INLINE + size_t + nbColumns() const + { + Assert(std::holds_alternative<std::array<size_t, 2>>(m_details)); + return std::get<std::array<size_t, 2>>(m_details)[1]; + } + PUGS_INLINE const std::string& nameOfTypeId() const @@ -129,6 +149,14 @@ class ASTNodeDataType return ASTNodeDataType{data_type, dimension}; } + template <DataType data_type> + [[nodiscard]] static ASTNodeDataType + build(const size_t nb_rows, const size_t nb_columns) + { + static_assert((data_type == matrix_t), "incorrect data_type construction: cannot have dimension"); + return ASTNodeDataType{data_type, nb_rows, nb_columns}; + } + template <DataType data_type> [[nodiscard]] static ASTNodeDataType build(const std::string& type_name) @@ -171,6 +199,10 @@ class ASTNodeDataType explicit ASTNodeDataType(DataType data_type, const size_t dimension) : m_data_type{data_type}, m_details{dimension} {} + explicit ASTNodeDataType(DataType data_type, const size_t nb_rows, const size_t nb_columns) + : m_data_type{data_type}, m_details{std::array{nb_rows, nb_columns}} + {} + explicit ASTNodeDataType(DataType data_type, const std::string& type_name) : m_data_type{data_type}, m_details{type_name} {} diff --git a/src/language/utils/ASTNodeDataTypeTraits.hpp b/src/language/utils/ASTNodeDataTypeTraits.hpp index ed668e5e40e1ff4920602014367f379aa384adb9..2ba019646dac53291dc73169fadc47e737f68bad 100644 --- a/src/language/utils/ASTNodeDataTypeTraits.hpp +++ b/src/language/utils/ASTNodeDataTypeTraits.hpp @@ -1,6 +1,7 @@ #ifndef AST_NODE_DATA_TYPE_TRAITS_HPP #define AST_NODE_DATA_TYPE_TRAITS_HPP +#include <algebra/TinyMatrix.hpp> #include <algebra/TinyVector.hpp> #include <language/utils/ASTNodeDataType.hpp> #include <language/utils/FunctionSymbolId.hpp> @@ -27,6 +28,8 @@ inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> = ASTNodeDataType::build<ASTNodeDataType::function_t>(); template <size_t N> inline ASTNodeDataType ast_node_data_type_from<TinyVector<N>> = ASTNodeDataType::build<ASTNodeDataType::vector_t>(N); +template <size_t N> +inline ASTNodeDataType ast_node_data_type_from<TinyMatrix<N>> = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(N, N); template <typename T> inline ASTNodeDataType ast_node_data_type_from<std::vector<T>> = diff --git a/src/language/utils/AffectationProcessorBuilder.hpp b/src/language/utils/AffectationProcessorBuilder.hpp index 02042ad8825c7c890727edba6dd5dc41691a7d9e..0668b566b925a8d23621a962b5c9f70b9c9eb79a 100644 --- a/src/language/utils/AffectationProcessorBuilder.hpp +++ b/src/language/utils/AffectationProcessorBuilder.hpp @@ -66,6 +66,18 @@ class AffectationToTinyVectorFromListProcessorBuilder final : public IAffectatio } }; +template <typename OperatorT, typename ValueT> +class AffectationToTinyMatrixFromListProcessorBuilder final : public IAffectationProcessorBuilder +{ + public: + AffectationToTinyMatrixFromListProcessorBuilder() = default; + std::unique_ptr<INodeProcessor> + getNodeProcessor(ASTNode& node) const + { + return std::make_unique<AffectationToTinyMatrixFromListProcessor<OperatorT, ValueT>>(node); + } +}; + template <typename OperatorT, typename ValueT> class AffectationFromZeroProcessorBuilder final : public IAffectationProcessorBuilder { @@ -76,10 +88,9 @@ class AffectationFromZeroProcessorBuilder final : public IAffectationProcessorBu { if (std::stoi(node.children[1]->string()) == 0) { return std::make_unique<AffectationFromZeroProcessor<ValueT>>(node); + } else { + throw ParseError("invalid integral value (0 is the solely valid value)", std::vector{node.children[1]->begin()}); } - // LCOV_EXCL_START - throw ParseError("unexpected error: invalid integral value", std::vector{node.children[1]->begin()}); - // LCOV_EXCL_STOP } }; diff --git a/src/language/utils/AffectationRegisterForRnxn.cpp b/src/language/utils/AffectationRegisterForRnxn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..314fb36aaf4d5116418c6366d7b69ad5718091b7 --- /dev/null +++ b/src/language/utils/AffectationRegisterForRnxn.cpp @@ -0,0 +1,138 @@ +#include <language/utils/AffectationRegisterForRnxn.hpp> + +#include <language/utils/AffectationProcessorBuilder.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> +#include <language/utils/OperatorRepository.hpp> + +template <size_t Dimension> +void +AffectationRegisterForRnxn<Dimension>::_register_eq_op() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository.addAffectation< + language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + std::make_shared<AffectationFromZeroProcessorBuilder<language::eq_op, TinyMatrix<Dimension>>>()); + + repository.addAffectation<language::eq_op>(Rnxn, + ASTNodeDataType::build<ASTNodeDataType::list_t>( + std::vector<std::shared_ptr<const ASTNodeDataType>>{}), + std::make_shared<AffectationToTinyMatrixFromListProcessorBuilder< + language::eq_op, TinyMatrix<Dimension>>>()); +} + +template <> +void +AffectationRegisterForRnxn<1>::_register_eq_op() +{ + constexpr size_t Dimension = 1; + + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository.addAffectation< + language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, bool>>()); + + repository.addAffectation< + language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, uint64_t>>()); + + repository.addAffectation< + language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, int64_t>>()); + + repository.addAffectation< + language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, double>>()); + + // repository + // .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), + // ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + // std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); + + // repository + // .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), + // ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + // std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); + + // repository + // .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), + // ASTNodeDataType::build<ASTNodeDataType::int_t>(), + // std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); + + // repository + // .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), + // ASTNodeDataType::build<ASTNodeDataType::double_t>(), + // std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); +} + +template <size_t Dimension> +void +AffectationRegisterForRnxn<Dimension>::_register_pluseq_op() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository + .addAffectation<language::pluseq_op>(Rnxn, Rnxn, + std::make_shared<AffectationProcessorBuilder< + language::pluseq_op, TinyMatrix<Dimension>, TinyMatrix<Dimension>>>()); +} + +template <size_t Dimension> +void +AffectationRegisterForRnxn<Dimension>::_register_minuseq_op() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository + .addAffectation<language::minuseq_op>(Rnxn, Rnxn, + std::make_shared<AffectationProcessorBuilder< + language::minuseq_op, TinyMatrix<Dimension>, TinyMatrix<Dimension>>>()); +} + +template <size_t Dimension> +void +AffectationRegisterForRnxn<Dimension>::_register_multiplyeq_op() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + std::make_shared<AffectationProcessorBuilder< + language::multiplyeq_op, TinyMatrix<Dimension>, bool>>()); + + repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + std::make_shared<AffectationProcessorBuilder< + language::multiplyeq_op, TinyMatrix<Dimension>, uint64_t>>()); + + repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + std::make_shared<AffectationProcessorBuilder< + language::multiplyeq_op, TinyMatrix<Dimension>, int64_t>>()); + + repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + std::make_shared<AffectationProcessorBuilder< + language::multiplyeq_op, TinyMatrix<Dimension>, double>>()); +} + +template <size_t Dimension> +AffectationRegisterForRnxn<Dimension>::AffectationRegisterForRnxn() +{ + BasicAffectationRegisterFor<TinyMatrix<Dimension>>{}; + this->_register_eq_op(); + this->_register_pluseq_op(); + this->_register_minuseq_op(); + this->_register_multiplyeq_op(); +} + +template class AffectationRegisterForRnxn<1>; +template class AffectationRegisterForRnxn<2>; +template class AffectationRegisterForRnxn<3>; diff --git a/src/language/utils/AffectationRegisterForRnxn.hpp b/src/language/utils/AffectationRegisterForRnxn.hpp new file mode 100644 index 0000000000000000000000000000000000000000..33f2ad07d3911f2b7488cd10b321be5e4f59f5e4 --- /dev/null +++ b/src/language/utils/AffectationRegisterForRnxn.hpp @@ -0,0 +1,19 @@ +#ifndef AFFECTATION_REGISTER_FOR_RNXN_HPP +#define AFFECTATION_REGISTER_FOR_RNXN_HPP + +#include <cstdlib> + +template <size_t Dimension> +class AffectationRegisterForRnxn +{ + private: + void _register_eq_op(); + void _register_pluseq_op(); + void _register_minuseq_op(); + void _register_multiplyeq_op(); + + public: + AffectationRegisterForRnxn(); +}; + +#endif // AFFECTATION_REGISTER_FOR_RNXN_HPP diff --git a/src/language/utils/BinaryOperatorRegisterForRnxn.cpp b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b44f42e913f2f24a6aeaf7d538f02fc14133b457 --- /dev/null +++ b/src/language/utils/BinaryOperatorRegisterForRnxn.cpp @@ -0,0 +1,69 @@ +#include <language/utils/BinaryOperatorRegisterForRnxn.hpp> + +#include <language/utils/BinaryOperatorProcessorBuilder.hpp> +#include <language/utils/OperatorRepository.hpp> + +template <size_t Dimension> +void +BinaryOperatorRegisterForRnxn<Dimension>::_register_comparisons() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + using Rnxn = TinyMatrix<Dimension>; + + repository.addBinaryOperator<language::eqeq_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::eqeq_op, bool, Rnxn, Rnxn>>()); + + repository.addBinaryOperator<language::not_eq_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::not_eq_op, bool, Rnxn, Rnxn>>()); +} + +template <size_t Dimension> +void +BinaryOperatorRegisterForRnxn<Dimension>::_register_product_by_a_scalar() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + using Rnxn = TinyMatrix<Dimension>; + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rnxn, bool, Rnxn>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rnxn, uint64_t, Rnxn>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rnxn, int64_t, Rnxn>>()); + + repository.addBinaryOperator<language::multiply_op>( + std::make_shared<BinaryOperatorProcessorBuilder<language::multiply_op, Rnxn, double, Rnxn>>()); +} + +template <size_t Dimension> +template <typename OperatorT> +void +BinaryOperatorRegisterForRnxn<Dimension>::_register_arithmetic() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + using Rnxn = TinyMatrix<Dimension>; + + repository.addBinaryOperator<OperatorT>( + std::make_shared<BinaryOperatorProcessorBuilder<OperatorT, Rnxn, Rnxn, Rnxn>>()); +} + +template <size_t Dimension> +BinaryOperatorRegisterForRnxn<Dimension>::BinaryOperatorRegisterForRnxn() +{ + this->_register_comparisons(); + + this->_register_product_by_a_scalar(); + + this->_register_arithmetic<language::plus_op>(); + this->_register_arithmetic<language::minus_op>(); + this->_register_arithmetic<language::multiply_op>(); +} + +template class BinaryOperatorRegisterForRnxn<1>; +template class BinaryOperatorRegisterForRnxn<2>; +template class BinaryOperatorRegisterForRnxn<3>; diff --git a/src/language/utils/BinaryOperatorRegisterForRnxn.hpp b/src/language/utils/BinaryOperatorRegisterForRnxn.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7efb4cbb8691c23cec22e5f82c5c7dae83b2b49c --- /dev/null +++ b/src/language/utils/BinaryOperatorRegisterForRnxn.hpp @@ -0,0 +1,21 @@ +#ifndef BINARY_OPERATOR_REGISTER_FOR_RNXN_HPP +#define BINARY_OPERATOR_REGISTER_FOR_RNXN_HPP + +#include <cstdlib> + +template <size_t Dimension> +class BinaryOperatorRegisterForRnxn +{ + private: + void _register_comparisons(); + + void _register_product_by_a_scalar(); + + template <typename OperatorT> + void _register_arithmetic(); + + public: + BinaryOperatorRegisterForRnxn(); +}; + +#endif // BINARY_OPERATOR_REGISTER_FOR_RNXN_HPP diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index ed105ca479f5b17c3366d44320505dba5d2eacad..eb24e0d935f4d351adf90fd35baf372eaacd1fca 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(PugsLanguageUtils AffectationRegisterForN.cpp AffectationRegisterForR.cpp AffectationRegisterForRn.cpp + AffectationRegisterForRnxn.cpp AffectationRegisterForString.cpp AffectationRegisterForZ.cpp ASTDotPrinter.cpp @@ -15,6 +16,7 @@ add_library(PugsLanguageUtils BinaryOperatorRegisterForN.cpp BinaryOperatorRegisterForR.cpp BinaryOperatorRegisterForRn.cpp + BinaryOperatorRegisterForRnxn.cpp BinaryOperatorRegisterForString.cpp BinaryOperatorRegisterForZ.cpp DataVariant.cpp @@ -27,6 +29,7 @@ add_library(PugsLanguageUtils UnaryOperatorRegisterForN.cpp UnaryOperatorRegisterForR.cpp UnaryOperatorRegisterForRn.cpp + UnaryOperatorRegisterForRnxn.cpp UnaryOperatorRegisterForZ.cpp ) diff --git a/src/language/utils/DataVariant.hpp b/src/language/utils/DataVariant.hpp index 55e537f0922a53020797b360d4c235f358bcbc8c..6add9e52853bcbf58ee42e4f2869649dab43d37d 100644 --- a/src/language/utils/DataVariant.hpp +++ b/src/language/utils/DataVariant.hpp @@ -1,6 +1,7 @@ #ifndef DATA_VARIANT_HPP #define DATA_VARIANT_HPP +#include <algebra/TinyMatrix.hpp> #include <algebra/TinyVector.hpp> #include <language/utils/EmbeddedData.hpp> #include <language/utils/FunctionSymbolId.hpp> @@ -22,6 +23,9 @@ using DataVariant = std::variant<std::monostate, TinyVector<1>, TinyVector<2>, TinyVector<3>, + TinyMatrix<1>, + TinyMatrix<2>, + TinyMatrix<3>, EmbeddedData, std::vector<bool>, std::vector<uint64_t>, @@ -31,6 +35,9 @@ using DataVariant = std::variant<std::monostate, std::vector<TinyVector<1>>, std::vector<TinyVector<2>>, std::vector<TinyVector<3>>, + std::vector<TinyMatrix<1>>, + std::vector<TinyMatrix<2>>, + std::vector<TinyMatrix<3>>, std::vector<EmbeddedData>, AggregateDataVariant, FunctionSymbolId>; diff --git a/src/language/utils/OperatorRepository.cpp b/src/language/utils/OperatorRepository.cpp index 93856da8c33793cad9189a25285b612b550f8d61..d34344b967f41c72ae09849a554958b8ebfcc1f3 100644 --- a/src/language/utils/OperatorRepository.cpp +++ b/src/language/utils/OperatorRepository.cpp @@ -5,6 +5,7 @@ #include <language/utils/AffectationRegisterForN.hpp> #include <language/utils/AffectationRegisterForR.hpp> #include <language/utils/AffectationRegisterForRn.hpp> +#include <language/utils/AffectationRegisterForRnxn.hpp> #include <language/utils/AffectationRegisterForString.hpp> #include <language/utils/AffectationRegisterForZ.hpp> @@ -12,6 +13,7 @@ #include <language/utils/BinaryOperatorRegisterForN.hpp> #include <language/utils/BinaryOperatorRegisterForR.hpp> #include <language/utils/BinaryOperatorRegisterForRn.hpp> +#include <language/utils/BinaryOperatorRegisterForRnxn.hpp> #include <language/utils/BinaryOperatorRegisterForString.hpp> #include <language/utils/BinaryOperatorRegisterForZ.hpp> @@ -23,6 +25,7 @@ #include <language/utils/UnaryOperatorRegisterForN.hpp> #include <language/utils/UnaryOperatorRegisterForR.hpp> #include <language/utils/UnaryOperatorRegisterForRn.hpp> +#include <language/utils/UnaryOperatorRegisterForRnxn.hpp> #include <language/utils/UnaryOperatorRegisterForZ.hpp> #include <utils/PugsAssert.hpp> @@ -65,6 +68,9 @@ OperatorRepository::_initialize() AffectationRegisterForRn<1>{}; AffectationRegisterForRn<2>{}; AffectationRegisterForRn<3>{}; + AffectationRegisterForRnxn<1>{}; + AffectationRegisterForRnxn<2>{}; + AffectationRegisterForRnxn<3>{}; AffectationRegisterForString{}; BinaryOperatorRegisterForB{}; @@ -74,6 +80,9 @@ OperatorRepository::_initialize() BinaryOperatorRegisterForRn<1>{}; BinaryOperatorRegisterForRn<2>{}; BinaryOperatorRegisterForRn<3>{}; + BinaryOperatorRegisterForRnxn<1>{}; + BinaryOperatorRegisterForRnxn<2>{}; + BinaryOperatorRegisterForRnxn<3>{}; BinaryOperatorRegisterForString{}; IncDecOperatorRegisterForN{}; @@ -87,4 +96,7 @@ OperatorRepository::_initialize() UnaryOperatorRegisterForRn<1>{}; UnaryOperatorRegisterForRn<2>{}; UnaryOperatorRegisterForRn<3>{}; + UnaryOperatorRegisterForRnxn<1>{}; + UnaryOperatorRegisterForRnxn<2>{}; + UnaryOperatorRegisterForRnxn<3>{}; } diff --git a/src/language/utils/UnaryOperatorRegisterForRnxn.cpp b/src/language/utils/UnaryOperatorRegisterForRnxn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..798a60086b30d008901f0d9b5fa2502e745d6fe9 --- /dev/null +++ b/src/language/utils/UnaryOperatorRegisterForRnxn.cpp @@ -0,0 +1,28 @@ +#include <language/utils/UnaryOperatorRegisterForRnxn.hpp> + +#include <language/utils/OperatorRepository.hpp> +#include <language/utils/UnaryOperatorProcessorBuilder.hpp> + +template <size_t Dimension> +void +UnaryOperatorRegisterForRnxn<Dimension>::_register_unary_minus() +{ + OperatorRepository& repository = OperatorRepository::instance(); + + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + + repository + .addUnaryOperator<language::unary_minus>(Rnxn, + std::make_shared<UnaryOperatorProcessorBuilder< + language::unary_minus, TinyMatrix<Dimension>, TinyMatrix<Dimension>>>()); +} + +template <size_t Dimension> +UnaryOperatorRegisterForRnxn<Dimension>::UnaryOperatorRegisterForRnxn() +{ + this->_register_unary_minus(); +} + +template class UnaryOperatorRegisterForRnxn<1>; +template class UnaryOperatorRegisterForRnxn<2>; +template class UnaryOperatorRegisterForRnxn<3>; diff --git a/src/language/utils/UnaryOperatorRegisterForRnxn.hpp b/src/language/utils/UnaryOperatorRegisterForRnxn.hpp new file mode 100644 index 0000000000000000000000000000000000000000..42084f2961504130189f40967b50757401b7b939 --- /dev/null +++ b/src/language/utils/UnaryOperatorRegisterForRnxn.hpp @@ -0,0 +1,16 @@ +#ifndef UNARY_OPERATOR_REGISTER_FOR_RNXN_HPP +#define UNARY_OPERATOR_REGISTER_FOR_RNXN_HPP + +#include <cstdlib> + +template <size_t Dimension> +class UnaryOperatorRegisterForRnxn +{ + private: + void _register_unary_minus(); + + public: + UnaryOperatorRegisterForRnxn(); +}; + +#endif // UNARY_OPERATOR_REGISTER_FOR_RNXN_HPP diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp index ecd72b1f04b52b47431e10d07b83d3dab441066e..d2aeabb06ed1e69c51e04a9c83842c260b796852 100644 --- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp @@ -1548,8 +1548,7 @@ let x : R, x=1; x/=2.3; ast->children.emplace_back(std::make_unique<ASTNode>()); ast->children[0]->m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>(); ast->children.emplace_back(std::make_unique<ASTNode>()); - REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, - "unexpected error: invalid implicit conversion: undefined -> string"); + REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, "undefined affectation type: string = undefined"); } SECTION("Invalid string affectation operator") @@ -1629,7 +1628,7 @@ let s : string, s="foo"; s*=2; let x : R^3; let y : R^1; x = y; )"; - std::string error_message = "invalid implicit conversion: R^1 -> R^3"; + std::string error_message = "undefined affectation type: R^3 = R^1"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1640,7 +1639,7 @@ let x : R^3; let y : R^1; x = y; let x : R^3; let y : R^2; x = y; )"; - std::string error_message = "invalid implicit conversion: R^2 -> R^3"; + std::string error_message = "undefined affectation type: R^3 = R^2"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1651,7 +1650,7 @@ let x : R^3; let y : R^2; x = y; let x : R^2; let y : R^1; x = y; )"; - std::string error_message = "invalid implicit conversion: R^1 -> R^2"; + std::string error_message = "undefined affectation type: R^2 = R^1"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1662,7 +1661,7 @@ let x : R^2; let y : R^1; x = y; let x : R^2; let y : R^3; x = y; )"; - std::string error_message = "invalid implicit conversion: R^3 -> R^2"; + std::string error_message = "undefined affectation type: R^2 = R^3"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1673,7 +1672,7 @@ let x : R^2; let y : R^3; x = y; let x : R^1; let y : R^2; x = y; )"; - std::string error_message = "invalid implicit conversion: R^2 -> R^1"; + std::string error_message = "undefined affectation type: R^1 = R^2"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1684,7 +1683,7 @@ let x : R^1; let y : R^2; x = y; let x : R^1; let y : R^3; x = y; )"; - std::string error_message = "invalid implicit conversion: R^3 -> R^1"; + std::string error_message = "undefined affectation type: R^1 = R^3"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1698,7 +1697,7 @@ let x : R^1; let y : R^3; x = y; let x : R^3, x = 3; )"; - std::string error_message = "invalid implicit conversion: Z -> R^3"; + std::string error_message = "invalid integral value (0 is the solely valid value)"; CHECK_AST_THROWS_WITH(data, error_message); } @@ -1709,7 +1708,7 @@ let x : R^3, x = 3; let x : R^2, x = 2; )"; - std::string error_message = "invalid implicit conversion: Z -> R^2"; + std::string error_message = "invalid integral value (0 is the solely valid value)"; CHECK_AST_THROWS_WITH(data, error_message); } diff --git a/tests/test_ASTNodeDataType.cpp b/tests/test_ASTNodeDataType.cpp index 2e6e9afb4715b86c67fa2511e7472418e912f8e8..e293cdd966bd141876a06678e1d99a73348a31d3 100644 --- a/tests/test_ASTNodeDataType.cpp +++ b/tests/test_ASTNodeDataType.cpp @@ -104,7 +104,7 @@ TEST_CASE("ASTNodeDataType", "[language]") { std::unique_ptr dimension_node = std::make_unique<ASTNode>(); dimension_node->set_type<language::integer>(); - dimension_node->source = "17"; + dimension_node->source = "3"; auto& source = dimension_node->source; dimension_node->m_begin = TAO_PEGTL_NAMESPACE::internal::iterator{&source[0]}; dimension_node->m_end = TAO_PEGTL_NAMESPACE::internal::iterator{&source[source.size()]}; @@ -113,8 +113,8 @@ TEST_CASE("ASTNodeDataType", "[language]") SECTION("good node") { - REQUIRE(getVectorDataType(*type_node) == ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)); - REQUIRE(getVectorDataType(*type_node).dimension() == 17); + REQUIRE(getVectorDataType(*type_node) == ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)); + REQUIRE(getVectorDataType(*type_node).dimension() == 3); } SECTION("bad node type") diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp index c15be1db66c0bbbe9a5e9eee4c895f21f3bb30d7..ad2684560290f6b1e7f499ca9f319d11bd529d97 100644 --- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp @@ -385,7 +385,7 @@ let x:R^2, x = (1,2); let y:R^3, y = x; )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"}); + CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation type: R^3 = R^2"}); } SECTION("invalid Z -> R^d conversion (non-zero)") @@ -394,7 +394,7 @@ let y:R^3, y = x; let x:R^2, x = 1; )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + CHECK_AST_THROWS_WITH(data, std::string{"invalid integral value (0 is the solely valid value)"}); } } } diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp index 75ba801b59cc8d06b213fd56b2dc18dbb74b7c45..2fb599bc13bb4335fdbe2eb0899efd611e6e0894 100644 --- a/tests/test_AffectationProcessor.cpp +++ b/tests/test_AffectationProcessor.cpp @@ -331,83 +331,83 @@ TEST_CASE("AffectationProcessor", "[language]") { SECTION("-> B") { - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 1; let b : B; b = n;", "invalid implicit conversion: N -> B"); - CHECK_AFFECTATION_THROWS_WITH("let b : B; b = 1;", "invalid implicit conversion: Z -> B"); - CHECK_AFFECTATION_THROWS_WITH("let b : B; b = 2.3;", "invalid implicit conversion: R -> B"); - CHECK_AFFECTATION_THROWS_WITH("let b : B; b = \"foo\";", "invalid implicit conversion: string -> B"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 1; let b : B; b = n;", "undefined affectation type: B = N"); + CHECK_AFFECTATION_THROWS_WITH("let b : B; b = 1;", "undefined affectation type: B = Z"); + CHECK_AFFECTATION_THROWS_WITH("let b : B; b = 2.3;", "undefined affectation type: B = R"); + CHECK_AFFECTATION_THROWS_WITH("let b : B; b = \"foo\";", "undefined affectation type: B = string"); } SECTION("-> N") { - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2.3;", "invalid implicit conversion: R -> N"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = \"bar\";", "invalid implicit conversion: string -> N"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2.3;", "undefined affectation type: N = R"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = \"bar\";", "undefined affectation type: N = string"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n += 1.1;", "invalid implicit conversion: R -> N"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n += \"foo\";", "invalid implicit conversion: string -> N"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n += 1.1;", "undefined affectation type: N += R"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n += \"foo\";", "undefined affectation type: N += string"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n -= 1.1;", "invalid implicit conversion: R -> N"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n -= \"bar\";", "invalid implicit conversion: string -> N"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n -= 1.1;", "undefined affectation type: N -= R"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n -= \"bar\";", "undefined affectation type: N -= string"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n *= 2.51;", "invalid implicit conversion: R -> N"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n *= \"foobar\";", "invalid implicit conversion: string -> N"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n *= 2.51;", "undefined affectation type: N *= R"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n *= \"foobar\";", "undefined affectation type: N *= string"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n /= 2.51;", "invalid implicit conversion: R -> N"); - CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n /= \"foo\";", "invalid implicit conversion: string -> N"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n /= 2.51;", "undefined affectation type: N /= R"); + CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 2; n /= \"foo\";", "undefined affectation type: N /= string"); } SECTION("-> Z") { - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = -2.3;", "invalid implicit conversion: R -> Z"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = \"foobar\";", "invalid implicit conversion: string -> Z"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = -2.3;", "undefined affectation type: Z = R"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = \"foobar\";", "undefined affectation type: Z = string"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z += 1.1;", "invalid implicit conversion: R -> Z"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z += \"foo\";", "invalid implicit conversion: string -> Z"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z += 1.1;", "undefined affectation type: Z += R"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z += \"foo\";", "undefined affectation type: Z += string"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z -= 2.1;", "invalid implicit conversion: R -> Z"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z -= \"bar\";", "invalid implicit conversion: string -> Z"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z -= 2.1;", "undefined affectation type: Z -= R"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z -= \"bar\";", "undefined affectation type: Z -= string"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z *= -2.51;", "invalid implicit conversion: R -> Z"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z *= \"foobar\";", "invalid implicit conversion: string -> Z"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z *= -2.51;", "undefined affectation type: Z *= R"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z *= \"foobar\";", "undefined affectation type: Z *= string"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 4; z /= -2.;", "invalid implicit conversion: R -> Z"); - CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z /= \"foo\";", "invalid implicit conversion: string -> Z"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 4; z /= -2.;", "undefined affectation type: Z /= R"); + CHECK_AFFECTATION_THROWS_WITH("let z : Z, z = 2; z /= \"foo\";", "undefined affectation type: Z /= string"); } SECTION("-> R") { - CHECK_AFFECTATION_THROWS_WITH("let x : R, x = \"foobar\";", "invalid implicit conversion: string -> R"); - CHECK_AFFECTATION_THROWS_WITH("let x : R, x = 2.3; x += \"foo\";", "invalid implicit conversion: string -> R"); - CHECK_AFFECTATION_THROWS_WITH("let x : R, x = 2.1; x -= \"bar\";", "invalid implicit conversion: string -> R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R, x = \"foobar\";", "undefined affectation type: R = string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R, x = 2.3; x += \"foo\";", "undefined affectation type: R += string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R, x = 2.1; x -= \"bar\";", "undefined affectation type: R -= string"); CHECK_AFFECTATION_THROWS_WITH("let x : R, x = 1.2; x *= \"foobar\";", - "invalid implicit conversion: string -> R"); - CHECK_AFFECTATION_THROWS_WITH("let x : R, x =-2.3; x /= \"foo\";", "invalid implicit conversion: string -> R"); + "undefined affectation type: R *= string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R, x =-2.3; x /= \"foo\";", "undefined affectation type: R /= string"); } SECTION("-> R^n") { - CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = \"foobar\";", "invalid implicit conversion: string -> R^2"); - CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = \"foobar\";", "invalid implicit conversion: string -> R^3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = \"foobar\";", "undefined affectation type: R^2 = string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = \"foobar\";", "undefined affectation type: R^3 = string"); - CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 3.2;", "invalid implicit conversion: R -> R^2"); - CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 2.3;", "invalid implicit conversion: R -> R^3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 3.2;", "undefined affectation type: R^2 = R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 2.3;", "undefined affectation type: R^3 = R"); - CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 4;", "invalid implicit conversion: Z -> R^2"); - CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 3;", "invalid implicit conversion: Z -> R^3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 4;", "invalid integral value (0 is the solely valid value)"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 3;", "invalid integral value (0 is the solely valid value)"); CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^2, y = x;", - "invalid implicit conversion: R^1 -> R^2"); + "undefined affectation type: R^2 = R^1"); CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^3, y = x;", - "invalid implicit conversion: R^1 -> R^3"); + "undefined affectation type: R^3 = R^1"); CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^1, y = x;", - "invalid implicit conversion: R^2 -> R^1"); + "undefined affectation type: R^1 = R^2"); CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^3, y = x;", - "invalid implicit conversion: R^2 -> R^3"); + "undefined affectation type: R^3 = R^2"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^1, y = x;", - "invalid implicit conversion: R^3 -> R^1"); + "undefined affectation type: R^1 = R^3"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^2, y = x;", - "invalid implicit conversion: R^3 -> R^2"); + "undefined affectation type: R^2 = R^3"); } } }