diff --git a/doc/lisp/share/pugs.el b/doc/lisp/share/pugs.el index 36830ffa5036575b65b08690cb22d986b34473a9..47b37a03ecaac8150196036ae9baaa8a0afb1e50 100644 --- a/doc/lisp/share/pugs.el +++ b/doc/lisp/share/pugs.el @@ -41,7 +41,7 @@ Ask to save the buffer if needed" "pugs mode is a major mode for editing pugs files" ;; define pugs keywords (defvar pugs-keywords - '("import" "let" "Z" "N" "B" "R" "string" "and" "or" "xor" "not" "true" "false" "let" "do" "while" "for" "if" "else" "break" "continue" "cout" "cerr" "clog" "+")) + '("import" "let" "Z" "N" "B" "R" "string" "and" "or" "xor" "not" "true" "false" "let" "do" "while" "for" "if" "else" "break" "continue" "cout" "cerr" "clog" "void")) (defvar pugs-special-symbols '(":" "," ";" "{" "}" "->" "<=" ">=" "=" "+" "-" "*" "/" "<" ">" "^")) diff --git a/doc/userdoc.org b/doc/userdoc.org index ba7cd798a6a7991d6451c405a5b9c81dfa2c0362..490db865223c800e05ee0ee31b52bd86486f8872 100644 --- a/doc/userdoc.org +++ b/doc/userdoc.org @@ -1852,6 +1852,72 @@ The use case of tuples is to provide lists of data to the ~C++~ underlying methods. A classical example is to provide a set of boundary conditions to a method. +**** Tuple and other variables + +If one cannot access to specific values of tuple variables, one can +however dispatch their values to compound variable lists or to simple +variable. To do so the tuple content must be convertible to each of +the compound variable using the operator ~=~ rules (see the conversion +table in section [[implicit-conversion]]). The one to one matching is +checked at runtime. +#+NAME: tuple-to-compound +#+BEGIN_SRC pugs :exports both :results output + let t:(R), t = (1, 2, 3.4, -5); + + let (x, y, u, A):R*R*R^1*R^1x1, (x, y, u, A) = t; + + cout << "t = " << t << "\n"; + cout << "x = " << x << "\n"; + cout << "y = " << y << "\n"; + cout << "u = " << u << "\n"; + cout << "A = " << A << "\n"; +#+END_SRC +This code gives +#+results: tuple-to-compound + +#+BEGIN_note +One could have separate the declarations of ~x~, ~y~, ~u~ and ~A~ from the +affectation. Writing simply at some point + +#+BEGIN_SRC pugs :exports code + (x, y, u, A) = t; +#+END_SRC + +#+END_note + +If the tuple contains only one entry, one can assign its value to a +simple variable. +#+NAME: tuple-to-variable +#+BEGIN_SRC pugs :exports both :results output + let t:(R^3), t = [1, 2, 3]; + + let x:R^3, x = t; + + cout << "t = " << t << "\n"; + cout << "x = " << x << "\n"; +#+END_SRC +One gets +#+results: tuple-to-variable + +If the size of the tuple does not match the number of space defining +the compound type, one gets a runtime error. For instance +#+NAME: tuple-to-compound-wrong-size +#+BEGIN_SRC pugs-error :exports both :results output + let t:(Z), t = (1, 2); + let (a, b, c):R*R*R, (a, b, c) = t; +#+END_SRC +produces +#+results: tuple-to-compound-wrong-size +or +#+NAME: tuple-to-variable-wrong-size +#+BEGIN_SRC pugs-error :exports both :results output + let t:(Z), t = (1, 2); + let a:R, a = t; +#+END_SRC +which gives +#+results: tuple-to-variable-wrong-size + + ** Statements The ~pugs~ language supports classical statements to control the data @@ -2160,6 +2226,21 @@ compound). The type of ~x~ is ~X~ and for lists, each argument ~xi~ belongs to ~Xi~. The function themselves are defined by the expressions ~e~ (or ~e1~, ..., ~em~) which types are set by ~Y~ (or ~Y1~, ..., ~Ym~). +#+BEGIN_warning +- ~X~, ~X1~, ..., ~Xn~ cannot be tuples spaces. +- ~Y~, ~Y1~, ..., ~Ym~ can be tuple spaces. + +Also, ~X~ can be the empty space $\varnothing$, but none of ~X1~, ..., ~Xn~ +(for $n>1$) and none of ~Y~, ~Y1~, ..., ~Ym~ can be $\varnothing$. In other +word one can define functions such as +\begin{align*} + \mbox{let }g:& \varnothing \to Y_1\times \cdots \times Y_m,\\ + & \varnothing\mapsto (y_1,\ldots,y_m)=g(\varnothing). +\end{align*} +The *keyword* associated to $\varnothing$ is ~void~. Keep in mind that ~void~ +is just a keyword in ~pugs~, it is not a type in the computer science +point of view (one cannot declare variables of type ~void~). +#+END_warning Let us give a few examples. #+NAME: R-to-R-function @@ -2184,6 +2265,14 @@ returned type #+END_SRC #+results: R-to-R1-function +But one cannot use tuples to define the domain +#+NAME: no-tuple-in-domain +#+BEGIN_SRC pugs-error :exports both :results output + let f: (N)->N, n -> 3; +#+END_SRC +produces the following compilation time error +#+results: no-tuple-in-domain + Using compound types as input and output, one can write #+NAME: R22-R-string-to-R-string-function #+BEGIN_SRC pugs :exports both :results output @@ -2208,6 +2297,25 @@ Using compound types as input and output, one can write This meaningless example produces the following result. #+results: R22-R-string-to-R-string-function +The following example shows how to use tuples as codomain. +#+NAME: R-to-tuple-R-function +#+BEGIN_SRC pugs :exports both :results output + let f: R -> (R), x -> (2*x, 2-x, 7*x-2, 2, x/3); + + cout << "f(3.2) = " << f(3.2) << "\n"; +#+END_SRC +#+results: R-to-tuple-R-function + +Finally, we give an example of an empty function. Observe the special +role of the ~void~ keyword +#+NAME: void-to-tuple-R-function +#+BEGIN_SRC pugs :exports both :results output + let f: void -> (R^2), void -> ([2, 3.5], [6, 7]); + + cout << "f() = " << f() << "\n"; +#+END_SRC +#+results: void-to-tuple-R-function + **** Lifetime of function arguments The arguments used to define a function are *local* variables that exist @@ -2325,7 +2433,8 @@ produces the following compilation time error In ~pugs~ language, builtin functions are ~C++~ pieces of code that can be called in scripts. Their usage is very similar to user-defined functions. They differ from user-defined functions in three points. -- Builtin functions may have no parameter or no returned value. +- Builtin functions may have no returned value. +- Builtin functions can use tuples as arguments. - Builtin functions are polymorphic. More precisely, this means that the signature of a builtin function is also defined by its expected argument types. @@ -2722,32 +2831,35 @@ The information produced concerns This type is used to designate kinds of items (cell, face, edge or node). -***** ~item_value~ +***** ~item_value~ and ~item_array~ -The type ~item_value~ is an abstract type use to designate arrays of -values defined on the entities of a ~mesh~. Actually, these values are -not associated to the mesh itself but to the *connectivity*. The values -on the entities can be of type ~B~, ~N~, ~Z~, ~R~, ~R^1~, ~R^2~, ~R^3~, ~R^1x1~, ~R^2x2~ -and ~R^3x3~. Entities themselves can be cells, faces, edges or nodes. +The types ~item_value~ and ~item_array~ are abstract types use to +designate values or arrays of values defined on each entities of a +~mesh~. Actually, these set of values (or arrays) are not associated to +the mesh itself but to the *connectivity*. The values on the entities +can be of type ~B~, ~N~, ~Z~, ~R~, ~R^1~, ~R^2~, ~R^3~, ~R^1x1~, ~R^2x2~ and +~R^3x3~. Entities themselves can be cells, faces, edges or nodes. These variables are used to pass data from one function to another. #+BEGIN_warning -By now, no mathematical operation is defined on ~item_value~ variables. +By now, no mathematical operation is defined on ~item_value~ or +~item_array~ variables. #+END_warning Moreover, ~item_value~ variables can be post processed. Observe that edge or face values cannot be post processed since neither ~VTK~ nor -~Gnuplot~ can handle these data. +~Gnuplot~ can handle these data. Also ~item_raray~ can only be post +processed if array per item contain scalar data ( ~B~, ~N~, ~Z~, ~R~). -***** ~sub_item_value~ +***** ~sub_item_value~ and ~sub_item_arrays~ -This abstract type handles values defined on the sub items of the -items of a ~mesh~. Similarly these values are attached to a *connectivity* -and not to a mesh. The values associated to the sub items can be of -type ~B~, ~N~, ~Z~, ~R~, ~R^1~, ~R^2~, ~R^3~, ~R^1x1~, ~R^2x2~ or ~R^3x3~. An example of -~sub_item_value~ is the $\mathbf{C}_{jr}$ vectors which are defined at each -node of each cell. +These abstract type handles values or arrays defined on the sub items +of the items of a ~mesh~. Similarly these sets of values or arrays are +attached to a *connectivity* and not to a mesh. The values associated to +the sub items can be of type ~B~, ~N~, ~Z~, ~R~, ~R^1~, ~R^2~, ~R^3~, ~R^1x1~, ~R^2x2~ +or ~R^3x3~. An example of ~sub_item_value~ is the $\mathbf{C}_{jr}$ vectors +which are defined at each node of each cell. These variables are used to pass data from one function to another. They cannot be post processed. diff --git a/src/algebra/SmallMatrix.hpp b/src/algebra/SmallMatrix.hpp index d0d6ee329f02c41626900384c794d1cfa490089c..b8d3b81b5fad0ac65521a94aa4f94183f4cff333 100644 --- a/src/algebra/SmallMatrix.hpp +++ b/src/algebra/SmallMatrix.hpp @@ -38,7 +38,7 @@ class [[nodiscard]] SmallMatrix // LCOV_EXCL_LINE friend PUGS_INLINE SmallMatrix<std::remove_const_t<DataType>> copy(const SmallMatrix& A) noexcept { - return {A.m_nb_rows, A.m_nb_columns, copy(A.m_values)}; + return SmallMatrix<std::remove_const_t<DataType>>{A.m_nb_rows, A.m_nb_columns, copy(A.m_values)}; } friend PUGS_INLINE SmallMatrix<std::remove_const_t<DataType>> transpose(const SmallMatrix& A) @@ -130,7 +130,8 @@ class [[nodiscard]] SmallMatrix // LCOV_EXCL_LINE { static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>, "incompatible data types"); - Assert((m_nb_rows == B.numberOfRows()) and (m_nb_columns == B.numberOfColumns()), "incompatible matrix sizes"); + Assert((m_nb_rows == B.numberOfRows()) and (m_nb_columns == B.numberOfColumns()), + "cannot add matrix: incompatible sizes"); parallel_for( m_values.size(), PUGS_LAMBDA(index_type i) { m_values[i] += B.m_values[i]; }); @@ -260,6 +261,12 @@ class [[nodiscard]] SmallMatrix // LCOV_EXCL_LINE SmallMatrix(SmallMatrix &&) = default; + explicit SmallMatrix(size_t nb_rows, size_t nb_columns, const SmallArray<DataType>& values) + : m_nb_rows{nb_rows}, m_nb_columns{nb_columns}, m_values{values} + { + Assert(m_values.size() == m_nb_columns * m_nb_rows, "incompatible array size and matrix dimensions") + } + explicit SmallMatrix(size_t nb_rows, size_t nb_columns) noexcept : m_nb_rows{nb_rows}, m_nb_columns{nb_columns}, m_values{nb_rows * nb_columns} {} diff --git a/src/algebra/SmallVector.hpp b/src/algebra/SmallVector.hpp index d20bb48f4cdb700f61a0881898fb5273217693aa..d4a0bf84268bdf1d164cf6216153117adafaab56 100644 --- a/src/algebra/SmallVector.hpp +++ b/src/algebra/SmallVector.hpp @@ -30,6 +30,18 @@ class SmallVector // LCOV_EXCL_LINE return os << x.m_values; } + [[nodiscard]] friend std::remove_const_t<DataType> + min(const SmallVector& x) + { + return min(x.m_values); + } + + [[nodiscard]] friend std::remove_const_t<DataType> + max(const SmallVector& x) + { + return max(x.m_values); + } + friend SmallVector<std::remove_const_t<DataType>> copy(const SmallVector& x) { @@ -40,7 +52,18 @@ class SmallVector // LCOV_EXCL_LINE return x_copy; } - friend SmallVector operator*(const DataType& a, const SmallVector& x) + PUGS_INLINE + SmallVector<std::remove_const_t<DataType>> + operator-() const + { + SmallVector<std::remove_const_t<DataType>> opposite(this->size()); + parallel_for( + opposite.size(), PUGS_LAMBDA(index_type i) { opposite.m_values[i] = -m_values[i]; }); + return opposite; + } + + friend SmallVector + operator*(const DataType& a, const SmallVector& x) { SmallVector<std::remove_const_t<DataType>> y = copy(x); return y *= a; @@ -51,14 +74,8 @@ class SmallVector // LCOV_EXCL_LINE dot(const SmallVector& x, const SmallVector<DataType2>& y) { Assert(x.size() == y.size(), "cannot compute dot product: incompatible vector sizes"); - // Quite ugly, TODO: fix me in C++20 - auto promoted = [] { - DataType a{0}; - DataType2 b{0}; - return a * b; - }(); - decltype(promoted) sum = 0; + decltype(std::declval<DataType>() * std::declval<DataType2>()) sum = 0; // Does not use parallel_for to preserve sum order for (index_type i = 0; i < x.size(); ++i) { @@ -136,7 +153,8 @@ class SmallVector // LCOV_EXCL_LINE } PUGS_INLINE - DataType& operator[](index_type i) const noexcept(NO_ASSERT) + DataType& + operator[](index_type i) const noexcept(NO_ASSERT) { return m_values[i]; } diff --git a/src/algebra/TinyVector.hpp b/src/algebra/TinyVector.hpp index ae616a4849d0e681bf09e613ad4d19263d0f035a..e39dcec6e9834e5cb5eb80e1e845de1054beb1b2 100644 --- a/src/algebra/TinyVector.hpp +++ b/src/algebra/TinyVector.hpp @@ -42,14 +42,12 @@ class [[nodiscard]] TinyVector return opposite; } - PUGS_INLINE - constexpr size_t dimension() const + [[nodiscard]] PUGS_INLINE constexpr size_t dimension() const { return N; } - PUGS_INLINE - constexpr bool operator==(const TinyVector& v) const + [[nodiscard]] PUGS_INLINE constexpr bool operator==(const TinyVector& v) const { for (size_t i = 0; i < N; ++i) { if (m_values[i] != v.m_values[i]) @@ -58,14 +56,12 @@ class [[nodiscard]] TinyVector return true; } - PUGS_INLINE - constexpr bool operator!=(const TinyVector& v) const + [[nodiscard]] PUGS_INLINE constexpr bool operator!=(const TinyVector& v) const { return not this->operator==(v); } - PUGS_INLINE - constexpr friend T dot(const TinyVector& u, const TinyVector& v) + [[nodiscard]] PUGS_INLINE constexpr friend T dot(const TinyVector& u, const TinyVector& v) { T t = u.m_values[0] * v.m_values[0]; for (size_t i = 1; i < N; ++i) { @@ -242,7 +238,7 @@ class [[nodiscard]] TinyVector }; template <size_t N, typename T> -PUGS_INLINE constexpr T +[[nodiscard]] PUGS_INLINE constexpr T l2Norm(const TinyVector<N, T>& x) { static_assert(std::is_arithmetic<T>(), "Cannot compute L2 norm for non-arithmetic types"); @@ -250,13 +246,39 @@ l2Norm(const TinyVector<N, T>& x) return std::sqrt(dot(x, x)); } -// Cross product is only defined for K^3 vectors +template <size_t N, typename T> +[[nodiscard]] PUGS_INLINE constexpr T +min(const TinyVector<N, T>& x) +{ + T m = x[0]; + for (size_t i = 1; i < N; ++i) { + if (x[i] < m) { + m = x[i]; + } + } + return m; +} + +template <size_t N, typename T> +[[nodiscard]] PUGS_INLINE constexpr T +max(const TinyVector<N, T>& x) +{ + T m = x[0]; + for (size_t i = 1; i < N; ++i) { + if (x[i] > m) { + m = x[i]; + } + } + return m; +} + +// Cross product is only defined for dimension 3 vectors template <typename T> -PUGS_INLINE constexpr TinyVector<3, T> +[[nodiscard]] PUGS_INLINE constexpr TinyVector<3, T> crossProduct(const TinyVector<3, T>& u, const TinyVector<3, T>& v) { TinyVector<3, T> cross_product(u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]); return cross_product; } -#endif // TINYVECTOR_HPP +#endif // TINY_VECTOR_HPP diff --git a/src/algebra/Vector.hpp b/src/algebra/Vector.hpp index c918ed409746a3c212720ad8ae6769cfb0882ba9..749a795a489f12a671f4ecfd452104702ba68147 100644 --- a/src/algebra/Vector.hpp +++ b/src/algebra/Vector.hpp @@ -31,6 +31,18 @@ class Vector // LCOV_EXCL_LINE return os << x.m_values; } + [[nodiscard]] friend std::remove_const_t<DataType> + min(const Vector& x) + { + return min(x.m_values); + } + + [[nodiscard]] friend std::remove_const_t<DataType> + max(const Vector& x) + { + return max(x.m_values); + } + friend Vector<std::remove_const_t<DataType>> copy(const Vector& x) { @@ -41,6 +53,16 @@ class Vector // LCOV_EXCL_LINE return x_copy; } + PUGS_INLINE + Vector<std::remove_const_t<DataType>> + operator-() const + { + Vector<std::remove_const_t<DataType>> opposite(this->size()); + parallel_for( + opposite.size(), PUGS_LAMBDA(index_type i) { opposite.m_values[i] = -m_values[i]; }); + return opposite; + } + friend Vector operator*(const DataType& a, const Vector& x) { @@ -53,14 +75,7 @@ class Vector // LCOV_EXCL_LINE dot(const Vector& x, const Vector<DataType2>& y) { Assert(x.size() == y.size(), "cannot compute dot product: incompatible vector sizes"); - // Quite ugly, TODO: fix me in C++20 - auto promoted = [] { - DataType a{0}; - DataType2 b{0}; - return a * b; - }(); - - decltype(promoted) sum = 0; + decltype(std::declval<DataType>() * std::declval<DataType2>()) sum = 0; // Does not use parallel_for to preserve sum order for (index_type i = 0; i < x.size(); ++i) { diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 0e98c2b4bf710b8e86563cabfc0b58dc45f820ff..e2aaeec547bfb3793da15e2305a4882d29fd22e3 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -72,6 +72,8 @@ struct B_set : TAO_PEGTL_KEYWORD("B"){}; struct N_set : TAO_PEGTL_KEYWORD("N"){}; struct Z_set : TAO_PEGTL_KEYWORD("Z"){}; struct R_set : TAO_PEGTL_KEYWORD("R"){}; +struct empty_set : TAO_PEGTL_KEYWORD("void"){}; +struct EMPTY_SET : seq< empty_set, ignored>{}; struct string_type : TAO_PEGTL_KEYWORD("string") {}; @@ -92,7 +94,7 @@ struct tuple_type_specifier : sor<try_catch< open_parent, simple_type_specifier struct TYPE_SPECIFIER : seq< sor<simple_type_specifier, tuple_type_specifier>, ignored >{}; struct type_expression : list_must< TYPE_SPECIFIER, seq< ignored, one< '*' >, ignored > >{}; -struct TYPE_EXPRESSION : seq< type_expression, ignored >{}; +struct TYPE_EXPRESSION : seq< sor< empty_set, type_expression >, ignored >{}; struct and_kw : TAO_PEGTL_KEYWORD("and") {}; struct or_kw : TAO_PEGTL_KEYWORD("or") {}; @@ -129,7 +131,7 @@ struct BREAK : seq < break_kw, ignored > {}; struct continue_kw : TAO_PEGTL_KEYWORD("continue") {}; struct CONTINUE : seq < continue_kw, ignored > {}; -struct keyword : sor < basic_type, import_kw, true_kw, false_kw, let_kw, do_kw, while_kw, for_kw, if_kw, else_kw, and_kw, or_kw, xor_kw, not_kw, break_kw, continue_kw> {}; +struct keyword : sor < empty_set, basic_type, import_kw, true_kw, false_kw, let_kw, do_kw, while_kw, for_kw, if_kw, else_kw, and_kw, or_kw, xor_kw, not_kw, break_kw, continue_kw> {}; struct identifier_minus_keyword : minus< identifier, keyword > {}; @@ -260,7 +262,7 @@ struct type_mapping : seq< TYPE_EXPRESSION, RIGHT_ARROW, TYPE_EXPRESSION >{}; struct name_list : seq< open_parent, list_must< NAME, COMMA >, close_parent >{}; -struct function_definition : seq< sor< name_list, NAME >, RIGHT_ARROW, sor< expression_list, expression > >{}; +struct function_definition : seq< sor< EMPTY_SET, name_list, NAME >, RIGHT_ARROW, sor< expression_list, expression > >{}; struct fct_declaration : seq< LET, NAME, COLUMN, type_mapping, COMMA, function_definition >{}; @@ -403,6 +405,9 @@ inline const std::string errors<language::not_at<subscript_expression_of_lvalue> template <> inline const std::string errors<language::simple_type_specifier>::error_message = "expecting simple type specifier"; +template <> +inline const std::string errors<language::TYPE_SPECIFIER>::error_message = "parse error, expecting type specifier"; + // clang-format on } // namespace language diff --git a/src/language/ast/ASTBuilder.cpp b/src/language/ast/ASTBuilder.cpp index 476c30201ffd43f1102efaa9c9430a5283cc8c89..326d4139e709507c95f6d40f49ca1f87411b7b5c 100644 --- a/src/language/ast/ASTBuilder.cpp +++ b/src/language/ast/ASTBuilder.cpp @@ -226,6 +226,7 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< language::N_set, language::Z_set, language::R_set, + language::empty_set, language::type_name_id, language::tuple_type_specifier, language::inner_expression_list, diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 1e7eb1c427042bef9566c2c55befeb72de0c5e67..b67d81af335e3de1d3c02b0307351f03e75f8089 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::unsigned_int_t>(); } else if (type_node.is_type<language::R_set>()) { data_type = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + } else if (type_node.is_type<language::empty_set>()) { + throw ParseError("'void' keyword does not define a type", std::vector{type_node.begin()}); } else if (type_node.is_type<language::vector_type>()) { data_type = getVectorDataType(type_node); } else if (type_node.is_type<language::matrix_type>()) { @@ -123,6 +125,8 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const n.m_data_type = getVectorDataType(n); } else if (n.is_type<language::matrix_type>()) { n.m_data_type = getMatrixDataType(n); + } else if (n.is_type<language::tuple_type_specifier>()) { + n.m_data_type = getTupleDataType(n); } else if (n.is_type<language::literal>()) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::string_t>(); @@ -173,6 +177,27 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const throw ParseError(message.str(), parameters_domain_node.begin()); } + { + if (parameters_domain_node.is_type<language::type_expression>()) { + for (size_t i_domain = 0; i_domain < parameters_domain_node.children.size(); ++i_domain) { + if (parameters_domain_node.children[i_domain]->is_type<language::tuple_type_specifier>()) { + std::ostringstream message; + message << "cannot use tuple " << rang::fgB::yellow + << dataTypeName(parameters_domain_node.children[i_domain]->m_data_type) << rang::fg::reset + << " as a domain for user functions" << rang::style::reset; + throw ParseError(message.str(), parameters_domain_node.children[i_domain]->begin()); + } + } + } else { + if (parameters_domain_node.is_type<language::tuple_type_specifier>()) { + std::ostringstream message; + message << "cannot use tuple " << rang::fgB::yellow << dataTypeName(parameters_domain_node.m_data_type) + << rang::fg::reset << " as a domain for user functions" << rang::style::reset; + throw ParseError(message.str(), parameters_domain_node.begin()); + } + } + } + auto simple_type_allocator = [&](const ASTNode& type_node, ASTNode& symbol_node) { Assert(symbol_node.is_type<language::name>()); @@ -194,18 +219,28 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const i_symbol->attributes().setDataType(data_type); }; - if (nb_parameter_domains == 1) { - simple_type_allocator(parameters_domain_node, parameters_name_node); + if (parameters_domain_node.is_type<language::empty_set>() or + parameters_name_node.is_type<language::empty_set>()) { + if (not parameters_domain_node.is_type<language::empty_set>()) { + std::ostringstream error_msg; + throw ParseError("unexpected 'void' keyword", std::vector{parameters_name_node.begin()}); + } else if (not parameters_name_node.is_type<language::empty_set>()) { + throw ParseError("expecting 'void' keyword", std::vector{parameters_name_node.begin()}); + } } else { - std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list; - sub_data_type_list.reserve(nb_parameter_domains); + if (nb_parameter_domains == 1) { + simple_type_allocator(parameters_domain_node, parameters_name_node); + } else { + std::vector<std::shared_ptr<const ASTNodeDataType>> sub_data_type_list; + sub_data_type_list.reserve(nb_parameter_domains); - for (size_t i = 0; i < nb_parameter_domains; ++i) { - simple_type_allocator(*parameters_domain_node.children[i], *parameters_name_node.children[i]); - sub_data_type_list.push_back( - std::make_shared<const ASTNodeDataType>(parameters_name_node.children[i]->m_data_type)); + for (size_t i = 0; i < nb_parameter_domains; ++i) { + simple_type_allocator(*parameters_domain_node.children[i], *parameters_name_node.children[i]); + sub_data_type_list.push_back( + std::make_shared<const ASTNodeDataType>(parameters_name_node.children[i]->m_data_type)); + } + parameters_name_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list); } - parameters_name_node.m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(sub_data_type_list); } this->_buildNodeDataTypes(function_descriptor.definitionNode()); @@ -218,32 +253,14 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const const size_t nb_image_expressions = (image_expression_node.is_type<language::expression_list>()) ? image_expression_node.children.size() : 1; - if (nb_image_domains != nb_image_expressions) { - if (image_domain_node.is_type<language::vector_type>()) { - ASTNodeDataType image_type = getVectorDataType(image_domain_node); - if (image_type.dimension() != nb_image_expressions) { - std::ostringstream message; - message << "expecting " << image_type.dimension() << " scalar expressions or an " - << dataTypeName(image_type) << ", found " << nb_image_expressions << " scalar expressions"; - throw ParseError(message.str(), image_expression_node.begin()); - } - } else if (image_domain_node.is_type<language::matrix_type>()) { - ASTNodeDataType image_type = getMatrixDataType(image_domain_node); - if (image_type.numberOfRows() * image_type.numberOfColumns() != nb_image_expressions) { - std::ostringstream message; - message << "expecting " << image_type.numberOfRows() * image_type.numberOfColumns() - << " scalar expressions or an " << dataTypeName(image_type) << ", found " << nb_image_expressions - << " scalar expressions"; - throw ParseError(message.str(), image_expression_node.begin()); - } - } else { - std::ostringstream message; - message << "number of image spaces (" << nb_image_domains << ") " << rang::fgB::yellow - << image_domain_node.string() << rang::style::reset << rang::style::bold - << " differs from number of expressions (" << nb_image_expressions << ") " << rang::fgB::yellow - << image_expression_node.string() << rang::style::reset; - throw ParseError(message.str(), image_domain_node.begin()); - } + if ((not image_domain_node.is_type<language::tuple_type_specifier>()) and + (nb_image_domains != nb_image_expressions)) { + std::ostringstream message; + message << "number of image spaces (" << nb_image_domains << ") " << rang::fgB::yellow + << image_domain_node.string() << rang::style::reset << rang::style::bold + << " differs from number of expressions (" << nb_image_expressions << ") " << rang::fgB::yellow + << image_expression_node.string() << rang::style::reset; + throw ParseError(message.str(), image_domain_node.begin()); } this->_buildNodeDataTypes(image_expression_node); @@ -518,6 +535,8 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const n.m_data_type = [&] { if (image_domain_node.m_data_type == ASTNodeDataType::type_id_t) { return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_domain_node.m_data_type.nameOfTypeId()); + } else if (image_domain_node.m_data_type == ASTNodeDataType::tuple_t) { + return ASTNodeDataType::build<ASTNodeDataType::tuple_t>(image_domain_node.m_data_type.contentType()); } else { return image_domain_node.m_data_type.contentType(); } @@ -582,6 +601,9 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } else if (n.is_type<language::R_set>()) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::double_t>()); + } else if (n.is_type<language::empty_set>()) { + n.m_data_type = + ASTNodeDataType::build<ASTNodeDataType::typename_t>(ASTNodeDataType::build<ASTNodeDataType::void_t>()); } else if (n.is_type<language::vector_type>()) { n.m_data_type = ASTNodeDataType::build<ASTNodeDataType::typename_t>(getVectorDataType(n)); } else if (n.is_type<language::matrix_type>()) { @@ -608,6 +630,6 @@ ASTNodeDataTypeBuilder::ASTNodeDataTypeBuilder(ASTNode& node) this->_buildNodeDataTypes(node); if (ConsoleManager::showPreamble()) { - std::cout << " - build node data types\n"; + std::cout << " - built node data types\n"; } } diff --git a/src/language/ast/ASTNodeDataTypeFlattener.cpp b/src/language/ast/ASTNodeDataTypeFlattener.cpp index 00b77e0bf98e13314fce52396c7a6cef5717254e..201906e28020345cd70a34c501bcb2cf0b5fa258 100644 --- a/src/language/ast/ASTNodeDataTypeFlattener.cpp +++ b/src/language/ast/ASTNodeDataTypeFlattener.cpp @@ -39,6 +39,11 @@ ASTNodeDataTypeFlattener::ASTNodeDataTypeFlattener(ASTNode& node, FlattenedDataT flattened_datatype_list.push_back( {ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_sub_domain->m_data_type.nameOfTypeId()), node}); break; + } + case ASTNodeDataType::tuple_t: { + flattened_datatype_list.push_back( + {ASTNodeDataType::build<ASTNodeDataType::tuple_t>(image_sub_domain->m_data_type.contentType()), node}); + break; } // LCOV_EXCL_START default: { diff --git a/src/language/ast/ASTNodeExpressionBuilder.cpp b/src/language/ast/ASTNodeExpressionBuilder.cpp index 70722aea1a1ac73851df7157820a029e87266a66..4ce7c9c026d41db6c3540b97bbfacb0844af5d02 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeExpressionBuilder.cpp @@ -182,6 +182,8 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) n.m_node_processor = std::make_unique<BreakProcessor>(); } else if (n.is_type<language::continue_kw>()) { n.m_node_processor = std::make_unique<ContinueProcessor>(); + } else if (n.is_type<language::empty_set>()) { + n.m_node_processor = std::make_unique<FakeProcessor>(); } else { std::ostringstream error_message; error_message << "undefined node processor type '" << rang::fgB::red << n.name() << rang::fg::reset << "'"; diff --git a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index 656000c69cd45b85bcf72907850230c7e0f9615b..7e0d981c33a6d2c9bcd9c8caf79ea7ea95407f4e 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -301,24 +301,30 @@ ASTNodeFunctionExpressionBuilder::_buildArgumentConverter(FunctionDescriptor& fu const size_t arguments_number = flattened_datatype_list.size(); - const size_t parameters_number = - parameter_variables.is_type<language::name_list>() ? parameter_variables.children.size() : 1; + const size_t parameters_number = [&]() -> size_t { + if (parameter_variables.is_type<language::name_list>()) { + return parameter_variables.children.size(); + } else if (parameter_variables.is_type<language::empty_set>()) { + return 0; + } else { + return 1; + } + }(); if (arguments_number != parameters_number) { std::ostringstream error_message; - error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number - << rang::style::reset << rang::style::bold << ", provided " << rang::fgB::yellow << arguments_number - << rang::style::reset; + error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number << rang::fg::reset + << ", provided " << rang::fgB::yellow << arguments_number; throw ParseError(error_message.str(), argument_nodes.begin()); } - if (arguments_number > 1) { + if (arguments_number == 1) { + this->_storeArgumentConverter(parameter_variables, flattened_datatype_list[0], *function_processor); + } else if (arguments_number > 1) { for (size_t i = 0; i < arguments_number; ++i) { ASTNode& parameter_variable = *parameter_variables.children[i]; this->_storeArgumentConverter(parameter_variable, flattened_datatype_list[i], *function_processor); } - } else { - this->_storeArgumentConverter(parameter_variables, flattened_datatype_list[0], *function_processor); } return function_processor; @@ -404,7 +410,7 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r return std::make_unique<FunctionExpressionProcessor<ReturnT, ReturnT>>(function_component_expression); } else { // LCOV_EXCL_START - throw ParseError("unexpected error: invalid dimension for returned vector", + throw ParseError("unexpected error: invalid dimensions for returned matrix", std::vector{function_component_expression.begin()}); // LCOV_EXCL_STOP } @@ -451,6 +457,547 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } }; + auto get_function_processor_for_expression_tuple_of_value = + [&](const auto& tuple_content_v) -> std::unique_ptr<INodeProcessor> { + using TupleContentT = std::decay_t<decltype(tuple_content_v)>; + switch (function_component_expression.m_data_type) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, bool>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, uint64_t>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, int64_t>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, double>>( + function_component_expression); + } + case ASTNodeDataType::string_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::string>>( + function_component_expression); + } + case ASTNodeDataType::type_id_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, EmbeddedData>>( + function_component_expression); + } + + case ASTNodeDataType::vector_t: { + switch (function_component_expression.m_data_type.dimension()) { + case 1: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyVector<1>>>( + function_component_expression); + } + case 2: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyVector<2>>>( + function_component_expression); + } + case 3: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyVector<3>>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::matrix_t: { + if (function_component_expression.m_data_type.numberOfRows() != + function_component_expression.m_data_type.numberOfColumns()) { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid dimensions for returned matrix", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + switch (function_component_expression.m_data_type.numberOfRows()) { + case 1: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyMatrix<1>>>( + function_component_expression); + } + case 2: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyMatrix<2>>>( + function_component_expression); + } + case 3: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TinyMatrix<3>>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::tuple_t: { + const ASTNodeDataType& tuple_content_type = function_component_expression.m_data_type.contentType(); + switch (tuple_content_type) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<bool>>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<uint64_t>>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<int64_t>>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<double>>>( + function_component_expression); + } + case ASTNodeDataType::type_id_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<EmbeddedData>>>( + function_component_expression); + } + case ASTNodeDataType::vector_t: { + switch (tuple_content_type.dimension()) { + case 1: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyVector<1>>>>( + function_component_expression); + } + case 2: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyVector<2>>>>( + function_component_expression); + } + case 3: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyVector<3>>>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::matrix_t: { + if (tuple_content_type.numberOfRows() != tuple_content_type.numberOfColumns()) { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid dimensions for returned matrix", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + switch (tuple_content_type.numberOfRows()) { + case 1: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyMatrix<1>>>>( + function_component_expression); + } + case 2: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyMatrix<2>>>>( + function_component_expression); + } + case 3: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TinyMatrix<3>>>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined parameter type", std::vector{m_node.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::string_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<std::string>>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, AggregateDataVariant>>( + function_component_expression); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + }; + + auto get_function_processor_for_expression_tuple_of_vector = + [&](const auto& tuple_content_v) -> std::unique_ptr<INodeProcessor> { + using TupleContentT = std::decay_t<decltype(tuple_content_v)>; + if constexpr (TupleContentT::Dimension == 1) { + switch (function_component_expression.m_data_type) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, bool>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, uint64_t>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, int64_t>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, double>>( + function_component_expression); + } + case ASTNodeDataType::vector_t: { + if (function_component_expression.m_data_type.dimension() == TupleContentT::Dimension) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TupleContentT>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, AggregateDataVariant>>( + function_component_expression); + } + case ASTNodeDataType::tuple_t: { + switch (function_component_expression.m_data_type.contentType()) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<bool>>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<uint64_t>>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<int64_t>>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<double>>>( + function_component_expression); + } + case ASTNodeDataType::vector_t: { + if (function_component_expression.m_data_type.contentType().dimension() == TupleContentT::Dimension) { + return std::make_unique< + FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TupleContentT>>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } else { + switch (function_component_expression.m_data_type) { + case ASTNodeDataType::int_t: { + if (function_component_expression.is_type<language::integer>()) { + if (std::stoi(function_component_expression.string()) == 0) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, ZeroType>>( + function_component_expression); + } + } + // LCOV_EXCL_START + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, AggregateDataVariant>>( + function_component_expression); + } + case ASTNodeDataType::vector_t: { + if (function_component_expression.m_data_type.dimension() == TupleContentT::Dimension) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TupleContentT>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::tuple_t: { + switch (function_component_expression.m_data_type.contentType()) { + case ASTNodeDataType::vector_t: { + if (function_component_expression.m_data_type.contentType().dimension() == TupleContentT::Dimension) { + return std::make_unique< + FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TupleContentT>>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + }; + + auto get_function_processor_for_expression_tuple_of_matrix = + [&](const auto& tuple_content_v) -> std::unique_ptr<INodeProcessor> { + using TupleContentT = std::decay_t<decltype(tuple_content_v)>; + static_assert(TupleContentT::NumberOfColumns == TupleContentT::NumberOfRows); + + if constexpr (TupleContentT::NumberOfRows == 1) { + switch (function_component_expression.m_data_type) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, bool>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, uint64_t>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, int64_t>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, double>>( + function_component_expression); + } + case ASTNodeDataType::matrix_t: { + if ((function_component_expression.m_data_type.numberOfRows() == TupleContentT::NumberOfRows) and + (function_component_expression.m_data_type.numberOfColumns() == TupleContentT::NumberOfColumns)) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TupleContentT>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid matrix_t dimensions", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, AggregateDataVariant>>( + function_component_expression); + } + case ASTNodeDataType::tuple_t: { + switch (function_component_expression.m_data_type.contentType()) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<bool>>>( + function_component_expression); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<uint64_t>>>( + function_component_expression); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<int64_t>>>( + function_component_expression); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<double>>>( + function_component_expression); + } + case ASTNodeDataType::matrix_t: { + if ((function_component_expression.m_data_type.contentType().numberOfRows() == + TupleContentT::NumberOfRows) and + (function_component_expression.m_data_type.contentType().numberOfColumns() == + TupleContentT::NumberOfColumns)) { + return std::make_unique< + FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TupleContentT>>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid matrix_t dimensions", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } else { + switch (function_component_expression.m_data_type) { + case ASTNodeDataType::int_t: { + if (function_component_expression.is_type<language::integer>()) { + if (std::stoi(function_component_expression.string()) == 0) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, ZeroType>>( + function_component_expression); + } + } + // LCOV_EXCL_START + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, AggregateDataVariant>>( + function_component_expression); + } + case ASTNodeDataType::matrix_t: { + if ((function_component_expression.m_data_type.numberOfColumns() == TupleContentT::NumberOfColumns) and + (function_component_expression.m_data_type.numberOfRows() == TupleContentT::NumberOfRows)) { + return std::make_unique<FunctionExpressionProcessor<std::vector<TupleContentT>, TupleContentT>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid matrix_t dimensions", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::tuple_t: { + switch (function_component_expression.m_data_type.contentType()) { + case ASTNodeDataType::matrix_t: { + if ((function_component_expression.m_data_type.contentType().numberOfColumns() == + TupleContentT::NumberOfColumns) and + (function_component_expression.m_data_type.contentType().numberOfRows() == TupleContentT::NumberOfRows)) { + return std::make_unique< + FunctionExpressionProcessor<std::vector<TupleContentT>, std::vector<TupleContentT>>>( + function_component_expression); + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid matrix_t dimensions", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + }; + + auto get_function_processor_for_expression_tuple = + [&](const auto& tuple_content_v) -> std::unique_ptr<INodeProcessor> { + switch (tuple_content_v) { + case ASTNodeDataType::vector_t: { + switch (tuple_content_v.dimension()) { + case 1: { + return get_function_processor_for_expression_tuple_of_vector(TinyVector<1>{}); + } + case 2: { + return get_function_processor_for_expression_tuple_of_vector(TinyVector<2>{}); + } + case 3: { + return get_function_processor_for_expression_tuple_of_vector(TinyVector<3>{}); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::matrix_t: { + if (tuple_content_v.numberOfRows() == tuple_content_v.numberOfColumns()) { + switch (tuple_content_v.numberOfRows()) { + case 1: { + return get_function_processor_for_expression_tuple_of_matrix(TinyMatrix<1>{}); + } + case 2: { + return get_function_processor_for_expression_tuple_of_matrix(TinyMatrix<2>{}); + } + case 3: { + return get_function_processor_for_expression_tuple_of_matrix(TinyMatrix<3>{}); + } + // LCOV_EXCL_START + default: { + throw ParseError("unexpected error: invalid vector_t dimension", + std::vector{function_component_expression.begin()}); + } + // LCOV_EXCL_STOP + } + } else { + // LCOV_EXCL_START + throw ParseError("unexpected error: invalid dimensions for returned matrix", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::bool_t: { + return get_function_processor_for_expression_tuple_of_value(bool{}); + } + case ASTNodeDataType::unsigned_int_t: { + return get_function_processor_for_expression_tuple_of_value(uint64_t{}); + } + case ASTNodeDataType::int_t: { + return get_function_processor_for_expression_tuple_of_value(int64_t{}); + } + case ASTNodeDataType::double_t: { + return get_function_processor_for_expression_tuple_of_value(double{}); + } + case ASTNodeDataType::type_id_t: { + return get_function_processor_for_expression_tuple_of_value(EmbeddedData{}); + } + case ASTNodeDataType::string_t: { + return get_function_processor_for_expression_tuple_of_value(std::string{}); + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid tuple content type"); + } + // LCOV_EXCL_STOP + } + }; + auto get_function_processor_for_value = [&]() { switch (return_value_type) { case ASTNodeDataType::bool_t: { @@ -516,6 +1063,9 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType& r } case ASTNodeDataType::type_id_t: { return get_function_processor_for_expression_type_id(return_value_type.nameOfTypeId()); + } + case ASTNodeDataType::tuple_t: { + return get_function_processor_for_expression_tuple(return_value_type.contentType()); } // LCOV_EXCL_START default: { @@ -548,6 +1098,9 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node } case ASTNodeDataType::type_id_t: { return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(image_domain_node.m_data_type.nameOfTypeId()); + } + case ASTNodeDataType::tuple_t: { + return ASTNodeDataType::build<ASTNodeDataType::tuple_t>(image_domain_node.m_data_type.contentType()); } // LCOV_EXCL_START default: { @@ -566,22 +1119,6 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1]; ASTNode& function_expression = *function_descriptor.definitionNode().children[1]; - const ASTNodeDataType function_return_type = [&] { - switch (function_image_domain.m_data_type) { - case ASTNodeDataType::typename_t: { - return function_image_domain.m_data_type.contentType(); - } - case ASTNodeDataType::type_id_t: { - return ASTNodeDataType::build<ASTNodeDataType::type_id_t>(function_image_domain.m_data_type.nameOfTypeId()); - } - // LCOV_EXCL_START - default: { - throw UnexpectedError("invalid function return type"); - } - // LCOV_EXCL_STOP - } - }(); - if (function_image_domain.is_type<language::vector_type>()) { ASTNodeDataType vector_type = getVectorDataType(function_image_domain); @@ -664,6 +1201,10 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node node.m_node_processor = std::move(function_processor); } + } else if (function_image_domain.is_type<language::tuple_type_specifier>()) { + add_component_expression(function_expression, function_image_domain); + + node.m_node_processor = std::move(function_processor); } else { if (function_expression.is_type<language::expression_list>()) { ASTNode& image_domain_node = function_image_domain; diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp index 5ec9c784508f92d9051e23d72e8cbd420712346c..ec499edb30589824b5578dbc0701db0b3639166b 100644 --- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.cpp @@ -9,6 +9,371 @@ #include <language/utils/AffectationMangler.hpp> #include <language/utils/OperatorRepository.hpp> +template <typename OperatorT, typename TupleContentType> +void +ASTNodeListAffectationExpressionBuilder::_buildListAffectationFromTupleProcessor( + ListAffectationFromTupleProcessor<OperatorT, TupleContentType>& list_affectation_processor) +{ + ASTNode& name_list_node = *m_node.children[0]; + for (size_t i = 0; i < name_list_node.children.size(); ++i) { + ASTNode& value_node = *name_list_node.children[i]; + if constexpr (std::is_same_v<TupleContentType, bool>) { + switch (value_node.m_data_type) { + case ASTNodeDataType::bool_t: { + list_affectation_processor.template add<bool>(value_node); + break; + } + case ASTNodeDataType::unsigned_int_t: { + list_affectation_processor.template add<uint64_t>(value_node); + break; + } + case ASTNodeDataType::int_t: { + list_affectation_processor.template add<int64_t>(value_node); + break; + } + case ASTNodeDataType::double_t: { + list_affectation_processor.template add<double>(value_node); + break; + } + case ASTNodeDataType::vector_t: { + if (value_node.m_data_type.dimension() == 1) { + list_affectation_processor.template add<TinyVector<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::matrix_t: { + if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) { + list_affectation_processor.template add<TinyMatrix<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + list_affectation_processor.template add<std::string>(value_node); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("incompatible tuple types in affectation"); + } + // LCOV_EXCL_STOP + } + } else if constexpr ((std::is_same_v<TupleContentType, uint64_t>) or (std::is_same_v<TupleContentType, int64_t>)) { + switch (value_node.m_data_type) { + case ASTNodeDataType::unsigned_int_t: { + list_affectation_processor.template add<uint64_t>(value_node); + break; + } + case ASTNodeDataType::int_t: { + list_affectation_processor.template add<int64_t>(value_node); + break; + } + case ASTNodeDataType::double_t: { + list_affectation_processor.template add<double>(value_node); + break; + } + case ASTNodeDataType::vector_t: { + if (value_node.m_data_type.dimension() == 1) { + list_affectation_processor.template add<TinyVector<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::matrix_t: { + if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) { + list_affectation_processor.template add<TinyMatrix<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + list_affectation_processor.template add<std::string>(value_node); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("incompatible tuple types in affectation"); + } + // LCOV_EXCL_STOP + } + } else if constexpr (std::is_same_v<TupleContentType, double>) { + switch (value_node.m_data_type) { + case ASTNodeDataType::double_t: { + list_affectation_processor.template add<double>(value_node); + break; + } + case ASTNodeDataType::vector_t: { + if (value_node.m_data_type.dimension() == 1) { + list_affectation_processor.template add<TinyVector<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::matrix_t: { + if ((value_node.m_data_type.numberOfRows() == 1) and (value_node.m_data_type.numberOfColumns() == 1)) { + list_affectation_processor.template add<TinyMatrix<1>>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + list_affectation_processor.template add<std::string>(value_node); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("incompatible tuple types in affectation"); + } + // LCOV_EXCL_STOP + } + } else if constexpr (is_tiny_vector_v<TupleContentType>) { + switch (value_node.m_data_type) { + case ASTNodeDataType::vector_t: { + if (value_node.m_data_type.dimension() == TupleContentType::Dimension) { + list_affectation_processor.template add<TupleContentType>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + list_affectation_processor.template add<std::string>(value_node); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("incompatible tuple types in affectation"); + } + // LCOV_EXCL_STOP + } + } else if constexpr (is_tiny_matrix_v<TupleContentType>) { + switch (value_node.m_data_type) { + case ASTNodeDataType::matrix_t: { + if ((value_node.m_data_type.numberOfRows() == TupleContentType::NumberOfRows) and + (value_node.m_data_type.numberOfColumns() == TupleContentType::NumberOfColumns)) { + list_affectation_processor.template add<TupleContentType>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid vector dimension"); + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + list_affectation_processor.template add<std::string>(value_node); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("incompatible tuple types in affectation"); + } + // LCOV_EXCL_STOP + } + } else if constexpr (std::is_same_v<std::string, TupleContentType>) { + if (value_node.m_data_type == ASTNodeDataType::string_t) { + list_affectation_processor.template add<std::string>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("incompatible tuple types in affectation"); + // LCOV_EXCL_STOP + } + } else if constexpr (std::is_same_v<EmbeddedData, TupleContentType>) { + if (value_node.m_data_type == ASTNodeDataType::type_id_t) { + list_affectation_processor.template add<EmbeddedData>(value_node); + } else { + // LCOV_EXCL_START + throw UnexpectedError("incompatible tuple types in affectation"); + // LCOV_EXCL_STOP + } + } else { + // LCOV_EXCL_START + throw UnexpectedError("incompatible tuple types in affectation"); + // LCOV_EXCL_STOP + } + } +} + +template <typename OperatorT> +void +ASTNodeListAffectationExpressionBuilder::_buildListAffectationFromTupleProcessor() +{ + auto& rhs = *m_node.children[1]; + + Assert(rhs.m_data_type == ASTNodeDataType::tuple_t); + + const ASTNodeSubDataType tuple_content_type{rhs.m_data_type.contentType(), rhs}; + + for (auto&& child : m_node.children[0]->children) { + if (child->m_data_type == ASTNodeDataType::tuple_t) { + throw ParseError("cannot affect a tuple to a compound type made of tuples", std::vector{child->begin()}); + } + + ASTNodeNaturalConversionChecker<AllowRToR1Conversion>(tuple_content_type, child->m_data_type); + } + + switch (rhs.m_data_type.contentType()) { + case ASTNodeDataType::bool_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, bool>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case ASTNodeDataType::unsigned_int_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, uint64_t>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case ASTNodeDataType::int_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, int64_t>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case ASTNodeDataType::double_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, double>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case ASTNodeDataType::vector_t: { + switch (rhs.m_data_type.contentType().dimension()) { + case 1: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<1>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case 2: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<2>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case 3: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyVector<3>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid vector dimension"); + } + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::matrix_t: { + if (rhs.m_data_type.contentType().numberOfColumns() != rhs.m_data_type.contentType().numberOfRows()) { + // LCOV_EXCL_START + throw UnexpectedError("invalid matrix dimensions"); + // LCOV_EXCL_STOP + } + switch (rhs.m_data_type.contentType().numberOfColumns()) { + case 1: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<1>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case 2: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<2>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case 3: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, TinyMatrix<3>>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid matrix dimensions"); + } + // LCOV_EXCL_STOP + } + break; + } + case ASTNodeDataType::string_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, std::string>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + case ASTNodeDataType::type_id_t: { + std::unique_ptr list_affectation_processor = + std::make_unique<ListAffectationFromTupleProcessor<OperatorT, EmbeddedData>>(m_node); + + this->_buildListAffectationFromTupleProcessor(*list_affectation_processor); + + m_node.m_node_processor = std::move(list_affectation_processor); + break; + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("undefined affectation type"); + } + // LCOV_EXCL_STOP + } +} + template <typename OperatorT> void ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( @@ -905,13 +1270,18 @@ ASTNodeListAffectationExpressionBuilder::_buildListAffectationProcessor() 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>()) { + node.children[1]->is_type<language::function_evaluation>() or + (node.children[1]->m_data_type == ASTNodeDataType::tuple_t)) { if (node.is_type<language::eq_op>()) { - this->_buildListAffectationProcessor<language::eq_op>(); + if (node.children[1]->m_data_type == ASTNodeDataType::tuple_t) { + this->_buildListAffectationFromTupleProcessor<language::eq_op>(); + } else { + this->_buildListAffectationProcessor<language::eq_op>(); + } } else { - throw ParseError("undefined affectation operator for tuples", std::vector{node.begin()}); + throw ParseError("undefined affectation operator for lists", std::vector{node.begin()}); } } else { - throw ParseError("invalid right hand side in tuple affectation", std::vector{node.children[1]->begin()}); + throw ParseError("invalid right hand side in list affectation", std::vector{node.children[1]->begin()}); } } diff --git a/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp b/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp index 50aaf94d27d364ecb5f40a3b125e09470c4b9d56..1cda4a94402b9d1803e0731484bf51a4eb8c2a14 100644 --- a/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp +++ b/src/language/ast/ASTNodeListAffectationExpressionBuilder.hpp @@ -4,6 +4,9 @@ #include <language/ast/ASTNode.hpp> #include <language/ast/ASTNodeSubDataType.hpp> +template <typename OperatorT, typename TupleType> +class ListAffectationFromTupleProcessor; + template <typename OperatorT> class ListAffectationProcessor; @@ -12,6 +15,12 @@ class ASTNodeListAffectationExpressionBuilder private: ASTNode& m_node; + template <typename OperatorT, typename TupleContentType> + void _buildListAffectationFromTupleProcessor(ListAffectationFromTupleProcessor<OperatorT, TupleContentType>&); + + template <typename OperatorT> + void _buildListAffectationFromTupleProcessor(); + template <typename OperatorT> void _buildAffectationProcessor(const ASTNodeSubDataType& rhs_node_sub_data_type, ASTNode& value_node, diff --git a/src/language/ast/ASTSymbolTableBuilder.cpp b/src/language/ast/ASTSymbolTableBuilder.cpp index 87baa5716cd36bd19db71e81e8e4398bfcb2e1fe..0fad55b80e7df5cdafb653fadbc08a5623818137 100644 --- a/src/language/ast/ASTSymbolTableBuilder.cpp +++ b/src/language/ast/ASTSymbolTableBuilder.cpp @@ -100,7 +100,9 @@ ASTSymbolTableBuilder::buildSymbolTable(ASTNode& n, std::shared_ptr<SymbolTable> i_symbol->attributes().setIsInitialized(); }; - if (n.children[0]->is_type<language::name>()) { + if (n.children[0]->is_type<language::empty_set>()) { + // nothing to do + } else if (n.children[0]->is_type<language::name>()) { register_and_initialize_symbol(*n.children[0]); } else { // treats the case of list of parameters Assert(n.children[0]->is_type<language::name_list>()); diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp index af1fca45e7dec5898a12731430358691728c7a2a..1f2d0ce4db829694dca9875593f168ebcac47b6a 100644 --- a/src/language/modules/MeshModule.cpp +++ b/src/language/modules/MeshModule.cpp @@ -5,6 +5,7 @@ #include <language/utils/BinaryOperatorProcessorBuilder.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/FunctionTable.hpp> +#include <language/utils/ItemArrayVariantFunctionInterpoler.hpp> #include <language/utils/ItemValueVariantFunctionInterpoler.hpp> #include <language/utils/OStream.hpp> #include <language/utils/OperatorRepository.hpp> @@ -17,6 +18,7 @@ #include <mesh/GmshReader.hpp> #include <mesh/IBoundaryDescriptor.hpp> #include <mesh/IZoneDescriptor.hpp> +#include <mesh/ItemArrayVariant.hpp> #include <mesh/ItemValueVariant.hpp> #include <mesh/Mesh.hpp> #include <mesh/MeshRelaxer.hpp> @@ -25,6 +27,7 @@ #include <mesh/NamedZoneDescriptor.hpp> #include <mesh/NumberedBoundaryDescriptor.hpp> #include <mesh/NumberedZoneDescriptor.hpp> +#include <mesh/SubItemArrayPerItemVariant.hpp> #include <mesh/SubItemValuePerItemVariant.hpp> #include <utils/Exceptions.hpp> @@ -39,7 +42,9 @@ MeshModule::MeshModule() this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const ItemType>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const ItemValueVariant>>); + this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const ItemArrayVariant>>); this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const SubItemValuePerItemVariant>>); + this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const SubItemArrayPerItemVariant>>); this->_addBuiltinFunction("cell", std::function( @@ -125,6 +130,17 @@ MeshModule::MeshModule() )); + this->_addBuiltinFunction( + "interpolate_array", + std::function( + + [](std::shared_ptr<const IMesh> mesh, std::shared_ptr<const ItemType> item_type, + const std::vector<FunctionSymbolId>& function_id_list) -> std::shared_ptr<const ItemArrayVariant> { + return ItemArrayVariantFunctionInterpoler{mesh, *item_type, function_id_list}.interpolate(); + } + + )); + this->_addBuiltinFunction("transform", std::function( [](std::shared_ptr<const IMesh> p_mesh, diff --git a/src/language/modules/MeshModule.hpp b/src/language/modules/MeshModule.hpp index bf9f0b714b327a1216f7ec3e54fc98a3ec65d70f..580f25aa839e2c1cc691247dd7359d8a6c1aa036 100644 --- a/src/language/modules/MeshModule.hpp +++ b/src/language/modules/MeshModule.hpp @@ -29,11 +29,21 @@ template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const ItemValueVariant>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("item_value"); +class ItemArrayVariant; +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const ItemArrayVariant>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("item_array"); + class SubItemValuePerItemVariant; template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const SubItemValuePerItemVariant>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("sub_item_value"); +class SubItemArrayPerItemVariant; +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const SubItemArrayPerItemVariant>> = + ASTNodeDataType::build<ASTNodeDataType::type_id_t>("sub_item_array"); + class MeshModule : public BuiltinModule { public: diff --git a/src/language/modules/WriterModule.cpp b/src/language/modules/WriterModule.cpp index aa479c0eb94005d59000d98dd460d8fedb89ab21..af7d0cb4b1cf50de79462a56d07f262cf1bf95ad 100644 --- a/src/language/modules/WriterModule.cpp +++ b/src/language/modules/WriterModule.cpp @@ -4,12 +4,14 @@ #include <language/utils/TypeDescriptor.hpp> #include <mesh/Connectivity.hpp> #include <mesh/GmshReader.hpp> +#include <mesh/ItemArrayVariant.hpp> #include <mesh/ItemValueVariant.hpp> #include <mesh/Mesh.hpp> #include <output/GnuplotWriter.hpp> #include <output/GnuplotWriter1D.hpp> #include <output/IWriter.hpp> #include <output/NamedDiscreteFunction.hpp> +#include <output/NamedItemArrayVariant.hpp> #include <output/NamedItemValueVariant.hpp> #include <output/VTKWriter.hpp> #include <scheme/DiscreteFunctionVariant.hpp> @@ -80,6 +82,7 @@ WriterModule::WriterModule() } )); + this->_addBuiltinFunction("name_output", std::function( [](std::shared_ptr<const ItemValueVariant> item_value_variant, @@ -90,6 +93,16 @@ WriterModule::WriterModule() )); + this->_addBuiltinFunction("name_output", std::function( + + [](std::shared_ptr<const ItemArrayVariant> item_array_variant, + const std::string& name) -> std::shared_ptr<const INamedDiscreteData> { + return std::make_shared<const NamedItemArrayVariant>(item_array_variant, + name); + } + + )); + this->_addBuiltinFunction("write_mesh", std::function( diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index f4c0d731a7a11ab91ffe7cb005bf14ebb5525dcf..8fea3a7546b9f96298e97b0603a849c84915f47a 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -82,7 +82,7 @@ struct AffOp<language::minuseq_op> struct IAffectationExecutor { - virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0; + virtual void affect(DataVariant&& rhs) = 0; IAffectationExecutor(const IAffectationExecutor&) = delete; IAffectationExecutor(IAffectationExecutor&&) = delete; @@ -101,9 +101,7 @@ class AffectationExecutor final : public IAffectationExecutor static inline const bool m_is_defined{[] { if constexpr (std::is_same_v<std::decay_t<ValueT>, bool>) { - if constexpr (not std::is_same_v<OperatorT, language::eq_op>) { - return false; - } + return std::is_same_v<OperatorT, language::eq_op>; } return true; }()}; @@ -119,7 +117,7 @@ class AffectationExecutor final : public IAffectationExecutor } PUGS_INLINE void - affect(ExecutionPolicy&, DataVariant&& rhs) + affect(DataVariant&& rhs) { if constexpr (m_is_defined) { if constexpr (not std::is_same_v<DataT, ZeroType>) { @@ -459,7 +457,7 @@ class AffectationProcessor final : public INodeProcessor execute(ExecutionPolicy& exec_policy) { try { - m_affectation_executor->affect(exec_policy, m_rhs_node.execute(exec_policy)); + m_affectation_executor->affect(m_rhs_node.execute(exec_policy)); } catch (std::domain_error& e) { throw ParseError(e.what(), m_rhs_node.begin()); @@ -550,20 +548,76 @@ class AffectationToTupleProcessor final : public AffectationToDataVariantProcess }; template <typename ValueT> -class AffectationToTupleFromListProcessor final : public AffectationToDataVariantProcessorBase +class AffectationFromTupleProcessor final : public AffectationToDataVariantProcessorBase { private: + ASTNode& m_lhs_node; ASTNode& m_rhs_node; - template <typename T> - std::string - stringify(const T& value) + public: + DataVariant + execute(ExecutionPolicy& exec_policy) { - std::ostringstream os; - os << std::boolalpha << value; - return os.str(); + DataVariant value = m_rhs_node.execute(exec_policy); + + try { + std::visit( + [&](auto&& v) { + using T = std::decay_t<decltype(v)>; + if constexpr (is_std_vector_v<T>) { + using TupleContentType = std::decay_t<typename T::value_type>; + if (v.size() == 1) { + if constexpr (std::is_same_v<TupleContentType, ValueT>) { + *m_lhs = std::move(static_cast<ValueT>(v[0])); + } else if constexpr (std::is_arithmetic_v<ValueT> and std::is_convertible_v<TupleContentType, ValueT>) { + if constexpr (std::is_same_v<uint64_t, ValueT> and std::is_same_v<int64_t, TupleContentType>) { + if (v[0] < 0) { + throw std::domain_error("trying to affect negative value (" + stringify(v[0]) + ")"); + } + } + *m_lhs = std::move(static_cast<ValueT>(v[0])); + } else if constexpr ((std::is_same_v<ValueT, TinyVector<1>> or + std::is_same_v<ValueT, TinyMatrix<1>>)and(std::is_arithmetic_v<TupleContentType>)) { + *m_lhs = std::move(ValueT(v[0])); + } else if constexpr (std::is_same_v<std::string, ValueT>) { + *m_lhs = std::move(stringify(static_cast<TupleContentType>(v[0]))); + } else { + // LCOV_EXCL_START + throw UnexpectedError("unexpected rhs tuple content"); + // LCOV_EXCL_STOP + } + } else { + std::ostringstream error_msg; + error_msg << "cannot affect a " << rang::fgB::yellow << dataTypeName(m_rhs_node.m_data_type) + << rang::fg::reset << " of size " << v.size() << " to a " << rang::fgB::yellow + << dataTypeName(m_lhs_node.m_data_type) << rang::fg::reset; + throw ParseError(error_msg.str(), m_rhs_node.begin()); + } + } else { + // LCOV_EXCL_START + throw UnexpectedError("right hand side must be a tuple"); + // LCOV_EXCL_STOP + } + }, + value); + } + catch (std::domain_error& e) { + throw ParseError(e.what(), m_rhs_node.begin()); + } + return {}; } + AffectationFromTupleProcessor(ASTNode& lhs_node, ASTNode& rhs_node) + : AffectationToDataVariantProcessorBase(lhs_node), m_lhs_node(lhs_node), m_rhs_node{rhs_node} + {} +}; + +template <typename ValueT> +class AffectationToTupleFromListProcessor final : public AffectationToDataVariantProcessorBase +{ + private: + ASTNode& m_rhs_node; + void _copyAggregateDataVariant(const AggregateDataVariant& children_values) { @@ -627,15 +681,48 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian *m_lhs = std::move(tuple_value); } + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + try { + std::visit( + [&](auto&& value_list) { + using ValueListT = std::decay_t<decltype(value_list)>; + if constexpr (std::is_same_v<AggregateDataVariant, ValueListT>) { + this->_copyAggregateDataVariant(value_list); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid rhs (expecting list)"); + // LCOV_EXCL_STOP + } + }, + m_rhs_node.execute(exec_policy)); + } + catch (std::domain_error& e) { + throw ParseError(e.what(), m_rhs_node.begin()); // LCOV_EXCL_LINE + } + return {}; + } + + AffectationToTupleFromListProcessor(ASTNode& lhs_node, ASTNode& rhs_node) + : AffectationToDataVariantProcessorBase(lhs_node), m_rhs_node{rhs_node} + {} +}; + +template <typename ValueT> +class AffectationToTupleFromTupleProcessor final : public AffectationToDataVariantProcessorBase +{ + private: + ASTNode& m_rhs_node; + template <typename DataType> void _copyVector(const std::vector<DataType>& values) { std::vector<ValueT> v(values.size()); if constexpr (std::is_same_v<ValueT, DataType>) { - for (size_t i = 0; i < values.size(); ++i) { - v[i] = values[i]; - } + v = std::move(values); } else if constexpr (std::is_arithmetic_v<ValueT> and std::is_convertible_v<DataType, ValueT>) { for (size_t i = 0; i < values.size(); ++i) { const DataType& vi = values[i]; @@ -646,6 +733,14 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian } v[i] = static_cast<DataType>(vi); } + } else if constexpr (std::is_same_v<TinyVector<1>, ValueT> and std::is_arithmetic_v<DataType>) { + for (size_t i = 0; i < values.size(); ++i) { + v[i][0] = values[i]; + } + } else if constexpr (std::is_same_v<TinyMatrix<1>, ValueT> and std::is_arithmetic_v<DataType>) { + for (size_t i = 0; i < values.size(); ++i) { + v[i](0, 0) = values[i]; + } } else if constexpr (std::is_same_v<ValueT, std::string>) { for (size_t i = 0; i < values.size(); ++i) { v[i] = std::move(stringify(values[i])); @@ -667,13 +762,11 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian std::visit( [&](auto&& value_list) { using ValueListT = std::decay_t<decltype(value_list)>; - if constexpr (std::is_same_v<AggregateDataVariant, ValueListT>) { - this->_copyAggregateDataVariant(value_list); - } else if constexpr (is_std_vector_v<ValueListT>) { + if constexpr (is_std_vector_v<ValueListT>) { this->_copyVector(value_list); } else { // LCOV_EXCL_START - throw UnexpectedError("invalid lhs (expecting list or tuple)"); + throw UnexpectedError("invalid rhs (expecting tuple)"); // LCOV_EXCL_STOP } }, @@ -685,7 +778,7 @@ class AffectationToTupleFromListProcessor final : public AffectationToDataVarian return {}; } - AffectationToTupleFromListProcessor(ASTNode& lhs_node, ASTNode& rhs_node) + AffectationToTupleFromTupleProcessor(ASTNode& lhs_node, ASTNode& rhs_node) : AffectationToDataVariantProcessorBase(lhs_node), m_rhs_node{rhs_node} {} }; @@ -744,7 +837,7 @@ class ListAffectationProcessor final : public INodeProcessor Assert(m_affectation_executor_list.size() == children_values.size()); for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) { try { - m_affectation_executor_list[i]->affect(exec_policy, std::move(children_values[i])); + m_affectation_executor_list[i]->affect(std::move(children_values[i])); } catch (std::domain_error& e) { throw ParseError(e.what(), m_node.children[1]->children[i]->begin()); @@ -756,4 +849,123 @@ class ListAffectationProcessor final : public INodeProcessor ListAffectationProcessor(ASTNode& node) : m_node{node} {} }; +struct IAffectationFromTupleExecutor +{ + virtual void affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) = 0; + + IAffectationFromTupleExecutor(const IAffectationFromTupleExecutor&) = delete; + IAffectationFromTupleExecutor(IAffectationFromTupleExecutor&&) = delete; + + IAffectationFromTupleExecutor() = default; + + virtual ~IAffectationFromTupleExecutor() = default; +}; + +template <typename OperatorT, typename ValueT, typename DataT> +class AffectationFromTupleExecutor final : public IAffectationFromTupleExecutor +{ + private: + DataVariant& m_lhs; + ASTNode& m_node; + + static_assert(std::is_same_v<OperatorT, language::eq_op>); + + public: + AffectationFromTupleExecutor(ASTNode& node, DataVariant& lhs) : m_lhs{lhs}, m_node{node} {} + + PUGS_INLINE void + affect(ExecutionPolicy&, DataVariant&& rhs) final + { + if constexpr (std::is_same_v<DataT, ValueT>) { + m_lhs = rhs; + } else if constexpr (std::is_convertible_v<DataT, ValueT>) { + const DataT& v = std::get<DataT>(rhs); + if constexpr (std::is_same_v<int64_t, DataT> and std::is_same_v<uint64_t, ValueT>) { + if (v < 0) { + throw std::domain_error("trying to affect negative value (" + stringify(v) + ")"); + } + } + m_lhs = static_cast<ValueT>(v); + } else if constexpr ((std::is_same_v<ValueT, TinyVector<1>>)and(std::is_arithmetic_v<DataT>)) { + m_lhs = std::move(ValueT(std::get<DataT>(rhs))); + } else if constexpr ((std::is_same_v<ValueT, TinyMatrix<1>>)and(std::is_arithmetic_v<DataT>)) { + m_lhs = std::move(ValueT(std::get<DataT>(rhs))); + } else if constexpr (std::is_same_v<ValueT, std::string>) { + m_lhs = std::move(stringify(std::get<DataT>(rhs))); + } else { + // LCOV_EXCL_START + throw UnexpectedError("incompatible types in affectation from tuple"); + // LCOV_EXCL_STOP + } + } +}; + +template <typename OperatorT, typename TupleContentType> +class ListAffectationFromTupleProcessor final : public INodeProcessor +{ + public: + static_assert(not is_std_vector_v<TupleContentType>); + + private: + ASTNode& m_node; + + std::vector<std::unique_ptr<IAffectationFromTupleExecutor>> m_affectation_executor_list; + + public: + template <typename ValueT> + void + add(ASTNode& lhs_node) + { + using DataT = std::decay_t<TupleContentType>; + + using AffectationExecutorT = AffectationFromTupleExecutor<OperatorT, ValueT, DataT>; + + if (lhs_node.is_type<language::name>()) { + const std::string& symbol = lhs_node.string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->end()); + Assert(found); + DataVariant& value = i_symbol->attributes().value(); + + if (not std::holds_alternative<ValueT>(value)) { + value = ValueT{}; + } + + m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, value)); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid left hand side"); + // LCOV_EXCL_STOP + } + } + + DataVariant + execute(ExecutionPolicy& exec_policy) + { + using TupleType = std::vector<TupleContentType>; + + TupleType tuple_values = std::move(std::get<TupleType>(m_node.children[1]->execute(exec_policy))); + + if (m_affectation_executor_list.size() == tuple_values.size()) { + for (size_t i = 0; i < m_affectation_executor_list.size(); ++i) { + try { + m_affectation_executor_list[i]->affect(exec_policy, + DataVariant(static_cast<TupleContentType>(tuple_values[i]))); + } + catch (std::domain_error& e) { + throw ParseError(e.what(), m_node.children[1]->begin()); + } + } + } else { + std::ostringstream error_msg; + error_msg << "cannot affect a " << rang::fgB::yellow << dataTypeName(m_node.children[1]->m_data_type) + << rang::fg::reset << " of size " << tuple_values.size() << " to a " << rang::fgB::yellow + << dataTypeName(m_node.children[0]->m_data_type) << rang::fg::reset; + throw ParseError(error_msg.str(), m_node.children[1]->begin()); + } + return {}; + } + + ListAffectationFromTupleProcessor(ASTNode& node) : m_node{node} {} +}; + #endif // AFFECTATION_PROCESSOR_HPP diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index 6a4075307e3af9f225cd493176fbd0a7873a3c75..36c5bab29c2517cffbec47476f2d74da55943667 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -131,8 +131,10 @@ class FunctionTinyVectorArgumentConverter final : public IFunctionArgumentConver std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value))); } } else { + // LCOV_EXCL_START throw UnexpectedError(std::string{"cannot convert '"} + demangle<ProvidedValueType>() + "' to '" + demangle<ExpectedValueType>() + "'"); + // LCOV_EXCL_STOP } return {}; } @@ -193,8 +195,10 @@ class FunctionTinyMatrixArgumentConverter final : public IFunctionArgumentConver std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value))); } } else { + // LCOV_EXCL_START throw UnexpectedError(std::string{"cannot convert '"} + demangle<ProvidedValueType>() + "' to '" + demangle<ExpectedValueType>() + "'"); + // LCOV_EXCL_STOP } return {}; diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp index bc8c3c0bdd6d9cd5a7e1b8fb91f7e21e3c45f8a8..2b3e65ecb130c6f50105a5cba08552e43e16596c 100644 --- a/src/language/node_processor/FunctionProcessor.hpp +++ b/src/language/node_processor/FunctionProcessor.hpp @@ -38,6 +38,224 @@ class FunctionExpressionProcessor final : public INodeProcessor (is_tiny_vector_v<ReturnType> or is_tiny_matrix_v<ReturnType>)) { static_assert(ReturnType::Dimension == 1, "invalid conversion"); return ReturnType(std::get<ExpressionValueType>(m_function_expression.execute(exec_policy))); + } else if constexpr (is_std_vector_v<ReturnType>) { + auto expression_value = m_function_expression.execute(exec_policy); + + const ExpressionValueType& v = std::get<ExpressionValueType>(expression_value); + + using TupleContentType = std::decay_t<typename ReturnType::value_type>; + + if constexpr (std::is_convertible_v<ExpressionValueType, TupleContentType>) { + if constexpr (std::is_same_v<TupleContentType, uint64_t> and std::is_same_v<ExpressionValueType, int64_t>) { + if (v < 0) { + throw std::domain_error("trying to convert negative value (" + stringify(v) + ")"); + } + } + return ReturnType{static_cast<TupleContentType>(v)}; + } else if constexpr (is_tiny_matrix_v<TupleContentType>) { + static_assert(ReturnType::value_type::NumberOfRows == ReturnType::value_type::NumberOfColumns); + if constexpr (ReturnType::value_type::NumberOfRows == 1) { + if constexpr (std::is_arithmetic_v<ExpressionValueType>) { + return ReturnType{TupleContentType(v)}; + } else if constexpr (std::is_same_v<ExpressionValueType, AggregateDataVariant>) { + ReturnType result(v.size()); + for (size_t i = 0; i < result.size(); ++i) { + std::visit( + [&](auto&& v_i) { + using ListElementType = std::decay_t<decltype(v_i)>; + if constexpr ((std::is_same_v<ListElementType, TupleContentType>) or + ((std::is_arithmetic_v<ListElementType>))) { + result[i] = static_cast<TupleContentType>(v_i); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + }, + v[i]); + } + return result; + } else { + static_assert(is_std_vector_v<ExpressionValueType>); + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + result[i] = static_cast<TupleContentType>(v[i]); + } + return result; + } + } else { + if constexpr (std::is_same_v<ExpressionValueType, int64_t>) { + return ReturnType{TupleContentType(ZeroType::zero)}; + } else if constexpr (std::is_same_v<ExpressionValueType, AggregateDataVariant>) { + ReturnType result(v.size()); + for (size_t i = 0; i < result.size(); ++i) { + std::visit( + [&](auto&& v_i) { + using ListElementType = std::decay_t<decltype(v_i)>; + if constexpr (std::is_same_v<ListElementType, TupleContentType>) { + result[i] = v_i; + } else if constexpr (std::is_same_v<ListElementType, int64_t>) { + result[i] = ZeroType::zero; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + }, + v[i]); + } + return result; + } else if constexpr (is_std_vector_v<ExpressionValueType>) { + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + if constexpr (std::is_same_v<typename ExpressionValueType::value_type, TupleContentType>) { + result[i] = v[i]; + } else if constexpr (std::is_same_v<typename ExpressionValueType::value_type, int64_t>) { + result[i] = ZeroType::zero; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + } + return result; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid expression value"); + // LCOV_EXCL_STOP + } + } + } else if constexpr (is_tiny_vector_v<TupleContentType>) { + if constexpr (ReturnType::value_type::Dimension == 1) { + if constexpr (std::is_arithmetic_v<ExpressionValueType>) { + return ReturnType{TupleContentType(v)}; + } else if constexpr (std::is_same_v<ExpressionValueType, AggregateDataVariant>) { + ReturnType result(v.size()); + for (size_t i = 0; i < result.size(); ++i) { + std::visit( + [&](auto&& v_i) { + using ListElementType = std::decay_t<decltype(v_i)>; + if constexpr ((std::is_same_v<ListElementType, TupleContentType>) or + ((std::is_arithmetic_v<ListElementType>))) { + result[i] = static_cast<TupleContentType>(v_i); + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + }, + v[i]); + } + return result; + } else { + static_assert(is_std_vector_v<ExpressionValueType>); + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + result[i] = static_cast<TupleContentType>(v[i]); + } + return result; + } + } else { + if constexpr (std::is_same_v<ExpressionValueType, int64_t>) { + return ReturnType{TupleContentType(ZeroType::zero)}; + } else if constexpr (std::is_same_v<ExpressionValueType, AggregateDataVariant>) { + ReturnType result(v.size()); + for (size_t i = 0; i < result.size(); ++i) { + std::visit( + [&](auto&& v_i) { + using ListElementType = std::decay_t<decltype(v_i)>; + if constexpr (std::is_same_v<ListElementType, TupleContentType>) { + result[i] = v_i; + } else if constexpr (std::is_same_v<ListElementType, int64_t>) { + result[i] = ZeroType::zero; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + }, + v[i]); + } + return result; + } else if constexpr (is_std_vector_v<ExpressionValueType>) { + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + if constexpr (std::is_same_v<typename ExpressionValueType::value_type, TupleContentType>) { + result[i] = v[i]; + } else if constexpr (std::is_same_v<typename ExpressionValueType::value_type, int64_t>) { + result[i] = ZeroType::zero; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid tuple element type"); + // LCOV_EXCL_STOP + } + } + return result; + } + } + // LCOV_EXCL_START + throw UnexpectedError("invalid expression type"); + // LCOV_EXCL_STOP + } else if constexpr (std::is_same_v<TupleContentType, std::string>) { + return ReturnType{stringify(v)}; + } else if constexpr (is_std_vector_v<ExpressionValueType>) { + using ExpressionContentType = typename ExpressionValueType::value_type; + if constexpr (std::is_convertible_v<ExpressionContentType, TupleContentType>) { + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + if constexpr (std::is_same_v<TupleContentType, uint64_t> and + std::is_same_v<ExpressionContentType, int64_t>) { + if (v[i] < 0) { + throw std::domain_error("trying to convert negative value (" + stringify(v[i]) + ")"); + } + } + result[i] = v[i]; + } + return result; + } else if constexpr (std::is_same_v<TupleContentType, std::string>) { + ReturnType result(v.size()); + for (size_t i = 0; i < v.size(); ++i) { + result[i] = stringify(v[i]); + } + return result; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid tuple type"); + // LCOV_EXCL_STOP + } + } else if constexpr (std::is_same_v<AggregateDataVariant, ExpressionValueType>) { + ReturnType result(v.size()); + for (size_t i = 0; i < result.size(); ++i) { + std::visit( + [&](auto&& v_i) { + using ListElementType = std::decay_t<decltype(v_i)>; + if constexpr (std::is_convertible_v<ListElementType, TupleContentType>) { + if constexpr (std::is_same_v<TupleContentType, uint64_t> and std::is_same_v<ListElementType, int64_t>) { + if (v_i < 0) { + throw std::domain_error("trying to convert negative value (" + stringify(v_i) + ")"); + } + } + result[i] = static_cast<TupleContentType>(v_i); + } else if constexpr (std::is_same_v<TupleContentType, std::string>) { + if constexpr (std::is_same_v<ListElementType, std::string>) { + result[i] = std::move(v_i); + } else { + result[i] = stringify(v_i); + } + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid list element type"); + // LCOV_EXCL_STOP + } + }, + v[i]); + } + return result; + } else { + // LCOV_EXCL_START + throw UnexpectedError("invalid tuple type"); + // LCOV_EXCL_STOP + } } else { // LCOV_EXCL_START throw UnexpectedError("invalid conversion"); diff --git a/src/language/utils/AffectationMangler.hpp b/src/language/utils/AffectationMangler.hpp index 85aaab35bfbabde5b9bdbc9b250f8440e68829e6..42592a091d1e1792f99d3d76e5af0d167732aeba 100644 --- a/src/language/utils/AffectationMangler.hpp +++ b/src/language/utils/AffectationMangler.hpp @@ -40,8 +40,6 @@ affectationMangler(const ASTNodeDataType& lhs, const ASTNodeDataType& rhs) const std::string rhs_name = [&]() -> std::string { if (rhs == ASTNodeDataType::list_t) { return "list"; - } else if (rhs == ASTNodeDataType::tuple_t) { - return "tuple"; } else { return dataTypeName(rhs); } diff --git a/src/language/utils/AffectationProcessorBuilder.hpp b/src/language/utils/AffectationProcessorBuilder.hpp index cc66971b2ccfbcc4a9a16ae708121c7905a1478b..6b5ff55841863b9e93afd8a12498bf306e4d51f4 100644 --- a/src/language/utils/AffectationProcessorBuilder.hpp +++ b/src/language/utils/AffectationProcessorBuilder.hpp @@ -44,6 +44,18 @@ class AffectationToTupleProcessorBuilder final : public IAffectationProcessorBui } }; +template <typename ValueT> +class AffectationFromTupleProcessorBuilder final : public IAffectationProcessorBuilder +{ + public: + AffectationFromTupleProcessorBuilder() = default; + std::unique_ptr<INodeProcessor> + getNodeProcessor(ASTNode& lhs_node, ASTNode& rhs_node) const final + { + return std::make_unique<AffectationFromTupleProcessor<ValueT>>(lhs_node, rhs_node); + } +}; + template <typename ValueT> class AffectationToTupleFromListProcessorBuilder final : public IAffectationProcessorBuilder { @@ -57,6 +69,19 @@ class AffectationToTupleFromListProcessorBuilder final : public IAffectationProc } }; +template <typename ValueT> +class AffectationToTupleFromTupleProcessorBuilder final : public IAffectationProcessorBuilder +{ + public: + AffectationToTupleFromTupleProcessorBuilder() = default; + std::unique_ptr<INodeProcessor> + getNodeProcessor(ASTNode& lhs_node, ASTNode& rhs_node) const final + { + ASTNodeNaturalConversionChecker<AllowRToR1Conversion>(rhs_node, lhs_node.m_data_type); + return std::make_unique<AffectationToTupleFromTupleProcessor<ValueT>>(lhs_node, rhs_node); + } +}; + template <typename OperatorT, typename ValueT> class AffectationFromZeroProcessorBuilder final : public IAffectationProcessorBuilder { diff --git a/src/language/utils/AffectationRegisterForN.cpp b/src/language/utils/AffectationRegisterForN.cpp index 64f93ad0f74da6490b636c3643de62bcf7afc0fc..9340545ea3320cca700b61076a5fce2ed8d9e166 100644 --- a/src/language/utils/AffectationRegisterForN.cpp +++ b/src/language/utils/AffectationRegisterForN.cpp @@ -9,23 +9,36 @@ AffectationRegisterForN::_register_eq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository - .addAffectation<language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + .addAffectation<language::eq_op>(N, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, uint64_t, bool>>()); repository.addAffectation< - language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(), - std::make_shared<AffectationProcessorBuilder<language::eq_op, uint64_t, int64_t>>()); + language::eq_op>(N, Z, std::make_shared<AffectationProcessorBuilder<language::eq_op, uint64_t, int64_t>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), B, std::make_shared<AffectationToTupleProcessorBuilder<uint64_t>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), Z, std::make_shared<AffectationToTupleProcessorBuilder<uint64_t>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<uint64_t>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<uint64_t>>()); + + repository.addAffectation<language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<uint64_t>>()); + + repository.addAffectation<language::eq_op>(N, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationFromTupleProcessorBuilder<uint64_t>>()); } void @@ -33,19 +46,19 @@ AffectationRegisterForN::_register_pluseq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository.addAffectation< - language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), - std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, bool>>()); + language::pluseq_op>(N, B, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, bool>>()); repository.addAffectation< - language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::pluseq_op>(N, N, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, uint64_t>>()); repository.addAffectation< - language::pluseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(), - std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, int64_t>>()); + language::pluseq_op>(N, Z, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, uint64_t, int64_t>>()); } void @@ -53,18 +66,19 @@ AffectationRegisterForN::_register_minuseq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository.addAffectation< - language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), - std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, bool>>()); + language::minuseq_op>(N, B, std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, bool>>()); repository.addAffectation< - language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::minuseq_op>(N, N, std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, uint64_t>>()); repository.addAffectation< - language::minuseq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::minuseq_op>(N, Z, std::make_shared<AffectationProcessorBuilder<language::minuseq_op, uint64_t, int64_t>>()); } @@ -73,17 +87,19 @@ AffectationRegisterForN::_register_multiplyeq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository.addAffectation< - language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + language::multiplyeq_op>(N, B, std::make_shared<AffectationProcessorBuilder<language::multiplyeq_op, uint64_t, bool>>()); - repository.addAffectation<language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::multiplyeq_op>(N, N, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, uint64_t, uint64_t>>()); - repository.addAffectation<language::multiplyeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::multiplyeq_op>(N, Z, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, uint64_t, int64_t>>()); } @@ -94,13 +110,14 @@ AffectationRegisterForN::_register_divideeq_op() OperatorRepository& repository = OperatorRepository::instance(); auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository.addAffectation< - language::divideeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::divideeq_op>(N, N, std::make_shared<AffectationProcessorBuilder<language::divideeq_op, uint64_t, uint64_t>>()); repository.addAffectation< - language::divideeq_op>(N, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::divideeq_op>(N, Z, std::make_shared<AffectationProcessorBuilder<language::divideeq_op, uint64_t, int64_t>>()); } diff --git a/src/language/utils/AffectationRegisterForR.cpp b/src/language/utils/AffectationRegisterForR.cpp index 7959b35b3d2119a8b6930cc6d4beb7d61f115da8..409e66815396bb9c539874ef114e6ef8e0e6688e 100644 --- a/src/language/utils/AffectationRegisterForR.cpp +++ b/src/language/utils/AffectationRegisterForR.cpp @@ -9,31 +9,51 @@ AffectationRegisterForR::_register_eq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); repository - .addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + .addAffectation<language::eq_op>(R, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, double, bool>>()); repository.addAffectation< - language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), - std::make_shared<AffectationProcessorBuilder<language::eq_op, double, uint64_t>>()); + language::eq_op>(R, N, std::make_shared<AffectationProcessorBuilder<language::eq_op, double, uint64_t>>()); repository - .addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + .addAffectation<language::eq_op>(R, Z, std::make_shared<AffectationProcessorBuilder<language::eq_op, double, int64_t>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), B, std::make_shared<AffectationToTupleProcessorBuilder<double>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), - ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), N, std::make_shared<AffectationToTupleProcessorBuilder<double>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), Z, std::make_shared<AffectationToTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationFromTupleProcessorBuilder<double>>()); + + repository.addAffectation<language::eq_op>(R, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationFromTupleProcessorBuilder<double>>()); } void diff --git a/src/language/utils/AffectationRegisterForRn.cpp b/src/language/utils/AffectationRegisterForRn.cpp index 180bd5ebce8d19dd8aa6f4b628a700632ea44ab0..9850970f3556a91ace84bb603fe54c55a9329ee2 100644 --- a/src/language/utils/AffectationRegisterForRn.cpp +++ b/src/language/utils/AffectationRegisterForRn.cpp @@ -11,14 +11,14 @@ AffectationRegisterForRn<Dimension>::_register_eq_op() OperatorRepository& repository = OperatorRepository::instance(); auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository.addAffectation< - language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::eq_op>(Rn, Z, std::make_shared<AffectationFromZeroProcessorBuilder<language::eq_op, TinyVector<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), Z, std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); } @@ -30,43 +30,80 @@ AffectationRegisterForRn<1>::_register_eq_op() OperatorRepository& repository = OperatorRepository::instance(); - auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + + auto R1 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension); repository.addAffectation< - language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + language::eq_op>(R1, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, bool>>()); repository.addAffectation< - language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::eq_op>(R1, N, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, uint64_t>>()); repository.addAffectation< - language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::eq_op>(R1, Z, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, int64_t>>()); repository.addAffectation< - language::eq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + language::eq_op>(R1, R, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyVector<Dimension>, double>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), B, std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), - ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), N, std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), Z, std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rn), - ASTNodeDataType::build<ASTNodeDataType::double_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), R, std::make_shared<AffectationToTupleProcessorBuilder<TinyVector<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyVector<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyVector<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyVector<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyVector<1>>>()); + + repository + .addAffectation<language::eq_op>(R1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyVector<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyVector<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyVector<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyVector<Dimension>>>()); } template <size_t Dimension> @@ -105,19 +142,24 @@ AffectationRegisterForRn<Dimension>::_register_multiplyeq_op() auto Rn = ASTNodeDataType::build<ASTNodeDataType::vector_t>(Dimension); - repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + + repository.addAffectation<language::multiplyeq_op>(Rn, B, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyVector<Dimension>, bool>>()); - repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::multiplyeq_op>(Rn, N, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyVector<Dimension>, uint64_t>>()); - repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::multiplyeq_op>(Rn, Z, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyVector<Dimension>, int64_t>>()); - repository.addAffectation<language::multiplyeq_op>(Rn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + repository.addAffectation<language::multiplyeq_op>(Rn, R, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyVector<Dimension>, double>>()); } diff --git a/src/language/utils/AffectationRegisterForRnxn.cpp b/src/language/utils/AffectationRegisterForRnxn.cpp index 0eaf1c6af2e0caccf0fa143208c774a047d6e550..04cb101667497c55002bae68d4c7727d49f4b3d6 100644 --- a/src/language/utils/AffectationRegisterForRnxn.cpp +++ b/src/language/utils/AffectationRegisterForRnxn.cpp @@ -10,15 +10,16 @@ AffectationRegisterForRnxn<Dimension>::_register_eq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); repository.addAffectation< - language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::eq_op>(Rnxn, Z, std::make_shared<AffectationFromZeroProcessorBuilder<language::eq_op, TinyMatrix<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), Z, std::make_shared<AffectationToTupleProcessorBuilder<TinyMatrix<Dimension>>>()); } @@ -30,43 +31,80 @@ AffectationRegisterForRnxn<1>::_register_eq_op() OperatorRepository& repository = OperatorRepository::instance(); - auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + + auto R1x1 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); repository.addAffectation< - language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + language::eq_op>(R1x1, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, bool>>()); repository.addAffectation< - language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::eq_op>(R1x1, N, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, uint64_t>>()); repository.addAffectation< - language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::eq_op>(R1x1, Z, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, int64_t>>()); repository.addAffectation< - language::eq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + language::eq_op>(R1x1, R, std::make_shared<AffectationProcessorBuilder<language::eq_op, TinyMatrix<Dimension>, double>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), B, std::make_shared<AffectationToTupleProcessorBuilder<TinyMatrix<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), - ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), N, std::make_shared<AffectationToTupleProcessorBuilder<TinyMatrix<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), Z, std::make_shared<AffectationToTupleProcessorBuilder<TinyMatrix<Dimension>>>()); repository - .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Rnxn), - ASTNodeDataType::build<ASTNodeDataType::double_t>(), + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), R, std::make_shared<AffectationToTupleProcessorBuilder<TinyMatrix<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyMatrix<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyMatrix<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyMatrix<1>>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<TinyMatrix<1>>>()); + + repository + .addAffectation<language::eq_op>(R1x1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyMatrix<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1x1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyMatrix<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1x1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyMatrix<Dimension>>>()); + + repository + .addAffectation<language::eq_op>(R1x1, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationFromTupleProcessorBuilder<TinyMatrix<Dimension>>>()); } template <size_t Dimension> @@ -103,21 +141,26 @@ AffectationRegisterForRnxn<Dimension>::_register_multiplyeq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + auto Rnxn = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(Dimension, Dimension); - repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + repository.addAffectation<language::multiplyeq_op>(Rnxn, B, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyMatrix<Dimension>, bool>>()); - repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::multiplyeq_op>(Rnxn, N, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyMatrix<Dimension>, uint64_t>>()); - repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::multiplyeq_op>(Rnxn, Z, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyMatrix<Dimension>, int64_t>>()); - repository.addAffectation<language::multiplyeq_op>(Rnxn, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + repository.addAffectation<language::multiplyeq_op>(Rnxn, R, std::make_shared<AffectationProcessorBuilder< language::multiplyeq_op, TinyMatrix<Dimension>, double>>()); } diff --git a/src/language/utils/AffectationRegisterForString.cpp b/src/language/utils/AffectationRegisterForString.cpp index 7946aeb45fc72e7569e5d8299e184c220baa7106..d9177dc7fc72c65f058a9537e4c1ee12c71d29cb 100644 --- a/src/language/utils/AffectationRegisterForString.cpp +++ b/src/language/utils/AffectationRegisterForString.cpp @@ -9,87 +9,166 @@ AffectationRegisterForString::_register_eq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + auto R1 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1); + auto R2 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2); + auto R3 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3); + auto R1x1 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1); + auto R2x2 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2); + auto R3x3 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3); + auto string_t = ASTNodeDataType::build<ASTNodeDataType::string_t>(); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), - std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, bool>>()); + language::eq_op>(string_t, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, bool>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::eq_op>(string_t, N, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, uint64_t>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::eq_op>(string_t, Z, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, int64_t>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + language::eq_op>(string_t, R, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, double_t>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), + language::eq_op>(string_t, R1, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<1>>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2), + language::eq_op>(string_t, R2, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<2>>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3), + language::eq_op>(string_t, R3, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyVector<3>>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1), + language::eq_op>(string_t, R1x1, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyMatrix<1>>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2), + language::eq_op>(string_t, R2x2, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyMatrix<2>>>()); repository.addAffectation< - language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3), + language::eq_op>(string_t, R3x3, std::make_shared<AffectationProcessorBuilder<language::eq_op, std::string, TinyMatrix<3>>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), B, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), N, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), Z, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::double_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R1, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::vector_t>(2), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R2, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::vector_t>(3), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R3, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R1x1, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R2x2, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), - ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), R3x3, std::make_shared<AffectationToTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2x2), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository + .addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_t), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3x3), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1x1), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2x2), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); + + repository.addAffectation<language::eq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3x3), + std::make_shared<AffectationFromTupleProcessorBuilder<std::string>>()); } void @@ -97,6 +176,17 @@ AffectationRegisterForString::_register_pluseq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); + auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); + auto R = ASTNodeDataType::build<ASTNodeDataType::double_t>(); + auto R1 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1); + auto R2 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2); + auto R3 = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3); + auto R1x1 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1); + auto R2x2 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2); + auto R3x3 = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3); + auto string_t = ASTNodeDataType::build<ASTNodeDataType::string_t>(); repository.addAffectation<language::pluseq_op>(string_t, string_t, @@ -104,42 +194,42 @@ AffectationRegisterForString::_register_pluseq_op() language::pluseq_op, std::string, std::string>>()); repository.addAffectation< - language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + language::pluseq_op>(string_t, B, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, bool>>()); repository.addAffectation< - language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + language::pluseq_op>(string_t, N, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, uint64_t>>()); repository.addAffectation< - language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::int_t>(), + language::pluseq_op>(string_t, Z, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, int64_t>>()); repository.addAffectation< - language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::double_t>(), + language::pluseq_op>(string_t, R, std::make_shared<AffectationProcessorBuilder<language::pluseq_op, std::string, double>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1), + repository.addAffectation<language::pluseq_op>(string_t, R1, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyVector<1>>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2), + repository.addAffectation<language::pluseq_op>(string_t, R2, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyVector<2>>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3), + repository.addAffectation<language::pluseq_op>(string_t, R3, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyVector<3>>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1), + repository.addAffectation<language::pluseq_op>(string_t, R1x1, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyMatrix<1>>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2), + repository.addAffectation<language::pluseq_op>(string_t, R2x2, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyMatrix<2>>>()); - repository.addAffectation<language::pluseq_op>(string_t, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3), + repository.addAffectation<language::pluseq_op>(string_t, R3x3, std::make_shared<AffectationProcessorBuilder< language::pluseq_op, std::string, TinyMatrix<3>>>()); } diff --git a/src/language/utils/AffectationRegisterForZ.cpp b/src/language/utils/AffectationRegisterForZ.cpp index 09c493e711cf96b913607da732da7dd9ef937bc5..648c680c23eb7a0c51d61d44aca2c75ee170c4ab 100644 --- a/src/language/utils/AffectationRegisterForZ.cpp +++ b/src/language/utils/AffectationRegisterForZ.cpp @@ -9,23 +9,36 @@ AffectationRegisterForZ::_register_eq_op() { OperatorRepository& repository = OperatorRepository::instance(); + auto B = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto N = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(); auto Z = ASTNodeDataType::build<ASTNodeDataType::int_t>(); repository - .addAffectation<language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + .addAffectation<language::eq_op>(Z, B, std::make_shared<AffectationProcessorBuilder<language::eq_op, int64_t, bool>>()); repository.addAffectation< - language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), - std::make_shared<AffectationProcessorBuilder<language::eq_op, int64_t, uint64_t>>()); + language::eq_op>(Z, N, std::make_shared<AffectationProcessorBuilder<language::eq_op, int64_t, uint64_t>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), - ASTNodeDataType::build<ASTNodeDataType::bool_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), B, std::make_shared<AffectationToTupleProcessorBuilder<int64_t>>()); - repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), - ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>(), + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), N, std::make_shared<AffectationToTupleProcessorBuilder<int64_t>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<int64_t>>()); + + repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(Z), + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<int64_t>>()); + + repository.addAffectation<language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(B), + std::make_shared<AffectationFromTupleProcessorBuilder<int64_t>>()); + + repository.addAffectation<language::eq_op>(Z, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(N), + std::make_shared<AffectationFromTupleProcessorBuilder<int64_t>>()); } void diff --git a/src/language/utils/BasicAffectationRegistrerFor.hpp b/src/language/utils/BasicAffectationRegistrerFor.hpp index ccae4c32b596b39ce7b663da38e31e70c8dfbebc..72569803014412bc9e7e556fb5ea8fb6e024ff54 100644 --- a/src/language/utils/BasicAffectationRegistrerFor.hpp +++ b/src/language/utils/BasicAffectationRegistrerFor.hpp @@ -29,7 +29,11 @@ class BasicAffectationRegisterFor repository.addAffectation<language::eq_op>(ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type), ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type), - std::make_shared<AffectationToTupleFromListProcessorBuilder<T>>()); + std::make_shared<AffectationToTupleFromTupleProcessorBuilder<T>>()); + + repository.addAffectation<language::eq_op>(ast_node_data_type, + ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ast_node_data_type), + std::make_shared<AffectationFromTupleProcessorBuilder<T>>()); } }; diff --git a/src/language/utils/CMakeLists.txt b/src/language/utils/CMakeLists.txt index a81ffa8aecdf7af0085296b181f2b3ec4d63238f..db3e7856b758b6a4822d97ac0330958b3b367176 100644 --- a/src/language/utils/CMakeLists.txt +++ b/src/language/utils/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(PugsLanguageUtils FunctionSymbolId.cpp IncDecOperatorRegisterForN.cpp IncDecOperatorRegisterForZ.cpp + ItemArrayVariantFunctionInterpoler.cpp ItemValueVariantFunctionInterpoler.cpp OFStream.cpp OperatorRepository.cpp diff --git a/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp index 3d820c561f623d01967c6a4d947eaa91a531e183..ea842f84c24276323f8aa61865e8d1de470ef10d 100644 --- a/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp +++ b/src/language/utils/EmbeddedDiscreteFunctionMathFunctions.cpp @@ -276,7 +276,7 @@ dot(const std::shared_ptr<const DiscreteFunctionVariant>& f, const TinyVector<Ve throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); } } else { - throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(f, a)); } }, f->discreteFunction()); @@ -301,7 +301,7 @@ dot(const TinyVector<VectorDimension>& a, const std::shared_ptr<const DiscreteFu throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); } } else { - throw NormalError(EmbeddedDiscreteFunctionUtils::invalidOperandType(f)); + throw NormalError(EmbeddedDiscreteFunctionUtils::incompatibleOperandTypes(a, f)); } }, f->discreteFunction()); @@ -541,7 +541,9 @@ vectorize_to(const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& } } else { - throw NormalError("discrete functions are not defined on the same mesh"); + // LCOV_EXCL_START + throw UnexpectedError("discrete functions are not defined on the same mesh"); + // LCOV_EXCL_STOP } } diff --git a/src/language/utils/ItemArrayVariantFunctionInterpoler.cpp b/src/language/utils/ItemArrayVariantFunctionInterpoler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02d47d399ed9ec0fdb570fc3877b0b384f7a5429 --- /dev/null +++ b/src/language/utils/ItemArrayVariantFunctionInterpoler.cpp @@ -0,0 +1,159 @@ +#include <language/utils/ItemArrayVariantFunctionInterpoler.hpp> + +#include <language/utils/InterpolateItemArray.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/ItemArrayVariant.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/MeshData.hpp> +#include <mesh/MeshDataManager.hpp> +#include <utils/Exceptions.hpp> + +#include <memory> + +template <size_t Dimension, typename DataType, typename ArrayType> +std::shared_ptr<ItemArrayVariant> +ItemArrayVariantFunctionInterpoler::_interpolate() const +{ + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(m_mesh); + using MeshDataType = MeshData<Dimension>; + + switch (m_item_type) { + case ItemType::cell: { + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*p_mesh); + return std::make_shared<ItemArrayVariant>( + InterpolateItemArray<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(m_function_id_list, + mesh_data.xj())); + } + case ItemType::face: { + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*p_mesh); + return std::make_shared<ItemArrayVariant>( + InterpolateItemArray<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::face>(m_function_id_list, + mesh_data.xl())); + } + case ItemType::edge: { + MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*p_mesh); + return std::make_shared<ItemArrayVariant>( + InterpolateItemArray<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::edge>(m_function_id_list, + mesh_data.xe())); + } + case ItemType::node: { + return std::make_shared<ItemArrayVariant>( + InterpolateItemArray<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::node>(m_function_id_list, + p_mesh->xr())); + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid item type"); + } + // LCOV_EXCL_STOP + } +} + +template <size_t Dimension> +std::shared_ptr<ItemArrayVariant> +ItemArrayVariantFunctionInterpoler::_interpolate() const +{ + const ASTNodeDataType data_type = [&] { + const auto& function0_descriptor = m_function_id_list[0].descriptor(); + Assert(function0_descriptor.domainMappingNode().children[1]->m_data_type == ASTNodeDataType::typename_t); + + ASTNodeDataType data_type = function0_descriptor.domainMappingNode().children[1]->m_data_type.contentType(); + + for (size_t i = 1; i < m_function_id_list.size(); ++i) { + const auto& function_descriptor = m_function_id_list[i].descriptor(); + Assert(function_descriptor.domainMappingNode().children[1]->m_data_type == ASTNodeDataType::typename_t); + if (data_type != function_descriptor.domainMappingNode().children[1]->m_data_type.contentType()) { + throw NormalError("functions must have the same type"); + } + } + + return data_type; + }(); + + switch (data_type) { + case ASTNodeDataType::bool_t: { + return this->_interpolate<Dimension, bool>(); + } + case ASTNodeDataType::unsigned_int_t: { + return this->_interpolate<Dimension, uint64_t>(); + } + case ASTNodeDataType::int_t: { + return this->_interpolate<Dimension, int64_t>(); + } + case ASTNodeDataType::double_t: { + return this->_interpolate<Dimension, double>(); + } + case ASTNodeDataType::vector_t: { + switch (data_type.dimension()) { + case 1: { + return this->_interpolate<Dimension, TinyVector<1>>(); + } + case 2: { + return this->_interpolate<Dimension, TinyVector<2>>(); + } + case 3: { + return this->_interpolate<Dimension, TinyVector<3>>(); + } + // LCOV_EXCL_START + default: { + std::ostringstream os; + os << "invalid vector dimension " << rang::fgB::red << data_type.dimension() << rang::style::reset; + + throw UnexpectedError(os.str()); + } + // LCOV_EXCL_STOP + } + } + case ASTNodeDataType::matrix_t: { + Assert(data_type.numberOfColumns() == data_type.numberOfRows(), "undefined matrix type"); + switch (data_type.numberOfColumns()) { + case 1: { + return this->_interpolate<Dimension, TinyMatrix<1>>(); + } + case 2: { + return this->_interpolate<Dimension, TinyMatrix<2>>(); + } + case 3: { + return this->_interpolate<Dimension, TinyMatrix<3>>(); + } + // LCOV_EXCL_START + default: { + std::ostringstream os; + os << "invalid vector dimension " << rang::fgB::red << data_type.dimension() << rang::style::reset; + + throw UnexpectedError(os.str()); + } + // LCOV_EXCL_STOP + } + } + // LCOV_EXCL_START + default: { + std::ostringstream os; + os << "invalid interpolation array type: " << rang::fgB::red << dataTypeName(data_type) << rang::style::reset; + + throw UnexpectedError(os.str()); + } + // LCOV_EXCL_STOP + } +} + +std::shared_ptr<ItemArrayVariant> +ItemArrayVariantFunctionInterpoler::interpolate() const +{ + switch (m_mesh->dimension()) { + case 1: { + return this->_interpolate<1>(); + } + case 2: { + return this->_interpolate<2>(); + } + case 3: { + return this->_interpolate<3>(); + } + // LCOV_EXCL_START + default: { + throw UnexpectedError("invalid dimension"); + } + // LCOV_EXCL_STOP + } +} diff --git a/src/language/utils/ItemArrayVariantFunctionInterpoler.hpp b/src/language/utils/ItemArrayVariantFunctionInterpoler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eac61b5fb067e83c2cf8f132060e68884316cad4 --- /dev/null +++ b/src/language/utils/ItemArrayVariantFunctionInterpoler.hpp @@ -0,0 +1,38 @@ +#ifndef ITEM_ARRAY_VARIANT_FUNCTION_INTERPOLER_HPP +#define ITEM_ARRAY_VARIANT_FUNCTION_INTERPOLER_HPP + +#include <language/utils/FunctionSymbolId.hpp> +#include <mesh/IMesh.hpp> +#include <mesh/IZoneDescriptor.hpp> +#include <mesh/ItemArrayVariant.hpp> +#include <mesh/ItemType.hpp> + +class ItemArrayVariantFunctionInterpoler +{ + private: + std::shared_ptr<const IMesh> m_mesh; + const ItemType m_item_type; + const std::vector<FunctionSymbolId> m_function_id_list; + + template <size_t Dimension, typename DataType, typename ArrayType = DataType> + std::shared_ptr<ItemArrayVariant> _interpolate() const; + + template <size_t Dimension> + std::shared_ptr<ItemArrayVariant> _interpolate() const; + + public: + std::shared_ptr<ItemArrayVariant> interpolate() const; + + ItemArrayVariantFunctionInterpoler(const std::shared_ptr<const IMesh>& mesh, + const ItemType& item_type, + const std::vector<FunctionSymbolId>& function_id_list) + : m_mesh{mesh}, m_item_type{item_type}, m_function_id_list{function_id_list} + {} + + ItemArrayVariantFunctionInterpoler(const ItemArrayVariantFunctionInterpoler&) = delete; + ItemArrayVariantFunctionInterpoler(ItemArrayVariantFunctionInterpoler&&) = delete; + + ~ItemArrayVariantFunctionInterpoler() = default; +}; + +#endif // ITEM_ARRAY_VARIANT_FUNCTION_INTERPOLER_HPP diff --git a/src/language/utils/ItemValueVariantFunctionInterpoler.cpp b/src/language/utils/ItemValueVariantFunctionInterpoler.cpp index 018dd7a9837997e4faf595898773f7c847f47f20..98dbe1658b45b8b8613892d0cfa72e67ccc67700 100644 --- a/src/language/utils/ItemValueVariantFunctionInterpoler.cpp +++ b/src/language/utils/ItemValueVariantFunctionInterpoler.cpp @@ -41,9 +41,11 @@ ItemValueVariantFunctionInterpoler::_interpolate() const InterpolateItemValue<DataType(TinyVector<Dimension>)>::template interpolate<ItemType::node>(m_function_id, p_mesh->xr())); } + // LCOV_EXCL_START default: { throw UnexpectedError("invalid item type"); } + // LCOV_EXCL_STOP } } @@ -58,13 +60,13 @@ ItemValueVariantFunctionInterpoler::_interpolate() const switch (data_type) { case ASTNodeDataType::bool_t: { - return this->_interpolate<Dimension, bool, double>(); + return this->_interpolate<Dimension, bool>(); } case ASTNodeDataType::unsigned_int_t: { - return this->_interpolate<Dimension, uint64_t, double>(); + return this->_interpolate<Dimension, uint64_t>(); } case ASTNodeDataType::int_t: { - return this->_interpolate<Dimension, int64_t, double>(); + return this->_interpolate<Dimension, int64_t>(); } case ASTNodeDataType::double_t: { return this->_interpolate<Dimension, double>(); diff --git a/src/mesh/ItemArrayVariant.hpp b/src/mesh/ItemArrayVariant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0284cce20965d6568c6272358163e866e70ed393 --- /dev/null +++ b/src/mesh/ItemArrayVariant.hpp @@ -0,0 +1,113 @@ +#ifndef ITEM_ARRAY_VARIANT_HPP +#define ITEM_ARRAY_VARIANT_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> +#include <mesh/ItemArray.hpp> +#include <utils/Exceptions.hpp> + +class ItemArrayVariant +{ + private: + using Variant = std::variant<NodeArray<const bool>, + NodeArray<const long int>, + NodeArray<const unsigned long int>, + NodeArray<const double>, + NodeArray<const TinyVector<1, double>>, + NodeArray<const TinyVector<2, double>>, + NodeArray<const TinyVector<3, double>>, + NodeArray<const TinyMatrix<1, 1, double>>, + NodeArray<const TinyMatrix<2, 2, double>>, + NodeArray<const TinyMatrix<3, 3, double>>, + + EdgeArray<const bool>, + EdgeArray<const long int>, + EdgeArray<const unsigned long int>, + EdgeArray<const double>, + EdgeArray<const TinyVector<1, double>>, + EdgeArray<const TinyVector<2, double>>, + EdgeArray<const TinyVector<3, double>>, + EdgeArray<const TinyMatrix<1, 1, double>>, + EdgeArray<const TinyMatrix<2, 2, double>>, + EdgeArray<const TinyMatrix<3, 3, double>>, + + FaceArray<const bool>, + FaceArray<const long int>, + FaceArray<const unsigned long int>, + FaceArray<const double>, + FaceArray<const TinyVector<1, double>>, + FaceArray<const TinyVector<2, double>>, + FaceArray<const TinyVector<3, double>>, + FaceArray<const TinyMatrix<1, 1, double>>, + FaceArray<const TinyMatrix<2, 2, double>>, + FaceArray<const TinyMatrix<3, 3, double>>, + + CellArray<const bool>, + CellArray<const long int>, + CellArray<const unsigned long int>, + CellArray<const double>, + CellArray<const TinyVector<1, double>>, + CellArray<const TinyVector<2, double>>, + CellArray<const TinyVector<3, double>>, + CellArray<const TinyMatrix<1, 1, double>>, + CellArray<const TinyMatrix<2, 2, double>>, + CellArray<const TinyMatrix<3, 3, double>>>; + + Variant m_item_array; + + public: + PUGS_INLINE + const Variant& + itemArray() const + { + return m_item_array; + } + + template <typename ItemArrayT> + PUGS_INLINE auto + get() const + { + using DataType = typename ItemArrayT::data_type; + constexpr ItemType item_type = ItemArrayT::item_t; + + if constexpr (std::is_same_v<ItemArrayT, ItemArray<DataType, item_type>> or + std::is_same_v<ItemArrayT, ItemArray<const DataType, item_type>> or + std::is_same_v<ItemArrayT, WeakItemArray<DataType, item_type>> or + std::is_same_v<ItemArrayT, WeakItemArray<const DataType, item_type>>) { + if (not std::holds_alternative<ItemArray<const DataType, item_type>>(this->m_item_array)) { + throw NormalError("invalid ItemArray type"); + } + return std::get<ItemArray<const DataType, item_type>>(this->itemArray()); + } else { + static_assert(std::is_same_v<ItemArrayT, ItemArrayT>, "invalid template argument"); + } + } + + template <typename DataType, ItemType item_type> + ItemArrayVariant(const ItemArray<DataType, item_type>& item_array) + : m_item_array{ItemArray<const DataType, item_type>{item_array}} + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, bool> or // + std::is_same_v<std::remove_const_t<DataType>, long int> or // + std::is_same_v<std::remove_const_t<DataType>, unsigned long int> or // + std::is_same_v<std::remove_const_t<DataType>, double> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<3, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<1, 1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<2, 2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<3, 3, double>>, + "ItemArray with this DataType is not allowed in variant"); + } + + ItemArrayVariant& operator=(ItemArrayVariant&&) = default; + ItemArrayVariant& operator=(const ItemArrayVariant&) = default; + + ItemArrayVariant(const ItemArrayVariant&) = default; + ItemArrayVariant(ItemArrayVariant&&) = default; + + ItemArrayVariant() = delete; + ~ItemArrayVariant() = default; +}; + +#endif // ITEM_ARRAY_VARIANT_HPP diff --git a/src/mesh/SubItemArrayPerItemVariant.hpp b/src/mesh/SubItemArrayPerItemVariant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ffb0ea673241236a7e6fd1a3ee0566439abcf765 --- /dev/null +++ b/src/mesh/SubItemArrayPerItemVariant.hpp @@ -0,0 +1,202 @@ +#ifndef SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP +#define SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP + +#include <algebra/TinyMatrix.hpp> +#include <algebra/TinyVector.hpp> +#include <mesh/SubItemArrayPerItem.hpp> +#include <utils/Exceptions.hpp> + +class SubItemArrayPerItemVariant +{ + private: + using Variant = std::variant<NodeArrayPerEdge<const bool>, + NodeArrayPerEdge<const long int>, + NodeArrayPerEdge<const unsigned long int>, + NodeArrayPerEdge<const double>, + NodeArrayPerEdge<const TinyVector<1, double>>, + NodeArrayPerEdge<const TinyVector<2, double>>, + NodeArrayPerEdge<const TinyVector<3, double>>, + NodeArrayPerEdge<const TinyMatrix<1, 1, double>>, + NodeArrayPerEdge<const TinyMatrix<2, 2, double>>, + NodeArrayPerEdge<const TinyMatrix<3, 3, double>>, + + NodeArrayPerFace<const bool>, + NodeArrayPerFace<const long int>, + NodeArrayPerFace<const unsigned long int>, + NodeArrayPerFace<const double>, + NodeArrayPerFace<const TinyVector<1, double>>, + NodeArrayPerFace<const TinyVector<2, double>>, + NodeArrayPerFace<const TinyVector<3, double>>, + NodeArrayPerFace<const TinyMatrix<1, 1, double>>, + NodeArrayPerFace<const TinyMatrix<2, 2, double>>, + NodeArrayPerFace<const TinyMatrix<3, 3, double>>, + + NodeArrayPerCell<const bool>, + NodeArrayPerCell<const long int>, + NodeArrayPerCell<const unsigned long int>, + NodeArrayPerCell<const double>, + NodeArrayPerCell<const TinyVector<1, double>>, + NodeArrayPerCell<const TinyVector<2, double>>, + NodeArrayPerCell<const TinyVector<3, double>>, + NodeArrayPerCell<const TinyMatrix<1, 1, double>>, + NodeArrayPerCell<const TinyMatrix<2, 2, double>>, + NodeArrayPerCell<const TinyMatrix<3, 3, double>>, + + EdgeArrayPerNode<const bool>, + EdgeArrayPerNode<const long int>, + EdgeArrayPerNode<const unsigned long int>, + EdgeArrayPerNode<const double>, + EdgeArrayPerNode<const TinyVector<1, double>>, + EdgeArrayPerNode<const TinyVector<2, double>>, + EdgeArrayPerNode<const TinyVector<3, double>>, + EdgeArrayPerNode<const TinyMatrix<1, 1, double>>, + EdgeArrayPerNode<const TinyMatrix<2, 2, double>>, + EdgeArrayPerNode<const TinyMatrix<3, 3, double>>, + + EdgeArrayPerFace<const bool>, + EdgeArrayPerFace<const long int>, + EdgeArrayPerFace<const unsigned long int>, + EdgeArrayPerFace<const double>, + EdgeArrayPerFace<const TinyVector<1, double>>, + EdgeArrayPerFace<const TinyVector<2, double>>, + EdgeArrayPerFace<const TinyVector<3, double>>, + EdgeArrayPerFace<const TinyMatrix<1, 1, double>>, + EdgeArrayPerFace<const TinyMatrix<2, 2, double>>, + EdgeArrayPerFace<const TinyMatrix<3, 3, double>>, + + EdgeArrayPerCell<const bool>, + EdgeArrayPerCell<const long int>, + EdgeArrayPerCell<const unsigned long int>, + EdgeArrayPerCell<const double>, + EdgeArrayPerCell<const TinyVector<1, double>>, + EdgeArrayPerCell<const TinyVector<2, double>>, + EdgeArrayPerCell<const TinyVector<3, double>>, + EdgeArrayPerCell<const TinyMatrix<1, 1, double>>, + EdgeArrayPerCell<const TinyMatrix<2, 2, double>>, + EdgeArrayPerCell<const TinyMatrix<3, 3, double>>, + + FaceArrayPerNode<const bool>, + FaceArrayPerNode<const long int>, + FaceArrayPerNode<const unsigned long int>, + FaceArrayPerNode<const double>, + FaceArrayPerNode<const TinyVector<1, double>>, + FaceArrayPerNode<const TinyVector<2, double>>, + FaceArrayPerNode<const TinyVector<3, double>>, + FaceArrayPerNode<const TinyMatrix<1, 1, double>>, + FaceArrayPerNode<const TinyMatrix<2, 2, double>>, + FaceArrayPerNode<const TinyMatrix<3, 3, double>>, + + FaceArrayPerEdge<const bool>, + FaceArrayPerEdge<const long int>, + FaceArrayPerEdge<const unsigned long int>, + FaceArrayPerEdge<const double>, + FaceArrayPerEdge<const TinyVector<1, double>>, + FaceArrayPerEdge<const TinyVector<2, double>>, + FaceArrayPerEdge<const TinyVector<3, double>>, + FaceArrayPerEdge<const TinyMatrix<1, 1, double>>, + FaceArrayPerEdge<const TinyMatrix<2, 2, double>>, + FaceArrayPerEdge<const TinyMatrix<3, 3, double>>, + + FaceArrayPerCell<const bool>, + FaceArrayPerCell<const long int>, + FaceArrayPerCell<const unsigned long int>, + FaceArrayPerCell<const double>, + FaceArrayPerCell<const TinyVector<1, double>>, + FaceArrayPerCell<const TinyVector<2, double>>, + FaceArrayPerCell<const TinyVector<3, double>>, + FaceArrayPerCell<const TinyMatrix<1, 1, double>>, + FaceArrayPerCell<const TinyMatrix<2, 2, double>>, + FaceArrayPerCell<const TinyMatrix<3, 3, double>>, + + CellArrayPerNode<const bool>, + CellArrayPerNode<const long int>, + CellArrayPerNode<const unsigned long int>, + CellArrayPerNode<const double>, + CellArrayPerNode<const TinyVector<1, double>>, + CellArrayPerNode<const TinyVector<2, double>>, + CellArrayPerNode<const TinyVector<3, double>>, + CellArrayPerNode<const TinyMatrix<1, 1, double>>, + CellArrayPerNode<const TinyMatrix<2, 2, double>>, + CellArrayPerNode<const TinyMatrix<3, 3, double>>, + + CellArrayPerEdge<const bool>, + CellArrayPerEdge<const long int>, + CellArrayPerEdge<const unsigned long int>, + CellArrayPerEdge<const double>, + CellArrayPerEdge<const TinyVector<1, double>>, + CellArrayPerEdge<const TinyVector<2, double>>, + CellArrayPerEdge<const TinyVector<3, double>>, + CellArrayPerEdge<const TinyMatrix<1, 1, double>>, + CellArrayPerEdge<const TinyMatrix<2, 2, double>>, + CellArrayPerEdge<const TinyMatrix<3, 3, double>>, + + CellArrayPerFace<const bool>, + CellArrayPerFace<const long int>, + CellArrayPerFace<const unsigned long int>, + CellArrayPerFace<const double>, + CellArrayPerFace<const TinyVector<1, double>>, + CellArrayPerFace<const TinyVector<2, double>>, + CellArrayPerFace<const TinyVector<3, double>>, + CellArrayPerFace<const TinyMatrix<1, 1, double>>, + CellArrayPerFace<const TinyMatrix<2, 2, double>>, + CellArrayPerFace<const TinyMatrix<3, 3, double>>>; + + Variant m_sub_item_array_per_item; + + public: + PUGS_INLINE + const Variant& + itemArray() const + { + return m_sub_item_array_per_item; + } + + template <typename SubItemArrayPerItemT> + PUGS_INLINE auto + get() const + { + using DataType = typename SubItemArrayPerItemT::data_type; + using ItemOfItemTypeT = typename SubItemArrayPerItemT::ItemOfItemType; + + if constexpr (std::is_same_v<SubItemArrayPerItemT, SubItemArrayPerItem<DataType, ItemOfItemTypeT>> or + std::is_same_v<SubItemArrayPerItemT, SubItemArrayPerItem<const DataType, ItemOfItemTypeT>> or + std::is_same_v<SubItemArrayPerItemT, WeakSubItemArrayPerItem<DataType, ItemOfItemTypeT>> or + std::is_same_v<SubItemArrayPerItemT, WeakSubItemArrayPerItem<const DataType, ItemOfItemTypeT>>) { + if (not std::holds_alternative<SubItemArrayPerItem<const DataType, ItemOfItemTypeT>>( + this->m_sub_item_array_per_item)) { + throw NormalError("invalid SubItemArrayPerItem type"); + } + return std::get<SubItemArrayPerItem<const DataType, ItemOfItemTypeT>>(this->m_sub_item_array_per_item); + } else { + static_assert(std::is_same_v<SubItemArrayPerItemT, SubItemArrayPerItemT>, "invalid template argument"); + } + } + + template <typename DataType, typename ItemOfItemTypeT> + SubItemArrayPerItemVariant(const SubItemArrayPerItem<DataType, ItemOfItemTypeT>& sub_item_array_per_item) + : m_sub_item_array_per_item{SubItemArrayPerItem<const DataType, ItemOfItemTypeT>{sub_item_array_per_item}} + { + static_assert(std::is_same_v<std::remove_const_t<DataType>, bool> or // + std::is_same_v<std::remove_const_t<DataType>, long int> or // + std::is_same_v<std::remove_const_t<DataType>, unsigned long int> or // + std::is_same_v<std::remove_const_t<DataType>, double> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyVector<3, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<1, 1, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<2, 2, double>> or // + std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<3, 3, double>>, + "SubItemArrayPerItem with this DataType is not allowed in variant"); + } + + SubItemArrayPerItemVariant& operator=(SubItemArrayPerItemVariant&&) = default; + SubItemArrayPerItemVariant& operator=(const SubItemArrayPerItemVariant&) = default; + + SubItemArrayPerItemVariant(const SubItemArrayPerItemVariant&) = default; + SubItemArrayPerItemVariant(SubItemArrayPerItemVariant&&) = default; + + SubItemArrayPerItemVariant() = delete; + ~SubItemArrayPerItemVariant() = default; +}; + +#endif // SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP diff --git a/src/output/INamedDiscreteData.hpp b/src/output/INamedDiscreteData.hpp index 5d22e82c2e9d599cb695970ec9ba7049efdf08bf..b4fae2b34a5bbbd14ca2127b5cad973beb6d9747 100644 --- a/src/output/INamedDiscreteData.hpp +++ b/src/output/INamedDiscreteData.hpp @@ -8,6 +8,7 @@ class INamedDiscreteData public: enum class Type { + item_array, item_value, discrete_function }; diff --git a/src/output/NamedItemArrayVariant.hpp b/src/output/NamedItemArrayVariant.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4b92d5585d56aa74067c29c7d3e6945262f642e8 --- /dev/null +++ b/src/output/NamedItemArrayVariant.hpp @@ -0,0 +1,47 @@ +#ifndef NAMED_ITEM_ARRAY_VARIANT_HPP +#define NAMED_ITEM_ARRAY_VARIANT_HPP + +#include <output/INamedDiscreteData.hpp> + +#include <memory> +#include <string> + +class ItemArrayVariant; + +class NamedItemArrayVariant final : public INamedDiscreteData +{ + private: + std::shared_ptr<const ItemArrayVariant> m_item_array_variant; + std::string m_name; + + public: + Type + type() const final + { + return INamedDiscreteData::Type::item_array; + } + + const std::string& + name() const final + { + return m_name; + } + + const std::shared_ptr<const ItemArrayVariant> + itemArrayVariant() const + { + return m_item_array_variant; + } + + NamedItemArrayVariant(const std::shared_ptr<const ItemArrayVariant>& item_array_variant, const std::string& name) + : m_item_array_variant{item_array_variant}, m_name{name} + {} + + NamedItemArrayVariant(const NamedItemArrayVariant&) = default; + NamedItemArrayVariant(NamedItemArrayVariant&&) = default; + + NamedItemArrayVariant() = default; + ~NamedItemArrayVariant() = default; +}; + +#endif // NAMED_ITEM_ARRAY_VARIANT_HPP diff --git a/src/output/WriterBase.cpp b/src/output/WriterBase.cpp index 83d890c2ab8bf31e60d7ed09e4e2da7770ebbfb8..a96da1e4e0a5e1eab52c4c3859dc9f0ae2304f08 100644 --- a/src/output/WriterBase.cpp +++ b/src/output/WriterBase.cpp @@ -1,8 +1,10 @@ #include <output/WriterBase.hpp> #include <mesh/IMesh.hpp> +#include <mesh/ItemArrayVariant.hpp> #include <mesh/ItemValueVariant.hpp> #include <output/NamedDiscreteFunction.hpp> +#include <output/NamedItemArrayVariant.hpp> #include <output/NamedItemValueVariant.hpp> #include <output/OutputNamedItemValueSet.hpp> #include <scheme/DiscreteFunctionP0.hpp> @@ -70,6 +72,75 @@ WriterBase::_checkConnectivity( } } +void +WriterBase::_checkSignature( + const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const +{ + using NameTypeMap = std::map<std::string, std::string>; + NameTypeMap name_type_map; + + for (auto named_discrete_data : named_discrete_data_list) { + switch (named_discrete_data->type()) { + case INamedDiscreteData::Type::item_value: { + const NamedItemValueVariant& named_item_value = dynamic_cast<const NamedItemValueVariant&>(*named_discrete_data); + std::visit( + [&](auto&& item_value) { + using ItemValueT = std::decay_t<decltype(item_value)>; + using DataType = std::decay_t<typename ItemValueT::data_type>; + + std::ostringstream type_name; + type_name << "item_value(" << dataTypeName(ast_node_data_type_from<DataType>) << ')'; + + name_type_map[named_discrete_data->name()] = type_name.str(); + }, + named_item_value.itemValueVariant()->itemValue()); + break; + } + case INamedDiscreteData::Type::item_array: { + const NamedItemArrayVariant& named_item_array = dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data); + std::visit( + [&](auto&& item_value) { + using ItemValueT = std::decay_t<decltype(item_value)>; + using DataType = std::decay_t<typename ItemValueT::data_type>; + + std::ostringstream type_name; + type_name << "item_array(" << dataTypeName(ast_node_data_type_from<DataType>) << ')'; + + name_type_map[named_discrete_data->name()] = type_name.str(); + }, + named_item_array.itemArrayVariant()->itemArray()); + break; + } + case INamedDiscreteData::Type::discrete_function: { + const NamedDiscreteFunction& named_discrete_function = + dynamic_cast<const NamedDiscreteFunction&>(*named_discrete_data); + std::visit( + [&](auto&& discrete_function) { + std::ostringstream type_name; + type_name << "Vh(" << dataTypeName(discrete_function.dataType()) << ')'; + + name_type_map[named_discrete_data->name()] = type_name.str(); + }, + named_discrete_function.discreteFunctionVariant()->discreteFunction()); + break; + } + } + } + + std::string signature{"|"}; + for (auto&& [name, type_name] : name_type_map) { + signature += name + std::string{"-"} + type_name + std::string{"|"}; + } + + if (m_signature.has_value()) { + if (m_signature.value() != signature) { + throw NormalError("output variable list changed"); + } + } else { + m_signature = signature; + } +} + void WriterBase::_checkMesh(const std::shared_ptr<const IMesh>& mesh, const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const @@ -147,6 +218,17 @@ WriterBase::_getMesh(const std::vector<std::shared_ptr<const INamedDiscreteData> auto&& item_value) { connectivity_set[item_value.connectivity_ptr()] = named_item_value_variant.name(); }, named_item_value_variant.itemValueVariant()->itemValue()); + break; + } + case INamedDiscreteData::Type::item_array: { + const NamedItemArrayVariant& named_item_array_variant = + dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data); + + std::visit([&]( + auto&& + item_array) { connectivity_set[item_array.connectivity_ptr()] = named_item_array_variant.name(); }, + named_item_array_variant.itemArrayVariant()->itemArray()); + break; } } } @@ -214,8 +296,26 @@ WriterBase::_getOutputNamedItemDataSet( item_value_variant.itemValue()); break; } - default: { - throw UnexpectedError("invalid discrete data type"); + case INamedDiscreteData::Type::item_array: { + const NamedItemArrayVariant& named_item_array_variant = + dynamic_cast<const NamedItemArrayVariant&>(*named_discrete_data); + + const std::string& name = named_item_array_variant.name(); + + const ItemArrayVariant& item_value_variant = *named_item_array_variant.itemArrayVariant(); + + std::visit( + [&](auto&& item_array) { + using ItemArrayType = std::decay_t<decltype(item_array)>; + using DataType = std::decay_t<typename ItemArrayType::data_type>; + if constexpr (std::is_arithmetic_v<DataType>) { + named_item_data_set.add(NamedItemData{name, item_array}); + } else { + throw NormalError("can only write item_array containing scalar values"); + } + }, + item_value_variant.itemArray()); + break; } } } @@ -223,10 +323,10 @@ WriterBase::_getOutputNamedItemDataSet( } WriterBase::WriterBase(const std::string& base_filename, const double& time_period) - : m_base_filename{base_filename}, m_period_manager(time_period) + : m_base_filename{base_filename}, m_period_manager(time_period), m_signature(std::nullopt) {} -WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename} {} +WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename}, m_signature(std::nullopt) {} void WriterBase::write(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const @@ -250,6 +350,7 @@ WriterBase::writeIfNeeded(const std::vector<std::shared_ptr<const INamedDiscrete if (time >= m_period_manager->nextTime()) { std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list); + this->_checkSignature(named_discrete_data_list); this->_writeAtTime(*mesh, named_discrete_data_list, time); m_period_manager->setSaveTime(time); } @@ -265,7 +366,9 @@ WriterBase::writeForced(const std::vector<std::shared_ptr<const INamedDiscreteDa if (m_period_manager.has_value()) { if (time == m_period_manager->getLastTime()) return; // output already performed + std::shared_ptr<const IMesh> mesh = _getMesh(named_discrete_data_list); + this->_checkSignature(named_discrete_data_list); this->_writeAtTime(*mesh, named_discrete_data_list, time); m_period_manager->setSaveTime(time); } else { @@ -280,8 +383,8 @@ WriterBase::writeOnMesh(const std::shared_ptr<const IMesh>& mesh, if (m_period_manager.has_value()) { throw NormalError("this writer requires time value"); } else { - _checkMesh(mesh, named_discrete_data_list); - _checkConnectivity(mesh, named_discrete_data_list); + this->_checkMesh(mesh, named_discrete_data_list); + this->_checkConnectivity(mesh, named_discrete_data_list); this->_write(*mesh, named_discrete_data_list); } } @@ -292,10 +395,12 @@ WriterBase::writeOnMeshIfNeeded(const std::shared_ptr<const IMesh>& mesh, double time) const { if (m_period_manager.has_value()) { - if (time == m_period_manager->getLastTime()) + if (time == m_period_manager->getLastTime()) { return; // output already performed - _checkMesh(mesh, named_discrete_data_list); - _checkConnectivity(mesh, named_discrete_data_list); + } + + this->_checkMesh(mesh, named_discrete_data_list); + this->_checkConnectivity(mesh, named_discrete_data_list); this->_writeAtTime(*mesh, named_discrete_data_list, time); m_period_manager->setSaveTime(time); } else { @@ -309,10 +414,11 @@ WriterBase::writeOnMeshForced(const std::shared_ptr<const IMesh>& mesh, double time) const { if (m_period_manager.has_value()) { - if (time == m_period_manager->getLastTime()) + if (time == m_period_manager->getLastTime()) { return; // output already performed - _checkMesh(mesh, named_discrete_data_list); - _checkConnectivity(mesh, named_discrete_data_list); + } + this->_checkMesh(mesh, named_discrete_data_list); + this->_checkConnectivity(mesh, named_discrete_data_list); this->_writeAtTime(*mesh, named_discrete_data_list, time); m_period_manager->setSaveTime(time); } else { diff --git a/src/output/WriterBase.hpp b/src/output/WriterBase.hpp index 7fae994d78ed0e97be8f10d63097464280c739fc..707ac52d3a3c69c749c46047bd594b0be46c408b 100644 --- a/src/output/WriterBase.hpp +++ b/src/output/WriterBase.hpp @@ -85,7 +85,11 @@ class WriterBase : public IWriter std::optional<PeriodManager> m_period_manager; + mutable std::optional<std::string> m_signature; + private: + void _checkSignature(const std::vector<std::shared_ptr<const INamedDiscreteData>>& named_discrete_data_list) const; + template <typename DiscreteFunctionType> static void _registerDiscreteFunction(const std::string& name, const DiscreteFunctionType&, OutputNamedItemDataSet&); diff --git a/src/scheme/FluxingAdvectionSolver.cpp b/src/scheme/FluxingAdvectionSolver.cpp index b655ff74fe36057766396c12e8e5754a730427da..c4884b62b107489fb5c9d17dfd6069a56013eb67 100644 --- a/src/scheme/FluxingAdvectionSolver.cpp +++ b/src/scheme/FluxingAdvectionSolver.cpp @@ -156,10 +156,9 @@ calculateRemapCycles(const std::shared_ptr<const MeshType>& old_mesh, const CellValue<size_t> ratio(old_mesh->connectivity()); parallel_for( old_mesh->numberOfCells(), - PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = std::ceil(abs(total_negative_flux[cell_id]) / Vj[cell_id]); }); - size_t number_of_cycle = max(ratio); - std::cout << " number_of_cycle " << number_of_cycle << "\n"; - return number_of_cycle; + PUGS_LAMBDA(CellId cell_id) { ratio[cell_id] = std::ceil(std::abs(total_negative_flux[cell_id]) / Vj[cell_id]); }); + + return max(ratio); } template <typename MeshType, typename DataType> @@ -358,7 +357,9 @@ FluxingAdvectionSolverHandler(const std::shared_ptr<const IMesh> new_mesh, FluxingAdvectionSolver<Dimension> solver(old_mesh0, new_mesh0); FaceValue<double> fluxing_volumes = solver.computeFluxVolume(); - size_t number_of_cycles = calculateRemapCycles(old_mesh0, fluxing_volumes); + const size_t number_of_cycles = calculateRemapCycles(old_mesh0, fluxing_volumes); + + std::cout << " number_of_cycle " << number_of_cycles << "\n"; DiscreteFunctionVariant new_variable = std::visit( [&](auto&& variable) -> DiscreteFunctionVariant { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0e585acac5ba1e5b7656ffa29411567e0f0d54f4..9f1f7d9005d6aa8a583283bf2bfda8dc6e23eedd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -131,6 +131,7 @@ add_executable (unit_tests test_RefItemList.cpp test_RevisionInfo.cpp test_SmallArray.cpp + test_SmallMatrix.cpp test_SmallVector.cpp test_Socket.cpp test_SocketModule.cpp @@ -177,6 +178,8 @@ add_executable (mpi_unit_tests test_InterpolateItemValue.cpp test_ItemArray.cpp test_ItemArrayUtils.cpp + test_ItemArrayVariant.cpp + test_ItemArrayVariantFunctionInterpoler.cpp test_ItemValue.cpp test_ItemValueUtils.cpp test_ItemValueVariant.cpp @@ -194,6 +197,7 @@ add_executable (mpi_unit_tests test_OFStream.cpp test_Partitioner.cpp test_RandomEngine.cpp + test_SubItemArrayPerItemVariant.cpp test_SubItemValuePerItem.cpp test_SubItemValuePerItemVariant.cpp test_SubItemValuePerItemUtils.cpp diff --git a/tests/test_ASTNodeAffectationExpressionBuilder.cpp b/tests/test_ASTNodeAffectationExpressionBuilder.cpp index 7055452b2b3e99f19fd2ec267c70477569297d4d..f52a33c297bdea413b9f728498eecf8d67e96b30 100644 --- a/tests/test_ASTNodeAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeAffectationExpressionBuilder.cpp @@ -171,6 +171,10 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou OperatorRepository::instance().reset(); \ } +#ifdef __clang__ +#pragma clang optimize off +#endif // __clang__ + // clazy:excludeall=non-pod-global-static TEST_CASE("ASTNodeAffectationExpressionBuilder", "[language]") @@ -179,9 +183,9 @@ TEST_CASE("ASTNodeAffectationExpressionBuilder", "[language]") SECTION("Affectations") { - SECTION("boolean affectation") + SECTION("-> B") { - SECTION("B <- B") + SECTION("B -> B") { std::string_view data = R"( let b:B, b=true; @@ -198,9 +202,9 @@ let b:B, b=true; } } - SECTION("unsigned integer affectation") + SECTION("-> N") { - SECTION("N <- B") + SECTION("B -> N") { std::string_view data = R"( let n:N, n=true; @@ -216,7 +220,7 @@ let n:N, n=true; CHECK_AST(data, result); } - SECTION("N <- N") + SECTION("N -> N") { std::string_view data = R"( let m : N; let n:N, n=m; @@ -232,7 +236,7 @@ let m : N; let n:N, n=m; CHECK_AST(data, result); } - SECTION("N <- Z") + SECTION("Z -> N") { std::string_view data = R"( let z:Z; let n :N, n=z; @@ -249,9 +253,9 @@ let z:Z; let n :N, n=z; } } - SECTION("integer affectation") + SECTION("-> Z") { - SECTION("Z <- B") + SECTION("B -> Z") { std::string_view data = R"( let z : Z, z=true; @@ -267,7 +271,7 @@ let z : Z, z=true; CHECK_AST(data, result); } - SECTION("Z <- N") + SECTION("N -> Z") { std::string_view data = R"( let m : N; let z : Z, z=m; @@ -283,7 +287,7 @@ let m : N; let z : Z, z=m; CHECK_AST(data, result); } - SECTION("Z <- Z") + SECTION("Z -> Z") { std::string_view data = R"( let q : Z; let z : Z, z=q; @@ -300,9 +304,9 @@ let q : Z; let z : Z, z=q; } } - SECTION("double affectation") + SECTION("-> R") { - SECTION("R <- B") + SECTION("B -> R") { std::string_view data = R"( let r : R, r=true; @@ -318,7 +322,7 @@ let r : R, r=true; CHECK_AST(data, result); } - SECTION("R <- N") + SECTION("N -> R") { std::string_view data = R"( let m : N; let r : R, r=m; @@ -334,7 +338,7 @@ let m : N; let r : R, r=m; CHECK_AST(data, result); } - SECTION("R <- Z") + SECTION("Z -> R") { std::string_view data = R"( let z : Z; let r : R, r=z; @@ -350,7 +354,7 @@ let z : Z; let r : R, r=z; CHECK_AST(data, result); } - SECTION("R <- R") + SECTION("R -> R") { std::string_view data = R"( let s : R; let r : R, r=s; @@ -367,9 +371,9 @@ let s : R; let r : R, r=s; } } - SECTION("R^d affectation") + SECTION("-> R^d") { - SECTION("R^1 <- R^1") + SECTION("R^1 -> R^1") { std::string_view data = R"( let x : R^1; @@ -386,7 +390,7 @@ let y : R^1, y = x; CHECK_AST(data, result); } - SECTION("R^1 <- R") + SECTION("R -> R^1") { std::string_view data = R"( let x : R^1, x = 1.3; @@ -402,7 +406,7 @@ let x : R^1, x = 1.3; CHECK_AST(data, result); } - SECTION("R^1 <- Z") + SECTION("Z -> R^1") { std::string_view data = R"( let x : R^1, x = -1; @@ -419,7 +423,7 @@ let x : R^1, x = -1; CHECK_AST(data, result); } - SECTION("R^1 <- N") + SECTION("N -> R^1") { std::string_view data = R"( let n : N; @@ -436,7 +440,7 @@ let x : R^1, x = n; CHECK_AST(data, result); } - SECTION("R^1 <- B") + SECTION("B -> R^1") { std::string_view data = R"( let b : B; @@ -453,7 +457,7 @@ let x : R^1, x = b; CHECK_AST(data, result); } - SECTION("R^1 <- 0") + SECTION("'0' -> R^1") { std::string_view data = R"( let x : R^1, x = 0; @@ -469,7 +473,7 @@ let x : R^1, x = 0; CHECK_AST(data, result); } - SECTION("R^2 <- R^2") + SECTION("R^2 -> R^2 [variable]") { std::string_view data = R"( let x : R^2; @@ -486,7 +490,7 @@ let y : R^2, y = x; CHECK_AST(data, result); } - SECTION("R^2 <- value") + SECTION("R^2 -> R^2 [value]") { std::string_view data = R"( let y : R^2, y = [0,1]; @@ -504,7 +508,7 @@ let y : R^2, y = [0,1]; CHECK_AST(data, result); } - SECTION("R^2 <- 0") + SECTION("'0' -> R^2") { std::string_view data = R"( let x : R^2, x = 0; @@ -520,7 +524,7 @@ let x : R^2, x = 0; CHECK_AST(data, result); } - SECTION("R^3 <- R^3") + SECTION("R^3 -> R^3") { std::string_view data = R"( let x : R^3; @@ -537,7 +541,7 @@ let y : R^3, y = x; CHECK_AST(data, result); } - SECTION("R^3 <- 0") + SECTION("'0' -> R^3") { std::string_view data = R"( let x : R^3, x = 0; @@ -553,7 +557,7 @@ let x : R^3, x = 0; CHECK_AST(data, result); } - SECTION("R^3 <- value") + SECTION("R^3 -> R^3 [value]") { std::string_view data = R"( let y : R^3, y = [1,2,3]; @@ -573,9 +577,9 @@ let y : R^3, y = [1,2,3]; } } - SECTION("string affectation") + SECTION("-> string") { - SECTION("string <- B") + SECTION("B -> string") { std::string_view data = R"( let s : string, s=true; @@ -592,7 +596,7 @@ let s : string, s=true; CHECK_AST(data, result); } - SECTION("string <- N") + SECTION("N -> string") { std::string_view data = R"( let n : N; let s : string, s=n; @@ -609,7 +613,7 @@ let n : N; let s : string, s=n; CHECK_AST(data, result); } - SECTION("string <- Z") + SECTION("Z -> string") { std::string_view data = R"( let z : Z; let s : string, s=z; @@ -627,7 +631,7 @@ let z : Z; let s : string, s=z; CHECK_AST(data, result); } - SECTION("string <- R") + SECTION("R -> string") { std::string_view data = R"( let r : R; let s : string, s=r; @@ -645,7 +649,7 @@ let r : R; let s : string, s=r; CHECK_AST(data, result); } - SECTION("string <- string") + SECTION("string -> string") { std::string_view data = R"( let s : string, s="foo"; @@ -663,9 +667,9 @@ let s : string, s="foo"; } } - SECTION("type_id affectation") + SECTION("-> type_id") { - SECTION("type_id <- type_id") + SECTION("type_id -> type_id") { std::string_view data = R"( let t : builtin_t, t=a; @@ -682,9 +686,9 @@ let t : builtin_t, t=a; } } - SECTION("tuples") + SECTION("list -> tuple") { - SECTION("B tuples") + SECTION("-> (B)") { std::string_view data = R"( let t : (B), t = (true, false); @@ -702,7 +706,7 @@ let t : (B), t = (true, false); CHECK_AST(data, result); } - SECTION("N tuples") + SECTION("-> (N)") { std::string_view data = R"( let t : (N), t = (1, 2, 3, 5); @@ -722,7 +726,7 @@ let t : (N), t = (1, 2, 3, 5); CHECK_AST(data, result); } - SECTION("Z tuples") + SECTION("-> (Z)") { std::string_view data = R"( let n : N, n = 3; @@ -745,26 +749,31 @@ let t : (Z), t = (2, n, true); CHECK_AST(data, result); } - SECTION("R tuples") + SECTION("-> (R)") { std::string_view data = R"( -let t : (R), t = (2, 3.1, 5); +let n : N, n = 2; +let t : (R), t = (n, 3.1, 5, true); )"; std::string_view result = R"( (root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:2:ValueProcessor) `-(language::eq_op:AffectationToTupleFromListProcessor<double>) +-(language::name:t:NameProcessor) `-(language::expression_list:ASTNodeExpressionListProcessor) - +-(language::integer:2:ValueProcessor) + +-(language::name:n:NameProcessor) +-(language::real:3.1:ValueProcessor) - `-(language::integer:5:ValueProcessor) + +-(language::integer:5:ValueProcessor) + `-(language::true_kw:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("R^d tuples") + SECTION("-> (R^d)") { std::string_view data = R"( let a : R^2, a = [2,3.1]; @@ -803,26 +812,128 @@ let t3 : (R^1), t3 = (1, 2.3, 0); CHECK_AST(data, result); } - SECTION("string tuples") + SECTION("-> (R^dxd)") + { + std::string_view data = R"( +let a : R^2x2, a = [[2, 5],[2, 3.1]]; +let t1 : (R^2x2), t1 = (a, [[1,2],[5,6]], 0); +let t2 : (R^3x3), t2 = (0, [[1,2,3],[4,5,6],[7,8,9]]); +let t3 : (R^1x1), t3 = (1, [[2.3]], 0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, TinyMatrix<2ul, 2ul, double>, TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:a:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:2:ValueProcessor) + | | `-(language::integer:5:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::real:3.1:ValueProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:t1:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::name:a:NameProcessor) + | +-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | | +-(language::row_expression:FakeProcessor) + | | | +-(language::integer:1:ValueProcessor) + | | | `-(language::integer:2:ValueProcessor) + | | `-(language::row_expression:FakeProcessor) + | | +-(language::integer:5:ValueProcessor) + | | `-(language::integer:6:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<3ul, 3ul, double> >) + | +-(language::name:t2:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:0:ValueProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:1:ValueProcessor) + | | +-(language::integer:2:ValueProcessor) + | | `-(language::integer:3:ValueProcessor) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:4:ValueProcessor) + | | +-(language::integer:5:ValueProcessor) + | | `-(language::integer:6:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:7:ValueProcessor) + | +-(language::integer:8:ValueProcessor) + | `-(language::integer:9:ValueProcessor) + `-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:t3:NameProcessor) + `-(language::expression_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>) + | `-(language::row_expression:FakeProcessor) + | `-(language::real:2.3:ValueProcessor) + `-(language::integer:0:ValueProcessor) +)"; + CHECK_AST(data, result); + } + + SECTION("-> (string)") { std::string_view data = R"( -let t : (string), t = ("foo", "bar"); +let n : N, n = 3; +let t : (string), t = ("foo", "bar", n, 1, 1.2, + [1], [1,2], [1,2,3], + [[2]], [[1,2],[3,4]], [[1,2,3],[4,5,6],[7,8,9]]); )"; std::string result = R"( (root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:3:ValueProcessor) `-(language::eq_op:AffectationToTupleFromListProcessor<)" + demangled_stdstring + R"( >) +-(language::name:t:NameProcessor) `-(language::expression_list:ASTNodeExpressionListProcessor) +-(language::literal:"foo":ValueProcessor) - `-(language::literal:"bar":ValueProcessor) + +-(language::literal:"bar":ValueProcessor) + +-(language::name:n:NameProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::real:1.2:ValueProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<1ul>) + | `-(language::integer:1:ValueProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<2ul>) + | +-(language::integer:1:ValueProcessor) + | `-(language::integer:2:ValueProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + +-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>) + | `-(language::row_expression:FakeProcessor) + | `-(language::integer:2:ValueProcessor) + +-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:1:ValueProcessor) + | | `-(language::integer:2:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:3:ValueProcessor) + | `-(language::integer:4:ValueProcessor) + `-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + +-(language::row_expression:FakeProcessor) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + +-(language::row_expression:FakeProcessor) + | +-(language::integer:4:ValueProcessor) + | +-(language::integer:5:ValueProcessor) + | `-(language::integer:6:ValueProcessor) + `-(language::row_expression:FakeProcessor) + +-(language::integer:7:ValueProcessor) + +-(language::integer:8:ValueProcessor) + `-(language::integer:9:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("type_id tuples") + SECTION("-> (builtin_t)") { std::string_view data = R"( let t : (builtin_t), t= (a,b,a); @@ -842,48 +953,108 @@ let t : (builtin_t), t= (a,b,a); } } - SECTION("tuples from singleton") + SECTION("value -> tuple") { - SECTION("B tuples") + SECTION(" -> (B)") { - std::string_view data = R"( + SECTION("B -> (B)") + { + std::string_view data = R"( let t : (B), t = true; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::eq_op:AffectationToTupleProcessor<bool>) +-(language::name:t:NameProcessor) `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } } - SECTION("N tuples") + SECTION("-> (N)") { - std::string_view data = R"( + SECTION("B -> (N)") + { + std::string_view data = R"( +let t : (N), t = true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N -> (N)") + { + std::string_view data = R"( +let n : N, n = 2; +let t : (N), t = n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + +-(language::name:t:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z -> (N)") + { + std::string_view data = R"( let t : (N), t = 1; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::eq_op:AffectationToTupleProcessor<unsigned long>) +-(language::name:t:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } } - SECTION("Z tuples") + SECTION("-> (Z)") { - std::string_view data = R"( + SECTION("B -> (Z)") + { + std::string_view data = R"( +let t : (Z), t = true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<long>) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N -> (Z)") + { + std::string_view data = R"( let n : N, n = 3; let t : (Z), t = n; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) | +-(language::name:n:NameProcessor) @@ -893,35 +1064,178 @@ let t : (Z), t = n; `-(language::name:n:NameProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } + + SECTION("Z -> (Z)") + { + std::string_view data = R"( +let t : (Z), t = -2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<long>) + +-(language::name:t:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } } - SECTION("R tuples") + SECTION("-> (R)") { - std::string_view data = R"( + SECTION("B -> (R)") + { + std::string_view data = R"( +let t : (R), t = true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<double>) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N -> (R)") + { + std::string_view data = R"( +let n : N, n = 2; +let t : (R), t = n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<double>) + +-(language::name:t:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z -> (R)") + { + std::string_view data = R"( +let t : (R), t = 3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<double>) + +-(language::name:t:NameProcessor) + `-(language::integer:3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R -> (R)") + { + std::string_view data = R"( let t : (R), t = 3.1; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::eq_op:AffectationToTupleProcessor<double>) +-(language::name:t:NameProcessor) `-(language::real:3.1:ValueProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } } - SECTION("R^d tuples") + SECTION("-> R^d") { - std::string_view data = R"( + SECTION("B -> (R^1)") + { + std::string_view data = R"( +let t : (R^1), t = false; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::false_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N -> (R^1)") + { + std::string_view data = R"( +let n : N, n = 3; +let t : (R^1), t = n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z -> (R^1)") + { + std::string_view data = R"( +let t : (R^1), t = 3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::integer:3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R -> (R^1)") + { + std::string_view data = R"( +let t : (R^1), t = 3.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::real:3.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^d -> (R^d)") + { + std::string_view data = R"( let a : R^2, a = [2,3.1]; let t1 : (R^2), t1 = a; let t2 : (R^3), t2 = 0; let t3 : (R^1), t3 = 2.3; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) +-(language::eq_op:AffectationProcessor<language::eq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >) | +-(language::name:a:NameProcessor) @@ -939,919 +1253,6281 @@ let t3 : (R^1), t3 = 2.3; `-(language::real:2.3:ValueProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } } - SECTION("string tuples") + SECTION("-> R^dxd") { - std::string_view data = R"( -let t : (string), t = "foo"; + SECTION("B -> (R^1x1)") + { + std::string_view data = R"( +let t : (R^1x1), t = false; )"; - std::string result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::eq_op:AffectationToTupleProcessor<)" + - demangled_stdstring + R"( >) + `-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) +-(language::name:t:NameProcessor) - `-(language::literal:"foo":ValueProcessor) + `-(language::false_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("type_id tuples") - { - std::string_view data = R"( -let t : (builtin_t), t = a; + SECTION("N -> (R^1x1)") + { + std::string_view data = R"( +let n : N, n = 3; +let t : (R^1x1), t = n; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::eq_op:AffectationToTupleProcessor<EmbeddedData>) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) +-(language::name:t:NameProcessor) - `-(language::name:a:NameProcessor) + `-(language::name:n:NameProcessor) )"; - CHECK_AST_WITH_BUILTIN(data, result); - } - } - } + CHECK_AST(data, result); + } - SECTION("+=") - { - SECTION("N += N") - { - std::string_view data = R"( -let n : N, n=1; n+=n; + SECTION("Z -> (R^1x1)") + { + std::string_view data = R"( +let t : (R^1x1), t = 3; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) - | +-(language::name:n:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, unsigned long, unsigned long>) - +-(language::name:n:NameProcessor) - `-(language::name:n:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::integer:3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R += N") - { - std::string_view data = R"( -let x : R, x=1; x+=2; + SECTION("R -> (R^1x1)") + { + std::string_view data = R"( +let t : (R^1x1), t = 3.3; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, double, long>) - +-(language::name:x:NameProcessor) - `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:t:NameProcessor) + `-(language::real:3.3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("string += N") - { - std::string_view data = R"( -let s : string, s="foo"; s+=2; + SECTION("R^dxd -> (R^dxd)") + { + std::string_view data = R"( +let a : R^2x2, a = [[2,3.1],[2,3.2]]; +let t1 : (R^2x2), t1 = a; +let t2 : (R^3x3), t2 = 0; +let t3 : (R^1x1), t3 = 2.3; )"; - std::string result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, )" + - demangled_stdstring + ", " + demangled_stdstring + R"( >) - | +-(language::name:s:NameProcessor) - | `-(language::literal:"foo":ValueProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, )" + - demangled_stdstring + - R"(, long>) - +-(language::name:s:NameProcessor) - `-(language::integer:2:ValueProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, TinyMatrix<2ul, 2ul, double>, TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:a:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:2:ValueProcessor) + | | `-(language::real:3.1:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::real:3.2:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:t1:NameProcessor) + | `-(language::name:a:NameProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<3ul, 3ul, double> >) + | +-(language::name:t2:NameProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:t3:NameProcessor) + `-(language::real:2.3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } + } - SECTION("R^1 += R^1") - { - std::string_view data = R"( -let x : R^1; -let y : R^1; -x += y; + SECTION("-> (string)") + { + SECTION("B -> (string)") + { + std::string_view data = R"( +let t : (string), t = true; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^2 += R^2") - { - std::string_view data = R"( -let x : R^2; -let y : R^2; -x += y; + SECTION("N -> (string)") + { + std::string_view data = R"( +let n : N, n = 2; +let t : (string), t = true; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^3 += R^3") - { - std::string_view data = R"( -let x : R^3; -let y : R^3; -x += y; + SECTION("Z -> (string)") + { + std::string_view data = R"( +let t : (string), t = -2; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } - SECTION("-=") - { - SECTION("Z -= Z") - { - std::string_view data = R"( -let z : Z, z=1; z-=2; + SECTION("R -> (string)") + { + std::string_view data = R"( +let t : (string), t = 3.2; )"; - std::string_view result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) - | +-(language::name:z:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, long, long>) - +-(language::name:z:NameProcessor) - `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::real:3.2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R -= R") - { - std::string_view data = R"( -let x : R, x=1; x-=2.3; + SECTION("R^1 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [1.5]; )"; - std::string_view result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, double, double>) - +-(language::name:x:NameProcessor) - `-(language::real:2.3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::vector_expression:TinyVectorExpressionProcessor<1ul>) + `-(language::real:1.5:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^1 -= R^1") - { - std::string_view data = R"( -let x : R^1; -let y : R^1; -x -= y; + SECTION("R^2 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [1.5, 2]; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::vector_expression:TinyVectorExpressionProcessor<2ul>) + +-(language::real:1.5:ValueProcessor) + `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^2 -= R^2") - { - std::string_view data = R"( -let x : R^2; -let y : R^2; -x -= y; + SECTION("R^3 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [1.5, 2, 1]; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + +-(language::real:1.5:ValueProcessor) + +-(language::integer:2:ValueProcessor) + `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^3 -= R^3") - { - std::string_view data = R"( -let x : R^3; -let y : R^3; -x -= y; + SECTION("R^1x1 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [[1.5]]; )"; - std::string result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::name:y:NameProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>) + `-(language::row_expression:FakeProcessor) + `-(language::real:1.5:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } - SECTION("*=") - { - SECTION("Z *= Z") - { - std::string_view data = R"( -let z : Z, z=1; z*=2; + SECTION("R^2x2 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [[1.5, 1],[-2, 3]]; )"; - std::string_view result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) - | +-(language::name:z:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, long, long>) - +-(language::name:z:NameProcessor) - `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + +-(language::row_expression:FakeProcessor) + | +-(language::real:1.5:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::row_expression:FakeProcessor) + +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | `-(language::integer:2:ValueProcessor) + `-(language::integer:3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R *= R") - { - std::string_view data = R"( -let x : R, x=1; x*=2.3; + SECTION("R^3x3 -> (string)") + { + std::string_view data = R"( +let t : (string), t = [[1.5, 1, -1],[-2, 3, 1],[-5, 1, 6]]; )"; - std::string_view result = R"( + std::string result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, double>) - +-(language::name:x:NameProcessor) - `-(language::real:2.3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + +-(language::row_expression:FakeProcessor) + | +-(language::real:1.5:ValueProcessor) + | +-(language::integer:1:ValueProcessor) + | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | `-(language::integer:1:ValueProcessor) + +-(language::row_expression:FakeProcessor) + | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | `-(language::integer:2:ValueProcessor) + | +-(language::integer:3:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::row_expression:FakeProcessor) + +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | `-(language::integer:5:ValueProcessor) + +-(language::integer:1:ValueProcessor) + `-(language::integer:6:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("string -> (string)") + { + std::string_view data = R"( +let t : (string), t = "foo"; )"; - CHECK_AST(data, result); - } + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:t:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; - SECTION("R^1 *= R") - { - std::string_view data = R"( -let x : R^1; x*=2.3; + CHECK_AST(data, result); + } + } + + SECTION("-> (type_id)") + { + std::string_view data = R"( +let t : (builtin_t), t = a; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, double>) - +-(language::name:x:NameProcessor) - `-(language::real:2.3:ValueProcessor) + `-(language::eq_op:AffectationToTupleProcessor<EmbeddedData>) + +-(language::name:t:NameProcessor) + `-(language::name:a:NameProcessor) )"; - CHECK_AST(data, result); + CHECK_AST_WITH_BUILTIN(data, result); + } } - SECTION("R^2 *= R") + SECTION("tuple -> value") { - std::string_view data = R"( -let x : R^2; x*= 6.2; + SECTION(" -> B") + { + SECTION("(B) -> B") + { + std::string_view data = R"( +let t : (B), t = true; +let b : B, b = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, double>) - +-(language::name:x:NameProcessor) - `-(language::real:6.2:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<bool>) + +-(language::name:b:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } + } - SECTION("R^3 *= R") - { - std::string_view data = R"( -let x : R^3; x*= 3.1; + SECTION("-> N") + { + SECTION("(B) -> N") + { + std::string_view data = R"( +let t : (B), t = true; +let n : N, n = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, double>) - +-(language::name:x:NameProcessor) - `-(language::real:3.1:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<unsigned long>) + +-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R *= Z") - { - std::string_view data = R"( -let x : R, x=1; x*=2; + SECTION("(N) -> N") + { + std::string_view data = R"( +let t : (N), t = 1; +let n : N, n = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) | `-(language::integer:1:ValueProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, long>) - +-(language::name:x:NameProcessor) - `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<unsigned long>) + +-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^1 *= Z") - { - std::string_view data = R"( -let x : R^1; x *= 3; + SECTION("(Z) -> N") + { + std::string_view data = R"( +let t : (Z), t = 1; +let n : N, n = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, long>) - +-(language::name:x:NameProcessor) - `-(language::integer:3:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<unsigned long>) + +-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } + } - SECTION("R^2 *= Z") - { - std::string_view data = R"( -let x : R^2; x *= 6; + SECTION("-> Z") + { + SECTION("(B) -> Z") + { + std::string_view data = R"( +let t : (B), t = true; +let z : Z, z = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, long>) - +-(language::name:x:NameProcessor) - `-(language::integer:6:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<long>) + +-(language::name:z:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^3 *= Z") - { - std::string_view data = R"( -let x : R^3; x *= 4; + SECTION("(N) -> Z") + { + std::string_view data = R"( +let t : (N), t = 2; +let z : Z, z = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, long>) - +-(language::name:x:NameProcessor) - `-(language::integer:4:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<long>) + +-(language::name:z:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R *= N") - { - std::string_view data = R"( -let n : N, n=2; let x : R, x=1; x *= n; + SECTION("(Z) -> Z") + { + std::string_view data = R"( +let t : (Z), t = -2; +let z : Z, z = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) - | +-(language::name:n:NameProcessor) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<long>) + +-(language::name:z:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("-> R") + { + SECTION("(B) -> R") + { + std::string_view data = R"( +let t : (B), t = true; +let x: R, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<double>) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(N) -> R") + { + std::string_view data = R"( +let t : (N), t = 2; +let x : R, x = 2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) | `-(language::integer:2:ValueProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, unsigned long>) + `-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) +-(language::name:x:NameProcessor) - `-(language::name:n:NameProcessor) + `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^1 *= N") - { - std::string_view data = R"( -let n : N; -let x : R^1; x *= n; + SECTION("(Z) -> R") + { + std::string_view data = R"( +let t : (Z), t = 3; +let x : R, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, unsigned long>) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<double>) +-(language::name:x:NameProcessor) - `-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^2 *= N") - { - std::string_view data = R"( -let n : N; -let x : R^2; x *= n; + SECTION("R -> (R)") + { + std::string_view data = R"( +let t : (R), t = 3.1; +let x : R, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, unsigned long>) + +-(language::eq_op:AffectationToTupleProcessor<double>) + | +-(language::name:t:NameProcessor) + | `-(language::real:3.1:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<double>) +-(language::name:x:NameProcessor) - `-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } + } - SECTION("R^3 *= N") - { - std::string_view data = R"( -let n : N; -let x : R^3; x *= n; + SECTION("-> R^d") + { + SECTION("(B) -> R^1") + { + std::string_view data = R"( +let t : (B), t = false; +let x : R^1, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, unsigned long>) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::false_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<1ul, double> >) +-(language::name:x:NameProcessor) - `-(language::name:n:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R *= B") - { - std::string_view data = R"( -let x : R, x=1; x *= true; + SECTION("(N) -> R^1") + { + std::string_view data = R"( +let t : (N), t = 3; +let x : R^1, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, bool>) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<1ul, double> >) +-(language::name:x:NameProcessor) - `-(language::true_kw:ValueProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^1 *= B") - { - std::string_view data = R"( -let x : R^1; x *= true; + SECTION("(Z) -> R^1") + { + std::string_view data = R"( +let t : (Z), t = 3; +let x : R^1, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, bool>) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<1ul, double> >) +-(language::name:x:NameProcessor) - `-(language::true_kw:ValueProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^2 *= B") - { - std::string_view data = R"( -let x : R^2; x *= false; + SECTION("(R) -> R^1") + { + std::string_view data = R"( +let t : (R), t = 3.3; +let x : R^1, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, bool>) + +-(language::eq_op:AffectationToTupleProcessor<double>) + | +-(language::name:t:NameProcessor) + | `-(language::real:3.3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<1ul, double> >) +-(language::name:x:NameProcessor) - `-(language::false_kw:ValueProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R^3 *= B") - { - std::string_view data = R"( -let b : B; let x : R^3; x *= b; + SECTION("(R^1) -> R^1") + { + std::string_view data = R"( +let t : (R^1), t = 2.3; +let x : R^1, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, bool>) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::real:2.3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<1ul, double> >) +-(language::name:x:NameProcessor) - `-(language::name:b:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } - SECTION("/=") - { - SECTION("Z /= Z") - { - std::string_view data = R"( -let z : Z, z=6; z/=2; + SECTION("(R^2) -> R^2") + { + std::string_view data = R"( +let t : (R^2), t = [2.3, 1]; +let x : R^2, x = t; )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) - | +-(language::name:z:NameProcessor) - | `-(language::integer:6:ValueProcessor) - `-(language::divideeq_op:AffectationProcessor<language::divideeq_op, long, long>) - +-(language::name:z:NameProcessor) - `-(language::integer:2:ValueProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<2ul>) + | +-(language::real:2.3:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<2ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^3) -> R^3") + { + std::string_view data = R"( +let t : (R^3), t = [2.3, 1, 1]; +let x : R^3, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::real:2.3:ValueProcessor) + | +-(language::integer:1:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyVector<3ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("-> R^dxd") + { + SECTION("(B) -> R^1x1") + { + std::string_view data = R"( +let t : (B), t = false; +let x : R^1x1, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::false_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(N) -> R^1x1") + { + std::string_view data = R"( +let t : (N), t = 3; +let x : R^1x1, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(Z) -> R^1x1") + { + std::string_view data = R"( +let t : (Z), t = 3; +let x : R^1x1, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R) -> R^1x1") + { + std::string_view data = R"( +let t : (R), t = 3.3; +let x : R^1x1, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<double>) + | +-(language::name:t:NameProcessor) + | `-(language::real:3.3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^1x1) -> R^1x1") + { + std::string_view data = R"( +let t : (R^1x1), t = 2.3; +let x : R^1x1, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::real:2.3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^2x2) -> R^2x2") + { + std::string_view data = R"( +let t : (R^2x2), t = [[2.3, 1], [6,5]]; +let x : R^2x2, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::real:2.3:ValueProcessor) + | | `-(language::integer:1:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:6:ValueProcessor) + | `-(language::integer:5:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<2ul, 2ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^3x3) -> R^3x3") + { + std::string_view data = R"( +let t : (R^3x3), t = [[2.3, 1, 1],[1, 2, 3], [2,1,2]]; +let x : R^3x3, x = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<3ul, 3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::real:2.3:ValueProcessor) + | | +-(language::integer:1:ValueProcessor) + | | `-(language::integer:1:ValueProcessor) + | +-(language::row_expression:FakeProcessor) + | | +-(language::integer:1:ValueProcessor) + | | +-(language::integer:2:ValueProcessor) + | | `-(language::integer:3:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::integer:2:ValueProcessor) + | +-(language::integer:1:ValueProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<TinyMatrix<3ul, 3ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("-> string") + { + SECTION("(B) -> string") + { + std::string_view data = R"( +let t : (B), t = true; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(N) -> string") + { + std::string_view data = R"( +let t : (N), t = true; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) + | `-(language::true_kw:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(Z) -> string") + { + std::string_view data = R"( +let t : (Z), t = -2; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R) -> string") + { + std::string_view data = R"( +let t : (R), t = 3.2; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<double>) + | +-(language::name:t:NameProcessor) + | `-(language::real:3.2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^1) -> string") + { + std::string_view data = R"( +let t : (R^1), t = [1.5]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<1ul>) + | `-(language::real:1.5:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^2) -> string") + { + std::string_view data = R"( +let t : (R^2), t = [1.5, 2]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<2ul>) + | +-(language::real:1.5:ValueProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^3) -> string") + { + std::string_view data = R"( +let t : (R^3), t = [1.5, 2, 1]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyVector<3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::real:1.5:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^1x1) -> string") + { + std::string_view data = R"( +let t : (R^1x1), t = [[1.5]]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<1ul, 1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>) + | `-(language::row_expression:FakeProcessor) + | `-(language::real:1.5:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^2x2) -> string") + { + std::string_view data = R"( +let t : (R^2x2), t = [[1.5, 1],[-2, 3]]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::real:1.5:ValueProcessor) + | | `-(language::integer:1:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | `-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(R^3x3) -> string") + { + std::string_view data = R"( +let t : (R^3x3), t = [[1.5, 1, -1],[-2, 3, 1],[-5, 1, 6]]; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<TinyMatrix<3ul, 3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + | +-(language::row_expression:FakeProcessor) + | | +-(language::real:1.5:ValueProcessor) + | | +-(language::integer:1:ValueProcessor) + | | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | `-(language::integer:1:ValueProcessor) + | +-(language::row_expression:FakeProcessor) + | | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | | `-(language::integer:2:ValueProcessor) + | | +-(language::integer:3:ValueProcessor) + | | `-(language::integer:1:ValueProcessor) + | `-(language::row_expression:FakeProcessor) + | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | `-(language::integer:5:ValueProcessor) + | +-(language::integer:1:ValueProcessor) + | `-(language::integer:6:ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("string -> (string)") + { + std::string_view data = R"( +let t : (string), t = "foo"; +let s : string, s = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<)" + + demangled_stdstring + R"( >) + | +-(language::name:t:NameProcessor) + | `-(language::literal:"foo":ValueProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<)" + + demangled_stdstring + R"( >) + +-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("-> type_id") + { + std::string_view data = R"( +let t : (builtin_t), t = a; +let bt: builtin_t, bt = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleProcessor<EmbeddedData>) + | +-(language::name:t:NameProcessor) + | `-(language::name:a:NameProcessor) + `-(language::eq_op:AffectationFromTupleProcessor<EmbeddedData>) + +-(language::name:bt:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST_WITH_BUILTIN(data, result); + } + } + } + + SECTION("+=") + { + SECTION("N += N") + { + std::string_view data = R"( +let n : N, n=1; n+=n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, unsigned long, unsigned long>) + +-(language::name:n:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R += N") + { + std::string_view data = R"( +let x : R, x=1; x+=2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, double, long>) + +-(language::name:x:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("string += N") + { + std::string_view data = R"( +let s : string, s="foo"; s+=2; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, )" + + demangled_stdstring + ", " + demangled_stdstring + R"( >) + | +-(language::name:s:NameProcessor) + | `-(language::literal:"foo":ValueProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, )" + + demangled_stdstring + + R"(, long>) + +-(language::name:s:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 += R^1") + { + std::string_view data = R"( +let x : R^1; +let y : R^1; +x += y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 += R^2") + { + std::string_view data = R"( +let x : R^2; +let y : R^2; +x += y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 += R^3") + { + std::string_view data = R"( +let x : R^3; +let y : R^3; +x += y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::pluseq_op:AffectationProcessor<language::pluseq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("-=") + { + SECTION("Z -= Z") + { + std::string_view data = R"( +let z : Z, z=1; z-=2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) + | +-(language::name:z:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, long, long>) + +-(language::name:z:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R -= R") + { + std::string_view data = R"( +let x : R, x=1; x-=2.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, double, double>) + +-(language::name:x:NameProcessor) + `-(language::real:2.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 -= R^1") + { + std::string_view data = R"( +let x : R^1; +let y : R^1; +x -= y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<1ul, double>, TinyVector<1ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 -= R^2") + { + std::string_view data = R"( +let x : R^2; +let y : R^2; +x -= y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<2ul, double>, TinyVector<2ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 -= R^3") + { + std::string_view data = R"( +let x : R^3; +let y : R^3; +x -= y; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + `-(language::minuseq_op:AffectationProcessor<language::minuseq_op, TinyVector<3ul, double>, TinyVector<3ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::name:y:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("*=") + { + SECTION("Z *= Z") + { + std::string_view data = R"( +let z : Z, z=1; z*=2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) + | +-(language::name:z:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, long, long>) + +-(language::name:z:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R *= R") + { + std::string_view data = R"( +let x : R, x=1; x*=2.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, double>) + +-(language::name:x:NameProcessor) + `-(language::real:2.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 *= R") + { + std::string_view data = R"( +let x : R^1; x*=2.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, double>) + +-(language::name:x:NameProcessor) + `-(language::real:2.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 *= R") + { + std::string_view data = R"( +let x : R^2; x*= 6.2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, double>) + +-(language::name:x:NameProcessor) + `-(language::real:6.2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 *= R") + { + std::string_view data = R"( +let x : R^3; x*= 3.1; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, double>) + +-(language::name:x:NameProcessor) + `-(language::real:3.1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R *= Z") + { + std::string_view data = R"( +let x : R, x=1; x*=2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, long>) + +-(language::name:x:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 *= Z") + { + std::string_view data = R"( +let x : R^1; x *= 3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, long>) + +-(language::name:x:NameProcessor) + `-(language::integer:3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 *= Z") + { + std::string_view data = R"( +let x : R^2; x *= 6; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, long>) + +-(language::name:x:NameProcessor) + `-(language::integer:6:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 *= Z") + { + std::string_view data = R"( +let x : R^3; x *= 4; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, long>) + +-(language::name:x:NameProcessor) + `-(language::integer:4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R *= N") + { + std::string_view data = R"( +let n : N, n=2; let x : R, x=1; x *= n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, unsigned long, long>) + | +-(language::name:n:NameProcessor) + | `-(language::integer:2:ValueProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, unsigned long>) + +-(language::name:x:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 *= N") + { + std::string_view data = R"( +let n : N; +let x : R^1; x *= n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, unsigned long>) + +-(language::name:x:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 *= N") + { + std::string_view data = R"( +let n : N; +let x : R^2; x *= n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, unsigned long>) + +-(language::name:x:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 *= N") + { + std::string_view data = R"( +let n : N; +let x : R^3; x *= n; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, unsigned long>) + +-(language::name:x:NameProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R *= B") + { + std::string_view data = R"( +let x : R, x=1; x *= true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, double, bool>) + +-(language::name:x:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^1 *= B") + { + std::string_view data = R"( +let x : R^1; x *= true; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<1ul, double>, bool>) + +-(language::name:x:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^2 *= B") + { + std::string_view data = R"( +let x : R^2; x *= false; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<2ul, double>, bool>) + +-(language::name:x:NameProcessor) + `-(language::false_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R^3 *= B") + { + std::string_view data = R"( +let b : B; let x : R^3; x *= b; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::multiplyeq_op:AffectationProcessor<language::multiplyeq_op, TinyVector<3ul, double>, bool>) + +-(language::name:x:NameProcessor) + `-(language::name:b:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("/=") + { + SECTION("Z /= Z") + { + std::string_view data = R"( +let z : Z, z=6; z/=2; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, long, long>) + | +-(language::name:z:NameProcessor) + | `-(language::integer:6:ValueProcessor) + `-(language::divideeq_op:AffectationProcessor<language::divideeq_op, long, long>) + +-(language::name:z:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R /= R") + { + std::string_view data = R"( +let x : R, x=1; x/=2.3; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) + | +-(language::name:x:NameProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::divideeq_op:AffectationProcessor<language::divideeq_op, double, double>) + +-(language::name:x:NameProcessor) + `-(language::real:2.3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("Errors") + { + SECTION("Invalid affectation operator") + { + auto ast = std::make_unique<ASTNode>(); + ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>(); + { + auto child_0 = std::make_unique<ASTNode>(); + child_0->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + auto child_1 = std::make_unique<ASTNode>(); + child_1->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); + ast->children.emplace_back(std::move(child_0)); + ast->children.emplace_back(std::move(child_1)); + } + REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, + "unexpected error: undefined affectation operator"); + } + + SECTION("Invalid string rhs") + { + auto ast = std::make_unique<ASTNode>(); + ast->set_type<language::eq_op>(); + + 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}, "undefined affectation type: string = undefined"); + } + + SECTION("Invalid string affectation operator") + { + SECTION("string -= string") + { + std::string_view data = R"( +let s : string, s="foo"; s-="bar"; +)"; + + std::string error_message = "undefined affectation type: string -= string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string *= Z") + { + std::string_view data = R"( +let s : string, s="foo"; s*=2; +)"; + + std::string error_message = "undefined affectation type: string *= Z"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string /= string") + { + std::string_view data = R"( + let s : string, s="foo"; s/="bar"; +)"; + + std::string error_message = "undefined affectation type: string /= string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + } + + SECTION("type_id operator") + { + std::string_view data = R"( + let s :builtin_t, s = a; s *= b; +)"; + + std::string error_message = "undefined affectation type: builtin_t *= builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + + SECTION("Invalid tuple operator") + { + std::string_view data = R"( + let s :(R), s=(1,2,3); s *= 4; +)"; + + std::string error_message = "undefined affectation type: (R) *= Z"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("Invalid tuple operator 2") + { + std::string_view data = R"( + let s : (builtin_t), s =(a,b); s *= b; +)"; + + std::string error_message = "undefined affectation type: (builtin_t) *= builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + + SECTION("Invalid R^n -> R^m affectation") + { + SECTION("R^3 <- R^1") + { + std::string_view data = R"( +let x : R^3; let y : R^1; x = y; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 <- R^2") + { + std::string_view data = R"( +let x : R^3; let y : R^2; x = y; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 <- R^1") + { + std::string_view data = R"( +let x : R^2; let y : R^1; x = y; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 <- R^3") + { + std::string_view data = R"( +let x : R^2; let y : R^3; x = y; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 <- R^2") + { + std::string_view data = R"( +let x : R^1; let y : R^2; x = y; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 <- R^3") + { + std::string_view data = R"( +let x : R^1; let y : R^3; x = y; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + } + + SECTION("Invalid Z -> R^m affectation [non-zero]") + { + SECTION("R^3 <- Z") + { + std::string_view data = R"( +let x : R^3, x = 3; +)"; + + std::string error_message = "invalid integral value (0 is the solely valid value)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 <- Z") + { + std::string_view data = R"( +let x : R^2, x = 2; +)"; + + std::string error_message = "invalid integral value (0 is the solely valid value)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + } + + SECTION("Invalid R^d -> R^d affectation operator") + { + SECTION("R^3 <- R^3") + { + std::string_view data = R"( +let x : R^3; let y : R^3; x /= y; +)"; + + std::string error_message = "undefined affectation type: R^3 /= R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 <- R^2") + { + std::string_view data = R"( +let x : R^2; let y : R^2; x /= y; +)"; + + std::string error_message = "undefined affectation type: R^2 /= R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 <- R^1") + { + std::string_view data = R"( +let x : R^1; let y : R^1; x /= y; +)"; + + std::string error_message = "undefined affectation type: R^1 /= R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + } + + SECTION("Invalid R^d -> R^d *= operand") + { + SECTION("R^3 <- R^3") + { + std::string_view data = R"( +let x : R^3; let y : R^3; x *= y; +)"; + + std::string error_message = "undefined affectation type: R^3 *= R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 <- R^2") + { + std::string_view data = R"( +let x : R^2; let y : R^2; x *= y; +)"; + + std::string error_message = "undefined affectation type: R^2 *= R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 <- R^1") + { + std::string_view data = R"( +let x : R^1; let y : R^1; x *= y; +)"; + + std::string error_message = "undefined affectation type: R^1 *= R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + } + + SECTION("incorrect declarative/definition number of symbols") + { + std::string_view data = R"( +let (x,y,z):R*R*R, (x,y) = (2,3); +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; + + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, + std::string{"invalid number of definition identifiers, expecting 3 found 2"}); + } + + SECTION("incorrect identifier/expression number of symbols") + { + std::string_view data = R"( +let y:R; +let x:R, (x,y) = (2,3); +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; + + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, + std::string{"unexpected variable list, expecting one identifier"}); + } + + SECTION("incorrect definition variable identifier") + { + std::string_view data = R"( +let y:R; +let x:R, y = 3; +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; + + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, std::string{"invalid identifier, expecting 'x'"}); + } + + SECTION("invalid definition variable identifier order") + { + std::string_view data = R"( +let (x,y):R, (y,x) = (3,2); +)"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; + + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, std::string{"invalid identifier, expecting 'x'"}); + } + + SECTION("undefined affectations =") + { + SECTION("-> value") + { + SECTION("value -> value") + { + SECTION("-> B") + { + SECTION("N -> B") + { + std::string_view data = R"( +let n:N, n = 1; +let b:B, b = n; +)"; + + std::string error_message = "undefined affectation type: B = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("Z -> B") + { + std::string_view data = R"( +let b:B, b = 1; +)"; + + std::string error_message = "undefined affectation type: B = Z"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> B") + { + std::string_view data = R"( +let b:B, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: B = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> B") + { + std::string_view data = R"( +let b:B, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: B = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> B") + { + std::string_view data = R"( +let b:B, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: B = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> B") + { + std::string_view data = R"( +let b:B, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: B = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> B") + { + std::string_view data = R"( +let b:B, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: B = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> B") + { + std::string_view data = R"( +let b:B, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: B = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> B") + { + std::string_view data = R"( +let b:B, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: B = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> B") + { + std::string_view data = R"( +let b:B, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: B = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> B") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : B, v = bt; +)"; + + std::string error_message = "undefined affectation type: B = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> N") + { + SECTION("R -> N") + { + std::string_view data = R"( +let b:N, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: N = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> N") + { + std::string_view data = R"( +let b:N, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: N = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> N") + { + std::string_view data = R"( +let b:N, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: N = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> N") + { + std::string_view data = R"( +let b:N, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: N = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> N") + { + std::string_view data = R"( +let b:N, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: N = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> N") + { + std::string_view data = R"( +let b:N, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: N = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> N") + { + std::string_view data = R"( +let b:N, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: N = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> N") + { + std::string_view data = R"( +let b:N, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: N = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> N") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : N, v = bt; +)"; + + std::string error_message = "undefined affectation type: N = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> Z") + { + SECTION("R -> Z") + { + std::string_view data = R"( +let b:Z, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: Z = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> Z") + { + std::string_view data = R"( +let b:Z, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: Z = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> Z") + { + std::string_view data = R"( +let b:Z, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: Z = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> Z") + { + std::string_view data = R"( +let b:Z, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: Z = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> Z") + { + std::string_view data = R"( +let b:Z, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: Z = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> Z") + { + std::string_view data = R"( +let b:Z, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: Z = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> Z") + { + std::string_view data = R"( +let b:Z, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: Z = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> Z") + { + std::string_view data = R"( +let b:Z, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: Z = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> Z") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : Z, v = bt; +)"; + + std::string error_message = "undefined affectation type: Z = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R") + { + SECTION("R^1 -> R") + { + std::string_view data = R"( +let b:R, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> R") + { + std::string_view data = R"( +let b:R, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R") + { + std::string_view data = R"( +let b:R, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R") + { + std::string_view data = R"( +let b:R, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R") + { + std::string_view data = R"( +let b:R, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R") + { + std::string_view data = R"( +let b:R, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R") + { + std::string_view data = R"( +let b:R, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R, v = bt; +)"; + + std::string error_message = "undefined affectation type: R = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^1") + { + SECTION("R^2 -> R^1") + { + std::string_view data = R"( +let b:R^1, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R^1") + { + std::string_view data = R"( +let b:R^1, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R^1") + { + std::string_view data = R"( +let b:R^1, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R^1") + { + std::string_view data = R"( +let b:R^1, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R^1") + { + std::string_view data = R"( +let b:R^1, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R^1 = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^1") + { + std::string_view data = R"( +let b:R^1, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^1 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^1") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^1, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^1 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^2") + { + SECTION("N -> R^2") + { + std::string_view data = R"( +let n:N, n = 1; +let b:R^2, b = n; +)"; + + std::string error_message = "undefined affectation type: R^2 = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> R^2") + { + std::string_view data = R"( +let b:R^2, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: R^2 = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> R^2") + { + std::string_view data = R"( +let b:R^2, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R^2") + { + std::string_view data = R"( +let b:R^2, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R^2") + { + std::string_view data = R"( +let b:R^2, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R^2") + { + std::string_view data = R"( +let b:R^2, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R^2") + { + std::string_view data = R"( +let b:R^2, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R^2 = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^2") + { + std::string_view data = R"( +let b:R^2, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^2 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^2") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^2, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^2 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^3") + { + SECTION("N -> R^3") + { + std::string_view data = R"( +let n:N, n = 1; +let b:R^3, b = n; +)"; + + std::string error_message = "undefined affectation type: R^3 = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> R^3") + { + std::string_view data = R"( +let b:R^3, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: R^3 = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> R^3") + { + std::string_view data = R"( +let b:R^3, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> R^3") + { + std::string_view data = R"( +let b:R^3, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R^3") + { + std::string_view data = R"( +let b:R^3, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R^3") + { + std::string_view data = R"( +let b:R^3, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R^3") + { + std::string_view data = R"( +let b:R^3, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R^3 = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^3") + { + std::string_view data = R"( +let b:R^3, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^3 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^3") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^3, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^3 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^1x1") + { + SECTION("R^1 -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^1x1") + { + std::string_view data = R"( +let b:R^1x1, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^1x1") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^1x1, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^2x2") + { + SECTION("N -> R^2x2") + { + std::string_view data = R"( +let n:N, n = 1; +let b:R^2x2, b = n; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^2x2") + { + std::string_view data = R"( +let b:R^2x2, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^2x2") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^2x2, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^3x3") + { + SECTION("N -> R^3x3") + { + std::string_view data = R"( +let n:N, n = 1; +let b:R^3x3, b = n; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = 1.2; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> R^3x3") + { + std::string_view data = R"( +let b:R^3x3, b = "foo"; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> R^3") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : R^3x3, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + } + + SECTION("tuple -> value") + { + SECTION("-> B") + { + SECTION("(N) -> B") + { + std::string_view data = R"( +let t:(N), t = 1; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(Z) -> B") + { + std::string_view data = R"( +let t:(Z), t = 1; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (Z)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> B") + { + std::string_view data = R"( +let t:(R), t = 1; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> B") + { + std::string_view data = R"( +let t:(R^1), t = 1; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> B") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> B") + { + std::string_view data = R"( +let t:(R^3), t = [1, 2, 3]; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> B") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> B") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> B") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> B") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:B, b = t; +)"; + + std::string error_message = "undefined affectation type: B = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> B") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : B, v = bt; +)"; + + std::string error_message = "undefined affectation type: B = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> N") + { + SECTION("(R) -> N") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> N") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> N") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> N") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> N") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> N") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> N") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> N") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:N, b = t; +)"; + + std::string error_message = "undefined affectation type: N = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> N") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : N, v = bt; +)"; + + std::string error_message = "undefined affectation type: N = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> Z") + { + SECTION("(R) -> Z") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> Z") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> Z") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> Z") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> Z") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> Z") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> Z") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> Z") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:Z, b = t; +)"; + + std::string error_message = "undefined affectation type: Z = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> Z") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : Z, v = bt; +)"; + + std::string error_message = "undefined affectation type: Z = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R") + { + SECTION("(R^1) -> R") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> R") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R, b = t; +)"; + + std::string error_message = "undefined affectation type: R = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R, v = bt; +)"; + + std::string error_message = "undefined affectation type: R = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^1") + { + SECTION("(R^2) -> R^1") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R^1") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R^1") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R^1") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R^1") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^1") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^1") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^1, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^1 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^2") + { + SECTION("(N) -> R^2") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:R^2, b = n; +)"; + + std::string error_message = "undefined affectation type: R^2 = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> R^2") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> R^2") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R^2") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R^2") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R^2") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R^2") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^2") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^2") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^2, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^2 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^3") + { + SECTION("(N) -> R^3") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:R^3, b = n; +)"; + + std::string error_message = "undefined affectation type: R^3 = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> R^3") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> R^3") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> R^3") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R^3") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R^3") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R^3") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^3") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^3") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^3, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^3 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^1x1") + { + SECTION("(R^1) -> R^1x1") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> R^1x1") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R^1x1") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R^1x1") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R^1x1") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^1x1") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^1x1, b = t; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^1x1") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^1x1, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^1x1 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^2x2") + { + SECTION("(N) -> R^2x2") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:R^2x2, b = n; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> R^2x2") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> R^2x2") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> R^2x2") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R^2x2") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R^2x2") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> R^2x2") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^2x2") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^2x2, b = t; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^2x2") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^2x2, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^2x2 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> R^3x3") + { + SECTION("(N) -> R^3x3") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:R^3x3, b = n; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> R^3x3") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> R^3x3") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> R^3x3") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> R^3x3") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> R^3x3") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> R^3x3") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> R^3x3") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:R^3x3, b = t; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> R^3x3") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : R^3x3, v = bt; +)"; + + std::string error_message = "undefined affectation type: R^3x3 = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + } + } + + SECTION("-> tuple") + { + SECTION("value -> tuple") + { + SECTION("-> (B)") + { + SECTION("N -> (B)") + { + std::string_view data = R"( +let n:N, n = 1; +let b:(B), b = n; +)"; + + std::string error_message = "undefined affectation type: (B) = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("Z -> (B)") + { + std::string_view data = R"( +let b:(B), b = 1; +)"; + + std::string error_message = "undefined affectation type: (B) = Z"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> (B)") + { + std::string_view data = R"( +let b:(B), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (B) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (B)") + { + std::string_view data = R"( +let b:(B), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (B) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (B)") + { + std::string_view data = R"( +let b:(B), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (B) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (B)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v:(B), v = bt; +)"; + + std::string error_message = "undefined affectation type: (B) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (N)") + { + SECTION("R -> (N)") + { + std::string_view data = R"( +let b:(N), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (N) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (N)") + { + std::string_view data = R"( +let b:(N), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (N) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (N)") + { + std::string_view data = R"( +let b:(N), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (N) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (N)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (N), v = bt; +)"; + + std::string error_message = "undefined affectation type: (N) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (Z)") + { + SECTION("R -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (Z) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (Z) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (Z)") + { + std::string_view data = R"( +let b:(Z), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (Z) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (Z)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (Z), v = bt; +)"; + + std::string error_message = "undefined affectation type: (Z) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R)") + { + SECTION("R^1 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R)") + { + std::string_view data = R"( +let b:(R), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R)") + { + std::string_view data = R"( +let b:(R), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v :(R), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^1)") + { + SECTION("R^2 -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R^1) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R^1) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R^1) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R^1) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R^1) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^1)") + { + std::string_view data = R"( +let b:(R^1), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^1) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^1)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^1), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^1) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^2)") + { + SECTION("N -> (R^2)") + { + std::string_view data = R"( +let n:N, n = 1; +let b:(R^2), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^2) = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R^2) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^2)") + { + std::string_view data = R"( +let b:(R^2), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^2) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^2)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^2), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^2) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^3)") + { + SECTION("N -> (R^3)") + { + std::string_view data = R"( +let n:N, n = 1; +let b:(R^3), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^3) = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R^3) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^3)") + { + std::string_view data = R"( +let b:(R^3), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^3) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^3)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^3), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^3) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^1x1)") + { + SECTION("R^1 -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^1x1)") + { + std::string_view data = R"( +let b:(R^1x1), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^1x1)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^1x1), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^1x1) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^2x2)") + { + SECTION("N -> (R^2x2)") + { + std::string_view data = R"( +let n:N, n = 1; +let b:(R^2x2), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3x3 -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = R^3x3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^2x2)") + { + std::string_view data = R"( +let b:(R^2x2), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^2x2)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^2x2), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^2x2) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^3x3)") + { + SECTION("N -> (R^3x3)") + { + std::string_view data = R"( +let n:N, n = 1; +let b:(R^3x3), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = N"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = 1.2; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1 -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = [1.2]; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R^1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2 -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = [1.2, 3]; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R^2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^3 -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = [1.2, 3, 1]; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R^3"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^1x1 -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = [[1.2]]; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R^1x1"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("R^2x2 -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = [[1.2, 3],[3,4]]; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = R^2x2"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("string -> (R^3x3)") + { + std::string_view data = R"( +let b:(R^3x3), b = "foo"; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = string"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("builtin_t -> (R^3x3)") + { + std::string_view data = R"( +let bt:builtin_t, bt = a; +let v : (R^3x3), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^3x3) = builtin_t"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + } + + SECTION("tuple -> tuple") + { + SECTION("-> (B)") + { + SECTION("(N) -> (B)") + { + std::string_view data = R"( +let t:(N), t = 1; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(Z) -> (B)") + { + std::string_view data = R"( +let t:(Z), t = 1; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (Z)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> (B)") + { + std::string_view data = R"( +let t:(R), t = 1; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> (B)") + { + std::string_view data = R"( +let t:(R^1), t = 1; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (B)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (B)") + { + std::string_view data = R"( +let t:(R^3), t = [1, 2, 3]; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (B)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (B)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (B)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (B)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(B), b = t; +)"; + + std::string error_message = "undefined affectation type: (B) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (B)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(B), v = bt; +)"; + + std::string error_message = "undefined affectation type: (B) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (N)") + { + SECTION("(R) -> (N)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> (N)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (N)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (N)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (N)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (N)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (N)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (N)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(N), b = t; +)"; + + std::string error_message = "undefined affectation type: (N) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (N)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(N), v = bt; +)"; + + std::string error_message = "undefined affectation type: (N) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (Z)") + { + SECTION("(R) -> (Z)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> (Z)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (Z)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (Z)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (Z)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (Z)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (Z)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (Z)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(Z), b = t; +)"; + + std::string error_message = "undefined affectation type: (Z) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (Z)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(Z), v = bt; +)"; + + std::string error_message = "undefined affectation type: (Z) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R)") + { + SECTION("(R^1) -> (R)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (R)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (R)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (R)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (R)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (R)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (R)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R), b = t; +)"; + + std::string error_message = "undefined affectation type: (R) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (R)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^1)") + { + SECTION("(R^2) -> (R^1)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (R^1)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (R^1)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (R^1)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (R^1)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (R^1)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^1), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (R^1)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R^1), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^1) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^2)") + { + SECTION("(N) -> (R^2)") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:(R^2), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> (R^2)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> (R^2)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3) -> (R^2)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R^3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (R^2)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (R^2)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (R^2)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (R^2)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^2), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (R^2)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v : (R^2), v = bt; +)"; + + std::string error_message = "undefined affectation type: (R^2) = (builtin_t)"; + + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^3)") + { + SECTION("(N) -> (R^3)") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:(R^3), b = n; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (N)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R) -> (R^3)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1) -> (R^3)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (R^3)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R^2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^1x1) -> (R^3)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R^1x1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (R^3)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R^2x2)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^3x3) -> (R^3)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (R^3x3)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(string) -> (R^3)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^3), b = t; +)"; + + std::string error_message = "undefined affectation type: (R^3) = (string)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(builtin_t) -> (R^3)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R^3), v = bt; )"; - CHECK_AST(data, result); - } + std::string error_message = "undefined affectation type: (R^3) = (builtin_t)"; - SECTION("R /= R") - { - std::string_view data = R"( -let x : R, x=1; x/=2.3; + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + + SECTION("-> (R^1x1)") + { + SECTION("(R^1) -> (R^1x1)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R^1x1), b = t; )"; - std::string_view result = R"( -(root:ASTNodeListProcessor) - +-(language::eq_op:AffectationProcessor<language::eq_op, double, long>) - | +-(language::name:x:NameProcessor) - | `-(language::integer:1:ValueProcessor) - `-(language::divideeq_op:AffectationProcessor<language::divideeq_op, double, double>) - +-(language::name:x:NameProcessor) - `-(language::real:2.3:ValueProcessor) + std::string error_message = "undefined affectation type: (R^1x1) = (R^1)"; + + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2) -> (R^1x1)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R^1x1), b = t; )"; - CHECK_AST(data, result); - } - } + std::string error_message = "undefined affectation type: (R^1x1) = (R^2)"; - SECTION("Errors") - { - SECTION("Invalid affectation operator") - { - auto ast = std::make_unique<ASTNode>(); - ast->m_data_type = ASTNodeDataType::build<ASTNodeDataType::void_t>(); - { - auto child_0 = std::make_unique<ASTNode>(); - child_0->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); - auto child_1 = std::make_unique<ASTNode>(); - child_1->m_data_type = ASTNodeDataType::build<ASTNodeDataType::bool_t>(); - ast->children.emplace_back(std::move(child_0)); - ast->children.emplace_back(std::move(child_1)); - } - REQUIRE_THROWS_WITH(ASTNodeAffectationExpressionBuilder{*ast}, - "unexpected error: undefined affectation operator"); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid string rhs") - { - auto ast = std::make_unique<ASTNode>(); - ast->set_type<language::eq_op>(); + SECTION("(R^3) -> (R^1x1)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R^1x1), b = t; +)"; - 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}, "undefined affectation type: string = undefined"); - } + std::string error_message = "undefined affectation type: (R^1x1) = (R^3)"; - SECTION("Invalid string affectation operator") - { - SECTION("string -= string") - { - std::string_view data = R"( -let s : string, s="foo"; s-="bar"; + CHECK_AST_THROWS_WITH(data, error_message); + } + + SECTION("(R^2x2) -> (R^1x1)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R^1x1), b = t; )"; - std::string error_message = "undefined affectation type: string -= string"; + std::string error_message = "undefined affectation type: (R^1x1) = (R^2x2)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("string *= Z") - { - std::string_view data = R"( -let s : string, s="foo"; s*=2; + SECTION("(R^3x3) -> (R^1x1)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R^1x1), b = t; )"; - std::string error_message = "undefined affectation type: string *= Z"; + std::string error_message = "undefined affectation type: (R^1x1) = (R^3x3)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("string /= string") - { - std::string_view data = R"( - let s : string, s="foo"; s/="bar"; + SECTION("(string) -> (R^1x1)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^1x1), b = t; )"; - std::string error_message = "undefined affectation type: string /= string"; + std::string error_message = "undefined affectation type: (R^1x1) = (string)"; - CHECK_AST_THROWS_WITH(data, error_message); - } - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("type_id operator") - { - std::string_view data = R"( - let s :builtin_t, s = a; s *= b; + SECTION("(builtin_t) -> (R^1x1)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R^1x1), v = bt; )"; - std::string error_message = "undefined affectation type: builtin_t *= builtin_t"; + std::string error_message = "undefined affectation type: (R^1x1) = (builtin_t)"; - CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); - } + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } - SECTION("Invalid tuple operator") - { - std::string_view data = R"( - let s :(R), s=(1,2,3); s *= 4; + SECTION("-> (R^2x2)") + { + SECTION("(N) -> (R^2x2)") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:(R^2x2), b = n; )"; - std::string error_message = "undefined affectation type: (R) *= Z"; + std::string error_message = "undefined affectation type: (R^2x2) = (N)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid tuple operator 2") - { - std::string_view data = R"( - let s : (builtin_t), s =(a,b); s *= b; + SECTION("(R) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: (builtin_t) *= builtin_t"; + std::string error_message = "undefined affectation type: (R^2x2) = (R)"; - CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid R^n -> R^m affectation") - { - SECTION("R^3 <- R^1") - { - std::string_view data = R"( -let x : R^3; let y : R^1; x = y; + SECTION("(R^1) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^3 = R^1"; + std::string error_message = "undefined affectation type: (R^2x2) = (R^1)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^3 <- R^2") - { - std::string_view data = R"( -let x : R^3; let y : R^2; x = y; + SECTION("(R^2) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^3 = R^2"; + std::string error_message = "undefined affectation type: (R^2x2) = (R^2)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^2 <- R^1") - { - std::string_view data = R"( -let x : R^2; let y : R^1; x = y; + SECTION("(R^3) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^2 = R^1"; + std::string error_message = "undefined affectation type: (R^2x2) = (R^3)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^2 <- R^3") - { - std::string_view data = R"( -let x : R^2; let y : R^3; x = y; + SECTION("(R^1x1) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^2 = R^3"; + std::string error_message = "undefined affectation type: (R^2x2) = (R^1x1)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^1 <- R^2") - { - std::string_view data = R"( -let x : R^1; let y : R^2; x = y; + SECTION("(R^3x3) -> (R^2x2)") + { + std::string_view data = R"( +let t:(R^3x3), t = [[1.2, 3, 1],[1,2,3],[4,2,1]]; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^1 = R^2"; + std::string error_message = "undefined affectation type: (R^2x2) = (R^3x3)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^1 <- R^3") - { - std::string_view data = R"( -let x : R^1; let y : R^3; x = y; + SECTION("(string) -> (R^2x2)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^2x2), b = t; )"; - std::string error_message = "undefined affectation type: R^1 = R^3"; + std::string error_message = "undefined affectation type: (R^2x2) = (string)"; - CHECK_AST_THROWS_WITH(data, error_message); - } - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid Z -> R^m affectation [non-zero]") - { - SECTION("R^3 <- Z") - { - std::string_view data = R"( -let x : R^3, x = 3; + SECTION("(builtin_t) -> (R^2x2)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R^2x2), v = bt; )"; - std::string error_message = "invalid integral value (0 is the solely valid value)"; + std::string error_message = "undefined affectation type: (R^2x2) = (builtin_t)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } - SECTION("R^2 <- Z") - { - std::string_view data = R"( -let x : R^2, x = 2; + SECTION("-> (R^3x3)") + { + SECTION("(N) -> (R^3x3)") + { + std::string_view data = R"( +let n:(N), n = 1; +let b:(R^3x3), b = n; )"; - std::string error_message = "invalid integral value (0 is the solely valid value)"; + std::string error_message = "undefined affectation type: (R^3x3) = (N)"; - CHECK_AST_THROWS_WITH(data, error_message); - } - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid R^d -> R^d affectation operator") - { - SECTION("R^3 <- R^3") - { - std::string_view data = R"( -let x : R^3; let y : R^3; x /= y; + SECTION("(R) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R), t = 1.2; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^3 /= R^3"; + std::string error_message = "undefined affectation type: (R^3x3) = (R)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^2 <- R^2") - { - std::string_view data = R"( -let x : R^2; let y : R^2; x /= y; + SECTION("(R^1) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R^1), t = [1.2]; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^2 /= R^2"; + std::string error_message = "undefined affectation type: (R^3x3) = (R^1)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^1 <- R^1") - { - std::string_view data = R"( -let x : R^1; let y : R^1; x /= y; + SECTION("(R^2) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R^2), t = [1.2, 3]; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^1 /= R^1"; + std::string error_message = "undefined affectation type: (R^3x3) = (R^2)"; - CHECK_AST_THROWS_WITH(data, error_message); - } - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("Invalid R^d -> R^d *= operand") - { - SECTION("R^3 <- R^3") - { - std::string_view data = R"( -let x : R^3; let y : R^3; x *= y; + SECTION("(R^3) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R^3), t = [1.2, 3, 1]; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^3 *= R^3"; + std::string error_message = "undefined affectation type: (R^3x3) = (R^3)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^2 <- R^2") - { - std::string_view data = R"( -let x : R^2; let y : R^2; x *= y; + SECTION("(R^1x1) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R^1x1), t = [[1.2]]; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^2 *= R^2"; + std::string error_message = "undefined affectation type: (R^3x3) = (R^1x1)"; - CHECK_AST_THROWS_WITH(data, error_message); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("R^1 <- R^1") - { - std::string_view data = R"( -let x : R^1; let y : R^1; x *= y; + SECTION("(R^2x2) -> (R^3x3)") + { + std::string_view data = R"( +let t:(R^2x2), t = [[1.2, 3],[3,4]]; +let b:(R^3x3), b = t; )"; - std::string error_message = "undefined affectation type: R^1 *= R^1"; + std::string error_message = "undefined affectation type: (R^3x3) = (R^2x2)"; - CHECK_AST_THROWS_WITH(data, error_message); - } - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("incorrect declarative/definition number of symbols") - { - std::string_view data = R"( -let (x,y,z):R*R*R, (x,y) = (2,3); + SECTION("(string) -> (R^3x3)") + { + std::string_view data = R"( +let t:(string), t = "foo"; +let b:(R^3x3), b = t; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - OperatorRepository::instance().reset(); - ASTModulesImporter{*ast}; + std::string error_message = "undefined affectation type: (R^3x3) = (string)"; - ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, - std::string{"invalid number of definition identifiers, expecting 3 found 2"}); - } + CHECK_AST_THROWS_WITH(data, error_message); + } - SECTION("incorrect identifier/expression number of symbols") - { - std::string_view data = R"( -let y:R; -let x:R, (x,y) = (2,3); + SECTION("(builtin_t) -> (R^3)") + { + std::string_view data = R"( +let bt:(builtin_t), bt = a; +let v :(R^3x3), v = bt; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - OperatorRepository::instance().reset(); - ASTModulesImporter{*ast}; + std::string error_message = "undefined affectation type: (R^3x3) = (builtin_t)"; - ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, - std::string{"unexpected variable list, expecting one identifier"}); + CHECK_AST_WITH_BUILTIN_THROWS_WITH(data, error_message); + } + } + } + } } - SECTION("incorrect definition variable identifier") + SECTION("void as a type") { - std::string_view data = R"( -let y:R; -let x:R, y = 3; + SECTION("declaration") + { + std::string_view data = R"( +let a:void; )"; + std::string error_message = "'void' keyword does not define a type"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - OperatorRepository::instance().reset(); - ASTModulesImporter{*ast}; + { + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; - ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, std::string{"invalid identifier, expecting 'x'"}); - } + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); + } + } - SECTION("invalid definition variable identifier order") - { - std::string_view data = R"( -let (x,y):R, (y,x) = (3,2); + SECTION("definition") + { + std::string_view data = R"( +let a:void, a = 3; )"; - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - OperatorRepository::instance().reset(); - ASTModulesImporter{*ast}; + std::string error_message = "'void' keyword does not define a type"; - ASTSymbolTableBuilder{*ast}; - REQUIRE_THROWS_WITH(ASTSymbolInitializationChecker{*ast}, std::string{"invalid identifier, expecting 'x'"}); + { + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + OperatorRepository::instance().reset(); + ASTModulesImporter{*ast}; + + ASTSymbolTableBuilder{*ast}; + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error_message); + } + } } } } + +#ifdef __clang__ +#pragma clang optimize on +#endif // __clang__ diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 5c449d7abf9bc9f083bd7c8206d377360f0f229c..2a5777b32272c8c10ba39543c30b103d4f629439 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -414,7 +414,7 @@ let square : R -> R^3, x -> (x, 2); ASTSymbolTableBuilder{*ast}; REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, - "expecting 3 scalar expressions or an R^3, found 2 scalar expressions"); + "number of image spaces (1) R^3 differs from number of expressions (2) (x, 2)"); } } } @@ -1126,7 +1126,7 @@ let f : R -> R^2x2, x -> (x, 2*x, 2); ASTSymbolTableBuilder{*ast}; REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, - "expecting 4 scalar expressions or an R^2x2, found 3 scalar expressions"); + "number of image spaces (1) R^2x2 differs from number of expressions (3) (x, 2*x, 2)"); } SECTION("undefined type identifier") @@ -1180,6 +1180,30 @@ let f: R -> X, x -> x; REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "invalid type identifier, 'X' was previously defined as a 'R'"); } + + SECTION("invalid tuple type domain") + { + std::string_view data = R"( +let f: (R) -> R, x -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "cannot use tuple (R) as a domain for user functions"); + } + + SECTION("invalid tuple type in compound domain") + { + std::string_view data = R"( +let f: N*(R^2) -> R, (x,t) -> x; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, "cannot use tuple (R^2) as a domain for user functions"); + } } } diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index 762202a671b1f7708b193ca8cd6c7aa599bfc780..7d760d2224fe4bbfb836b409a035830efd18b6fa 100644 --- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp @@ -115,107 +115,111 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou TEST_CASE("ASTNodeFunctionExpressionBuilder", "[language]") { - SECTION("return a B") + SECTION("value or compounds of values") { - SECTION("B argument") + SECTION("without conversion") { - SECTION("B parameter") + SECTION("return a B") { - std::string_view data = R"( + SECTION("B argument") + { + SECTION("B parameter") + { + std::string_view data = R"( let not_v : B -> B, a -> not a; not_v(true); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:not_v:NameProcessor) `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } + } - SECTION("N argument") - { - std::string_view data = R"( + SECTION("N argument") + { + std::string_view data = R"( let test : N -> B, n -> n<10; test(2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:test:NameProcessor) `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Z argument") - { - std::string_view data = R"( + SECTION("Z argument") + { + std::string_view data = R"( let test : Z -> B, z -> z>3; test(2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:test:NameProcessor) `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R argument") - { - std::string_view data = R"( + SECTION("R argument") + { + std::string_view data = R"( let test : R -> B, x -> x>2.3; test(2.1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:test:NameProcessor) `-(language::real:2.1:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } + } - SECTION("return a N") - { - SECTION("N argument") - { - std::string_view data = R"( + SECTION("return a N") + { + SECTION("N argument") + { + std::string_view data = R"( let test : N -> N, n -> n+2; test(2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:test:NameProcessor) `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Z argument") - { - std::string_view data = R"( + SECTION("Z argument") + { + std::string_view data = R"( let absolute : Z -> N, z -> (z>0)*z -(z<=0)*z; absolute(-2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:absolute:NameProcessor) @@ -223,37 +227,37 @@ absolute(-2); `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } + } - SECTION("return a Z") - { - SECTION("N argument") - { - std::string_view data = R"( + SECTION("return a Z") + { + SECTION("N argument") + { + std::string_view data = R"( let minus : N -> Z, n -> -n; minus(true); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:minus:NameProcessor) `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Z argument") - { - std::string_view data = R"( + SECTION("Z argument") + { + std::string_view data = R"( let times_2 : Z -> Z, z -> z*2; times_2(-2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:times_2:NameProcessor) @@ -261,20 +265,20 @@ times_2(-2); `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } - } + CHECK_AST(data, result); + } + } - SECTION("return a string") - { - SECTION("string argument") - { - std::string_view data = R"( + SECTION("return a string") + { + SECTION("string argument") + { + std::string_view data = R"( let cat : string*string -> string, (s1,s2) -> s1+s2; cat("foo", "bar"); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:cat:NameProcessor) @@ -283,17 +287,17 @@ cat("foo", "bar"); `-(language::literal:"bar":ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("B argument conversion") - { - std::string_view data = R"( + SECTION("B argument conversion") + { + std::string_view data = R"( let cat : string*string -> string, (s1,s2) -> s1+s2; cat("foo", true); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:cat:NameProcessor) @@ -302,18 +306,18 @@ cat("foo", true); `-(language::true_kw:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("N argument conversion") - { - std::string_view data = R"( + SECTION("N argument conversion") + { + std::string_view data = R"( let cat : string*string -> string, (s1,s2) -> s1+s2; let n : N, n = 2; cat("foo", n); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:cat:NameProcessor) @@ -322,17 +326,17 @@ cat("foo", n); `-(language::name:n:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Z argument conversion") - { - std::string_view data = R"( + SECTION("Z argument conversion") + { + std::string_view data = R"( let cat : string*string -> string, (s1,s2) -> s1+s2; cat("foo", -1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:cat:NameProcessor) @@ -342,17 +346,17 @@ cat("foo", -1); `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("R argument conversion") - { - std::string_view data = R"( + SECTION("R argument conversion") + { + std::string_view data = R"( let cat : string*string -> string, (s1,s2) -> s1+s2; cat("foo", 2.5e-3); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:cat:NameProcessor) @@ -361,12 +365,13 @@ cat("foo", 2.5e-3); `-(language::real:2.5e-3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } + } - SECTION("Return R^1 -> R^1") - { - std::string_view data = R"( + SECTION("Return a R^1") + { + std::string_view data = R"( let f : R^1 -> R^1, x -> x+x; let x : R^1, x = 1; f(x); @@ -377,7 +382,7 @@ f(2); f(1.4); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) +-(language::function_evaluation:FunctionProcessor) | +-(language::name:f:NameProcessor) @@ -396,48 +401,48 @@ f(1.4); `-(language::real:1.4:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return R^2 -> R^2") - { - std::string_view data = R"( + SECTION("Return a R^2") + { + std::string_view data = R"( let f : R^2 -> R^2, x -> x+x; let x : R^2, x = (1,2); f(x); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::name:x:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return R^3 -> R^3") - { - std::string_view data = R"( + SECTION("Return a R^3") + { + std::string_view data = R"( let f : R^3 -> R^3, x -> x+x; let x : R^3, x = (1,2,3); f(x); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::name:x:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return R^1x1 -> R^1x1") - { - std::string_view data = R"( + SECTION("Return a R^1x1") + { + std::string_view data = R"( let f : R^1x1 -> R^1x1, x -> x+x; let x : R^1x1, x = 1; f(x); @@ -448,7 +453,7 @@ f(2); f(1.4); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) +-(language::function_evaluation:FunctionProcessor) | +-(language::name:f:NameProcessor) @@ -467,70 +472,70 @@ f(1.4); `-(language::real:1.4:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return R^2x2 -> R^2x2") - { - std::string_view data = R"( + SECTION("Return a R^2x2") + { + std::string_view data = R"( let f : R^2x2 -> R^2x2, x -> x+x; let x : R^2x2, x = (1,2,3,4); f(x); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::name:x:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return R^3x3 -> R^3x3") - { - std::string_view data = R"( + SECTION("Return a R^3x3") + { + std::string_view data = R"( let f : R^3x3 -> R^3x3, x -> x+x; let x : R^3x3, x = (1,2,3,4,5,6,7,8,9); f(x); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::name:x:NameProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return scalar -> R^1") - { - std::string_view data = R"( -let f : R -> R^1, x -> x+1; + SECTION("Return a R^1") + { + std::string_view data = R"( +let f : R -> R^1, x -> [x+1]; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return tuple -> R^2") - { - std::string_view data = R"( + SECTION("Return a R^2") + { + std::string_view data = R"( let f : R*R -> R^2, (x,y) -> [x,y]; f(1,2); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) @@ -539,17 +544,17 @@ f(1,2); `-(language::integer:2:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return tuple -> R^3") - { - std::string_view data = R"( + SECTION("Return a R^3") + { + std::string_view data = R"( let f : R*R*R -> R^3, (x,y,z) -> [x,y,z]; f(1,2,3); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) @@ -559,34 +564,34 @@ f(1,2,3); `-(language::integer:3:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return scalar -> R^1x1") - { - std::string_view data = R"( -let f : R -> R^1x1, x -> x+1; + SECTION("Return a R^1x1") + { + std::string_view data = R"( +let f : R -> R^1x1, x -> [[x+1]]; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return tuple -> R^2x2") - { - std::string_view data = R"( + SECTION("Return a R^2x2") + { + std::string_view data = R"( let f : R*R*R*R -> R^2x2, (x,y,z,t) -> [[x,y],[z,t]]; f(1,2,3,4); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) @@ -597,17 +602,17 @@ f(1,2,3,4); `-(language::integer:4:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return tuple -> R^3x3") - { - std::string_view data = R"( + SECTION("Return a R^3x3") + { + std::string_view data = R"( let f : R^3*R^3*R^3 -> R^3x3, (x,y,z) -> [[x[0],x[1],x[2]],[y[0],y[1],y[2]],[z[0],z[1],z[2]]]; f([1,2,3],[4,5,6],[7,8,9]); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) @@ -626,298 +631,360 @@ f([1,2,3],[4,5,6],[7,8,9]); `-(language::integer:9:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return '0' -> R^1") - { - std::string_view data = R"( -let f : R -> R^1, x -> 0; -f(1); + SECTION("return a builtin_t") + { + SECTION("builtin_t argument") + { + std::string_view data = R"( +let foo : builtin_t -> builtin_t, b -> b; +let b0 : builtin_t; +foo(b0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) - `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<1ul, double>, ZeroType>) - +-(language::name:f:NameProcessor) - `-(language::integer:1:ValueProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:foo:NameProcessor) + `-(language::name:b0:NameProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } + } } - SECTION("Return '0' -> R^2") + SECTION("with return conversion") { - std::string_view data = R"( + SECTION("Return scalar -> R^1") + { + std::string_view data = R"( +let f : R -> R^1, x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return scalar -> R^1x1") + { + std::string_view data = R"( +let f : R -> R^1x1, x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> R^1") + { + std::string_view data = R"( +let f : R -> R^1, x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<1ul, double>, ZeroType>) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> R^2") + { + std::string_view data = R"( let f : R -> R^2, x -> 0; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<2ul, double>, ZeroType>) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return '0' -> R^3") - { - std::string_view data = R"( + SECTION("Return '0' -> R^3") + { + std::string_view data = R"( let f : R -> R^3, x -> 0; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<3ul, double>, ZeroType>) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return '0' -> R^1x1") - { - std::string_view data = R"( + SECTION("Return '0' -> R^1x1") + { + std::string_view data = R"( let f : R -> R^1x1, x -> 0; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<1ul, 1ul, double>, ZeroType>) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return '0' -> R^2x2") - { - std::string_view data = R"( + SECTION("Return '0' -> R^2x2") + { + std::string_view data = R"( let f : R -> R^2x2, x -> 0; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<2ul, 2ul, double>, ZeroType>) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return '0' -> R^3x3") - { - std::string_view data = R"( + SECTION("Return '0' -> R^3x3") + { + std::string_view data = R"( let f : R -> R^3x3, x -> 0; f(1); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionExpressionProcessor<TinyMatrix<3ul, 3ul, double>, ZeroType>) +-(language::name:f:NameProcessor) `-(language::integer:1:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return embedded R^d compound") - { - std::string_view data = R"( -let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, [x], [x,y], [x,y,z]); -f(1,2,3,4); + SECTION("Arguments '0' -> R^1") + { + std::string_view data = R"( +let f : R^1 -> R^1, x -> x; +f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::function_argument_list:ASTNodeExpressionListProcessor) - +-(language::integer:1:ValueProcessor) - +-(language::integer:2:ValueProcessor) - +-(language::integer:3:ValueProcessor) - `-(language::integer:4:ValueProcessor) + `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return embedded R^dxd compound") - { - std::string_view data = R"( -let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, [[x]], [[x,y],[z,t]], [[x,y,z], [x,x,x], [t,t,t]]); -f(1,2,3,4); + SECTION("Arguments '0' -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x; +f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::function_argument_list:ASTNodeExpressionListProcessor) - +-(language::integer:1:ValueProcessor) - +-(language::integer:2:ValueProcessor) - +-(language::integer:3:ValueProcessor) - `-(language::integer:4:ValueProcessor) + `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return embedded R^d compound with '0'") - { - std::string_view data = R"( -let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, 0, 0, [x,y,z]); -f(1,2,3,4); + SECTION("Arguments '0' -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x; +f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::function_argument_list:ASTNodeExpressionListProcessor) - +-(language::integer:1:ValueProcessor) - +-(language::integer:2:ValueProcessor) - +-(language::integer:3:ValueProcessor) - `-(language::integer:4:ValueProcessor) + `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Return embedded R^dxd compound with '0'") - { - std::string_view data = R"( -let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, 0, 0, [[x, y, z], [t, x, y], [z, t, x]]); -f(1,2,3,4); + SECTION("Arguments '0' -> R^1x1") + { + std::string_view data = R"( +let f : R^1x1 -> R^1x1, x -> x; +f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::function_argument_list:ASTNodeExpressionListProcessor) - +-(language::integer:1:ValueProcessor) - +-(language::integer:2:ValueProcessor) - +-(language::integer:3:ValueProcessor) - `-(language::integer:4:ValueProcessor) + `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Arguments '0' -> R^1") - { - std::string_view data = R"( -let f : R^1 -> R^1, x -> x; + SECTION("Arguments '0' -> R^2x2") + { + std::string_view data = R"( +let f : R^2x2 -> R^2x2, x -> x; f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); - } + CHECK_AST(data, result); + } - SECTION("Arguments '0' -> R^2") - { - std::string_view data = R"( -let f : R^2 -> R^2, x -> x; + SECTION("Arguments '0' -> R^3x3") + { + std::string_view data = R"( +let f : R^3x3 -> R^3x3, x -> x; f(0); )"; - std::string_view result = R"( + std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) `-(language::integer:0:ValueProcessor) )"; - CHECK_AST(data, result); + CHECK_AST(data, result); + } } + } - SECTION("Arguments '0' -> R^3") + SECTION("compound return type") + { + SECTION("Return compound with R^d") { std::string_view data = R"( -let f : R^3 -> R^3, x -> x; -f(0); +let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, [x], [x,y], [x,y,z]); +f(1,2,3,4); )"; std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::integer:0:ValueProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("Arguments '0' -> R^1x1") + SECTION("Return compound with R^dxd") { std::string_view data = R"( -let f : R^1x1 -> R^1x1, x -> x; -f(0); +let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, [[x]], [[x,y],[z,t]], [[x,y,z], [x,x,x], [t,t,t]]); +f(1,2,3,4); )"; std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::integer:0:ValueProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("Arguments '0' -> R^2x2") + SECTION("Return R^d compound with '0'") { std::string_view data = R"( -let f : R^2x2 -> R^2x2, x -> x; -f(0); +let f : R*R*R*R -> R*R^1*R^2*R^3, (x,y,z,t) -> (t, 0, 0, [x,y,z]); +f(1,2,3,4); )"; std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::integer:0:ValueProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("Arguments '0' -> R^3x3") + SECTION("Return R^dxd compound with '0'") { std::string_view data = R"( -let f : R^3x3 -> R^3x3, x -> x; -f(0); +let f : R*R*R*R -> R*R^1x1*R^2x2*R^3x3, (x,y,z,t) -> (t, 0, 0, [[x, y, z], [t, x, y], [z, t, x]]); +f(1,2,3,4); )"; std::string_view result = R"( (root:ASTNodeListProcessor) `-(language::function_evaluation:FunctionProcessor) +-(language::name:f:NameProcessor) - `-(language::integer:0:ValueProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) )"; CHECK_AST(data, result); } - SECTION("Arguments tuple -> R^d") + SECTION("Arguments R^d") { std::string_view data = R"( let f: R^3 -> R, x -> x[0]+x[1]+x[2]; @@ -966,7 +1033,7 @@ f([[1,2,3],[4,5,6],[7,8,9]]); CHECK_AST(data, result); } - SECTION("Arguments compound with tuple") + SECTION("Arguments compound with R^d and R^dxd") { std::string_view data = R"( let f: R*R^3*R^2x2->R, (t,x,y) -> t*(x[0]+x[1]+x[2])*y[0,0]+y[1,1]; @@ -995,480 +1062,3006 @@ f(2,[1,2,3],[[2,3],[-1,1.3]]); CHECK_AST(data, result); } - } - SECTION("return a builtin_t") - { - SECTION("builtin_t argument") + SECTION("errors") { - std::string_view data = R"( -let foo : builtin_t -> builtin_t, b -> b; -let b0 : builtin_t; -foo(b0); + SECTION("wrong argument number") + { + std::string_view data = R"( +let Id : Z -> Z, z -> z; +Id(2,3); )"; - std::string_view result = R"( -(root:ASTNodeListProcessor) - `-(language::function_evaluation:FunctionProcessor) - +-(language::name:foo:NameProcessor) - `-(language::name:b0:NameProcessor) -)"; - - CHECK_AST(data, result); - } - } - - SECTION("errors") - { - SECTION("wrong argument number") - { - std::string_view data = R"( -let Id : Z -> Z, z -> z; -Id(2,3); -)"; - - CHECK_AST_THROWS(data); - } + CHECK_AST_THROWS(data); + } - SECTION("wrong argument number 2") - { - std::string_view data = R"( + SECTION("wrong argument number 2") + { + std::string_view data = R"( let sum : R*R -> R, (x,y) -> x+y; sum(2); )"; - CHECK_AST_THROWS(data); - } + CHECK_AST_THROWS(data); + } - SECTION("invalid return implicit conversion") - { - SECTION("string -> R") + SECTION("invalid return implicit conversion") { - std::string_view data = R"( + SECTION("string -> R") + { + std::string_view data = R"( let bad_conv : string -> R, s -> s; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); - } + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } - SECTION("R -> B") - { - std::string_view data = R"( + SECTION("R -> B") + { + std::string_view data = R"( let bad_B : R -> B, x -> x; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); - } + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } - SECTION("R -> N") - { - std::string_view data = R"( + SECTION("R -> N") + { + std::string_view data = R"( let next : R -> N, x -> x; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); - } + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } - SECTION("R -> Z") - { - std::string_view data = R"( + SECTION("R -> Z") + { + std::string_view data = R"( let prev : R -> Z, x -> x; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); - } + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } - SECTION("N -> B") - { - std::string_view data = R"( + SECTION("N -> B") + { + std::string_view data = R"( let bad_B : N -> B, n -> n; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); - } + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } - SECTION("Z -> B") - { - std::string_view data = R"( + SECTION("Z -> B") + { + std::string_view data = R"( let bad_B : Z -> B, n -> n; )"; - CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } } - } - SECTION("invalid argument implicit conversion") - { - SECTION("N -> B") + SECTION("invalid argument implicit conversion") { - std::string_view data = R"( + SECTION("N -> B") + { + std::string_view data = R"( let negate : B -> B, b -> not b; let n : N, n = 2; negate(n); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } - SECTION("Z -> B") - { - std::string_view data = R"( + SECTION("Z -> B") + { + std::string_view data = R"( let negate : B -> B, b -> not b; negate(3-4); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } - SECTION("R -> B") - { - std::string_view data = R"( + SECTION("R -> B") + { + std::string_view data = R"( let negate : B -> B, b -> not b; negate(3.24); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } - SECTION("R -> N") - { - std::string_view data = R"( + SECTION("R -> N") + { + std::string_view data = R"( let next : N -> N, n -> n+1; next(3.24); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } - SECTION("R -> Z") - { - std::string_view data = R"( + SECTION("R -> Z") + { + std::string_view data = R"( let prev : Z -> Z, z -> z-1; prev(3 + .24); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } - SECTION("B -> R^2") - { - std::string_view data = R"( + SECTION("B -> R^2") + { + std::string_view data = R"( let f : R^2 -> R^2, x -> x; f(true); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2"}); + } - SECTION("N -> R^2") - { - std::string_view data = R"( + SECTION("N -> R^2") + { + std::string_view data = R"( let f : R^2 -> R^2, x -> x; let n : N, n = 2; f(n); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2"}); + } - SECTION("Z -> R^2") - { - std::string_view data = R"( + SECTION("Z -> R^2") + { + std::string_view data = R"( let f : R^2 -> R^2, x -> x; f(-2); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + } - SECTION("R -> R^2") - { - std::string_view data = R"( + SECTION("R -> R^2") + { + std::string_view data = R"( let f : R^2 -> R^2, x -> x; f(1.3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2"}); + } - SECTION("B -> R^3") - { - std::string_view data = R"( + SECTION("B -> R^3") + { + std::string_view data = R"( let f : R^3 -> R^3, x -> x; f(true); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3"}); + } - SECTION("N -> R^3") - { - std::string_view data = R"( + SECTION("N -> R^3") + { + std::string_view data = R"( let f : R^3 -> R^3, x -> x; let n : N, n = 2; f(n); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3"}); + } - SECTION("Z -> R^3") - { - std::string_view data = R"( + SECTION("Z -> R^3") + { + std::string_view data = R"( let f : R^3 -> R^3, x -> x; f(-2); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"}); + } - SECTION("R -> R^3") - { - std::string_view data = R"( + SECTION("R -> R^3") + { + std::string_view data = R"( let f : R^3 -> R^3, x -> x; f(1.3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3"}); + } - SECTION("B -> R^2x2") - { - std::string_view data = R"( + SECTION("B -> R^2x2") + { + std::string_view data = R"( let f : R^2x2 -> R^2x2, x -> x; f(true); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2x2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2x2"}); + } - SECTION("N -> R^2x2") - { - std::string_view data = R"( + SECTION("N -> R^2x2") + { + std::string_view data = R"( let f : R^2x2 -> R^2x2, x -> x; let n : N, n = 2; f(n); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2x2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2x2"}); + } - SECTION("Z -> R^2x2") - { - std::string_view data = R"( + SECTION("Z -> R^2x2") + { + std::string_view data = R"( let f : R^2x2 -> R^2x2, x -> x; f(-2); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2x2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2x2"}); + } - SECTION("R -> R^2x2") - { - std::string_view data = R"( + SECTION("R -> R^2x2") + { + std::string_view data = R"( let f : R^2x2 -> R^2x2, x -> x; f(1.3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2x2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2x2"}); + } - SECTION("B -> R^3x3") - { - std::string_view data = R"( + SECTION("B -> R^3x3") + { + std::string_view data = R"( let f : R^3x3 -> R^3x3, x -> x; f(true); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3x3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3x3"}); + } - SECTION("N -> R^3x3") - { - std::string_view data = R"( + SECTION("N -> R^3x3") + { + std::string_view data = R"( let f : R^3x3 -> R^3x3, x -> x; let n : N, n = 2; f(n); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3x3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3x3"}); + } - SECTION("Z -> R^3x3") - { - std::string_view data = R"( + SECTION("Z -> R^3x3") + { + std::string_view data = R"( let f : R^3x3 -> R^3x3, x -> x; f(-2); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3x3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3x3"}); + } - SECTION("R -> R^3x3") - { - std::string_view data = R"( + SECTION("R -> R^3x3") + { + std::string_view data = R"( let f : R^3x3 -> R^3x3, x -> x; f(1.3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3x3"}); + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3x3"}); + } } - } - SECTION("arguments invalid tuple -> R^d conversion") - { - SECTION("tuple[2] -> R^2") + SECTION("arguments invalid tuple -> R^d conversion") { - std::string_view data = R"( + SECTION("tuple[2] -> R^2") + { + std::string_view data = R"( let f : R^2 -> R, x->x[0]; f((1,2)); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); + } - SECTION("tuple[3] -> R^3") - { - std::string_view data = R"( + SECTION("tuple[3] -> R^3") + { + std::string_view data = R"( let f : R^3 -> R, x->x[0]; f((1,2,3)); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); + } - SECTION("compound tuple[2] -> R^2") - { - std::string_view data = R"( + SECTION("compound -> R^2") + { + std::string_view data = R"( let f : R*R^2 -> R, (t,x)->x[0]; f(1,(1,2)); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); + } - SECTION("compound tuple[2] -> R^3") - { - std::string_view data = R"( + SECTION("compound -> R^3") + { + std::string_view data = R"( let f : R^3*R^2 -> R, (x,y)->x[0]*y[1]; f((1,2,3),[3,4]); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); + } - SECTION("list instead of tuple -> R^3") - { - std::string_view data = R"( + SECTION("list instead of tuple -> R^3") + { + std::string_view data = R"( let f : R^3 -> R, x -> x[0]*x[1]; f(1,2,3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 1, provided 3"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 1, provided 3"}); + } - SECTION("list instead of tuple -> R^3*R^2") - { - std::string_view data = R"( + SECTION("list instead of tuple -> R^3*R^2") + { + std::string_view data = R"( let f : R^3*R^2 -> R, (x,y) -> x[0]*x[1]-y[0]; f([1,2,3],2,3); )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 2, provided 3"}); + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 2, provided 3"}); + } } - } - SECTION("non pure function") - { - SECTION("argument modification") + SECTION("non pure function") { - SECTION("++ argument") + SECTION("argument modification") { - std::string_view data = R"( + SECTION("++ argument") + { + std::string_view data = R"( let non_pure : N -> N, x -> 3 * ++x; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("argument ++") - { - std::string_view data = R"( + SECTION("argument ++") + { + std::string_view data = R"( let non_pure : N -> N, x -> 1 + x ++; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("-- argument") - { - std::string_view data = R"( + SECTION("-- argument") + { + std::string_view data = R"( let non_pure : Z -> Z, x -> 3 * --x; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("argument --") - { - std::string_view data = R"( + SECTION("argument --") + { + std::string_view data = R"( let non_pure : Z -> Z, x -> 1 + x --; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } } - } - SECTION("outer variable modification") - { - SECTION("++ outer variable") + SECTION("outer variable modification") { - std::string_view data = R"( + SECTION("++ outer variable") + { + std::string_view data = R"( let a:N, a = 4; let non_pure : Z -> Z, x -> x * ++a; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("outer variable ++") - { - std::string_view data = R"( + SECTION("outer variable ++") + { + std::string_view data = R"( let a:N, a = 4; let non_pure : N -> N, x -> x + a++; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("-- outer variable") - { - std::string_view data = R"( + SECTION("-- outer variable") + { + std::string_view data = R"( let a:Z, a = 4; let non_pure : Z -> Z, x -> x * --a; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); - } + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } - SECTION("outer variable --") - { - std::string_view data = R"( + SECTION("outer variable --") + { + std::string_view data = R"( let a:Z, a = 4; let non_pure : Z -> Z, x -> x + a--; )"; - CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ - "invalid function definition. Function data must be constant!"}); + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } } } } } + + SECTION("tuples") + { + SECTION("from list of values") + { + SECTION("return a (B)") + { + SECTION("B argument") + { + SECTION("B parameter") + { + std::string_view data = R"( +let not_v : B -> (B), a -> (not a, a, true); +not_v(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:not_v:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("N argument") + { + std::string_view data = R"( +let test : N -> (B), n -> (n<10, n>1, false); +test(2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:test:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z argument") + { + std::string_view data = R"( +let test : Z -> (B), z -> (z>3, z<5); +test(2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:test:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R argument") + { + std::string_view data = R"( +let test : R -> (B), x -> (x>2.3, 2*x>3); +test(2.1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:test:NameProcessor) + `-(language::real:2.1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("return a (N)") + { + SECTION("N argument") + { + std::string_view data = R"( +let test : N -> (N), n -> (n+2, n, true); +test(2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:test:NameProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z argument") + { + std::string_view data = R"( +let absolute : Z -> (N), z -> ((z>0)*z -(z<=0)*z, 3, true); +absolute(-2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:absolute:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("return a (Z)") + { + SECTION("B argument") + { + std::string_view data = R"( +let minus : B -> (Z), b -> (-b, b, true); +minus(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:minus:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N argument") + { + std::string_view data = R"( +let minus : N -> (Z), n -> (-n, n, true); +minus(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:minus:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z argument") + { + std::string_view data = R"( +let times_2 : Z -> (Z), z -> (z*2, 2, false); +times_2(-2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:times_2:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("return a (R)") + { + SECTION("B argument") + { + std::string_view data = R"( +let minus : B -> (Z), b -> (-b, b, true); +minus(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:minus:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N argument") + { + std::string_view data = R"( +let minus : N -> (R), n -> (-n, n, true); +minus(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:minus:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z argument") + { + std::string_view data = R"( +let times_2 : Z -> (R), z -> (z*2, 2, false); +times_2(-2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:times_2:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R argument") + { + std::string_view data = R"( +let times_2 : R -> (R), r -> (r*2, 2, false); +times_2(-2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:times_2:NameProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("return a (string)") + { + SECTION("string argument") + { + std::string_view data = R"( +let cat : string*string -> (string), (s1,s2) -> (s1+s2, true, -3, 2.4); +cat("foo", "bar"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:cat:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::literal:"bar":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("B argument conversion") + { + std::string_view data = R"( +let cat : string*string -> (string), (s1,s2) -> (s1+s2, true, 2, 2.5); +cat("foo", true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:cat:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("N argument conversion") + { + std::string_view data = R"( +let cat : string*string -> (string), (s1,s2) -> (s1+s2, 4, [1.2], [2,2]); +let n : N, n = 2; +cat("foo", n); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:cat:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::name:n:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Z argument conversion") + { + std::string_view data = R"( +let cat : string*string -> (string), (s1,s2) -> (s1+s2, s2); +cat("foo", -1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:cat:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("R argument conversion") + { + std::string_view data = R"( +let cat : string*string -> (string), (s1,s2) -> (s1+s2, 1.3); +cat("foo", 2.5e-3); +)"; + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:cat:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::literal:"foo":ValueProcessor) + `-(language::real:2.5e-3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("Return a (R^1)") + { + std::string_view data = R"( +let f : R^1 -> (R^1), x -> (x+x, 2.3, [1.2]); +let x : R^1, x = 1; +f(x); +let n:N, n=1; +f(true); +f(n); +f(2); +f(1.4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::name:x:NameProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::true_kw:ValueProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::name:n:NameProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::real:1.4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2)") + { + std::string_view data = R"( +let f : R^2 -> (R^2), x -> (x+x, 0, [1, 3]); +let x : R^2, x = (1,2); +f(x); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::name:x:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3)") + { + std::string_view data = R"( +let f : R^3 -> (R^3), x -> (x+x, 2*x, [1,2,3], 0); +let x : R^3, x = (1,2,3); +f(x); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::name:x:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1x1)") + { + std::string_view data = R"( +let f : R^1x1 -> (R^1x1), x -> (x+x, [[1]], 3, 0); +let x : R^1x1, x = 1; +f(x); +let n:N, n=1; +f(true); +f(n); +f(2); +f(1.4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::name:x:NameProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::true_kw:ValueProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::name:n:NameProcessor) + +-(language::function_evaluation:FunctionProcessor) + | +-(language::name:f:NameProcessor) + | `-(language::integer:2:ValueProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::real:1.4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2x2)") + { + std::string_view data = R"( +let f : R^2x2 -> (R^2x2), x -> (x+x, 0, [[1,2],[3,4]]); +let x : R^2x2, x = (1,2,3,4); +f(x); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::name:x:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3x3)") + { + std::string_view data = R"( +let f : R^3x3 -> (R^3x3), x -> (x+x, 0, [[1,2,3],[4,5,6],[7,8,9]]); +let x : R^3x3, x = (1,2,3,4,5,6,7,8,9); +f(x); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::name:x:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (builtin_t)") + { + std::string_view data = R"( +let foo : builtin_t -> (builtin_t), b -> (b, b, b); +let b0 : builtin_t; +foo(b0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:foo:NameProcessor) + `-(language::name:b0:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("from single value") + { + SECTION("without conversion") + { + SECTION("Return a (B)") + { + std::string_view data = R"( +let f : B -> (B), b -> b; +f(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N)") + { + std::string_view data = R"( +let f : N -> (N), n -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z)") + { + std::string_view data = R"( +let f : Z -> (Z), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R)") + { + std::string_view data = R"( +let f : R -> (R), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (string)") + { + std::string_view data = R"( +let f : string -> (string), s -> s; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1)") + { + std::string_view data = R"( +let f : R -> (R^1), x -> [x+1]; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2)") + { + std::string_view data = R"( +let f : R*R -> (R^2), (x,y) -> [x,y]; +f(1,2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3)") + { + std::string_view data = R"( +let f : R*R*R -> (R^3), (x,y,z) -> [x,y,z]; +f(1,2,3); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + `-(language::integer:3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1x1)") + { + std::string_view data = R"( +let f : R -> (R^1x1), x -> [[x+1]]; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2x2)") + { + std::string_view data = R"( +let f : R*R*R*R -> (R^2x2), (x,y,z,t) -> [[x,y],[z,t]]; +f(1,2,3,4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3x3)") + { + std::string_view data = R"( +let f : R^3*R^3*R^3 -> (R^3x3), (x,y,z) -> [[x[0],x[1],x[2]],[y[0],y[1],y[2]],[z[0],z[1],z[2]]]; +f([1,2,3],[4,5,6],[7,8,9]); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:4:ValueProcessor) + | +-(language::integer:5:ValueProcessor) + | `-(language::integer:6:ValueProcessor) + `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + +-(language::integer:7:ValueProcessor) + +-(language::integer:8:ValueProcessor) + `-(language::integer:9:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("return a (builtin_t)") + { + std::string_view data = R"( +let foo : builtin_t -> (builtin_t), b -> b; +let b0 : builtin_t; +foo(b0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:foo:NameProcessor) + `-(language::name:b0:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("with conversion") + { + SECTION("Return a B -> (R^1)") + { + std::string_view data = R"( +let f : B -> (R^1), b -> b; +f(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a N -> (R^1)") + { + std::string_view data = R"( +let f : N -> (R^1), n -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a Z -> (R^1)") + { + std::string_view data = R"( +let f : Z -> (R^1), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a R -> (R^1)") + { + std::string_view data = R"( +let f : R -> (R^1), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a B -> (R^1x1)") + { + std::string_view data = R"( +let f : B -> (R^1x1), b -> b; +f(true); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::true_kw:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a N -> (R^1x1)") + { + std::string_view data = R"( +let f : N -> (R^1x1), n -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a Z -> (R^1x1)") + { + std::string_view data = R"( +let f : Z -> (R^1x1), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a R -> (R^1x1)") + { + std::string_view data = R"( +let f : R -> (R^1x1), x -> x+1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^1)") + { + std::string_view data = R"( +let f : R -> (R^1), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^2)") + { + std::string_view data = R"( +let f : R -> (R^2), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^3)") + { + std::string_view data = R"( +let f : R -> (R^3), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^1x1)") + { + std::string_view data = R"( +let f : R -> (R^1x1), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^2x2)") + { + std::string_view data = R"( +let f : R -> (R^2x2), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return '0' -> (R^3x3)") + { + std::string_view data = R"( +let f : R -> (R^3x3), x -> 0; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + } + + SECTION("from tuple value") + { + SECTION("without conversion") + { + SECTION("Return a (B)") + { + std::string_view data = R"( +let b:(B), b = (true, false); +let f : Z -> (B), z -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (N)") + { + std::string_view data = R"( +let b : (B), b = (true, false); +let f : N -> (N), n -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N)") + { + std::string_view data = R"( +let n : (N), n = (1, 2, 3); +let f : N -> (N), i -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z) -> (N)") + { + std::string_view data = R"( +let z : (Z), z = (1, 2, 3); +let f : N -> (Z), i -> z; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (Z)") + { + std::string_view data = R"( +let b : (B), b = (true, true); +let f : Z -> (Z), x -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N) -> (Z)") + { + std::string_view data = R"( +let n : (N), n = (1, 2, 3); +let f : Z -> (Z), x -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z)") + { + std::string_view data = R"( +let z : (Z), z = (1, 2, 3); +let f : Z -> (Z), x -> z; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (R)") + { + std::string_view data = R"( +let b:(B), b = (true, false); +let f : R -> (R), x -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N) -> (R)") + { + std::string_view data = R"( +let n:(N), n = (1, 2, 3); +let f : R -> (R), x -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z) -> (R)") + { + std::string_view data = R"( +let z:(Z), z = (1, -2, 3); +let f : R -> (R), x -> z; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R)") + { + std::string_view data = R"( +let r:(R), r = (1.1, -2, 3.2); +let f : R -> (R), x -> r; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (string)") + { + std::string_view data = R"( +let b : (B), b = (true, false); +let f : string -> (string), t -> b; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N) -> (string)") + { + std::string_view data = R"( +let n : (N), n = (1, 2, 3); +let f : string -> (string), t -> n; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z) -> (string)") + { + std::string_view data = R"( +let z : (Z), z = (1, -2, 3); +let f : string -> (string), t -> z; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R) -> (string)") + { + std::string_view data = R"( +let r : (R), r = (1, -2, 3); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1) -> (string)") + { + std::string_view data = R"( +let r : (R^1), r = (1, [-2], 3); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2) -> (string)") + { + std::string_view data = R"( +let r : (R^2), r = ([1, 2], [-2, 3], [3, -4]); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3) -> (string)") + { + std::string_view data = R"( +let r : (R^3), r = ([1, 2, 3], [0, -2, 3], [3, -4, 2]); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1x1) -> (string)") + { + std::string_view data = R"( +let r : (R^1x1), r = (1, [[-2]], 3); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2x2) -> (string)") + { + std::string_view data = R"( +let r : (R^2x2), r = ([[1, 2], [-2, 3]], [[3, -4], [2, 1]]); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3x3) -> (string)") + { + std::string_view data = R"( +let r : (R^3x3), r = ([[1, 2, 3], [0, -2, 3], [3, -4, 2]], 0); +let f : string -> (string), t -> r; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (string)") + { + std::string_view data = R"( +let s : (string), s = ("foo", "bar"); +let f : string -> (string), t -> s; +f("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (R^1)") + { + std::string_view data = R"( +let b : (B), b = (true, false); +let f : R -> (R^1), x -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N) -> (R^1)") + { + std::string_view data = R"( +let n : (N), n = (1, 2, 3); +let f : R -> (R^1), x -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z) -> (R^1)") + { + std::string_view data = R"( +let z : (Z), z = (1, 2, 3); +let f : R -> (R^1), x -> z; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R) -> (R^1)") + { + std::string_view data = R"( +let r : (R), r = (1, 2, 3); +let f : R -> (R^1), x -> r; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1)") + { + std::string_view data = R"( +let r1 : (R^1), r1 = (1, 2, 3); +let f : R -> (R^1), x -> r1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2)") + { + std::string_view data = R"( +let r2: (R^2), r2 = ([1, 2], [3, 4], 0); +let f : R*R -> (R^2), (x,y) -> r2; +f(1,2); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3)") + { + std::string_view data = R"( +let r3: (R^3), r3 = ([1, 2, 3], [1, 3, 4], 0); +let f : R*R*R -> (R^3), (x,y,z) -> r3; +f(1,2,3); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + `-(language::integer:3:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (B) -> (R^1x1)") + { + std::string_view data = R"( +let b: (B), b = (false, true); +let f : R -> (R^1x1), x -> b; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (N) -> (R^1x1)") + { + std::string_view data = R"( +let n: (N), n = (1, 2, 3); +let f : R -> (R^1x1), x -> n; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (Z) -> (R^1x1)") + { + std::string_view data = R"( +let z: (Z), z = (1, -2, 3); +let f : R -> (R^1x1), x -> z; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R) -> (R^1x1)") + { + std::string_view data = R"( +let r: (R), r = (1, -2, 3); +let f : R -> (R^1x1), x -> r; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^1x1)") + { + std::string_view data = R"( +let r1: (R^1x1), r1 = (1, -2, 3); +let f : R -> (R^1x1), x -> r1; +f(1); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^2x2)") + { + std::string_view data = R"( +let r2: (R^2x2), r2 = ([1, -2], [3, 2], 0); +let f : R*R*R*R -> (R^2x2), (x,y,z,t) -> r2; +f(1,2,3,4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return a (R^3x3)") + { + std::string_view data = R"( +let r3: (R^3x3), r3 = ([1, -2, 2], [3, 1, 2], 0); +let f : R^3*R^3*R^3 -> (R^3x3), (x,y,z) -> r3; +f([1,2,3],[4,5,6],[7,8,9]); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:4:ValueProcessor) + | +-(language::integer:5:ValueProcessor) + | `-(language::integer:6:ValueProcessor) + `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + +-(language::integer:7:ValueProcessor) + +-(language::integer:8:ValueProcessor) + `-(language::integer:9:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("return a (builtin_t)") + { + std::string_view data = R"( +let b0 : builtin_t; +let bt : (builtin_t), bt = (b0, b0, b0); +let foo : builtin_t -> (builtin_t), b -> bt; +foo(b0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:foo:NameProcessor) + `-(language::name:b0:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + } + + SECTION("Return tuple in compound") + { + SECTION("Return (R^d) in compound") + { + std::string_view data = R"( +let b0 : builtin_t; +let f : R*R*builtin_t*R*R -> R*R^1*(R^2)*(builtin_t)*(R^3), (x,y,b,z,t) -> (t, [x], [x,y], (b,b), ([x,y,z], 0)); +f(1,2,b0,3,4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::name:b0:NameProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return (R^dxd) in compound") + { + std::string_view data = R"( +let f : R*R*R*R -> R*R^1x1*(R^2x2)*(R^3x3), (x,y,z,t) -> (t, [[x]], (0,[[x,y],[z,t]]), ([[x,y,z], [x,x,x], [t,t,t]], 0)); +f(1,2,3,4); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + +-(language::integer:2:ValueProcessor) + +-(language::integer:3:ValueProcessor) + `-(language::integer:4:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("errors") + { + SECTION("wrong argument number") + { + std::string_view data = R"( +let Id : Z -> Z, z -> z; +Id(2,3); +)"; + + CHECK_AST_THROWS(data); + } + + SECTION("wrong argument number 2") + { + std::string_view data = R"( +let sum : R*R -> R, (x,y) -> x+y; +sum(2); +)"; + + CHECK_AST_THROWS(data); + } + + SECTION("tuple as domain") + { + SECTION("basic type string") + { + std::string_view data = R"( +let bad_tuple : (string) -> N, s -> 2; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"cannot use tuple (string) as a domain for user functions"}); + } + + SECTION("basic type R") + { + std::string_view data = R"( +let bad_tuple : (R) -> R, x -> 2; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"cannot use tuple (R) as a domain for user functions"}); + } + } + + SECTION("invalid return implicit conversion") + { + SECTION("string -> R") + { + std::string_view data = R"( +let bad_conv : string -> R, s -> s; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } + + SECTION("string -> R") + { + std::string_view data = R"( +let bad_conv : R -> R, x -> "foo"; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } + + SECTION("string -> (R)") + { + std::string_view data = R"( +let bad_conv : R -> (R), x -> (x, "bar"); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } + + SECTION("string -> (R) 2") + { + std::string_view data = R"( +let bad_conv : R -> (R), x -> "bar"; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } + + SECTION("R -> B") + { + std::string_view data = R"( +let bad_B : R -> B, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } + + SECTION("R -> (B)") + { + std::string_view data = R"( +let bad_B : R -> (B), x -> (true, x, false); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } + + SECTION("R -> (B) 2") + { + std::string_view data = R"( +let bad_B : R -> (B), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } + + SECTION("R -> N") + { + std::string_view data = R"( +let next : R -> N, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } + + SECTION("R -> (N)") + { + std::string_view data = R"( +let next : R -> (N), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } + + SECTION("R -> (N) 2") + { + std::string_view data = R"( +let next : R -> (N), x -> (6, 2, x); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } + + SECTION("R -> Z") + { + std::string_view data = R"( +let prev : R -> Z, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } + + SECTION("R -> (Z)") + { + std::string_view data = R"( +let prev : R -> (Z), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } + + SECTION("R -> (Z) 2") + { + std::string_view data = R"( +let prev : R -> (Z), x -> (x, 2, -3); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } + + SECTION("N -> B") + { + std::string_view data = R"( +let bad_B : N -> B, n -> n; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } + + SECTION("N -> (B)") + { + std::string_view data = R"( +let bad_B : N -> (B), n -> n; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } + + SECTION("N -> (B)") + { + std::string_view data = R"( +let bad_B : N -> (B), n -> (true, n); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } + + SECTION("Z -> B") + { + std::string_view data = R"( +let bad_B : Z -> B, n -> n; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } + + SECTION("Z -> (B)") + { + std::string_view data = R"( +let bad_B : Z -> (B), n -> n; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } + + SECTION("Z -> (B)") + { + std::string_view data = R"( +let bad_B : Z -> (B), n -> (true, n, true); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } + + SECTION("Z -> R^2") + { + std::string_view data = R"( +let bad_B : Z -> R^2, n -> 1; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + } + + SECTION("Z -> (R^2)") + { + std::string_view data = R"( +let bad_B : Z -> (R^2), n -> (n, [2,1]); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + } + + SECTION("R^1 -> R^2") + { + std::string_view data = R"( +let bad_B : R^1 -> R^2, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2"}); + } + + SECTION("R^1 -> (R^2)") + { + std::string_view data = R"( +let bad_B : R^1 -> (R^2), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2"}); + } + + SECTION("R^1 -> (R^2)") + { + std::string_view data = R"( +let bad_B : R^1 -> (R^2), x -> ([1,2], x); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2"}); + } + + SECTION("Z -> (R^3)") + { + std::string_view data = R"( +let bad_B : Z -> (R^3), n -> (n, [2,1,2]); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"}); + } + + SECTION("R^1 -> R^3") + { + std::string_view data = R"( +let bad_B : R^1 -> R^3, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3"}); + } + + SECTION("R^1 -> (R^3)") + { + std::string_view data = R"( +let bad_B : R^1 -> (R^3), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3"}); + } + + SECTION("R^1 -> (R^3)") + { + std::string_view data = R"( +let bad_B : R^1 -> (R^3), x -> ([1,2,2], x); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3"}); + } + + SECTION("R^2 -> R^3") + { + std::string_view data = R"( +let bad_B : R^2 -> R^3, x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"}); + } + + SECTION("R^2 -> (R^3)") + { + std::string_view data = R"( +let bad_B : R^2 -> (R^3), x -> x; +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"}); + } + + SECTION("R^2 -> (R^3)") + { + std::string_view data = R"( +let bad_B : R^2 -> (R^3), x -> ([1,2,5], x); +)"; + + CHECK_TYPE_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"}); + } + } + + SECTION("invalid argument implicit conversion") + { + SECTION("N -> B") + { + std::string_view data = R"( +let negate : B -> B, b -> not b; +let n : N, n = 2; +negate(n); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } + + SECTION("Z -> B") + { + std::string_view data = R"( +let negate : B -> B, b -> not b; +negate(3-4); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } + + SECTION("R -> B") + { + std::string_view data = R"( +let negate : B -> B, b -> not b; +negate(3.24); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } + + SECTION("R -> N") + { + std::string_view data = R"( +let next : N -> N, n -> n+1; +next(3.24); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } + + SECTION("R -> Z") + { + std::string_view data = R"( +let prev : Z -> Z, z -> z-1; +prev(3 + .24); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } + + SECTION("B -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x; +f(true); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2"}); + } + + SECTION("N -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x; +let n : N, n = 2; +f(n); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2"}); + } + + SECTION("Z -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x; +f(-2); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + } + + SECTION("R -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x; +f(1.3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2"}); + } + + SECTION("B -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x; +f(true); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3"}); + } + + SECTION("N -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x; +let n : N, n = 2; +f(n); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3"}); + } + + SECTION("Z -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x; +f(-2); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"}); + } + + SECTION("R -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x; +f(1.3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3"}); + } + + SECTION("B -> R^2x2") + { + std::string_view data = R"( +let f : R^2x2 -> R^2x2, x -> x; +f(true); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2x2"}); + } + + SECTION("N -> R^2x2") + { + std::string_view data = R"( +let f : R^2x2 -> R^2x2, x -> x; +let n : N, n = 2; +f(n); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2x2"}); + } + + SECTION("Z -> R^2x2") + { + std::string_view data = R"( +let f : R^2x2 -> R^2x2, x -> x; +f(-2); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2x2"}); + } + + SECTION("R -> R^2x2") + { + std::string_view data = R"( +let f : R^2x2 -> R^2x2, x -> x; +f(1.3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2x2"}); + } + + SECTION("B -> R^3x3") + { + std::string_view data = R"( +let f : R^3x3 -> R^3x3, x -> x; +f(true); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3x3"}); + } + + SECTION("N -> R^3x3") + { + std::string_view data = R"( +let f : R^3x3 -> R^3x3, x -> x; +let n : N, n = 2; +f(n); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3x3"}); + } + + SECTION("Z -> R^3x3") + { + std::string_view data = R"( +let f : R^3x3 -> R^3x3, x -> x; +f(-2); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3x3"}); + } + + SECTION("R -> R^3x3") + { + std::string_view data = R"( +let f : R^3x3 -> R^3x3, x -> x; +f(1.3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3x3"}); + } + } + + SECTION("arguments invalid tuple -> R^d conversion") + { + SECTION("tuple[2] -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R, x->x[0]; +f((1,2)); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); + } + + SECTION("tuple[3] -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R, x->x[0]; +f((1,2,3)); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); + } + + SECTION("compound -> R^2") + { + std::string_view data = R"( +let f : R*R^2 -> R, (t,x)->x[0]; +f(1,(1,2)); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^2"}); + } + + SECTION("compound -> R^3") + { + std::string_view data = R"( +let f : R^3*R^2 -> R, (x,y)->x[0]*y[1]; +f((1,2,3),[3,4]); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"cannot convert list to R^3"}); + } + + SECTION("list instead of tuple -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R, x -> x[0]*x[1]; +f(1,2,3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 1, provided 3"}); + } + + SECTION("list instead of tuple -> R^3*R^2") + { + std::string_view data = R"( +let f : R^3*R^2 -> R, (x,y) -> x[0]*x[1]-y[0]; +f([1,2,3],2,3); +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{"bad number of arguments: expecting 2, provided 3"}); + } + } + + SECTION("non pure function") + { + SECTION("argument modification") + { + SECTION("++ argument") + { + std::string_view data = R"( +let non_pure : N -> N, x -> 3 * ++x; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("argument ++") + { + std::string_view data = R"( +let non_pure : N -> N, x -> 1 + x ++; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("-- argument") + { + std::string_view data = R"( +let non_pure : Z -> Z, x -> 3 * --x; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("argument --") + { + std::string_view data = R"( +let non_pure : Z -> Z, x -> 1 + x --; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + } + + SECTION("outer variable modification") + { + SECTION("++ outer variable") + { + std::string_view data = R"( +let a:N, a = 4; +let non_pure : Z -> Z, x -> x * ++a; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("outer variable ++") + { + std::string_view data = R"( +let a:N, a = 4; +let non_pure : N -> N, x -> x + a++; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("-- outer variable") + { + std::string_view data = R"( +let a:Z, a = 4; +let non_pure : Z -> Z, x -> x * --a; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + + SECTION("outer variable --") + { + std::string_view data = R"( +let a:Z, a = 4; +let non_pure : Z -> Z, x -> x + a--; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } + } + } + } + } + + SECTION("empty functions") + { + SECTION("void -> value") + { + std::string_view data = R"( +let f:void -> R, void -> 2.3; + +f(); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("void -> compound") + { + std::string_view data = R"( +let f:void -> R*(Z)*R^2, void -> (2.3, (1,2,3), [1.2, 2.3]); + +f(); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("errors") + { + SECTION("void as a parameter") + { + std::string_view data = R"( +let g:R -> R, void -> 2; +)"; + + std::string error = "unexpected 'void' keyword"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error); + } + + SECTION("void as a parameter") + { + std::string_view data = R"( +let g:void -> R, x -> 2; +)"; + + std::string error = "expecting 'void' keyword"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTNodeDataTypeBuilder{*ast}, error); + } + + SECTION("void in compound domain") + { + std::string_view data = R"( +let h:R*void -> R, (x,void) -> 2.5; +)"; + + std::string error = "parse error, expecting type specifier"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + // auto ast = ASTBuilder::build(input); + + // ASTModulesImporter{*ast}; + // ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + // ASTSymbolTableBuilder{*ast}; + // ASTNodeDataTypeBuilder{*ast}; + + REQUIRE_THROWS_WITH(ASTBuilder::build(input), error); + } + + SECTION("void in compound codomain") + { + std::string_view data = R"( +let h:R*void -> R, (x,void) -> 2.5; +)"; + std::string error = "parse error, expecting type specifier"; + + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + REQUIRE_THROWS_WITH(ASTBuilder::build(input), error); + } + } + } } diff --git a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp index 7af93f6fb54b60dedad9e25f0504e69424613436..3f71228607f80f2ac04ad69fc408258ced89b413 100644 --- a/tests/test_ASTNodeListAffectationExpressionBuilder.cpp +++ b/tests/test_ASTNodeListAffectationExpressionBuilder.cpp @@ -61,25 +61,37 @@ const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const dou REQUIRE(ast_output.str() == expected_output); \ } -#define CHECK_AST_THROWS_WITH(data, error) \ - { \ - static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ - static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>); \ - \ - TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ - auto ast = ASTBuilder::build(input); \ - \ - ASTModulesImporter{*ast}; \ - ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ - \ - ASTSymbolTableBuilder{*ast}; \ - ASTNodeDataTypeBuilder{*ast}; \ - \ - ASTNodeDeclarationToAffectationConverter{*ast}; \ - ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ - ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \ - \ - REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error); \ +#define CHECK_AST_THROWS_WITH(data, error) \ + { \ + static_assert(std::is_same_v<std::decay_t<decltype(data)>, std::string_view>); \ + static_assert(std::is_same_v<std::decay_t<decltype(error)>, std::string>); \ + \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTModulesImporter{*ast}; \ + BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \ + \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + SymbolTable& symbol_table = *ast->m_symbol_table; \ + auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin()); \ + if (not success) { \ + throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); \ + } \ + \ + i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); \ + i_symbol->attributes().setIsInitialized(); \ + i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); \ + symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; \ + \ + REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error); \ } // clazy:excludeall=non-pod-global-static @@ -1507,106 +1519,1607 @@ let (b0,b1): builtin_t*builtin_t, (b0,b1) = (b0,b1); } } - SECTION("Errors") + SECTION("list from tuple") { - SECTION("invalid affectation rhs") + SECTION("(B) -> list") { std::string_view data = R"( -let x:R; -let i:R; -(x,i) = 3; +let t : (B), t = (true, false, true, false, false, true, false); +let (b,n,z,r,x1,x11,s):B*N*Z*R*R^1*R^1x1*string, + (b,n,z,r,x1,x11,s) = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<bool>) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::true_kw:ValueProcessor) + | +-(language::false_kw:ValueProcessor) + | +-(language::true_kw:ValueProcessor) + | +-(language::false_kw:ValueProcessor) + | +-(language::false_kw:ValueProcessor) + | +-(language::true_kw:ValueProcessor) + | `-(language::false_kw:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, bool>) + +-(language::name_list:FakeProcessor) + | +-(language::name:b:NameProcessor) + | +-(language::name:n:NameProcessor) + | +-(language::name:z:NameProcessor) + | +-(language::name:r:NameProcessor) + | +-(language::name:x1:NameProcessor) + | +-(language::name:x11:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid right hand side in tuple affectation"}); + CHECK_AST(data, result); } - SECTION("incompatible list sizes") + SECTION("(N) -> list") { std::string_view data = R"( -let (x,y) : R*R, (x,y) = (3, 3, 2); +let t : (N), t = (1, 3, 6, 2, 7, 1); +let (n,z,r,x1,x11,s):N*Z*R*R^1*R^1x1*string, + (n,z,r,x1,x11,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<unsigned long>) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:3:ValueProcessor) + | +-(language::integer:6:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | +-(language::integer:7:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, unsigned long>) + +-(language::name_list:FakeProcessor) + | +-(language::name:n:NameProcessor) + | +-(language::name:z:NameProcessor) + | +-(language::name:r:NameProcessor) + | +-(language::name:x1:NameProcessor) + | +-(language::name:x11:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("incompatible list sizes 2") + SECTION("(Z) -> list") { std::string_view data = R"( -let (x,y,z):R*R*R, (x,y,z) = (1, 2); +let t : (Z), t = (1, 3, 6, 2, 7, 1); +let (n,z,r,x1,x11,s):N*Z*R*R^1*R^1x1*string, + (n,z,r,x1,x11,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<long>) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:3:ValueProcessor) + | +-(language::integer:6:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | +-(language::integer:7:ValueProcessor) + | `-(language::integer:1:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, long>) + +-(language::name_list:FakeProcessor) + | +-(language::name:n:NameProcessor) + | +-(language::name:z:NameProcessor) + | +-(language::name:r:NameProcessor) + | +-(language::name:x1:NameProcessor) + | +-(language::name:x11:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("incompatible list sizes from function evaluation") + SECTION("(R) -> list") { std::string_view data = R"( -let f: R -> R, x -> x*x; -let(x,y) : R*R, (x,y) = f(3); +let t : (R), t = (6.2, -2.1, 7.2, 3); +let (r,x1,x11,s):R*R^1*R^1x1*string, + (r,x1,x11,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<double>) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::real:6.2:ValueProcessor) + | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | | `-(language::real:2.1:ValueProcessor) + | +-(language::real:7.2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, double>) + +-(language::name_list:FakeProcessor) + | +-(language::name:r:NameProcessor) + | +-(language::name:x1:NameProcessor) + | +-(language::name:x11:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("incompatible list sizes from function evaluation") + SECTION("(R^1) -> list") { std::string_view data = R"( -let(x,y):R*R,(x,y)=(2,3); -(x,y) += (1,4); +let t : (R^1), t = (6.2, [-2.1]); +let (x1,s):R^1*string, + (x1,s) = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::real:6.2:ValueProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<1ul>) + | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | `-(language::real:2.1:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<1ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x1:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation operator for tuples"}); + CHECK_AST(data, result); } - SECTION("invalid operand type for affectation") + SECTION("(R^2) -> list") { std::string_view data = R"( -let f: R -> R, x -> x+1; -let (x,y) : R*R, (x,y) = (f,2); +let t : (R^2), t = ([6.2, -2.1], 0); +let (x2,s):R^2*string, + (x2,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> R"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::vector_expression:TinyVectorExpressionProcessor<2ul>) + | | +-(language::real:6.2:ValueProcessor) + | | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | | `-(language::real:2.1:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<2ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x2:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("invalid operand type for string affectation") + SECTION("(R^3) -> list") { std::string_view data = R"( -let f: R -> R, x -> x+1; -let (s,n):string*N, (s,n) = (f,2); +let t : (R^3), t = ([6.2, -2.1, 0], [1, 2, 3]); +let (x3,s):R^3*string, + (x3,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> string"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyVector<3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | | +-(language::real:6.2:ValueProcessor) + | | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | | | `-(language::real:2.1:ValueProcessor) + | | `-(language::integer:0:ValueProcessor) + | `-(language::vector_expression:TinyVectorExpressionProcessor<3ul>) + | +-(language::integer:1:ValueProcessor) + | +-(language::integer:2:ValueProcessor) + | `-(language::integer:3:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyVector<3ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x3:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("invalid value type for affectation") + SECTION("(R^1x1) -> list") { std::string_view data = R"( -let f: R -> R, x -> x+1; -let x:R; +let t : (R^1x1), t = (6.2, [[-2.1]]); +let (x11,s):R^1x1*string, + (x11,s) = t; +)"; -(f,x) = (3,2); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<1ul, 1ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::real:6.2:ValueProcessor) + | `-(language::matrix_expression:TinyMatrixExpressionProcessor<1ul, 1ul>) + | `-(language::row_expression:FakeProcessor) + | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | `-(language::real:2.1:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<1ul, 1ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x11:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> function"}); + CHECK_AST(data, result); } - SECTION("invalid R^n -> R^m conversion") + SECTION("(R^2x2) -> list") { std::string_view data = R"( -let x:R^2, x = [1,2]; -let y:R^3, y = x; +let t : (R^2x2), t = ([[6.2, -2.1],[1, 2]], 0); +let (x22,s):R^2x2*string, + (x22,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation type: R^3 = R^2"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<2ul, 2ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::matrix_expression:TinyMatrixExpressionProcessor<2ul, 2ul>) + | | +-(language::row_expression:FakeProcessor) + | | | +-(language::real:6.2:ValueProcessor) + | | | `-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | | | `-(language::real:2.1:ValueProcessor) + | | `-(language::row_expression:FakeProcessor) + | | +-(language::integer:1:ValueProcessor) + | | `-(language::integer:2:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<2ul, 2ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x22:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); } - SECTION("invalid Z -> R^d conversion (non-zero)") + SECTION("(R^3x3) -> list") { std::string_view data = R"( -let x:R^2, x = 1; +let t : (R^3x3), t = ([[6.2, -2.1, 0], [1, 2, 3], [0, -2, 1]], 0); +let (x33,s):R^3x3*string, + (x33,s) = t; )"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid integral value (0 is the solely valid value)"}); + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<TinyMatrix<3ul, 3ul, double> >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::matrix_expression:TinyMatrixExpressionProcessor<3ul, 3ul>) + | | +-(language::row_expression:FakeProcessor) + | | | +-(language::real:6.2:ValueProcessor) + | | | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, double, double>) + | | | | `-(language::real:2.1:ValueProcessor) + | | | `-(language::integer:0:ValueProcessor) + | | +-(language::row_expression:FakeProcessor) + | | | +-(language::integer:1:ValueProcessor) + | | | +-(language::integer:2:ValueProcessor) + | | | `-(language::integer:3:ValueProcessor) + | | `-(language::row_expression:FakeProcessor) + | | +-(language::integer:0:ValueProcessor) + | | +-(language::unary_minus:UnaryExpressionProcessor<language::unary_minus, long, long>) + | | | `-(language::integer:2:ValueProcessor) + | | `-(language::integer:1:ValueProcessor) + | `-(language::integer:0:ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, TinyMatrix<3ul, 3ul, double> >) + +-(language::name_list:FakeProcessor) + | +-(language::name:x33:NameProcessor) + | `-(language::name:s:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(string) -> list") + { + std::string_view data = R"( +let t : (string), t = ("foo", "bar", "foobar"); +let (s1,s2,s3):string*string*string, + (s1,s2,s3) = t; +)"; + + std::string result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<)" + + demangled_stdstring + R"( >) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::literal:"foo":ValueProcessor) + | +-(language::literal:"bar":ValueProcessor) + | `-(language::literal:"foobar":ValueProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, )" + + demangled_stdstring + R"( >) + +-(language::name_list:FakeProcessor) + | +-(language::name:s1:NameProcessor) + | +-(language::name:s2:NameProcessor) + | `-(language::name:s3:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("(builtin_t) -> list") + { + std::string_view data = R"( +let b: builtin_t, b = b; +let t: (builtin_t), t = (b,b,b); +let (b1,b2,b3): builtin_t*builtin_t*builtin_t, (b1,b2,b3) = t; +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + +-(language::eq_op:AffectationProcessor<language::eq_op, EmbeddedData, EmbeddedData>) + | +-(language::name:b:NameProcessor) + | `-(language::name:b:NameProcessor) + +-(language::eq_op:AffectationToTupleFromListProcessor<EmbeddedData>) + | +-(language::name:t:NameProcessor) + | `-(language::expression_list:ASTNodeExpressionListProcessor) + | +-(language::name:b:NameProcessor) + | +-(language::name:b:NameProcessor) + | `-(language::name:b:NameProcessor) + `-(language::eq_op:ListAffectationFromTupleProcessor<language::eq_op, EmbeddedData>) + +-(language::name_list:FakeProcessor) + | +-(language::name:b1:NameProcessor) + | +-(language::name:b2:NameProcessor) + | `-(language::name:b3:NameProcessor) + `-(language::name:t:NameProcessor) +)"; + + CHECK_AST(data, result); + } + } + + SECTION("Errors") + { + SECTION("invalid affectation rhs") + { + std::string_view data = R"( +let x:R; +let i:R; +(x,i) = 3; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid right hand side in list affectation"}); + } + + SECTION("incompatible list sizes") + { + std::string_view data = R"( +let (x,y) : R*R, (x,y) = (3, 3, 2); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + } + + SECTION("incompatible list sizes 2") + { + std::string_view data = R"( +let (x,y,z):R*R*R, (x,y,z) = (1, 2); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + } + + SECTION("incompatible list sizes from function evaluation") + { + std::string_view data = R"( +let f: R -> R, x -> x*x; +let(x,y) : R*R, (x,y) = f(3); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"incompatible list sizes in affectation"}); + } + + SECTION("incompatible list sizes from function evaluation") + { + std::string_view data = R"( +let(x,y):R*R,(x,y)=(2,3); +(x,y) += (1,4); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation operator for lists"}); + } + + SECTION("invalid operand type for affectation") + { + std::string_view data = R"( +let f: R -> R, x -> x+1; +let (x,y) : R*R, (x,y) = (f,2); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> R"}); + } + + SECTION("invalid operand type for string affectation") + { + std::string_view data = R"( +let f: R -> R, x -> x+1; +let (s,n):string*N, (s,n) = (f,2); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: function -> string"}); + } + + SECTION("invalid value type for affectation") + { + std::string_view data = R"( +let f: R -> R, x -> x+1; +let x:R; + +(f,x) = (3,2); +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> function"}); + } + + SECTION("invalid R^n -> R^m conversion") + { + std::string_view data = R"( +let x:R^2, x = [1,2]; +let y:R^3, y = x; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"undefined affectation type: R^3 = R^2"}); + } + + SECTION("invalid Z -> R^d conversion (non-zero)") + { + std::string_view data = R"( +let x:R^2, x = 1; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid integral value (0 is the solely valid value)"}); + } + + SECTION("tuples -> list") + { + SECTION("bad cast") + { + SECTION("from (string)") + { + SECTION("string -> B") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,b) : string*B, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> B"}); + } + + SECTION("string -> N") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,n) : string*N, (s,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> N"}); + } + + SECTION("string -> Z") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (z,n) : Z*N, (z,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> Z"}); + } + + SECTION("string -> R") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); + } + + SECTION("string -> R^1") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^1, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^1"}); + } + + SECTION("string -> R^2") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^2, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^2"}); + } + + SECTION("string -> R^3") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^3, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^3"}); + } + + SECTION("string -> R^1x1") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^1x1, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^1x1"}); + } + + SECTION("string -> R^2x2") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^2x2, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^2x2"}); + } + + SECTION("string -> R^3x3") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*R^3x3, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R^3x3"}); + } + + SECTION("string -> builtin_t") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s,r) : string*builtin_t, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> builtin_t"}); + } + } + + SECTION("from (builtin_t)") + { + SECTION("builtin_t -> B") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,b) : builtin_t*B, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> B"}); + } + + SECTION("builtin_t -> N") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,n) : builtin_t*N, (s,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> N"}); + } + + SECTION("builtin_t -> Z") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (z,n) : Z*N, (z,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> Z"}); + } + + SECTION("builtin_t -> R") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R"}); + } + + SECTION("builtin_t -> R^1") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^1, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^1"}); + } + + SECTION("builtin_t -> R^2") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^2, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^2"}); + } + + SECTION("builtin_t -> R^3") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^3, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^3"}); + } + + SECTION("builtin_t -> R^1x1") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^1x1, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^1x1"}); + } + + SECTION("builtin_t -> R^2x2") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^2x2, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^2x2"}); + } + + SECTION("builtin_t -> R^3x3") + { + std::string_view data = R"( +let bt:builtin_t, bt = bt; +let t:(builtin_t), t = (bt, bt); +let (s,r) : builtin_t*R^3x3, (s,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: builtin_t -> R^3x3"}); + } + } + + SECTION("from (B)") + { + SECTION("B -> R^2") + { + std::string_view data = R"( +let t:(B), t = (true, false); +let (r,b) : R^2*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2"}); + } + + SECTION("B -> R^3") + { + std::string_view data = R"( +let t:(B), t = (true, false); +let (r,b) : R^3*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3"}); + } + + SECTION("B -> R^2x2") + { + std::string_view data = R"( +let t:(B), t = (true, false); +let (r,b) : R^2x2*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^2x2"}); + } + + SECTION("B -> R^3x3") + { + std::string_view data = R"( +let t:(B), t = (true, false); +let (r,b) : R^3x3*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> R^3x3"}); + } + + SECTION("B -> builtin_t") + { + std::string_view data = R"( +let t:(B), t = (true, false); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: B -> builtin_t"}); + } + } + + SECTION("from (N)") + { + SECTION("N -> B") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (r,b) : B*N, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> B"}); + } + + SECTION("N -> R^2") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (r,b) : R^2*N, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2"}); + } + + SECTION("N -> R^3") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (r,b) : R^3*N, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3"}); + } + + SECTION("N -> R^2x2") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (r,b) : R^2x2*N, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^2x2"}); + } + + SECTION("N -> R^3x3") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (r,b) : R^3x3*N, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> R^3x3"}); + } + + SECTION("N -> builtin_t") + { + std::string_view data = R"( +let t:(N), t = (1, 3); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: N -> builtin_t"}); + } + } + + SECTION("from (Z)") + { + SECTION("Z -> B") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (r,b) : B*Z, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> B"}); + } + + SECTION("Z -> R^2") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (r,b) : R^2*Z, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2"}); + } + + SECTION("Z -> R^3") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (r,b) : R^3*Z, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3"}); + } + + SECTION("Z -> R^2x2") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (r,b) : R^2x2*Z, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^2x2"}); + } + + SECTION("Z -> R^3x3") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (r,b) : R^3x3*Z, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> R^3x3"}); + } + + SECTION("Z -> builtin_t") + { + std::string_view data = R"( +let t:(Z), t = (1, 3); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> builtin_t"}); + } + } + + SECTION("from (R)") + { + SECTION("R -> B") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (r,b) : R*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> B"}); + } + + SECTION("R -> N") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (r,n) : R*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> N"}); + } + + SECTION("R -> Z") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (r,z) : R*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> Z"}); + } + + SECTION("R -> R^2") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (x,r) : R^2*R, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2"}); + } + + SECTION("R -> R^3") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (x,r) : R^3*R, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3"}); + } + + SECTION("R -> R^2x2") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (x,r) : R^2x2*R, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^2x2"}); + } + + SECTION("R -> R^3x3") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (x,r) : R^3x3*R, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> R^3x3"}); + } + + SECTION("R -> builtin_t") + { + std::string_view data = R"( +let t:(R), t = (1.2, 3.2); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R -> builtin_t"}); + } + } + + SECTION("from (R^1)") + { + SECTION("R^1 -> B") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (r,b) : R^1*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> B"}); + } + + SECTION("R^1 -> N") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (r,n) : R^1*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> N"}); + } + + SECTION("R^1 -> Z") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (r,z) : R^1*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> Z"}); + } + + SECTION("R^1 -> R") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (r,x) : R^1*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R"}); + } + + SECTION("R^1 -> R^2") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (x,r) : R^2*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2"}); + } + + SECTION("R^1 -> R^3") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (x,r) : R^3*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3"}); + } + + SECTION("R^1 -> R^1x1") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (x,r) : R^1x1*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^1x1"}); + } + + SECTION("R^1 -> R^2x2") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (x,r) : R^2x2*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^2x2"}); + } + + SECTION("R^1 -> R^3x3") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (x,r) : R^3x3*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> R^3x3"}); + } + + SECTION("R^1 -> builtin_t") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, 3.2); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1 -> builtin_t"}); + } + } + + SECTION("from (R^2)") + { + SECTION("R^2 -> B") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (r,b) : R^2*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> B"}); + } + + SECTION("R^2 -> N") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (r,n) : R^2*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> N"}); + } + + SECTION("R^2 -> Z") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (r,z) : R^2*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> Z"}); + } + + SECTION("R^2 -> R") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (r,x) : R^2*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R"}); + } + + SECTION("R^2 -> R^1") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (x,r) : R^2*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^1"}); + } + + SECTION("R^2 -> R^3") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (x,r) : R^3*R^2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3"}); + } + + SECTION("R^2 -> R^1x1") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (x,r) : R^1x1*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^1x1"}); + } + + SECTION("R^2 -> R^2x2") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (x,r) : R^2x2*R^2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^2x2"}); + } + + SECTION("R^2 -> R^3x3") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (x,r) : R^3x3*R^2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> R^3x3"}); + } + + SECTION("R^2 -> builtin_t") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 3.2], 0); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2 -> builtin_t"}); + } + } + + SECTION("from (R^3)") + { + SECTION("R^3 -> B") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (r,b) : R^3*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> B"}); + } + + SECTION("R^3 -> N") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (r,n) : R^3*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> N"}); + } + + SECTION("R^3 -> Z") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (r,z) : R^3*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> Z"}); + } + + SECTION("R^3 -> R") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (r,x) : R^3*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R"}); + } + + SECTION("R^3 -> R^1") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (x,r) : R^3*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^1"}); + } + + SECTION("R^3 -> R^2") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (x,r) : R^3*R^2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^2"}); + } + + SECTION("R^3 -> R^1x1") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (x,r) : R^1x1*R^3, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^1x1"}); + } + + SECTION("R^3 -> R^2x2") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (x,r) : R^2x2*R^3, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^2x2"}); + } + + SECTION("R^3 -> R^3x3") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (x,r) : R^3x3*R^2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> R^3x3"}); + } + + SECTION("R^3 -> builtin_t") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 3.2, 1], 0); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3 -> builtin_t"}); + } + } + + SECTION("from (R^1x1)") + { + SECTION("R^1x1 -> B") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (r,b) : R^1x1*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> B"}); + } + + SECTION("R^1x1 -> N") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (r,n) : R^1x1*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> N"}); + } + + SECTION("R^1x1 -> Z") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (r,z) : R^1x1*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> Z"}); + } + + SECTION("R^1x1 -> R") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (r,x) : R^1x1*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R"}); + } + + SECTION("R^1x1 -> R^2") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (x,r) : R^2*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^2"}); + } + + SECTION("R^1x1 -> R^3") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (x,r) : R^3*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^3"}); + } + + SECTION("R^1x1 -> R^1") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (x,r) : R^1x1*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^1"}); + } + + SECTION("R^1x1 -> R^2x2") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (x,r) : R^2x2*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^2x2"}); + } + + SECTION("R^1x1 -> R^3x3") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (x,r) : R^3x3*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> R^3x3"}); + } + + SECTION("R^1x1 -> builtin_t") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, 3.2); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^1x1 -> builtin_t"}); + } + } + + SECTION("from (R^2x2)") + { + SECTION("R^2x2 -> B") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (r,b) : R^2x2*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> B"}); + } + + SECTION("R^2x2 -> N") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (r,n) : R^2x2*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> N"}); + } + + SECTION("R^2x2 -> Z") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (r,z) : R^2x2*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> Z"}); + } + + SECTION("R^2x2 -> R") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (r,x) : R^2x2*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R"}); + } + + SECTION("R^2x2 -> R^2") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (x,r) : R^2*R^2x2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^2"}); + } + + SECTION("R^2x2 -> R^3") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (x,r) : R^3*R^2x2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^3"}); + } + + SECTION("R^2x2 -> R^1") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (x,r) : R^2x2*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^1"}); + } + + SECTION("R^2x2 -> R^1x1") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (x,r) : R^2x2*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^1x1"}); + } + + SECTION("R^2x2 -> R^3x3") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (x,r) : R^3x3*R^2x2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> R^3x3"}); + } + + SECTION("R^2x2 -> builtin_t") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 3.2],[2.1, -3.1]], 0); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^2x2 -> builtin_t"}); + } + } + + SECTION("from (R^3x3)") + { + SECTION("R^3x3 -> B") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (r,b) : R^3x3*B, (r,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> B"}); + } + + SECTION("R^3x3 -> N") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (r,n) : R^3x3*N, (r,n) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> N"}); + } + + SECTION("R^3x3 -> Z") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (r,z) : R^3x3*Z, (r,z) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> Z"}); + } + + SECTION("R^3x3 -> R") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (r,x) : R^3x3*R, (r,x) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R"}); + } + + SECTION("R^3x3 -> R^2") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (x,r) : R^2*R^3x3, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^2"}); + } + + SECTION("R^3x3 -> R^3") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (x,r) : R^3*R^3x3, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^3"}); + } + + SECTION("R^3x3 -> R^1") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (x,r) : R^3x3*R^1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^1"}); + } + + SECTION("R^3x3 -> R^1x1") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (x,r) : R^3x3*R^1x1, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^1x1"}); + } + + SECTION("R^3x3 -> R^2x2") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (x,r) : R^3x3*R^2x2, (x,r) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> R^2x2"}); + } + + SECTION("R^3x3 -> builtin_t") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 3.2, 0],[1, 2.1, -3.1],[3, -1, 7]], 0); +let (s,b) : string*builtin_t, (s,b) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: R^3x3 -> builtin_t"}); + } + } + } + + SECTION("tuple -> list with tuple") + { + std::string_view data = R"( +let t:(N), t = (1, 2, 3, 4); +let (a,b,c,d) : R*N*(R)*Z, (a,b,c,d) = t; +)"; + + CHECK_AST_THROWS_WITH(data, std::string{"cannot affect a tuple to a compound type made of tuples"}); + } } } } diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp index 4314b3b96165e200a528378a2e1053be27346e87..71670fd5d75b4ae7d20d8ece4b3ef980165cd382 100644 --- a/tests/test_AffectationProcessor.cpp +++ b/tests/test_AffectationProcessor.cpp @@ -10,7 +10,13 @@ #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <language/utils/ASTPrinter.hpp> +#include <language/utils/DataHandler.hpp> +#include <language/utils/TypeDescriptor.hpp> #include <utils/Demangle.hpp> +#include <utils/Stringify.hpp> + +#include <FixturesForBuiltinT.hpp> +#include <language/utils/BasicAffectationRegistrerFor.hpp> #include <pegtl/string_input.hpp> @@ -46,6 +52,66 @@ REQUIRE(value == expected_value); \ } +#define CHECK_BUILTIN_AFFECTATION_RESULT(data, variable_name, expected_value) \ + { \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTModulesImporter{*ast}; \ + \ + BasicAffectationRegisterFor<EmbeddedData>{ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t")}; \ + \ + SymbolTable& symbol_table = *ast->m_symbol_table; \ + auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), ast->begin()); \ + if (not success) { \ + throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); \ + } \ + \ + i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); \ + i_symbol->attributes().setIsInitialized(); \ + i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); \ + symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); \ + \ + auto [i_symbol_bt_a, success_bt_a] = symbol_table.add("bt_a", ast->begin()); \ + if (not success_bt_a) { \ + throw UnexpectedError("cannot add 'bt_a' of type builtin_t for testing"); \ + } \ + i_symbol_bt_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_bt_a->attributes().setIsInitialized(); \ + i_symbol_bt_a->attributes().value() = \ + EmbeddedData(std::make_shared<DataHandler<const double>>(std::make_shared<double>(3.2))); \ + \ + auto [i_symbol_bt_b, success_bt_b] = symbol_table.add("bt_b", ast->begin()); \ + if (not success_bt_b) { \ + throw UnexpectedError("cannot add 'bt_b' of type builtin_t for testing"); \ + } \ + i_symbol_bt_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); \ + i_symbol_bt_b->attributes().setIsInitialized(); \ + i_symbol_bt_b->attributes().value() = \ + EmbeddedData(std::make_shared<DataHandler<const double>>(std::make_shared<double>(5.3))); \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + ExecutionPolicy exec_policy; \ + ast->execute(exec_policy); \ + \ + using namespace TAO_PEGTL_NAMESPACE; \ + position use_position{internal::iterator{"fixture"}, "fixture"}; \ + use_position.byte = 10000; \ + auto [symbol, found] = symbol_table.find(variable_name, use_position); \ + \ + auto attributes = symbol->attributes(); \ + auto embedded_value = std::get<EmbeddedData>(attributes.value()); \ + \ + double value = *dynamic_cast<const DataHandler<const double>&>(embedded_value.get()).data_ptr(); \ + REQUIRE(value == expected); \ + } + #define CHECK_AFFECTATION_THROWS_WITH(data, error_message) \ { \ TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ @@ -93,91 +159,396 @@ TEST_CASE("AffectationProcessor", "[language]") { SECTION("Affectations") { - SECTION("B") + SECTION("from value") { - CHECK_AFFECTATION_RESULT("let b : B; b = true;", "b", true); - } + SECTION("-> B") + { + CHECK_AFFECTATION_RESULT("let b : B; b = true;", "b", true); + } - SECTION("N") - { - CHECK_AFFECTATION_RESULT("let n : N, n = 1;", "n", 1ul); - CHECK_AFFECTATION_RESULT("let m : N, m = 2; let n : N, n = m;", "n", 2ul); - CHECK_AFFECTATION_RESULT("let n : N, n = true;", "n", 1ul); - CHECK_AFFECTATION_RESULT("let n : N, n = false;", "n", 0ul); - } + SECTION("-> N") + { + CHECK_AFFECTATION_RESULT("let n : N, n = 1;", "n", 1ul); + CHECK_AFFECTATION_RESULT("let m : N, m = 2; let n : N, n = m;", "n", 2ul); + CHECK_AFFECTATION_RESULT("let n : N, n = true;", "n", 1ul); + CHECK_AFFECTATION_RESULT("let n : N, n = false;", "n", 0ul); + } - SECTION("Z") - { - CHECK_AFFECTATION_RESULT("let z : Z, z = -1;", "z", -1l); - CHECK_AFFECTATION_RESULT("let z : Z, z = true;", "z", 1l); - CHECK_AFFECTATION_RESULT("let z : Z, z = false;", "z", 0l); - } + SECTION("-> Z") + { + CHECK_AFFECTATION_RESULT("let z : Z, z = -1;", "z", -1l); + CHECK_AFFECTATION_RESULT("let z : Z, z = true;", "z", 1l); + CHECK_AFFECTATION_RESULT("let z : Z, z = false;", "z", 0l); + } - SECTION("R") - { - CHECK_AFFECTATION_RESULT("let r : R, r = -1;", "r", double{-1}); - CHECK_AFFECTATION_RESULT("let r : R, r = true;", "r", double{1}); - CHECK_AFFECTATION_RESULT("let r : R, r = false;", "r", double{0}); - CHECK_AFFECTATION_RESULT("let r : R, r = -2.3;", "r", double{-2.3}); - } + SECTION("-> R") + { + CHECK_AFFECTATION_RESULT("let r : R, r = -1;", "r", double{-1}); + CHECK_AFFECTATION_RESULT("let r : R, r = true;", "r", double{1}); + CHECK_AFFECTATION_RESULT("let r : R, r = false;", "r", double{0}); + CHECK_AFFECTATION_RESULT("let r : R, r = -2.3;", "r", double{-2.3}); + } - SECTION("R^1") - { - CHECK_AFFECTATION_RESULT("let x : R^1, x = -1;", "x", (TinyVector<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = true;", "x", (TinyVector<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = false;", "x", (TinyVector<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = -2.3;", "x", (TinyVector<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = [-1];", "x", (TinyVector<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = [true];", "x", (TinyVector<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = [false];", "x", (TinyVector<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = [-2.3];", "x", (TinyVector<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = 0;", "x", (TinyVector<1>{zero})); - } + SECTION("-> R^1") + { + CHECK_AFFECTATION_RESULT("let x : R^1, x = -1;", "x", (TinyVector<1>{-1})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = true;", "x", (TinyVector<1>{true})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = false;", "x", (TinyVector<1>{false})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = -2.3;", "x", (TinyVector<1>{-2.3})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = [-1];", "x", (TinyVector<1>{-1})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = [true];", "x", (TinyVector<1>{true})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = [false];", "x", (TinyVector<1>{false})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = [-2.3];", "x", (TinyVector<1>{-2.3})); + CHECK_AFFECTATION_RESULT("let x : R^1, x = 0;", "x", (TinyVector<1>{zero})); + } - SECTION("R^2") - { - CHECK_AFFECTATION_RESULT("let x : R^2, x = [-1, true];", "x", (TinyVector<2>{-1, true})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = [true, false];", "x", (TinyVector<2>{true, false})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = [-0.3, 12];", "x", (TinyVector<2>{-0.3, 12})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = 0;", "x", (TinyVector<2>{zero})); - } + SECTION("-> R^2") + { + CHECK_AFFECTATION_RESULT("let x : R^2, x = [-1, true];", "x", (TinyVector<2>{-1, true})); + CHECK_AFFECTATION_RESULT("let x : R^2, x = [true, false];", "x", (TinyVector<2>{true, false})); + CHECK_AFFECTATION_RESULT("let x : R^2, x = [-0.3, 12];", "x", (TinyVector<2>{-0.3, 12})); + CHECK_AFFECTATION_RESULT("let x : R^2, x = 0;", "x", (TinyVector<2>{zero})); + } - SECTION("R^3") - { - CHECK_AFFECTATION_RESULT("let x : R^3, x = [-1, true, false];", "x", (TinyVector<3>{-1, true, false})); - CHECK_AFFECTATION_RESULT("let x : R^3, x = [-0.3, 12, 6.2];", "x", (TinyVector<3>{-0.3, 12, 6.2})); - CHECK_AFFECTATION_RESULT("let x : R^3; x = 0;", "x", (TinyVector<3>{zero})); - } + SECTION("-> R^3") + { + CHECK_AFFECTATION_RESULT("let x : R^3, x = [-1, true, false];", "x", (TinyVector<3>{-1, true, false})); + CHECK_AFFECTATION_RESULT("let x : R^3, x = [-0.3, 12, 6.2];", "x", (TinyVector<3>{-0.3, 12, 6.2})); + CHECK_AFFECTATION_RESULT("let x : R^3; x = 0;", "x", (TinyVector<3>{zero})); + } - SECTION("R^1x1") - { - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = -1;", "x", (TinyMatrix<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = true;", "x", (TinyMatrix<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = false;", "x", (TinyMatrix<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = -2.3;", "x", (TinyMatrix<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[-1]];", "x", (TinyMatrix<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[true]];", "x", (TinyMatrix<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[false]];", "x", (TinyMatrix<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[-2.3]];", "x", (TinyMatrix<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1x1; x = 0;", "x", (TinyMatrix<1>{zero})); - } + SECTION("-> R^1x1") + { + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = -1;", "x", (TinyMatrix<1>{-1})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = true;", "x", (TinyMatrix<1>{true})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = false;", "x", (TinyMatrix<1>{false})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = -2.3;", "x", (TinyMatrix<1>{-2.3})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[-1]];", "x", (TinyMatrix<1>{-1})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[true]];", "x", (TinyMatrix<1>{true})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[false]];", "x", (TinyMatrix<1>{false})); + CHECK_AFFECTATION_RESULT("let x : R^1x1, x = [[-2.3]];", "x", (TinyMatrix<1>{-2.3})); + CHECK_AFFECTATION_RESULT("let x : R^1x1; x = 0;", "x", (TinyMatrix<1>{zero})); + } - SECTION("R^2x2") - { - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[-1, true], [3, 5]];", "x", (TinyMatrix<2>{-1, true, 3, 5})); - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[true, false], [1==2, 2==2]];", "x", - (TinyMatrix<2>{true, false, false, true})); - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[-0.3, 12],[2, -3]];", "x", (TinyMatrix<2>{-0.3, 12, 2, -3})); - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = 0;", "x", (TinyMatrix<2>{zero})); + SECTION("-> R^2x2") + { + CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[-1, true], [3, 5]];", "x", (TinyMatrix<2>{-1, true, 3, 5})); + CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[true, false], [1==2, 2==2]];", "x", + (TinyMatrix<2>{true, false, false, true})); + CHECK_AFFECTATION_RESULT("let x : R^2x2, x = [[-0.3, 12],[2, -3]];", "x", (TinyMatrix<2>{-0.3, 12, 2, -3})); + CHECK_AFFECTATION_RESULT("let x : R^2x2, x = 0;", "x", (TinyMatrix<2>{zero})); + } + + SECTION("-> R^3x3") + { + CHECK_AFFECTATION_RESULT("let x : R^3x3, x = [[-1, true, false], [2, 3.1, 4], [-1, true, 2]];", "x", + (TinyMatrix<3>{-1, true, false, 2, 3.1, 4, -1, true, 2})); + CHECK_AFFECTATION_RESULT("let x : R^3x3, x = [[-0.3, 12, 6.2], [7.1, 3.2, 2-3], [2, -1, 0]];", "x", + (TinyMatrix<3>{-0.3, 12, 6.2, 7.1, 3.2, 2 - 3, 2, -1, 0})); + CHECK_AFFECTATION_RESULT("let x : R^3x3, x = 0;", "x", (TinyMatrix<3>{zero})); + } + + SECTION("-> string") + { + CHECK_AFFECTATION_RESULT("let x : string, x = true;", "x", (stringify(true))); + CHECK_AFFECTATION_RESULT("let n:N, n = 3; let x : string, x = n;", "x", (stringify(3ul))); + CHECK_AFFECTATION_RESULT("let x : string, x = -2;", "x", (stringify(-2l))); + CHECK_AFFECTATION_RESULT("let x : string, x = 1.7;", "x", (stringify(double{1.7}))); + + CHECK_AFFECTATION_RESULT("let x : string, x = [1.7];", "x", (stringify(TinyVector<1>{1.7}))); + CHECK_AFFECTATION_RESULT("let x : string, x = [1.7, 2];", "x", (stringify(TinyVector<2>{1.7, 2}))); + CHECK_AFFECTATION_RESULT("let x : string, x = [1.7, 5, 2];", "x", (stringify(TinyVector<3>{1.7, 5, 2}))); + + CHECK_AFFECTATION_RESULT("let x : string, x = [[1.7]];", "x", (stringify(TinyMatrix<1>{1.7}))); + CHECK_AFFECTATION_RESULT("let x : string, x = [[1.7, 2],[1,3]];", "x", + (stringify(TinyMatrix<2>{1.7, 2, 1, 3}))); + CHECK_AFFECTATION_RESULT("let x : string, x = [[1.7, 5, 2],[1,3,5],[-1,2,6]];", "x", + (stringify(TinyMatrix<3>{1.7, 5, 2, 1, 3, 5, -1, 2, 6}))); + + CHECK_AFFECTATION_RESULT("let x : string, x = \"foobar\";", "x", (std::string{"foobar"})); + } + + SECTION("-> builtin_t") + { + const double expected = double{3.2}; + CHECK_BUILTIN_AFFECTATION_RESULT("let b:builtin_t, b = bt_a;", "b", expected); + } } - SECTION("R^3x3") + SECTION("from tuple") { - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = [[-1, true, false], [2, 3.1, 4], [-1, true, 2]];", "x", - (TinyMatrix<3>{-1, true, false, 2, 3.1, 4, -1, true, 2})); - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = [[-0.3, 12, 6.2], [7.1, 3.2, 2-3], [2, -1, 0]];", "x", - (TinyMatrix<3>{-0.3, 12, 6.2, 7.1, 3.2, 2 - 3, 2, -1, 0})); - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = 0;", "x", (TinyMatrix<3>{zero})); + SECTION("-> B") + { + CHECK_AFFECTATION_RESULT("let b : B; b = true;", "b", true); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let b:B, b = t; +)"}, + "b", true); + } + + SECTION("-> N") + { + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let n:N, n = t; +)"}, + "n", 1ul); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 1; +let n:N, n = t; +)"}, + "n", 1ul); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t = 2; +let n:N, n = t; +)"}, + "n", 2ul); + } + + SECTION("-> Z") + { + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let z:Z, z = t; +)"}, + "z", 1l); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 2; +let z:Z, z = t; +)"}, + "z", 2l); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t = 3; +let z:Z, z = t; +)"}, + "z", 3l); + } + + SECTION("-> R") + { + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let r:R, r = t; +)"}, + "r", double{1}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 2; +let r:R, r = t; +)"}, + "r", double{2}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t =-3; +let r:R, r = t; +)"}, + "r", double{-3}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R), t =-3.2; +let r:R, r = t; +)"}, + "r", double{-3.2}); + } + + SECTION("-> R^1") + { + using R1x1 = TinyVector<1>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let r:R^1, r = t; +)"}, + "r", R1x1{1}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 2; +let r:R^1, r = t; +)"}, + "r", R1x1{2}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t =-3; +let r:R^1, r = t; +)"}, + "r", R1x1{-3}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R), t =-3.2; +let r:R^1, r = t; +)"}, + "r", R1x1{-3.2}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^1), t =-1.2; +let r:R^1, r = t; +)"}, + "r", R1x1{-1.2}); + } + + SECTION("-> R^2") + { + using R2 = TinyVector<2>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^2), t =[-1.2, 2]; +let r:R^2, r = t; +)"}, + "r", (R2{-1.2, 2})); + } + + SECTION("-> R^3") + { + using R3 = TinyVector<3>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^3), t =[-1.2, 2, 1]; +let r:R^3, r = t; +)"}, + "r", (R3{-1.2, 2, 1})); + } + + SECTION("-> R^1x1") + { + using R1x1 = TinyMatrix<1>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let r:R^1x1, r = t; +)"}, + "r", R1x1{1}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 2; +let r:R^1x1, r = t; +)"}, + "r", R1x1{2}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t =-3; +let r:R^1x1, r = t; +)"}, + "r", R1x1{-3}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R), t =-3.2; +let r:R^1x1, r = t; +)"}, + "r", R1x1{-3.2}); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^1x1), t =-1.2; +let r:R^1x1, r = t; +)"}, + "r", R1x1{-1.2}); + } + + SECTION("-> R^2x2") + { + using R2x2 = TinyMatrix<2>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^2x2), t =[[-1.2, 2],[1,3]]; +let r:R^2x2, r = t; +)"}, + "r", (R2x2{-1.2, 2, 1, 3})); + } + + SECTION("-> R^3x3") + { + using R3x3 = TinyMatrix<3>; + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^3x3), t = [[-1.2, 2, 1],[-2.2, 1, 7],[-3, 1, 2]]; +let r:R^3x3, r = t; +)"}, + "r", (R3x3{-1.2, 2, 1, -2.2, 1, 7, -3, 1, 2})); + } + + SECTION("-> string") + { + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(B), t = true; +let x:string, x = t; +)"}, + "x", (stringify(true))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(N), t = 3; +let x:string, x = t; +)"}, + "x", (stringify(3ul))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(Z), t = -2; +let x:string, x = t; +)"}, + "x", (stringify(-2l))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R), t = 1.7; +let x:string, x = t; +)"}, + "x", (stringify(double{1.7}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^1), t = [1.7]; +let x:string, x = t; +)"}, + "x", (stringify(TinyVector<1>{1.7}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^2), t = [1.7, 2]; +let x:string, x = t; +)"}, + "x", (stringify(TinyVector<2>{1.7, 2}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^3), t = [1.7, 5, 2]; +let x:string, x = t; +)"}, + "x", (stringify(TinyVector<3>{1.7, 5, 2}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^1x1), t = [[1.7]]; +let x:string, x = t; +)"}, + "x", (stringify(TinyMatrix<1>{1.7}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^2x2), t = [[1.7, 2],[1,3]]; +let x:string, x = t; +)"}, + "x", (stringify(TinyMatrix<2>{1.7, 2, 1, 3}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(R^3x3), t = [[1.7, 5, 2],[1,3,5],[-1,2,6]]; +let x:string, x = t; +)"}, + "x", (stringify(TinyMatrix<3>{1.7, 5, 2, 1, 3, 5, -1, 2, 6}))); + + CHECK_AFFECTATION_RESULT(std::string{R"( +let t:(string), t = "foobar"; +let x:string, x = t; +)"}, + "x", (std::string{"foobar"})); + } + + SECTION("-> builtin_t") + { + const double expected = double{3.2}; + CHECK_BUILTIN_AFFECTATION_RESULT(std::string{R"( +let t:(builtin_t), t = bt_a; +let x:builtin_t, x = t; +)"}, + "x", expected); + } } } @@ -360,6 +731,33 @@ TEST_CASE("AffectationProcessor", "[language]") { SECTION("invalid affectations") { + SECTION("tuple -> value") + { + CHECK_AFFECTATION_EXEC_THROWS_WITH( + std::string_view{ + R"( +let t : (B), t = (true, 2>1, false); +let b : B; b = t; +)"}, + "cannot affect a (B) of size 3 to a B"); + + CHECK_AFFECTATION_EXEC_THROWS_WITH( + std::string_view{ + R"( +let t :(N), t = (2, 3, 6); +let z : Z; z = t; +)"}, + "cannot affect a (N) of size 3 to a Z"); + + CHECK_AFFECTATION_EXEC_THROWS_WITH( + std::string_view{ + R"( +let t :(R^1), t = (2, 3, 6); +let r : R^1; r = t; +)"}, + "cannot affect a (R^1) of size 3 to a R^1"); + } + SECTION("-> B") { CHECK_AFFECTATION_THROWS_WITH("let n : N, n = 1; let b : B; b = n;", "undefined affectation type: B = N"); diff --git a/tests/test_AffectationToTupleProcessor.cpp b/tests/test_AffectationToTupleProcessor.cpp index 1ecaf971ffa09028c6baf59093c1517326c0dc14..84d1a1639d52107a802ff66f8cff9dfd3bff0b5f 100644 --- a/tests/test_AffectationToTupleProcessor.cpp +++ b/tests/test_AffectationToTupleProcessor.cpp @@ -206,35 +206,279 @@ let t :(R^1x1); t = (x,2); SECTION("Affectations from tuple") { - CHECK_AFFECTATION_RESULT(R"( -let x :(R^3), x = [1,2,3]; -let s :(string); s = x; + SECTION(" -> (B)") + { + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(B), b = a; )", - "s", (std::vector<std::string>{stringify(TinyVector<3, double>{1, 2, 3})})); + "b", (std::vector<bool>{true, false, true})); + } - CHECK_AFFECTATION_RESULT(R"( -let A :(R^3x3), A = ([[1,2,3],[4,5,6],[7,8,9]]); -let s :(string); s = A; + SECTION(" -> (N)") + { + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(N), b = a; )", - "s", (std::vector<std::string>{stringify(TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})})); + "b", (std::vector<uint64_t>{true, false, true})); - CHECK_AFFECTATION_RESULT(R"( -let x :(R), x = (1,2,3); -let s :(string); s = x; + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(N), b = a; )", - "s", (std::vector<std::string>{stringify(1.), stringify(2.), stringify(3.)})); + "b", (std::vector<uint64_t>{1, 2, 3})); - CHECK_AFFECTATION_RESULT(R"( -let n :(N), n = (1,2,3); -let t :(R); t = n; + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, 6, 2); +let b:(N), b = a; )", - "t", (std::vector<double>{1, 2, 3})); + "b", (std::vector<uint64_t>{5, 6, 2})); + } - CHECK_AFFECTATION_RESULT(R"( -let s :(N), s = (1,2,3); -let t :(N); t = s; + SECTION(" -> (Z)") + { + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(Z), b = a; +)", + "b", (std::vector<int64_t>{true, false, true})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(Z), b = a; +)", + "b", (std::vector<int64_t>{1, 2, 3})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, -6, 2); +let b:(Z), b = a; +)", + "b", (std::vector<int64_t>{5, -6, 2})); + } + + SECTION(" -> (R)") + { + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(R), b = a; )", - "t", (std::vector<uint64_t>{1, 2, 3})); + "b", (std::vector<double>{true, false, true})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(R), b = a; +)", + "b", (std::vector<double>{1, 2, 3})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, -6, 2); +let b:(R), b = a; +)", + "b", (std::vector<double>{5, -6, 2})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R), a = (5.2, -6.3, 2.1); +let b:(R), b = a; +)", + "b", (std::vector<double>{5.2, -6.3, 2.1})); + } + + SECTION(" -> (R^1)") + { + using R1 = TinyVector<1>; + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(R^1), b = a; +)", + "b", (std::vector<R1>{R1{true}, R1{false}, R1{true}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(R^1), b = a; +)", + "b", (std::vector<R1>{R1{1}, R1{2}, R1{3}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, -6, 2); +let b:(R^1), b = a; +)", + "b", (std::vector<R1>{R1{5}, R1{-6}, R1{2}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R), a = (5.2, -6.3, 2.1); +let b:(R^1), b = a; +)", + "b", (std::vector<R1>{R1{5.2}, R1{-6.3}, R1{2.1}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R^1), a = (5.2, -6.3, 2.1); +let b:(R^1), b = a; +)", + "b", (std::vector<R1>{R1{5.2}, R1{-6.3}, R1{2.1}})); + } + + SECTION(" -> (R^2)") + { + using R2 = TinyVector<2>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^2), a = ([5.2, -6.3], [2.1, 0]); +let b:(R^2), b = a; +)", + "b", (std::vector<R2>{R2{5.2, -6.3}, R2{2.1, 0}})); + } + + SECTION(" -> (R^3)") + { + using R3 = TinyVector<3>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^3), a = ([5.2, -6.3, 2], [2.1, 0, -1.1]); +let b:(R^3), b = a; +)", + "b", (std::vector<R3>{R3{5.2, -6.3, 2}, R3{2.1, 0, -1.1}})); + } + + SECTION(" -> (R^1x1)") + { + using R1x1 = TinyMatrix<1>; + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(R^1x1), b = a; +)", + "b", (std::vector<R1x1>{R1x1{true}, R1x1{false}, R1x1{true}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(R^1x1), b = a; +)", + "b", (std::vector<R1x1>{R1x1{1}, R1x1{2}, R1x1{3}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, -6, 2); +let b:(R^1x1), b = a; +)", + "b", (std::vector<R1x1>{R1x1{5}, R1x1{-6}, R1x1{2}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R), a = (5.2, -6.3, 2.1); +let b:(R^1x1), b = a; +)", + "b", (std::vector<R1x1>{R1x1{5.2}, R1x1{-6.3}, R1x1{2.1}})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R^1x1), a = (5.2, -6.3, 2.1); +let b:(R^1x1), b = a; +)", + "b", (std::vector<R1x1>{R1x1{5.2}, R1x1{-6.3}, R1x1{2.1}})); + } + + SECTION(" -> (R^2x2)") + { + using R2x2 = TinyMatrix<2>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^2x2), a = ([[5.2, -6.3], [2.1, 0]], 0); +let b:(R^2x2), b = a; +)", + "b", (std::vector<R2x2>{R2x2{5.2, -6.3, 2.1, 0}, R2x2{zero}})); + } + + SECTION(" -> (R^3x3)") + { + using R3x3 = TinyMatrix<3>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^3x3), a = ([[5.2, -6.3, 2], [2.1, 0, -1.1], [1,-1.2,-0.7]] , 0); +let b:(R^3x3), b = a; +)", + "b", (std::vector<R3x3>{R3x3{5.2, -6.3, 2, 2.1, 0, -1.1, 1, -1.2, -0.7}, R3x3{zero}})); + } + + SECTION(" -> (string)") + { + CHECK_AFFECTATION_RESULT(R"( +let a:(B), a = (true, false, true); +let b:(string), b = a; +)", + "b", (std::vector<std::string>{stringify(true), stringify(false), stringify(true)})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(N), a = (1, 2, 3); +let b:(string), b = a; +)", + "b", (std::vector<std::string>{stringify(1ul), stringify(2ul), stringify(3ul)})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(Z), a = (5, -6, 2); +let b:(string), b = a; +)", + "b", (std::vector<std::string>{stringify(5l), stringify(-6l), stringify(2l)})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(R), a = (5.2, -6.3, 2.1); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(double{5.2}), stringify(double{-6.3}), + stringify(double{2.1})})); + + using R1 = TinyVector<1>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^1), a = ([5.2], [-6.3], [2.1]); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R1{5.2}), stringify(R1{-6.3}), stringify(R1{2.1})})); + + using R2 = TinyVector<2>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^2), a = ([5.2, 1.2], [-6.3, 4], [2.1, -1]); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R2{5.2, 1.2}), stringify(R2{-6.3, 4}), + stringify(R2{2.1, -1})})); + + using R3 = TinyVector<3>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^3), a = ([5.2, 1.2, 2.1], [-6.3, 4, 0], [2.1, -1, 3]); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R3{5.2, 1.2, 2.1}), stringify(R3{-6.3, 4, 0}), + stringify(R3{2.1, -1, 3})})); + + using R1x1 = TinyMatrix<1>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^1x1), a = ([[5.2]], [[-6.3]], [[2.1]]); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R1x1{5.2}), stringify(R1x1{-6.3}), + stringify(R1x1{2.1})})); + + using R2x2 = TinyMatrix<2>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^2x2), a = ([[5.2, 1.2], [-6.3, 4]], [[2.1, -1],[1,3]], 0); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R2x2{5.2, 1.2, -6.3, 4}), + stringify(R2x2{2.1, -1, 1, 3}), stringify(R2x2{zero})})); + + using R3x3 = TinyMatrix<3>; + CHECK_AFFECTATION_RESULT(R"( +let a:(R^3x3), a = ([[5.2, 1.2, 2.1], [-6.3, 4, 0], [2.1, -1, 3]], 0); +let b:(string), b = a; +)", + "b", + (std::vector<std::string>{stringify(R3x3{5.2, 1.2, 2.1, -6.3, 4, 0, 2.1, -1, 3}), + stringify(R3x3{zero})})); + + CHECK_AFFECTATION_RESULT(R"( +let a:(string), a = ("foo", "bar", "foobar"); +let b:(string), b = a; +)", + "b", (std::vector<std::string>{"foo", "bar", "foobar"})); + } } SECTION("errors") @@ -256,6 +500,12 @@ let z : (Z), z = (2,-5,6); let n : (N), n = z; )", "trying to affect negative value (-5)"); + + CHECK_AFFECTATION_EXEC_THROWS_WITH(R"( +let z : (Z), z = -3; +let n : N, n = z; +)", + "trying to affect negative value (-3)"); } SECTION("affect negative values to (N) in lists") diff --git a/tests/test_ConsoleManager.cpp b/tests/test_ConsoleManager.cpp index 68559e449a746cf901dca8820d1bf5b4ebd82172..9fd1fb330842d3bcfc14d25387464026311a2c7a 100644 --- a/tests/test_ConsoleManager.cpp +++ b/tests/test_ConsoleManager.cpp @@ -29,5 +29,13 @@ TEST_CASE("ConsoleManager", "[utils]") REQUIRE(rang::rang_implementation::controlMode() == rang::control::Off); rang::setControlMode(saved_control); + + const bool show_preamble = ConsoleManager::showPreamble(); + + ConsoleManager::setShowPreamble(not show_preamble); + REQUIRE(show_preamble != ConsoleManager::showPreamble()); + + ConsoleManager::setShowPreamble(show_preamble); + REQUIRE(show_preamble == ConsoleManager::showPreamble()); } } diff --git a/tests/test_DiscreteFunctionP0.cpp b/tests/test_DiscreteFunctionP0.cpp index 48c107e4ad2f07391a49270a04c9a3dc20d2db4a..39b91c4de355c1a96feaa1f1b5e2a59bf9c494d8 100644 --- a/tests/test_DiscreteFunctionP0.cpp +++ b/tests/test_DiscreteFunctionP0.cpp @@ -4,6 +4,10 @@ #include <MeshDataBaseForTests.hpp> #include <scheme/DiscreteFunctionP0.hpp> +#ifdef __clang__ +#pragma clang optimize off +#endif // __clang__ + // clazy:excludeall=non-pod-global-static TEST_CASE("DiscreteFunctionP0", "[scheme]") @@ -3435,7 +3439,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { const double x = xj[cell_id][0]; Ah[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, // - -0.2 * x - 1, 2 + x}; + -0.2 * x - 1, 2 + x}; }); { @@ -3457,7 +3461,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { const double x = xj[cell_id][0]; Ah[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, // - -0.2 * x - 1, 2 + x}; + -0.2 * x - 1, 2 + x}; }); { @@ -3479,7 +3483,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { const double x = xj[cell_id][0]; Ah[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, // - -0.2 * x - 1, 2 + x}; + -0.2 * x - 1, 2 + x}; }); { @@ -3501,7 +3505,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") mesh->numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { const double x = xj[cell_id][0]; Ah[cell_id] = TinyMatrix<2>{x + 1, 2 * x - 3, // - -0.2 * x - 1, 2 + x}; + -0.2 * x - 1, 2 + x}; }); { @@ -3697,3 +3701,7 @@ TEST_CASE("DiscreteFunctionP0", "[scheme]") } #endif // NDEBUG } + +#ifdef __clang__ +#pragma clang optimize on +#endif // __clang__ diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp index ed0331dde90ba7270c0050a633a84982545a5e7b..887d0785da4ce3b5b02ce9b9e7e8eec7dd841159 100644 --- a/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions1D.cpp @@ -496,6 +496,10 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_u, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_R1x1_u, p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(dot(p_R2x2_u, p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(dot(p_R3x3_u, p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); } @@ -514,6 +518,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(det(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("trace Vh -> Vh") @@ -531,6 +536,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(trace(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("inverse Vh -> Vh") @@ -548,6 +554,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(inverse(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("transpose Vh -> Vh") @@ -565,6 +572,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(transpose(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("sum_of_Vh Vh -> Vh") @@ -625,6 +633,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), "error: discrete functions are not defined on the same mesh"); REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_Vector3_u}), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("dot Vh*Rd -> Vh") @@ -635,6 +644,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(p_u, TinyVector<2>{1, 2}), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), @@ -650,6 +664,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_Vector3_u), + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), @@ -674,6 +693,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("integral_of_R* Vh -> R*") @@ -709,6 +729,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions1D", "[scheme]") REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } } } diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp index dfbdb01500b08f73dd9804d4d4581aafe4c4ba63..ddbf9266412e1395b922d70d3f83c6ca3ad977a5 100644 --- a/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions2D.cpp @@ -498,6 +498,10 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_u, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_R1x1_u, p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(dot(p_R2x2_u, p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(dot(p_R3x3_u, p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); } @@ -516,6 +520,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(det(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("trace Vh -> Vh") @@ -533,6 +538,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(trace(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("inverse Vh -> Vh") @@ -550,6 +556,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(inverse(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("transpose Vh -> Vh") @@ -567,6 +574,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(transpose(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("sum_of_Vh Vh -> Vh") @@ -627,6 +635,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), "error: discrete functions are not defined on the same mesh"); REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_Vector3_u}), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("dot Vh*Rd -> Vh") @@ -637,6 +646,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(p_u, TinyVector<2>{1, 2}), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), @@ -652,6 +666,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_Vector3_u), + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), @@ -676,6 +695,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("integral_of_R* Vh -> R*") @@ -711,6 +731,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions2D", "[scheme]") REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } } } diff --git a/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp b/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp index 5f9896ad64df5601f54f9d701fc5bfe94f4d51b9..efb77fdde37448c15de9b95499cd28d01805e63f 100644 --- a/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionMathFunctions3D.cpp @@ -496,6 +496,10 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(dot(p_R2_u, p_other_mesh_R2_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R3_u, p_other_mesh_R3_u), "error: operands are defined on different meshes"); REQUIRE_THROWS_WITH(dot(p_R1_u, p_R3_u), "error: incompatible operand types Vh(P0:R^1) and Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(dot(p_u, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_R1x1_u, p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); + REQUIRE_THROWS_WITH(dot(p_R2x2_u, p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); + REQUIRE_THROWS_WITH(dot(p_R3x3_u, p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); REQUIRE_THROWS_WITH(dot(p_Vector3_u, p_Vector2_w), "error: operands have different dimension"); } @@ -514,6 +518,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(det(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(det(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(det(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(det(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("trace Vh -> Vh") @@ -531,6 +536,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(trace(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(trace(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(trace(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(trace(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("inverse Vh -> Vh") @@ -548,6 +554,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(inverse(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(inverse(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(inverse(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(inverse(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("transpose Vh -> Vh") @@ -565,6 +572,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(transpose(p_R1_u), "error: invalid operand type Vh(P0:R^1)"); REQUIRE_THROWS_WITH(transpose(p_R2_u), "error: invalid operand type Vh(P0:R^2)"); REQUIRE_THROWS_WITH(transpose(p_R3_u), "error: invalid operand type Vh(P0:R^3)"); + REQUIRE_THROWS_WITH(transpose(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("sum_of_Vh Vh -> Vh") @@ -625,6 +633,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(vectorize(std::vector{p_u, p_other_mesh_u}), "error: discrete functions are not defined on the same mesh"); REQUIRE_THROWS_WITH(vectorize(std::vector{p_R1_u}), "error: invalid operand type Vh(P0:R^1)"); + REQUIRE_THROWS_WITH(vectorize(std::vector{p_Vector3_u}), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("dot Vh*Rd -> Vh") @@ -635,6 +644,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_VHxW_TO_VH_FUNCTION_EVALUATION(p_R3_u, (TinyVector<3>{-1, 5, 2}), dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(p_u, TinyVector<2>{1, 2}), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(p_Vector3_u, TinyVector<2>{1, 2}), + "error: incompatible operand types Vh(P0Vector:R) and R^2"); + REQUIRE_THROWS_WITH(dot(p_R1_u, (TinyVector<2>{-6, 2})), "error: incompatible operand types Vh(P0:R^1) and R^2"); REQUIRE_THROWS_WITH(dot(p_R2_u, (TinyVector<3>{-1, 5, 2})), @@ -650,6 +664,11 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") DiscreteFunctionR2, DiscreteFunctionR); CHECK_EMBEDDED_WxVH_TO_VH_FUNCTION_EVALUATION((TinyVector<3>{-1, 5, 2}), p_R3_u, dot, // DiscreteFunctionR3, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_u), "error: invalid operand type Vh(P0:R)"); + REQUIRE_THROWS_WITH(dot(TinyVector<2>{1, 2}, p_Vector3_u), + "error: incompatible operand types R^2 and Vh(P0Vector:R)"); + REQUIRE_THROWS_WITH(dot((TinyVector<2>{-6, 2}), p_R1_u), "error: incompatible operand types R^2 and Vh(P0:R^1)"); REQUIRE_THROWS_WITH(dot((TinyVector<3>{-1, 5, 2}), p_R2_u), @@ -674,6 +693,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(sum_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(sum_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(sum_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } SECTION("integral_of_R* Vh -> R*") @@ -709,6 +729,7 @@ TEST_CASE("EmbeddedDiscreteFunctionVariantMathFunctions3D", "[scheme]") REQUIRE_THROWS_WITH(integral_of<double>(p_R1x1_u), "error: invalid operand type Vh(P0:R^1x1)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R2x2_u), "error: invalid operand type Vh(P0:R^2x2)"); REQUIRE_THROWS_WITH(integral_of<double>(p_R3x3_u), "error: invalid operand type Vh(P0:R^3x3)"); + REQUIRE_THROWS_WITH(integral_of<double>(p_Vector3_u), "error: invalid operand type Vh(P0Vector:R)"); } } } diff --git a/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp index 5538543de393bd2fb8009e3d2cbd04d57107ead3..47ff54931e0f569dedda032a1b99608ad0b22bd0 100644 --- a/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionOperators1D.cpp @@ -681,6 +681,12 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators1D", "[scheme]") REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyVector<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1"); + + REQUIRE_THROWS_WITH(p_R3x3_u * (TinyVector<2>{2, 1}), + "error: incompatible operand types Vh(P0:R^3x3) and R^2"); + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); @@ -829,6 +835,8 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators1D", "[scheme]") DiscreteFunctionR, DiscreteFunctionR); CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(3.2 / p_R1_v, "error: incompatible operand types R and Vh(P0:R^1)"); } } } diff --git a/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp index fbf114d085d04a76da6715d3493516c9ead57044..f6885617190de4a928626105697eaeabab641b40 100644 --- a/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionOperators2D.cpp @@ -681,6 +681,12 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators2D", "[scheme]") REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyVector<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1"); + + REQUIRE_THROWS_WITH(p_R3x3_u * (TinyVector<2>{2, 1}), + "error: incompatible operand types Vh(P0:R^3x3) and R^2"); + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); @@ -831,6 +837,8 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators2D", "[scheme]") DiscreteFunctionR, DiscreteFunctionR); CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(3.2 / p_R1_v, "error: incompatible operand types R and Vh(P0:R^1)"); } } } diff --git a/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp b/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp index 1b24d0a9128db6bcc8d4c3eff70a38a3c5fc9ee4..60b68b473def74a34e839a0d558a3e08f21eb58f 100644 --- a/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp +++ b/tests/test_EmbeddedDiscreteFunctionOperators3D.cpp @@ -681,6 +681,12 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators3D", "[scheme]") REQUIRE_THROWS_WITH(p_R2x2_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0:R^2x2) and R^3x3"); + REQUIRE_THROWS_WITH(p_R2x2_u * (TinyVector<1>{2}), + "error: incompatible operand types Vh(P0:R^2x2) and R^1"); + + REQUIRE_THROWS_WITH(p_R3x3_u * (TinyVector<2>{2, 1}), + "error: incompatible operand types Vh(P0:R^3x3) and R^2"); + REQUIRE_THROWS_WITH(p_Vector3_u * (TinyMatrix<3>{1, 3, 6, 4, 7, 2, 5, 9, 8}), "error: incompatible operand types Vh(P0Vector:R) and R^3x3"); REQUIRE_THROWS_WITH(p_Vector3_u * (double{2}), "error: incompatible operand types Vh(P0Vector:R) and R"); @@ -831,6 +837,8 @@ TEST_CASE("EmbeddedDiscreteFunctionOperators3D", "[scheme]") DiscreteFunctionR, DiscreteFunctionR); CHECK_EMBEDDED_XxVH_TO_VH(double{1.3}, /, p_R_u, // DiscreteFunctionR, DiscreteFunctionR); + + REQUIRE_THROWS_WITH(3.2 / p_R1_v, "error: incompatible operand types R and Vh(P0:R^1)"); } } } diff --git a/tests/test_FunctionProcessor.cpp b/tests/test_FunctionProcessor.cpp index 97cc8d6be42199f684739dba21b1b3f9a2cab644..500998b50f1729e9416b26cef7462bcc101b3151 100644 --- a/tests/test_FunctionProcessor.cpp +++ b/tests/test_FunctionProcessor.cpp @@ -9,6 +9,7 @@ #include <language/ast/ASTNodeTypeCleaner.hpp> #include <language/ast/ASTSymbolTableBuilder.hpp> #include <utils/Demangle.hpp> +#include <utils/Stringify.hpp> #include <pegtl/string_input.hpp> @@ -570,6 +571,16 @@ let fx:R^3x3, fx = f(3); (TinyMatrix<3>{x, 2 * x, x * x, 3 * x, 2 + x, x - 1, x + 0.5, 2 * x - 1, 1 / x})); } + + SECTION(" -> N*(R)") + { + std::string_view data = R"( +let f : R -> (R)*R, x -> ((2*x, x+2, 3), x); +let (t,x):(R)*R, (t,x) = f(3.2); +)"; + CHECK_FUNCTION_EVALUATION_RESULT(data, "x", double{3.2}); + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", (std::vector<double>{double{2 * 3.2}, double{3.2 + 2}, double{3}})); + } } SECTION("multi-expression functions (using R^d)") @@ -823,52 +834,1113 @@ let x:R, x = g(f(3)); } } - SECTION("errors") + SECTION("tuple functions") { - SECTION("negative value to N") + SECTION("-> (B)") { - SECTION("single N argument") + SECTION("from B") { std::string_view data = R"( -let f : N -> N, n -> 2; -f(2); -f(-1); +let f : B -> (B), b -> not b; +let b:(B), b = f(true); )"; + std::vector<bool> result{false}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "b", result); + } - CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)"); + SECTION("from list") + { + std::string_view data = R"( +let f : B -> (B), n -> (not n, n, false); +let t:(B), t = f(true); +)"; + std::vector<bool> result{false, true, false}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); } - SECTION("multiple N arguments") + SECTION("from (B)") { std::string_view data = R"( -let f : R*N -> R, (n,x) -> n*x; -f(-2, 3); -f(-1,-4); +let a:(B), a = (true, false); +let f : N -> (B), n -> a; +let t:(B), t = f(true); )"; + std::vector<bool> result{true, false}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } - CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-4)"); + SECTION("-> (N)") + { + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (N), n -> not n; +let t:(N), t = f(false); +)"; + std::vector<uint64_t> result{true}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); } - SECTION("single N return value") + SECTION("from N") { std::string_view data = R"( -let f : N*N -> N, (m,n) -> m-n; -f(2, 1); -f(1, 3); +let f : N -> (N), n -> n; +let t:(N), t = f(7); +)"; + std::vector<uint64_t> result{7}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (N), p -> -p; +let t:(N), t = f(-2); )"; + std::vector<uint64_t> result{2}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } - CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)"); + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (N), n -> l; +let t:(N), t = f(false); +)"; + std::vector<uint64_t> result{1, 0, 1}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); } - SECTION("compound N return value") + SECTION("from (N)") { std::string_view data = R"( -let f : N*N -> N*N, (m,n) -> (m+n, m-n); -f(3, 2); -f(1, 4); +let l :(N), l = (2,3,6); +let f : N -> (N), n -> l; +let t :(N), t = f(2); )"; + std::vector<uint64_t> result{2, 3, 6}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } - CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)"); + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, 6, 7); +let f : Z -> (N), p -> l; +let t :(N), t = f(-2); +)"; + std::vector<uint64_t> result{2, 6, 7}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (N), b -> (b, n, 12); +let t :(N), t = f(false); +)"; + std::vector<uint64_t> result{false, 3, 12}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (Z)") + { + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (Z), n -> not n; +let t:(Z), t = f(false); +)"; + std::vector<int64_t> result{true}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> (Z), n -> n; +let t:(Z), t = f(7); +)"; + std::vector<int64_t> result{7}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (Z), p -> p; +let t:(Z), t = f(-2); +)"; + std::vector<int64_t> result{-2}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (Z), n -> l; +let t:(Z), t = f(false); +)"; + std::vector<int64_t> result{1, 0, 1}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let l :(N), l = (2,3,6); +let f : N -> (Z), n -> l; +let t :(Z), t = f(2); +)"; + std::vector<int64_t> result{2, 3, 6}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, -6, 7); +let f : Z -> (Z), p -> l; +let t :(Z), t = f(-2); +)"; + std::vector<int64_t> result{2, -6, 7}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (Z), b -> (b, n, -12); +let t :(Z), t = f(false); +)"; + std::vector<int64_t> result{false, 3, -12}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R)") + { + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (R), n -> not n; +let t:(R), t = f(false); +)"; + std::vector<double> result{true}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> (R), n -> n; +let t:(R), t = f(7); +)"; + std::vector<double> result{7}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (R), p -> p; +let t:(R), t = f(-2); +)"; + std::vector<double> result{-2}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : Z -> (R), p -> 2.3*p; +let t:(R), t = f(-2); +)"; + std::vector<double> result{-2l * 2.3}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (R), n -> l; +let t:(R), t = f(false); +)"; + std::vector<double> result{true, false, true}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let l :(N), l = (2,3,6); +let f : N -> (R), n -> l; +let t :(R), t = f(2); +)"; + std::vector<double> result{2ul, 3ul, 6ul}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, -6, 7); +let f : Z -> (R), p -> l; +let t :(R), t = f(-2); +)"; + std::vector<double> result{2l, -6l, 7l}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R)") + { + std::string_view data = R"( +let l :(R), l = (2.2, -6, 7.3); +let f : Z -> (R), p -> l; +let t :(R), t = f(-2); +)"; + std::vector<double> result{2.2, -6, 7.3}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (R), b -> (b, n, -12, 2.3); +let t :(R), t = f(false); +)"; + std::vector<double> result{false, 3ul, -12l, 2.3}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^1)") + { + using Rd = TinyVector<1>; + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (R^1), n -> not n; +let t:(R^1), t = f(false); +)"; + std::vector<Rd> result{Rd{true}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> (R^1), n -> n; +let t:(R^1), t = f(7); +)"; + std::vector<Rd> result{Rd{7}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (R^1), p -> p; +let t:(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{-2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : Z -> (R^1), p -> 2.3*p; +let t:(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{-2l * 2.3}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^1") + { + std::string_view data = R"( +let f : Z -> (R^1), p -> 2.2*[p]; +let t:(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{-2l * 2.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (R^1), n -> l; +let t:(R^1), t = f(false); +)"; + std::vector<Rd> result{Rd{true}, Rd{false}, Rd{true}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let l :(N), l = (2,3,6); +let f : N -> (R^1), n -> l; +let t :(R^1), t = f(2); +)"; + std::vector<Rd> result{Rd{2ul}, Rd{3ul}, Rd{6ul}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, -6, 7); +let f : Z -> (R^1), p -> l; +let t :(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{2l}, Rd{-6l}, Rd{7l}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R)") + { + std::string_view data = R"( +let l :(R), l = (2.2, -6.1, 7.4); +let f : Z -> (R^1), p -> l; +let t :(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{2.2}, Rd{-6.1}, Rd{7.4}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^1)") + { + std::string_view data = R"( +let l :(R^1), l = ([2.2], -[6.1], [7.4]); +let f : Z -> (R^1), p -> l; +let t :(R^1), t = f(-2); +)"; + std::vector<Rd> result{Rd{2.2}, Rd{-6.1}, Rd{7.4}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (R^1), b -> (b, n, -12, 2.3, [4.2]); +let t :(R^1), t = f(false); +)"; + std::vector<Rd> result{Rd{false}, Rd{3ul}, Rd{-12l}, Rd{2.3}, Rd{4.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^2)") + { + using Rd = TinyVector<2>; + SECTION("from R^2") + { + std::string_view data = R"( +let f : Z -> (R^2), p -> 2.2*[p, 2*p]; +let t:(R^2), t = f(-2); +)"; + std::vector<Rd> result{Rd{-2l * 2.2, -4l * 2.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from '0'") + { + std::string_view data = R"( +let f : Z -> (R^2), p -> 0; +let t :(R^2), t = f(-2); +)"; + std::vector<Rd> result{Rd{zero}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^2)") + { + std::string_view data = R"( +let l :(R^2), l = ([2.2, 1.2], -[6.1, 7], [7.4, 1]); +let f : Z -> (R^2), p -> l; +let t :(R^2), t = f(-2); +)"; + std::vector<Rd> result{Rd{2.2, 1.2}, -Rd{6.1, 7}, Rd{7.4, 1}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let f : B -> (R^2), b -> ([1.2, 3], 0, [4.2, 1]); +let t :(R^2), t = f(false); +)"; + std::vector<Rd> result{Rd{1.2, 3}, Rd{zero}, Rd{4.2, 1}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^3)") + { + using Rd = TinyVector<3>; + SECTION("from R^3") + { + std::string_view data = R"( +let f : Z -> (R^3), p -> 2.2*[p, 2*p, 2]; +let t:(R^3), t = f(-2); +)"; + std::vector<Rd> result{Rd{-2l * 2.2, -4l * 2.2, 4.4}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from '0'") + { + std::string_view data = R"( +let f : Z -> (R^3), p -> 0; +let t :(R^3), t = f(-2); +)"; + std::vector<Rd> result{Rd{zero}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^3)") + { + std::string_view data = R"( +let l :(R^3), l = ([2.2, 1.2, 2], -[6.1, 7, 5], [7.4, 1, -1]); +let f : Z -> (R^3), p -> l; +let t :(R^3), t = f(-2); +)"; + std::vector<Rd> result{Rd{2.2, 1.2, 2}, -Rd{6.1, 7, 5}, Rd{7.4, 1, -1}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let f : B -> (R^3), b -> ([1.2, 3, 1], 0, [4.2, 1, 7]); +let t :(R^3), t = f(false); +)"; + std::vector<Rd> result{Rd{1.2, 3, 1}, Rd{zero}, Rd{4.2, 1, 7}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^1x1)") + { + using Rdxd = TinyMatrix<1>; + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (R^1x1), n -> not n; +let t:(R^1x1), t = f(false); +)"; + std::vector<Rdxd> result{Rdxd{true}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> (R^1x1), n -> n; +let t:(R^1x1), t = f(7); +)"; + std::vector<Rdxd> result{Rdxd{7}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (R^1x1), p -> p; +let t:(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{-2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : Z -> (R^1x1), p -> 2.3*p; +let t:(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{-2l * 2.3}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^1x1") + { + std::string_view data = R"( +let f : Z -> (R^1x1), p -> 2.2*[[p]]; +let t:(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{-2l * 2.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (R^1x1), n -> l; +let t:(R^1x1), t = f(false); +)"; + std::vector<Rdxd> result{Rdxd{true}, Rdxd{false}, Rdxd{true}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let l :(N), l = (2,3,6); +let f : N -> (R^1x1), n -> l; +let t :(R^1x1), t = f(2); +)"; + std::vector<Rdxd> result{Rdxd{2ul}, Rdxd{3ul}, Rdxd{6ul}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, -6, 7); +let f : Z -> (R^1x1), p -> l; +let t :(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{2l}, Rdxd{-6l}, Rdxd{7l}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R)") + { + std::string_view data = R"( +let l :(R), l = (2.2, -6.1, 7.4); +let f : Z -> (R^1x1), p -> l; +let t :(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{2.2}, Rdxd{-6.1}, Rdxd{7.4}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^1x1)") + { + std::string_view data = R"( +let l :(R^1x1), l = ([[2.2]], -[[6.1]], [[7.4]]); +let f : Z -> (R^1x1), p -> l; +let t :(R^1x1), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{2.2}, Rdxd{-6.1}, Rdxd{7.4}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (R^1x1), b -> (b, n, -12, 2.3, [[4.2]]); +let t :(R^1x1), t = f(false); +)"; + std::vector<Rdxd> result{Rdxd{false}, Rdxd{3ul}, Rdxd{-12l}, Rdxd{2.3}, Rdxd{4.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^2x2)") + { + using Rdxd = TinyMatrix<2>; + SECTION("from R^2x2") + { + std::string_view data = R"( +let f : Z -> (R^2x2), p -> 2.2*[[p, 2*p], [2,3]]; +let t:(R^2x2), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{-2l * 2.2, -4l * 2.2, 2l * 2.2, 3l * 2.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from '0'") + { + std::string_view data = R"( +let f : Z -> (R^2x2), p -> 0; +let t :(R^2x2), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{zero}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^2x2)") + { + std::string_view data = R"( +let l :(R^2x2), l = ([[2.2, 1.2],[6.1, 7]], [[7.4, 1],[3.4, -2]]); +let f : Z -> (R^2x2), p -> l; +let t :(R^2x2), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{2.2, 1.2, 6.1, 7}, Rdxd{7.4, 1, 3.4, -2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let f : B -> (R^2x2), b -> ([[1.2, 3],[4.5, 6]], 0, [[4.2, 1],[1.3,-6]]); +let t :(R^2x2), t = f(false); +)"; + std::vector<Rdxd> result{Rdxd{1.2, 3, 4.5, 6}, Rdxd{zero}, Rdxd{4.2, 1, 1.3, -6}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (R^3x3)") + { + using Rdxd = TinyMatrix<3>; + SECTION("from R^3x3") + { + std::string_view data = R"( +let f : Z -> (R^3x3), p -> 2.2*[[p, 2*p, 2],[2,3,5],[3,6,2]]; +let t:(R^3x3), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{-2l * 2.2, -4l * 2.2, 2l * 2.2, // + 2l * 2.2, 3l * 2.2, 5l * 2.2, // + 3l * 2.2, 6l * 2.2, 2l * 2.2}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from '0'") + { + std::string_view data = R"( +let f : Z -> (R^3x3), p -> 0; +let t :(R^3x3), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{zero}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^3x3)") + { + std::string_view data = R"( +let l :(R^3x3), l = ([[2.2, 1.2, 2], [-6.1, 7, 5], [7.4, 1, -1]], 0); +let f : Z -> (R^3x3), p -> l; +let t :(R^3x3), t = f(-2); +)"; + std::vector<Rdxd> result{Rdxd{2.2, 1.2, 2, // + -6.1, 7, 5, // + 7.4, 1, -1}, + Rdxd{zero}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let f : B -> (R^3x3), b -> ([[1.2, 3, 1],[1,2,3],[4.2,2,6]], 0, [[4.2, 1, 7],[2,4,6],[2,3,1]]); +let t :(R^3x3), t = f(false); +)"; + std::vector<Rdxd> result{Rdxd{1.2, 3, 1, // + 1, 2, 3, // + 4.2, 2, 6}, + Rdxd{zero}, + Rdxd{4.2, 1, 7, // + 2, 4, 6, // + 2, 3, 1}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("-> (string)") + { + SECTION("from B") + { + std::string_view data = R"( +let f : B -> (string), n -> not n; +let t:(string), t = f(false); +)"; + std::vector<std::string> result{stringify(true)}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from N") + { + std::string_view data = R"( +let f : N -> (string), n -> n; +let t:(string), t = f(7); +)"; + std::vector<std::string> result{stringify(7)}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from Z") + { + std::string_view data = R"( +let f : Z -> (string), p -> p; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(-2)}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R") + { + std::string_view data = R"( +let f : Z -> (string), p -> 2.3*p; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(-2l * 2.3)}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^1") + { + std::string_view data = R"( +let f : Z -> (string), p -> [2.3*p]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyVector<1>{-2l * 2.3})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^2") + { + std::string_view data = R"( +let f : Z -> (string), p -> [2.3*p, 3]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyVector<2>{-2l * 2.3, 3})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^3") + { + std::string_view data = R"( +let f : Z -> (string), p -> [1, 2.3*p, 3]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyVector<3>{1, -2l * 2.3, 3})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^1x1") + { + std::string_view data = R"( +let f : Z -> (string), p -> [[2.3*p]]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyMatrix<1>{-2l * 2.3})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^2x2") + { + std::string_view data = R"( +let f : Z -> (string), p -> [[2.3*p, 3],[2, p]]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyMatrix<2>{-2l * 2.3, 3, 2, -2})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from R^3x3") + { + std::string_view data = R"( +let f : Z -> (string), p -> [[1, 2.3*p, 3],[1.2, 2.3, 0.5],[0.1, 1.4, 6]]; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(TinyMatrix<3>{1, -2l * 2.3, 3, // + 1.2, 2.3, 0.5, // + 0.1, 1.4, 6})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from string") + { + std::string_view data = R"( +let f : Z -> (string), p -> "foo"; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{std::string{"foo"}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (B)") + { + std::string_view data = R"( +let l : (B), l = (true, false, true); +let f : B -> (string), n -> l; +let t:(string), t = f(false); +)"; + std::vector<std::string> result{stringify(std::vector<bool>{true, false, true})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let l :(N), l = (2,3,6); +let f : N -> (string), n -> l; +let t :(string), t = f(2); +)"; + std::vector<std::string> result{stringify(std::vector<double>{2ul, 3ul, 6ul})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let l :(Z), l = (2, -6, 7); +let f : Z -> (string), p -> l; +let t :(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<double>{2l, -6l, 7l})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R)") + { + std::string_view data = R"( +let l :(R), l = (2.2, -6, 7.3); +let f : Z -> (string), p -> l; +let t :(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<double>{2.2, -6, 7.3})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^1)") + { + using Rd = TinyVector<1>; + + std::string_view data = R"( +let l : (R^1), l = (0, [2], [3.5]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<Rd>{Rd{zero}, Rd{2}, Rd{3.5}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^2)") + { + using Rd = TinyVector<2>; + + std::string_view data = R"( +let l : (R^2), l = ([1, 2], 0, [2, 3.5]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<Rd>{Rd{1, 2}, Rd{zero}, Rd{2, 3.5}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^3)") + { + using Rd = TinyVector<3>; + + std::string_view data = R"( +let l : (R^3), l = ([1, 2, 3], 0, [2, 3.5, 7]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<Rd>{Rd{1, 2, 3}, Rd{zero}, Rd{2, 3.5, 7}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^1x1)") + { + using Rdxd = TinyMatrix<1>; + + std::string_view data = R"( +let l : (R^1x1), l = ([[1]], 0, [[3.5]]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{stringify(std::vector<Rdxd>{Rdxd{1}, Rdxd{zero}, Rdxd{3.5}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^2x2)") + { + using Rdxd = TinyMatrix<2>; + + std::string_view data = R"( +let l : (R^2x2), l = ([[1,2],[3,4]], 0, [[3.5,-5],[3.7,2.9]]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{ + stringify(std::vector<Rdxd>{Rdxd{1, 2, 3, 4}, Rdxd{zero}, Rdxd{3.5, -5, 3.7, 2.9}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (R^3x3)") + { + using Rdxd = TinyMatrix<3>; + + std::string_view data = R"( +let l : (R^3x3), l = ([[1,2,3],[3,5,6],[9,3,4]], 0, [[1,3,7],[3.5,-5,2.3],[2.1,3.7,2.9]]); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + + std::vector<std::string> result{stringify(std::vector<Rdxd>{Rdxd{1, 2, 3, 3, 5, 6, 9, 3, 4}, // + Rdxd{zero}, // + Rdxd{1, 3, 7, 3.5, -5, 2.3, 2.1, 3.7, 2.9}})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from (string)") + { + std::string_view data = R"( +let l:(string), l = ("foo", "bar", "foobar"); +let f : Z -> (string), p -> l; +let t:(string), t = f(-2); +)"; + std::vector<std::string> result{std::vector<std::string>{"foo", "bar", "foobar"}}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("from list") + { + std::string_view data = R"( +let n : N, n = 3; +let f : B -> (string), b -> (b, n, -12, 2.3, "foo"); +let t :(string), t = f(false); +)"; + + std::vector<std::string> result{stringify( + std::vector<std::string>{stringify(false), stringify(3ul), stringify(-12l), stringify(2.3), "foo"})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + } + + SECTION("empty functions") + { + SECTION("to value") + { + std::string_view data = R"( +let f : void -> R^3, void -> [1,2,3]; +let x :R^3, x = f(); +)"; + + CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (TinyVector<3>{1, 2, 3})); + } + + SECTION("to tuple") + { + std::string_view data = R"( +let n : N, n = 3; +let f : void -> (string), void -> (false, n, -12, 2.3, "foo"); +n+=5; +let t :(string), t = f(); +)"; + + std::vector<std::string> result{stringify( + std::vector<std::string>{stringify(false), stringify(8ul), stringify(-12l), stringify(2.3), "foo"})}; + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", result); + } + + SECTION("to compound") + { + std::string_view data = R"( +let n : N, n = 3; +let f : void -> N*(R)*R^2, void -> (n, (1,2,3), [-12, 2.3]); +n+=5; +let (m,t,x):N*(R)*R^2, (m,t,x) = f(); +)"; + + CHECK_FUNCTION_EVALUATION_RESULT(data, "m", 8ul); + CHECK_FUNCTION_EVALUATION_RESULT(data, "t", (std::vector<double>{1, 2, 3})); + CHECK_FUNCTION_EVALUATION_RESULT(data, "x", (TinyVector<2>{-12, 2.3})); + } + } + } + + SECTION("errors") + { + SECTION("negative value to N") + { + SECTION("single N argument") + { + std::string_view data = R"( +let f : N -> N, n -> 2; +f(2); +f(-1); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)"); + } + + SECTION("multiple N arguments") + { + std::string_view data = R"( +let f : R*N -> R, (n,x) -> n*x; +f(-2, 3); +f(-1,-4); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-4)"); + } + + SECTION("single N return value") + { + std::string_view data = R"( +let f : N*N -> N, (m,n) -> m-n; +f(2, 1); +f(1, 3); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)"); + } + + SECTION("compound N return value") + { + std::string_view data = R"( +let f : N*N -> N*N, (m,n) -> (m+n, m-n); +f(3, 2); +f(1, 4); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)"); + } + } + + SECTION("negative value to (N)") + { + SECTION("return N -> (N)") + { + std::string_view data = R"( +let f : N -> (N), n -> -2; +f(2); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-2)"); + } + + SECTION("return (Z) -> (N)") + { + std::string_view data = R"( +let z :(Z), z = (1, 2, -3); +let f : N -> (N), n -> z; +f(2); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-3)"); + } + + SECTION("return list") + { + std::string_view data = R"( +let f : N*N -> (N), (m,n) -> (m, n, n-m); +f(2, 1); +f(1, 2); +)"; + + CHECK_FUNCTION_EVALUATION_THROWS(data, "trying to convert negative value (-1)"); } } } diff --git a/tests/test_ItemArrayVariant.cpp b/tests/test_ItemArrayVariant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3b529126f6552cff212790f024728b1d3a2cda9 --- /dev/null +++ b/tests/test_ItemArrayVariant.cpp @@ -0,0 +1,101 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/ItemArrayVariant.hpp> +#include <mesh/Mesh.hpp> +#include <utils/Messenger.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("ItemArrayVariant", "[mesh]") +{ + std::shared_ptr mesh = MeshDataBaseForTests::get().hybrid2DMesh(); + + const Connectivity<2>& connectivity = *mesh->shared_connectivity(); + + using R1 = TinyVector<1>; + using R2 = TinyVector<2>; + using R3 = TinyVector<3>; + + using R1x1 = TinyMatrix<1>; + using R2x2 = TinyMatrix<2>; + using R3x3 = TinyMatrix<3>; + + SECTION("NodeArray<double>") + { + NodeArray<double> node_array{connectivity, 2}; + ItemArrayVariant v(node_array); + REQUIRE_NOTHROW(v.get<NodeArray<const double>>()); + REQUIRE_THROWS_WITH(v.get<NodeArray<int64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<uint64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R1x1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R2x2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<NodeArray<const R3x3>>(), "error: invalid ItemArray type"); + + REQUIRE_THROWS_WITH(v.get<EdgeArray<const double>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const double>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const double>>(), "error: invalid ItemArray type"); + } + + SECTION("EdgeArray<R3>") + { + EdgeArray<R3> node_array{connectivity, 3}; + ItemArrayVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<EdgeArray<int64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<uint64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<double>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R2>>(), "error: invalid ItemArray type"); + REQUIRE_NOTHROW(v.get<EdgeArray<const R3>>()); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R1x1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R2x2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R3x3>>(), "error: invalid ItemArray type"); + + REQUIRE_THROWS_WITH(v.get<NodeArray<const R3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R3>>(), "error: invalid ItemArray type"); + } + + SECTION("FaceArray<R3x3>") + { + FaceArray<R3x3> node_array{connectivity, 2}; + ItemArrayVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<FaceArray<int64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<uint64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<double>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R1x1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const R2x2>>(), "error: invalid ItemArray type"); + REQUIRE_NOTHROW(v.get<FaceArray<const R3x3>>()); + + REQUIRE_THROWS_WITH(v.get<NodeArray<const R3x3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const R3x3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R3x3>>(), "error: invalid ItemArray type"); + } + + SECTION("CellArray<int64_t>") + { + CellArray<int64_t> node_array{connectivity, 2}; + ItemArrayVariant v(node_array); + REQUIRE_NOTHROW(v.get<CellArray<const int64_t>>()); + REQUIRE_THROWS_WITH(v.get<CellArray<const uint64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const double>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R3>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R1x1>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R2x2>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<CellArray<const R3x3>>(), "error: invalid ItemArray type"); + + REQUIRE_THROWS_WITH(v.get<NodeArray<const int64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<EdgeArray<const int64_t>>(), "error: invalid ItemArray type"); + REQUIRE_THROWS_WITH(v.get<FaceArray<const int64_t>>(), "error: invalid ItemArray type"); + } +} diff --git a/tests/test_ItemArrayVariantFunctionInterpoler.cpp b/tests/test_ItemArrayVariantFunctionInterpoler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..640e3e77aa5e6ede05fe0f217d7587f7839e4d56 --- /dev/null +++ b/tests/test_ItemArrayVariantFunctionInterpoler.cpp @@ -0,0 +1,648 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <language/ast/ASTBuilder.hpp> +#include <language/ast/ASTModulesImporter.hpp> +#include <language/ast/ASTNodeDataTypeBuilder.hpp> +#include <language/ast/ASTNodeExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionEvaluationExpressionBuilder.hpp> +#include <language/ast/ASTNodeFunctionExpressionBuilder.hpp> +#include <language/ast/ASTNodeTypeCleaner.hpp> +#include <language/ast/ASTSymbolTableBuilder.hpp> +#include <language/utils/PugsFunctionAdapter.hpp> +#include <language/utils/SymbolTable.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/MeshData.hpp> +#include <mesh/MeshDataManager.hpp> + +#include <language/utils/ItemArrayVariantFunctionInterpoler.hpp> + +#include <pegtl/string_input.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("ItemArrayVariantFunctionInterpoler", "[scheme]") +{ + auto same_item_array = [](auto f, auto g) -> bool { + using ItemIdType = typename decltype(f)::index_type; + if (f.sizeOfArrays() != g.sizeOfArrays()) { + return false; + } + + for (ItemIdType item_id = 0; item_id < f.numberOfItems(); ++item_id) { + for (size_t i = 0; i < f.sizeOfArrays(); ++i) { + if (f[item_id][i] != g[item_id][i]) { + return false; + } + } + } + + return true; + }; + + SECTION("1D") + { + constexpr size_t Dimension = 1; + + std::array mesh_list = MeshDataBaseForTests::get().all1DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh_1d = named_mesh.mesh(); + + auto xj = MeshDataManager::instance().getMeshData(*mesh_1d).xj(); + auto xr = mesh_1d->xr(); + + std::string_view data = R"( +import math; +let B_scalar_non_linear1_1d: R^1 -> B, x -> (exp(2 * x[0]) + 3 > 4); +let B_scalar_non_linear2_1d: R^1 -> B, x -> (exp(2 * x[0]) + 3 < 4); + +let N_scalar_non_linear1_1d: R^1 -> N, x -> floor(3 * x[0] * x[0] + 2); +let N_scalar_non_linear2_1d: R^1 -> N, x -> floor(2 * x[0] * x[0]); + +let Z_scalar_non_linear1_1d: R^1 -> Z, x -> floor(exp(2 * x[0]) - 1); +let Z_scalar_non_linear2_1d: R^1 -> Z, x -> floor(cos(2 * x[0]) + 0.5); + +let R_scalar_non_linear1_1d: R^1 -> R, x -> 2 * exp(x[0]) + 3; +let R_scalar_non_linear2_1d: R^1 -> R, x -> 2 * sin(x[0]) + 1; +let R_scalar_non_linear3_1d: R^1 -> R, x -> x[0] * sin(x[0]); + +let R1_non_linear1_1d: R^1 -> R^1, x -> 2 * exp(x[0]); +let R1_non_linear2_1d: R^1 -> R^1, x -> 2 * exp(x[0])*x[0]; + +let R2_non_linear_1d: R^1 -> R^2, x -> [2 * exp(x[0]), -3*x[0]]; + +let R3_non_linear_1d: R^1 -> R^3, x -> [2 * exp(x[0]) + 3, x[0] - 2, 3]; + +let R1x1_non_linear_1d: R^1 -> R^1x1, x -> (2 * exp(x[0]) * sin(x[0]) + 3); + +let R2x2_non_linear_1d: R^1 -> R^2x2, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0])], [3, x[0] * x[0]]]; + +let R3x3_non_linear_1d: R^1 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[0]) + 3, sin(x[0] - 2 * x[0]), 3], [x[0] * x[0], -4*x[0], 2*x[0]+1], [3, -6*x[0], exp(x[0])]]; +)"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("B_scalar_non_linear_1d") + { + auto [i_symbol_f1, found_f1] = symbol_table->find("B_scalar_non_linear1_1d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("B_scalar_non_linear2_1d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + CellArray<bool> cell_array{mesh_1d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = std::exp(2 * x[0]) + 3 > 4; + cell_array[cell_id][1] = std::exp(2 * x[0]) + 3 < 4; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_data_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_data_variant->get<CellArray<bool>>())); + } + + SECTION("N_scalar_non_linear_1d") + { + auto [i_symbol_f1, found_f1] = symbol_table->find("N_scalar_non_linear1_1d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("N_scalar_non_linear2_1d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + NodeArray<uint64_t> node_array{mesh_1d->connectivity(), 2}; + parallel_for( + node_array.numberOfItems(), PUGS_LAMBDA(const NodeId node_id) { + const TinyVector<Dimension>& x = xr[node_id]; + node_array[node_id][0] = std::floor(3 * x[0] * x[0] + 2); + node_array[node_id][1] = std::floor(2 * x[0] * x[0]); + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::node, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_data_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(node_array, item_data_variant->get<NodeArray<uint64_t>>())); + } + + SECTION("Z_scalar_non_linear_1d") + { + auto [i_symbol_f1, found_f1] = symbol_table->find("Z_scalar_non_linear1_1d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("Z_scalar_non_linear2_1d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + CellArray<int64_t> cell_array{mesh_1d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = std::floor(std::exp(2 * x[0]) - 1); + cell_array[cell_id][1] = std::floor(cos(2 * x[0]) + 0.5); + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<int64_t>>())); + } + + SECTION("R_scalar_non_linear_1d") + { + auto [i_symbol_f1, found_f1] = symbol_table->find("R_scalar_non_linear1_1d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("R_scalar_non_linear2_1d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + auto [i_symbol_f3, found_f3] = symbol_table->find("R_scalar_non_linear3_1d", position); + REQUIRE(found_f3); + REQUIRE(i_symbol_f3->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function3_symbol_id(std::get<uint64_t>(i_symbol_f3->attributes().value()), symbol_table); + + CellArray<double> cell_array{mesh_1d->connectivity(), 3}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + + cell_array[cell_id][0] = 2 * std::exp(x[0]) + 3; + cell_array[cell_id][1] = 2 * std::sin(x[0]) + 1; + cell_array[cell_id][2] = x[0] * std::sin(x[0]); + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, + {function1_symbol_id, function2_symbol_id, + function3_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<double>>())); + } + + SECTION("R1_non_linear_1d") + { + using DataType = TinyVector<1>; + + auto [i_symbol_f1, found_f1] = symbol_table->find("R1_non_linear1_1d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("R1_non_linear2_1d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 2}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + + cell_array[cell_id][0] = DataType{2 * std::exp(x[0])}; + cell_array[cell_id][1] = DataType{2 * std::exp(x[0]) * x[0]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + + SECTION("R2_non_linear_1d") + { + using DataType = TinyVector<2>; + + auto [i_symbol, found] = symbol_table->find("R2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 1}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + + cell_array[cell_id][0] = DataType{2 * std::exp(x[0]), -3 * x[0]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + + SECTION("R3_non_linear_1d") + { + using DataType = TinyVector<3>; + + auto [i_symbol, found] = symbol_table->find("R3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 1}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = DataType{2 * std::exp(x[0]) + 3, x[0] - 2, 3}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + + SECTION("R1x1_non_linear_1d") + { + using DataType = TinyMatrix<1>; + + auto [i_symbol, found] = symbol_table->find("R1x1_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 1}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + + SECTION("R2x2_non_linear_1d") + { + using DataType = TinyMatrix<2>; + + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 1}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + cell_array[cell_id][0] = + DataType{2 * std::exp(x[0]) * std::sin(x[0]) + 3, std::sin(x[0] - 2 * x[0]), 3, x[0] * x[0]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + + SECTION("R3x3_non_linear_1d") + { + using DataType = TinyMatrix<3>; + + auto [i_symbol, found] = symbol_table->find("R3x3_non_linear_1d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + CellArray<DataType> cell_array{mesh_1d->connectivity(), 1}; + parallel_for( + cell_array.numberOfItems(), PUGS_LAMBDA(const CellId cell_id) { + const TinyVector<Dimension>& x = xj[cell_id]; + + cell_array[cell_id][0] = DataType{2 * exp(x[0]) * std::sin(x[0]) + 3, + std::sin(x[0] - 2 * x[0]), + 3, + x[0] * x[0], + -4 * x[0], + 2 * x[0] + 1, + 3, + -6 * x[0], + std::exp(x[0])}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_1d, ItemType::cell, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(cell_array, item_array_variant->get<CellArray<DataType>>())); + } + } + } + } + + SECTION("2D") + { + constexpr size_t Dimension = 2; + + std::array mesh_list = MeshDataBaseForTests::get().all2DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh_2d = named_mesh.mesh(); + + auto xl = MeshDataManager::instance().getMeshData(*mesh_2d).xl(); + + std::string_view data = R"( +import math; +let B_scalar_non_linear1_2d: R^2 -> B, x -> (exp(2 * x[0])< 2*x[1]); +let B_scalar_non_linear2_2d: R^2 -> B, x -> (sin(2 * x[0])< x[1]); + +let R2_non_linear_2d: R^2 -> R^2, x -> [2 * exp(x[0]), -3*x[1]]; + +let R3x3_non_linear_2d: R^2 -> R^3x3, x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(x[1] - 2 * x[0]), 3], + [x[1] * x[0], -4*x[1], 2*x[0]+1], + [3, -6*x[0], exp(x[1])]]; + )"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("B_scalar_non_linear_2d") + { + using DataType = bool; + + auto [i_symbol_f1, found_f1] = symbol_table->find("B_scalar_non_linear1_2d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("B_scalar_non_linear2_2d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + FaceArray<DataType> face_array{mesh_2d->connectivity(), 2}; + parallel_for( + face_array.numberOfItems(), PUGS_LAMBDA(const FaceId face_id) { + const TinyVector<Dimension>& x = xl[face_id]; + face_array[face_id][0] = std::exp(2 * x[0]) < 2 * x[1]; + face_array[face_id][1] = std::sin(2 * x[0]) < x[1]; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_2d, ItemType::face, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(face_array, item_array_variant->get<FaceArray<DataType>>())); + } + + SECTION("R2_non_linear_2d") + { + using DataType = TinyVector<2>; + + auto [i_symbol, found] = symbol_table->find("R2_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + FaceArray<DataType> face_array{mesh_2d->connectivity(), 1}; + parallel_for( + face_array.numberOfItems(), PUGS_LAMBDA(const FaceId face_id) { + const TinyVector<Dimension>& x = xl[face_id]; + + face_array[face_id][0] = DataType{2 * std::exp(x[0]), -3 * x[1]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_2d, ItemType::face, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(face_array, item_array_variant->get<FaceArray<DataType>>())); + } + + SECTION("R3x3_non_linear_2d") + { + using DataType = TinyMatrix<3>; + + auto [i_symbol, found] = symbol_table->find("R3x3_non_linear_2d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + FaceArray<DataType> face_array{mesh_2d->connectivity(), 1}; + parallel_for( + face_array.numberOfItems(), PUGS_LAMBDA(const FaceId face_id) { + const TinyVector<Dimension>& x = xl[face_id]; + + face_array[face_id][0] = DataType{2 * std::exp(x[0]) * std::sin(x[1]) + 3, + std::sin(x[1] - 2 * x[0]), + 3, + x[1] * x[0], + -4 * x[1], + 2 * x[0] + 1, + 3, + -6 * x[0], + std::exp(x[1])}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_2d, ItemType::face, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(face_array, item_array_variant->get<FaceArray<DataType>>())); + } + } + } + } + + SECTION("3D") + { + constexpr size_t Dimension = 3; + + std::array mesh_list = MeshDataBaseForTests::get().all3DMeshes(); + + for (const auto& named_mesh : mesh_list) { + SECTION(named_mesh.name()) + { + auto mesh_3d = named_mesh.mesh(); + + auto xe = MeshDataManager::instance().getMeshData(*mesh_3d).xe(); + + std::string_view data = R"( +import math; +let R_scalar_non_linear1_3d: R^3 -> R, x -> 2 * exp(x[0]+x[2]) + 3 * x[1]; +let R_scalar_non_linear2_3d: R^3 -> R, x -> 3 * sin(x[0]+x[2]) + 2 * x[1]; + +let R3_non_linear_3d: R^3 -> R^3, x -> [2 * exp(x[0]) + 3, x[1] - 2, 3 * x[2]]; +let R2x2_non_linear_3d: R^3 -> R^2x2, + x -> [[2 * exp(x[0]) * sin(x[1]) + 3, sin(x[2] - 2 * x[0])], + [3, x[1] * x[0] - x[2]]]; + )"; + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; + + auto ast = ASTBuilder::build(input); + + ASTModulesImporter{*ast}; + ASTNodeTypeCleaner<language::import_instruction>{*ast}; + + ASTSymbolTableBuilder{*ast}; + ASTNodeDataTypeBuilder{*ast}; + + ASTNodeTypeCleaner<language::var_declaration>{*ast}; + ASTNodeTypeCleaner<language::fct_declaration>{*ast}; + ASTNodeExpressionBuilder{*ast}; + + std::shared_ptr<SymbolTable> symbol_table = ast->m_symbol_table; + + TAO_PEGTL_NAMESPACE::position position{TAO_PEGTL_NAMESPACE::internal::iterator{"fixture"}, "fixture"}; + position.byte = data.size(); // ensure that variables are declared at this point + + SECTION("R_scalar_non_linear_3d") + { + auto [i_symbol_f1, found_f1] = symbol_table->find("R_scalar_non_linear1_3d", position); + REQUIRE(found_f1); + REQUIRE(i_symbol_f1->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function1_symbol_id(std::get<uint64_t>(i_symbol_f1->attributes().value()), symbol_table); + + auto [i_symbol_f2, found_f2] = symbol_table->find("R_scalar_non_linear2_3d", position); + REQUIRE(found_f2); + REQUIRE(i_symbol_f2->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function2_symbol_id(std::get<uint64_t>(i_symbol_f2->attributes().value()), symbol_table); + + EdgeArray<double> edge_array{mesh_3d->connectivity(), 2}; + parallel_for( + edge_array.numberOfItems(), PUGS_LAMBDA(const EdgeId edge_id) { + const TinyVector<Dimension>& x = xe[edge_id]; + + edge_array[edge_id][0] = 2 * std::exp(x[0] + x[2]) + 3 * x[1]; + edge_array[edge_id][1] = 3 * std::sin(x[0] + x[2]) + 2 * x[1]; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_3d, ItemType::edge, + {function1_symbol_id, function2_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(edge_array, item_array_variant->get<EdgeArray<double>>())); + } + + SECTION("R3_non_linear_3d") + { + using DataType = TinyVector<3>; + + auto [i_symbol, found] = symbol_table->find("R3_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + EdgeArray<DataType> edge_array{mesh_3d->connectivity(), 1}; + parallel_for( + edge_array.numberOfItems(), PUGS_LAMBDA(const EdgeId edge_id) { + const TinyVector<Dimension>& x = xe[edge_id]; + + edge_array[edge_id][0] = DataType{2 * std::exp(x[0]) + 3, x[1] - 2, 3 * x[2]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_3d, ItemType::edge, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(edge_array, item_array_variant->get<EdgeArray<DataType>>())); + } + + SECTION("R2x2_non_linear_3d") + { + using DataType = TinyMatrix<2>; + + auto [i_symbol, found] = symbol_table->find("R2x2_non_linear_3d", position); + REQUIRE(found); + REQUIRE(i_symbol->attributes().dataType() == ASTNodeDataType::function_t); + + FunctionSymbolId function_symbol_id(std::get<uint64_t>(i_symbol->attributes().value()), symbol_table); + + EdgeArray<DataType> edge_array{mesh_3d->connectivity(), 1}; + parallel_for( + edge_array.numberOfItems(), PUGS_LAMBDA(const EdgeId edge_id) { + const TinyVector<Dimension>& x = xe[edge_id]; + edge_array[edge_id][0] = + DataType{2 * std::exp(x[0]) * std::sin(x[1]) + 3, std::sin(x[2] - 2 * x[0]), 3, x[1] * x[0] - x[2]}; + }); + + ItemArrayVariantFunctionInterpoler interpoler(mesh_3d, ItemType::edge, {function_symbol_id}); + std::shared_ptr item_array_variant = interpoler.interpolate(); + + REQUIRE(same_item_array(edge_array, item_array_variant->get<EdgeArray<DataType>>())); + } + } + } + } +} diff --git a/tests/test_ListAffectationProcessor.cpp b/tests/test_ListAffectationProcessor.cpp index 219b9a2f16907f3d6010d3144b7d2b903455d6fa..2c28e6e0b0e6a8c8ae8c61d4b5778c8e3617af58 100644 --- a/tests/test_ListAffectationProcessor.cpp +++ b/tests/test_ListAffectationProcessor.cpp @@ -45,6 +45,25 @@ REQUIRE(value == expected_value); \ } +#define CHECK_AFFECTATION_THROW_WITH(data, error_message) \ + { \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + auto ast = ASTBuilder::build(input); \ + \ + ASTModulesImporter{*ast}; \ + ASTNodeTypeCleaner<language::import_instruction>{*ast}; \ + \ + ASTSymbolTableBuilder{*ast}; \ + ASTNodeDataTypeBuilder{*ast}; \ + \ + ASTNodeDeclarationToAffectationConverter{*ast}; \ + ASTNodeTypeCleaner<language::var_declaration>{*ast}; \ + \ + ASTNodeExpressionBuilder{*ast}; \ + ExecutionPolicy exec_policy; \ + REQUIRE_THROWS_WITH(ast->execute(exec_policy), error_message); \ + } + // clazy:excludeall=non-pod-global-static TEST_CASE("ListAffectationProcessor", "[language]") @@ -738,4 +757,176 @@ let (s1,b2) : (string)*B, (s1,b2) = (s, false); } } } + + SECTION("list from tuple affectation") + { + SECTION("from (B)") + { + std::string_view data = R"( +let t:(B), t = (true, false, true, false, true, false, true); +let (b,n,z,r,r1,r11,s):B*N*Z*R*R^1*R^1x1*string, (b,n,z,r,r1,r11,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "b", (true)); + CHECK_AFFECTATION_RESULT(data, "n", (0ul)); + CHECK_AFFECTATION_RESULT(data, "z", (1l)); + CHECK_AFFECTATION_RESULT(data, "r", (double{0})); + CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{1})); + CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{0})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(true)})); + } + + SECTION("from (N)") + { + std::string_view data = R"( +let t:(N), t = (1, 2, 3, 4, 5, 6); +let (n,z,r,r1,r11,s):N*Z*R*R^1*R^1x1*string, (n,z,r,r1,r11,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "n", (1ul)); + CHECK_AFFECTATION_RESULT(data, "z", (2l)); + CHECK_AFFECTATION_RESULT(data, "r", (double{3})); + CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{4})); + CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{5})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(6ul)})); + } + + SECTION("from (Z)") + { + std::string_view data = R"( +let t:(Z), t = (1, -2, 3, -4, 5, 6); +let (n,z,r,r1,r11,s):N*Z*R*R^1*R^1x1*string, (n,z,r,r1,r11,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "n", (1ul)); + CHECK_AFFECTATION_RESULT(data, "z", (-2l)); + CHECK_AFFECTATION_RESULT(data, "r", (double{3})); + CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{-4})); + CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{5})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(6l)})); + } + + SECTION("from (R)") + { + std::string_view data = R"( +let t:(R), t = (1.2, -2.3, 7.3, -4.2); +let (r,r1,r11,s):R*R^1*R^1x1*string, (r,r1,r11,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r", (double{1.2})); + CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{-2.3})); + CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{7.3})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(-4.2)})); + } + + SECTION("from (R^1)") + { + std::string_view data = R"( +let t:(R^1), t = (1.2, -[2.3]); +let (r1,s):R^1*string, (r1,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r1", (TinyVector<1>{1.2})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<1>{-2.3})})); + } + + SECTION("from (R^2)") + { + std::string_view data = R"( +let t:(R^2), t = ([1.2, 2], [2.3, 0]); +let (r2,s):R^2*string, (r2,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r2", (TinyVector<2>{1.2, 2})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<2>{2.3, 0})})); + } + + SECTION("from (R^3)") + { + std::string_view data = R"( +let t:(R^3), t = ([1.2, 2, -1], [2.3, 0, 2]); +let (r3,s):R^3*string, (r3,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r3", (TinyVector<3>{1.2, 2, -1})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyVector<3>{2.3, 0, 2})})); + } + + SECTION("from (R^1x1)") + { + std::string_view data = R"( +let t:(R^1x1), t = (1.2, -[[2.3]]); +let (r11,s):R^1x1*string, (r11,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r11", (TinyMatrix<1>{1.2})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<1>{-2.3})})); + } + + SECTION("from (R^2x2)") + { + std::string_view data = R"( +let t:(R^2x2), t = ([[1.2, 2], [2.3, 0]], [[1.1, 2.2], [-1.3, 2]]); +let (r22,s):R^2x2*string, (r22,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r22", (TinyMatrix<2>{1.2, 2, 2.3, 0})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<2>{1.1, 2.2, -1.3, 2})})); + } + + SECTION("from (R^3x3)") + { + std::string_view data = R"( +let t:(R^3x3), t = ([[1.2, 2, -1], [2.3, 0, 2], [1, 4, 5]], 0); +let (r33,s):R^3x3*string, (r33,s)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "r33", (TinyMatrix<3>{1.2, 2, -1, 2.3, 0, 2, 1, 4, 5})); + CHECK_AFFECTATION_RESULT(data, "s", (std::string{stringify(TinyMatrix<3>{zero})})); + } + + SECTION("from (string)") + { + std::string_view data = R"( +let t:(string), t = ("foo", "bar"); +let (s1,s2):string*string, (s1,s2)=t; +)"; + + CHECK_AFFECTATION_RESULT(data, "s1", (std::string{"foo"})); + CHECK_AFFECTATION_RESULT(data, "s2", (std::string{"bar"})); + } + + SECTION("errors") + { + SECTION("negative (Z) -> N") + { + std::string_view data = R"( +let t:(Z), t = (2, 3, -4, 5); +let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t; +)"; + + CHECK_AFFECTATION_THROW_WITH(data, "trying to affect negative value (-4)"); + } + + SECTION("tuple too small") + { + std::string_view data = R"( +let t:(Z), t = (2, 3, 4); +let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t; +)"; + + CHECK_AFFECTATION_THROW_WITH(data, "cannot affect a (Z) of size 3 to a Z*N*N*R"); + } + + SECTION("tuple too large") + { + std::string_view data = R"( +let t:(Z), t = (1, 2, 3, 4, 5); +let (a,b,c,d):Z*N*N*R , (a,b,c,d)=t; +)"; + + CHECK_AFFECTATION_THROW_WITH(data, "cannot affect a (Z) of size 5 to a Z*N*N*R"); + } + } + } } diff --git a/tests/test_SmallMatrix.cpp b/tests/test_SmallMatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9712e13e330ee84adc55afeee1bcf81150312bc9 --- /dev/null +++ b/tests/test_SmallMatrix.cpp @@ -0,0 +1,416 @@ +#include <catch2/catch_approx.hpp> +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <Kokkos_Core.hpp> + +#include <utils/PugsAssert.hpp> +#include <utils/Types.hpp> + +#include <algebra/SmallMatrix.hpp> + +#include <sstream> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("SmallMatrix", "[algebra]") +{ + SmallMatrix<int> A{3, 4}; + + REQUIRE(A.numberOfRows() == 3); + REQUIRE(A.numberOfColumns() == 4); + + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 4; ++j) { + A(i, j) = 1 + 4 * i + j; + } + } + + REQUIRE(not A.isSquare()); + + REQUIRE(((A(0, 0) == 1) and (A(0, 1) == 2) and (A(0, 2) == 3) and (A(0, 3) == 4) and // + (A(1, 0) == 5) and (A(1, 1) == 6) and (A(1, 2) == 7) and (A(1, 3) == 8) and // + (A(2, 0) == 9) and (A(2, 1) == 10) and (A(2, 2) == 11) and (A(2, 3) == 12))); + + SmallMatrix<int> B{3, 4}; + B(0, 0) = -6; + B(0, 1) = 5; + B(0, 2) = 3; + B(0, 3) = 8; + + B(1, 0) = -4; + B(1, 1) = 6; + B(1, 2) = 5; + B(1, 3) = 3; + + B(2, 0) = 7; + B(2, 1) = 1; + B(2, 2) = 3; + B(2, 3) = 6; + + SECTION("copy and shallow copy") + { + SmallMatrix<const int> affected_A; + + REQUIRE(affected_A.numberOfRows() == 0); + REQUIRE(affected_A.numberOfColumns() == 0); + + affected_A = A; + REQUIRE(&A(0, 0) == &affected_A(0, 0)); + + REQUIRE(affected_A.numberOfRows() == A.numberOfRows()); + REQUIRE(affected_A.numberOfColumns() == A.numberOfColumns()); + + const SmallMatrix<int> copy_A = copy(A); + + REQUIRE(copy_A.numberOfRows() == A.numberOfRows()); + REQUIRE(copy_A.numberOfColumns() == A.numberOfColumns()); + + bool is_same = true; + for (size_t i = 0; i < A.numberOfRows(); ++i) { + for (size_t j = 0; j < A.numberOfColumns(); ++j) { + is_same &= (copy_A(i, j) == A(i, j)); + } + } + REQUIRE(is_same); + + REQUIRE(&A(0, 0) != ©_A(0, 0)); + } + + SECTION("fill and special affectations") + { + SmallMatrix<int> M(5); + REQUIRE(M.isSquare()); + M.fill(1); + for (size_t i = 0; i < M.numberOfRows(); ++i) { + for (size_t j = 0; j < M.numberOfColumns(); ++j) { + REQUIRE(M(i, j) == 1); + } + } + + M.fill(-4); + for (size_t i = 0; i < M.numberOfRows(); ++i) { + for (size_t j = 0; j < M.numberOfColumns(); ++j) { + REQUIRE(M(i, j) == -4); + } + } + + M = zero; + for (size_t i = 0; i < M.numberOfRows(); ++i) { + for (size_t j = 0; j < M.numberOfColumns(); ++j) { + REQUIRE(M(i, j) == 0); + } + } + + M = identity; + for (size_t i = 0; i < M.numberOfRows(); ++i) { + for (size_t j = 0; j < M.numberOfColumns(); ++j) { + REQUIRE(M(i, j) == (i == j)); + } + } + } + + SECTION("build from TinyMatrix") + { + TinyMatrix<3, 4> T{1, 2, 3, 4, 0.5, 1, 1.5, 2, 0.3, 0.6, 0.9, 1.2}; + SmallMatrix S{T}; + + REQUIRE(S.numberOfRows() == T.numberOfRows()); + REQUIRE(S.numberOfColumns() == T.numberOfColumns()); + + for (size_t i = 0; i < S.numberOfRows(); ++i) { + for (size_t j = 0; j < S.numberOfColumns(); ++j) { + REQUIRE(S(i, j) == T(i, j)); + } + } + } + + SmallMatrix AT = transpose(A); + + SECTION("transposed") + { + REQUIRE(AT.numberOfColumns() == A.numberOfRows()); + REQUIRE(AT.numberOfRows() == A.numberOfColumns()); + + bool is_same = true; + for (size_t i = 0; i < A.numberOfRows(); ++i) { + for (size_t j = 0; j < A.numberOfColumns(); ++j) { + is_same &= (AT(j, i) == A(i, j)); + } + } + REQUIRE(is_same); + } + + SECTION("sum") + { + SmallMatrix AaddB = copy(A); + AaddB += B; + + REQUIRE(AaddB(0, 0) == -5); + REQUIRE(AaddB(0, 1) == 7); + REQUIRE(AaddB(0, 2) == 6); + REQUIRE(AaddB(0, 3) == 12); + + REQUIRE(AaddB(1, 0) == 1); + REQUIRE(AaddB(1, 1) == 12); + REQUIRE(AaddB(1, 2) == 12); + REQUIRE(AaddB(1, 3) == 11); + + REQUIRE(AaddB(2, 0) == 16); + REQUIRE(AaddB(2, 1) == 11); + REQUIRE(AaddB(2, 2) == 14); + REQUIRE(AaddB(2, 3) == 18); + + SmallMatrix ApB = A + B; + for (size_t i = 0; i < ApB.numberOfRows(); ++i) { + for (size_t j = 0; j < ApB.numberOfColumns(); ++j) { + REQUIRE(AaddB(i, j) == ApB(i, j)); + } + } + } + + SECTION("difference") + { + SmallMatrix AsubsB = copy(A); + AsubsB -= B; + + REQUIRE(AsubsB(0, 0) == 7); + REQUIRE(AsubsB(0, 1) == -3); + REQUIRE(AsubsB(0, 2) == 0); + REQUIRE(AsubsB(0, 3) == -4); + + REQUIRE(AsubsB(1, 0) == 9); + REQUIRE(AsubsB(1, 1) == 0); + REQUIRE(AsubsB(1, 2) == 2); + REQUIRE(AsubsB(1, 3) == 5); + + REQUIRE(AsubsB(2, 0) == 2); + REQUIRE(AsubsB(2, 1) == 9); + REQUIRE(AsubsB(2, 2) == 8); + REQUIRE(AsubsB(2, 3) == 6); + + SmallMatrix AmB = A - B; + for (size_t i = 0; i < AmB.numberOfRows(); ++i) { + for (size_t j = 0; j < AmB.numberOfColumns(); ++j) { + REQUIRE(AsubsB(i, j) == AmB(i, j)); + } + } + } + + SECTION("left product by a scalar") + { + int a = 2; + + SmallMatrix aA = a * A; + + { + bool is_same = true; + for (size_t i = 0; i < A.numberOfRows(); ++i) { + for (size_t j = 0; j < A.numberOfColumns(); ++j) { + is_same &= (aA(i, j) == a * A(i, j)); + } + } + REQUIRE(is_same); + } + + SmallMatrix copy_A = copy(A); + copy_A *= a; + + { + bool is_same = true; + for (size_t i = 0; i < A.numberOfRows(); ++i) { + for (size_t j = 0; j < A.numberOfColumns(); ++j) { + is_same &= (aA(i, j) == copy_A(i, j)); + } + } + REQUIRE(is_same); + } + } + + SECTION("divide by a scalar") + { + SmallMatrix<double> M(3, 5); + M(0, 0) = 2; + M(0, 1) = 4; + M(0, 2) = 6; + M(0, 3) = 8; + M(0, 4) = 10; + + M(1, 0) = 12; + M(1, 1) = 14; + M(1, 2) = 16; + M(1, 3) = 18; + M(1, 4) = 20; + + M(2, 0) = 22; + M(2, 1) = 24; + M(2, 2) = 26; + M(2, 3) = 28; + M(2, 4) = 30; + + M /= 2; + + for (size_t i = 0; i < M.numberOfRows(); ++i) { + for (size_t j = 0; j < M.numberOfColumns(); ++j) { + REQUIRE(M(i, j) == 1 + i * M.numberOfColumns() + j); + } + } + } + + SECTION("matrix-vector product") + { + SmallVector<int> u(4); + + u[0] = 1; + u[1] = 3; + u[2] = -2; + u[3] = -1; + + SmallVector v = B * u; + REQUIRE(((v[0] == -5) and (v[1] == 1) and (v[2] == -2))); + } + + SECTION("matrix-matrix product") + { + SmallMatrix<int> BAT = B * AT; + REQUIRE(BAT.isSquare()); + REQUIRE(BAT.numberOfRows() == 3); + REQUIRE(BAT.numberOfColumns() == 3); + + REQUIRE(BAT(0, 0) == 45); + REQUIRE(BAT(0, 1) == 85); + REQUIRE(BAT(0, 2) == 125); + + REQUIRE(BAT(1, 0) == 35); + REQUIRE(BAT(1, 1) == 75); + REQUIRE(BAT(1, 2) == 115); + + REQUIRE(BAT(2, 0) == 42); + REQUIRE(BAT(2, 1) == 110); + REQUIRE(BAT(2, 2) == 178); + + SmallMatrix<int> ATB = AT * B; + REQUIRE(ATB.isSquare()); + REQUIRE(ATB.numberOfRows() == 4); + REQUIRE(ATB.numberOfColumns() == 4); + + REQUIRE(ATB(0, 0) == 37); + REQUIRE(ATB(0, 1) == 44); + REQUIRE(ATB(0, 2) == 55); + REQUIRE(ATB(0, 3) == 77); + + REQUIRE(ATB(1, 0) == 34); + REQUIRE(ATB(1, 1) == 56); + REQUIRE(ATB(1, 2) == 66); + REQUIRE(ATB(1, 3) == 94); + + REQUIRE(ATB(2, 0) == 31); + REQUIRE(ATB(2, 1) == 68); + REQUIRE(ATB(2, 2) == 77); + REQUIRE(ATB(2, 3) == 111); + + REQUIRE(ATB(3, 0) == 28); + REQUIRE(ATB(3, 1) == 80); + REQUIRE(ATB(3, 2) == 88); + REQUIRE(ATB(3, 3) == 128); + } + + SECTION("output") + { + std::ostringstream out; + out << A; + + std::ostringstream expected; + expected << "0| 0:1 1:2 2:3 3:4\n"; + expected << "1| 0:5 1:6 2:7 3:8\n"; + expected << "2| 0:9 1:10 2:11 3:12\n"; + + REQUIRE(out.str() == expected.str()); + } + +#ifndef NDEBUG + SECTION("matrix-vector compatibility") + { + SmallVector<int> v(5); + REQUIRE_THROWS_WITH(A * v, "cannot compute matrix-vector product: incompatible sizes"); + } + + SECTION("matrix-matrix compatibility") + { + SmallMatrix C = copy(A); + REQUIRE_THROWS_WITH(C * A, "cannot compute matrix product: incompatible sizes"); + REQUIRE_THROWS_WITH(C -= AT, "cannot substract matrix: incompatible sizes"); + REQUIRE_THROWS_WITH(C += AT, "cannot add matrix: incompatible sizes"); + REQUIRE_THROWS_WITH(C + AT, "cannot compute matrix sum: incompatible sizes"); + REQUIRE_THROWS_WITH(C - AT, "cannot compute matrix difference: incompatible sizes"); + } + + SECTION("invalid element") + { + REQUIRE_THROWS_WITH(A(A.numberOfRows(), 0), "cannot access element: invalid indices"); + REQUIRE_THROWS_WITH(A(0, A.numberOfColumns()), "cannot access element: invalid indices"); + } + + SECTION("invalid identity affectation") + { + SmallMatrix<double> C(3, 2); + REQUIRE_THROWS_WITH((C = identity), "identity must be a square matrix"); + } + + SECTION("invalid constructor") + { + REQUIRE_THROWS_WITH((SmallMatrix{2, 3, SmallArray<double>{7}}), "incompatible array size and matrix dimensions"); + } + + SECTION("output with signaling NaN") + { + SmallMatrix<double> A(2, 3); + A(0, 0) = 1; + A(0, 2) = 3; + A(1, 0) = 2; + std::ostringstream A_ost; + A_ost << A; + + std::ostringstream ref_ost; + ref_ost << "0| 0:1 1:nan 2:3\n"; + ref_ost << "1| 0:2 1:nan 2:nan\n"; + + REQUIRE(A_ost.str() == ref_ost.str()); + } + + // SECTION("checking for bounds violation") + // { + // REQUIRE_THROWS_AS(A(3, 0), AssertError); + // REQUIRE_THROWS_AS(A(0, 4), AssertError); + + // REQUIRE_THROWS_AS(getMinor(A, 3, 0), AssertError); + // REQUIRE_THROWS_AS(getMinor(A, 0, 4), AssertError); + + // const TinyMatrix<3, 4, int>& constA = A; + // REQUIRE_THROWS_AS(constA(3, 0), AssertError); + // REQUIRE_THROWS_AS(constA(0, 4), AssertError); + // } + + // SECTION("checking for nan initialization") + // { + // TinyMatrix<3, 4, double> B; + + // for (size_t i = 0; i < B.numberOfRows(); ++i) { + // for (size_t j = 0; j < B.numberOfColumns(); ++j) { + // REQUIRE(std::isnan(B(i, j))); + // } + // } + // } + + // SECTION("checking for bad initialization") + // { + // TinyMatrix<3, 4, int> B; + + // for (size_t i = 0; i < B.numberOfRows(); ++i) { + // for (size_t j = 0; j < B.numberOfColumns(); ++j) { + // REQUIRE(B(i, j) == std::numeric_limits<int>::max() / 2); + // } + // } + // } +#endif // NDEBUG +} diff --git a/tests/test_SmallVector.cpp b/tests/test_SmallVector.cpp index 3b499c3ab3e984247b7f20f96b626f8ee413763a..b5ffc6819736b2e55d33706aeb18f1e1d28dabca 100644 --- a/tests/test_SmallVector.cpp +++ b/tests/test_SmallVector.cpp @@ -360,6 +360,60 @@ TEST_CASE("SmallVector", "[algebra]") REQUIRE(z[4] == 4); } + SECTION("unary minus") + { + SmallVector<int> x{5}; + x[0] = 2; + x[1] = 3; + x[2] = 5; + x[3] = 7; + x[4] = 8; + + SmallVector<const int> y = x; + + SmallVector<int> z = -x; + + REQUIRE(z[0] == -2); + REQUIRE(z[1] == -3); + REQUIRE(z[2] == -5); + REQUIRE(z[3] == -7); + REQUIRE(z[4] == -8); + + z = -y; + REQUIRE(z[0] == -2); + REQUIRE(z[1] == -3); + REQUIRE(z[2] == -5); + REQUIRE(z[3] == -7); + REQUIRE(z[4] == -8); + } + + SECTION("min/max") + { + SmallVector<int> u(5); + u[0] = 1; + u[1] = 7; + u[2] = 6; + u[3] = 2; + u[4] = 9; + + REQUIRE(min(u) == 1); + REQUIRE(max(u) == 9); + REQUIRE(min(-u) == -9); + REQUIRE(max(-u) == -1); + + SmallVector<int> v(5); + v[0] = 1; + v[1] = 11; + v[2] = 6; + v[3] = -2; + v[4] = 9; + + REQUIRE(min(v) == -2); + REQUIRE(max(v) == 11); + REQUIRE(min(-v) == -11); + REQUIRE(max(-v) == 2); + } + SECTION("output") { SmallVector<int> x{5}; diff --git a/tests/test_SubItemArrayPerItemVariant.cpp b/tests/test_SubItemArrayPerItemVariant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e3413aec062f9c785592884650a706706f21088 --- /dev/null +++ b/tests/test_SubItemArrayPerItemVariant.cpp @@ -0,0 +1,204 @@ +#include <catch2/catch_test_macros.hpp> +#include <catch2/matchers/catch_matchers_all.hpp> + +#include <MeshDataBaseForTests.hpp> +#include <mesh/Connectivity.hpp> +#include <mesh/Mesh.hpp> +#include <mesh/SubItemArrayPerItemVariant.hpp> +#include <utils/Messenger.hpp> + +// clazy:excludeall=non-pod-global-static + +TEST_CASE("SubItemArrayPerItemVariant", "[mesh]") +{ + std::shared_ptr mesh = MeshDataBaseForTests::get().hybrid3DMesh(); + + const Connectivity<3>& connectivity = *mesh->shared_connectivity(); + + using R1 = TinyVector<1>; + using R2 = TinyVector<2>; + using R3 = TinyVector<3>; + using R1x1 = TinyMatrix<1>; + using R2x2 = TinyMatrix<2>; + using R3x3 = TinyMatrix<3>; + + SECTION("NodeArrayPerCell<double>") + { + NodeArrayPerCell<double> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_NOTHROW(v.get<NodeArrayPerCell<double>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("NodeArrayPerFace<R1>") + { + NodeArrayPerFace<R1> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<NodeArrayPerFace<const R1>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<const R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("NodeArrayPerEdge<int64_t>") + { + NodeArrayPerEdge<int64_t> node_array{connectivity, 3}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<NodeArrayPerEdge<int64_t>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("EdgeArrayPerCell<R2>") + { + EdgeArrayPerCell<R2> node_array{connectivity, 3}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<EdgeArrayPerCell<R2>>()); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerCell<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("EdgeArrayPerFace<R1>") + { + EdgeArrayPerFace<R1> node_array{connectivity, 1}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<const double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<EdgeArrayPerFace<R1>>()); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerFace<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("EdgeArrayPerNode<double>") + { + EdgeArrayPerNode<double> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_NOTHROW(v.get<EdgeArrayPerNode<double>>()); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<EdgeArrayPerNode<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("FaceArrayPerCell<R3x3>") + { + FaceArrayPerCell<R3x3> node_array{connectivity, 1}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerCell<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<FaceArrayPerCell<R3x3>>()); + } + + SECTION("FaceArrayPerEdge<R2x2>") + { + FaceArrayPerEdge<R2x2> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<FaceArrayPerEdge<R2x2>>()); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerEdge<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("FaceArrayPerNode<uint64_t>") + { + FaceArrayPerNode<uint64_t> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<FaceArrayPerNode<uint64_t>>()); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<FaceArrayPerNode<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("NodeArrayPerCell<R1x1>") + { + NodeArrayPerCell<R1x1> node_array{connectivity, 1}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<NodeArrayPerCell<R1x1>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerCell<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("NodeArrayPerFace<R3>") + { + NodeArrayPerFace<R3> node_array{connectivity, 3}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<double>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_NOTHROW(v.get<NodeArrayPerFace<R3>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerFace<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } + + SECTION("NodeArrayPerEdge<double>") + { + NodeArrayPerEdge<double> node_array{connectivity, 2}; + SubItemArrayPerItemVariant v(node_array); + REQUIRE_NOTHROW(v.get<NodeArrayPerEdge<double>>()); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<int64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<uint64_t>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R3>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R1x1>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R2x2>>(), "error: invalid SubItemArrayPerItem type"); + REQUIRE_THROWS_WITH(v.get<NodeArrayPerEdge<R3x3>>(), "error: invalid SubItemArrayPerItem type"); + } +} diff --git a/tests/test_TinyVector.cpp b/tests/test_TinyVector.cpp index 9c4dc2e5a2c4b185904fcf04a706fa70b572a197..6a3942e84b1c95680d8c63080b5c8b37330f139b 100644 --- a/tests/test_TinyVector.cpp +++ b/tests/test_TinyVector.cpp @@ -87,6 +87,23 @@ TEST_CASE("TinyVector", "[algebra]") REQUIRE(crossProduct(a, b) == TinyVector<3, int>(-16, 6, 7)); } + SECTION("min/max") + { + TinyVector<5, int> u{1, 7, 6, 2, 9}; + + REQUIRE(min(u) == 1); + REQUIRE(max(u) == 9); + REQUIRE(min(-u) == -9); + REQUIRE(max(-u) == -1); + + TinyVector<5, int> v{1, 11, 6, -2, 9}; + + REQUIRE(min(v) == -2); + REQUIRE(max(v) == 11); + REQUIRE(min(-v) == -11); + REQUIRE(max(-v) == 2); + } + #ifndef NDEBUG SECTION("output with signaling NaN") { diff --git a/tests/test_Vector.cpp b/tests/test_Vector.cpp index e31bf166713b70f69ca108d7dace6dc07179dc5b..0d8d0e898321070f74b3cf99f8fb0e04686c9b0d 100644 --- a/tests/test_Vector.cpp +++ b/tests/test_Vector.cpp @@ -359,6 +359,60 @@ TEST_CASE("Vector", "[algebra]") REQUIRE(z[4] == 4); } + SECTION("unary minus") + { + Vector<int> x{5}; + x[0] = 2; + x[1] = 3; + x[2] = 5; + x[3] = 7; + x[4] = 8; + + Vector<const int> y = x; + + Vector<int> z = -x; + + REQUIRE(z[0] == -2); + REQUIRE(z[1] == -3); + REQUIRE(z[2] == -5); + REQUIRE(z[3] == -7); + REQUIRE(z[4] == -8); + + z = -y; + REQUIRE(z[0] == -2); + REQUIRE(z[1] == -3); + REQUIRE(z[2] == -5); + REQUIRE(z[3] == -7); + REQUIRE(z[4] == -8); + } + + SECTION("min/max") + { + Vector<int> u(5); + u[0] = 1; + u[1] = 7; + u[2] = 6; + u[3] = 2; + u[4] = 9; + + REQUIRE(min(u) == 1); + REQUIRE(max(u) == 9); + REQUIRE(min(-u) == -9); + REQUIRE(max(-u) == -1); + + Vector<int> v(5); + v[0] = 1; + v[1] = 11; + v[2] = 6; + v[3] = -2; + v[4] = 9; + + REQUIRE(min(v) == -2); + REQUIRE(max(v) == 11); + REQUIRE(min(-v) == -11); + REQUIRE(max(-v) == 2); + } + SECTION("output") { Vector<int> x{5}; diff --git a/tools/pgs-pygments.sh b/tools/pgs-pygments.sh index 98f90c55e028546aa8fa49fc069f06b1fe3f057a..168760cc83772fd8f35629cbf999314c320a1c91 100755 --- a/tools/pgs-pygments.sh +++ b/tools/pgs-pygments.sh @@ -1,4 +1,4 @@ -#!/bin/env bash +#! /bin/bash arguments=()