From 5cbe971f8e756f6d7c77bcdbde6392b980a7af4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Tue, 10 May 2022 09:15:48 +0200 Subject: [PATCH] Remove variable subscript affectations This means that one cannot write anymore things like ``` x[0] = 1; ``` or ``` A[0,0] = 1; ``` where x is an R^d and A an R^dxd. This is done for these reasons: - first these kind of instructions are more or less useless. - Second they do not follow the philosophy of pugs since they give the sensation that one could modify specific values of discrete functions for instance, which should never enter the language - Finally, getting ride of these constructions permits to ensure that all variables in a pugs' script are properly initialized Fixes #28 --- src/language/PEGGrammar.hpp | 11 +- src/language/ast/ASTBuilder.cpp | 8 +- .../ast/ASTSymbolInitializationChecker.cpp | 13 +- .../node_processor/AffectationProcessor.hpp | 362 ------------------ tests/test_ASTBuilder.cpp | 27 -- tests/test_ASTNodeDataTypeBuilder.cpp | 8 +- tests/test_ASTNodeExpressionBuilder.cpp | 10 +- tests/test_ASTSymbolInitializationChecker.cpp | 42 -- tests/test_AffectationProcessor.cpp | 209 +++++----- tests/test_ListAffectationProcessor.cpp | 17 - 10 files changed, 144 insertions(+), 563 deletions(-) diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 5f8b21d3a..d173f5074 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -237,9 +237,8 @@ struct expression_list : seq< open_parent, sor< seq< tuple_expression, struct affect_op : sor< eq_op, multiplyeq_op, divideeq_op, pluseq_op, minuseq_op > {}; -struct name_subscript_expression : seq< NAME, plus< subscript_expression > >{}; - -struct lvalue_expression : sor< name_subscript_expression, NAME >{}; +struct subscript_expression_of_lvalue : subscript_expression {}; +struct lvalue_expression : if_must<NAME, not_at<subscript_expression_of_lvalue> >{}; struct lvalue_list : seq< open_parent, list_must< lvalue_expression, COMMA >, close_parent >{}; @@ -389,6 +388,12 @@ inline const std::string errors<language::slashstar>::error_message = "block com template <> inline const std::string errors<language::open_brace>::error_message = "open brace was never closed, missing '}'"; +template <> +inline const std::string errors<language::close_parent>::error_message = "parse error, expecting ')'"; + +template <> +inline const std::string errors<language::not_at<subscript_expression_of_lvalue> >::error_message = "parse error, using subscript expression as lvalue is not allowed"; + template <> inline const std::string errors<language::simple_type_specifier>::error_message = "expecting simple type specifier"; diff --git a/src/language/ast/ASTBuilder.cpp b/src/language/ast/ASTBuilder.cpp index 109ce527c..db7f77b29 100644 --- a/src/language/ast/ASTBuilder.cpp +++ b/src/language/ast/ASTBuilder.cpp @@ -57,8 +57,7 @@ struct ASTBuilder::simplify_unary : TAO_PEGTL_NAMESPACE::parse_tree::apply<ASTBu transform(std::unique_ptr<ASTNode>& n, States&&... st) { if (n->children.size() == 1) { - if (n->is_type<language::unary_expression>() or n->is_type<language::type_expression>() or - n->is_type<language::name_subscript_expression>()) { + if (n->is_type<language::unary_expression>() or n->is_type<language::type_expression>()) { n = std::move(n->children.back()); transform(n, st...); } else if (n->is_type<language::unary_minus>()) { @@ -105,7 +104,7 @@ struct ASTBuilder::simplify_unary : TAO_PEGTL_NAMESPACE::parse_tree::apply<ASTBu } } - if (n->is_type<language::unary_expression>() or n->is_type<language::name_subscript_expression>()) { + if (n->is_type<language::unary_expression>()) { if (n->children.size() > 1) { if (n->children[1]->is_type<language::subscript_expression>()) { std::swap(n->children[0], n->children[1]); @@ -262,8 +261,7 @@ using selector = TAO_PEGTL_NAMESPACE::parse_tree::selector< language::subscript_expression, language::tuple_type_specifier, language::type_expression, - language::unary_expression, - language::name_subscript_expression>, + language::unary_expression>, TAO_PEGTL_NAMESPACE::parse_tree::remove_content::on<language::plus_op, language::minus_op, language::shift_left_op, diff --git a/src/language/ast/ASTSymbolInitializationChecker.cpp b/src/language/ast/ASTSymbolInitializationChecker.cpp index 8fe9ac4f7..9ce181ca7 100644 --- a/src/language/ast/ASTSymbolInitializationChecker.cpp +++ b/src/language/ast/ASTSymbolInitializationChecker.cpp @@ -86,22 +86,15 @@ ASTSymbolInitializationChecker::_checkSymbolInitialization(ASTNode& node) if (node.children[0]->is_type<language::name>()) { set_is_initialized(*node.children[0]); - } else if (node.children[0]->is_type<language::subscript_expression>()) { - ASTNode& subscript_node = *node.children[0]; - ASTNode& name_node = *subscript_node.children[0]; - - Assert(name_node.is_type<language::name>()); - set_is_initialized(name_node); } else if (node.children[0]->is_type<language::name_list>() or node.children[0]->is_type<language::lvalue_list>()) { ASTNode& list_node = *node.children[0]; for (auto& child_node : list_node.children) { if (child_node->is_type<language::name>()) { set_is_initialized(*child_node); } else { - Assert(child_node->is_type<language::subscript_expression>()); - ASTNode& name_node = *child_node->children[0]; - Assert(name_node.is_type<language::name>()); - set_is_initialized(name_node); + // LCOV_EXCL_START + throw UnexpectedError("elements of the list should be language::name"); + // LCOV_EXCL_STOP } } } diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index 002c0e4ed..6b764b8d8 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -202,165 +202,6 @@ class AffectationExecutor final : public IAffectationExecutor } }; -template <typename OperatorT, typename ArrayT, typename ValueT, typename DataT> -class MatrixComponentAffectationExecutor final : public IAffectationExecutor -{ - private: - ArrayT& m_lhs_array; - ASTNode& m_index0_expression; - ASTNode& m_index1_expression; - - static inline const bool m_is_defined{[] { - if constexpr (not std::is_same_v<typename ArrayT::data_type, ValueT>) { - return false; - } else 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 true; - }()}; - - public: - MatrixComponentAffectationExecutor(ASTNode& lhs_node, - ArrayT& lhs_array, - ASTNode& index0_expression, - ASTNode& index1_expression) - : m_lhs_array{lhs_array}, m_index0_expression{index0_expression}, m_index1_expression{index1_expression} - { - // LCOV_EXCL_START - if constexpr (not m_is_defined) { - throw ParseError("unexpected error: invalid operands to affectation expression", std::vector{lhs_node.begin()}); - } - // LCOV_EXCL_STOP - } - - PUGS_INLINE void - affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) - { - if constexpr (m_is_defined) { - auto get_index_value = [&](DataVariant&& value_variant) -> int64_t { - int64_t index_value = 0; - std::visit( - [&](auto&& value) { - using IndexValueT = std::decay_t<decltype(value)>; - if constexpr (std::is_integral_v<IndexValueT>) { - index_value = value; - } else { - // LCOV_EXCL_START - throw UnexpectedError("invalid index type"); - // LCOV_EXCL_STOP - } - }, - value_variant); - return index_value; - }; - - const int64_t index0_value = get_index_value(m_index0_expression.execute(exec_policy)); - const int64_t index1_value = get_index_value(m_index1_expression.execute(exec_policy)); - - if constexpr (std::is_same_v<ValueT, std::string>) { - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - if constexpr (std::is_same_v<std::string, DataT>) { - m_lhs_array(index0_value, index1_value) = std::get<DataT>(rhs); - } else { - m_lhs_array(index0_value, index1_value) = std::to_string(std::get<DataT>(rhs)); - } - } else { - if constexpr (std::is_same_v<std::string, DataT>) { - m_lhs_array(index0_value, index1_value) += std::get<std::string>(rhs); - } else { - m_lhs_array(index0_value, index1_value) += std::to_string(std::get<DataT>(rhs)); - } - } - } else { - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - static_assert(std::is_convertible_v<DataT, ValueT>, "unexpected types"); - m_lhs_array(index0_value, index1_value) = static_cast<ValueT>(std::get<DataT>(rhs)); - } else { - AffOp<OperatorT>().eval(m_lhs_array(index0_value, index1_value), std::get<DataT>(rhs)); - } - } - } - } -}; - -template <typename OperatorT, typename ArrayT, typename ValueT, typename DataT> -class VectorComponentAffectationExecutor final : public IAffectationExecutor -{ - private: - ArrayT& m_lhs_array; - ASTNode& m_index_expression; - - static inline const bool m_is_defined{[] { - if constexpr (not std::is_same_v<typename ArrayT::data_type, ValueT>) { - return false; - } else 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 true; - }()}; - - public: - VectorComponentAffectationExecutor(ASTNode& node, ArrayT& lhs_array, ASTNode& index_expression) - : m_lhs_array{lhs_array}, m_index_expression{index_expression} - { - // LCOV_EXCL_START - if constexpr (not m_is_defined) { - throw ParseError("unexpected error: invalid operands to affectation expression", std::vector{node.begin()}); - } - // LCOV_EXCL_STOP - } - - PUGS_INLINE void - affect(ExecutionPolicy& exec_policy, DataVariant&& rhs) - { - if constexpr (m_is_defined) { - const int64_t index_value = [&](DataVariant&& value_variant) -> int64_t { - int64_t index_value = 0; - std::visit( - [&](auto&& value) { - using IndexValueT = std::decay_t<decltype(value)>; - if constexpr (std::is_integral_v<IndexValueT>) { - index_value = value; - } else { - // LCOV_EXCL_START - throw ParseError("unexpected error: invalid index type", std::vector{m_index_expression.begin()}); - // LCOV_EXCL_STOP - } - }, - value_variant); - return index_value; - }(m_index_expression.execute(exec_policy)); - - if constexpr (std::is_same_v<ValueT, std::string>) { - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - if constexpr (std::is_same_v<std::string, DataT>) { - m_lhs_array[index_value] = std::get<DataT>(rhs); - } else { - m_lhs_array[index_value] = std::to_string(std::get<DataT>(rhs)); - } - } else { - if constexpr (std::is_same_v<std::string, DataT>) { - m_lhs_array[index_value] += std::get<std::string>(rhs); - } else { - m_lhs_array[index_value] += std::to_string(std::get<DataT>(rhs)); - } - } - } else { - if constexpr (std::is_same_v<OperatorT, language::eq_op>) { - static_assert(std::is_convertible_v<DataT, ValueT>, "incompatible data and value types"); - m_lhs_array[index_value] = static_cast<ValueT>(std::get<DataT>(rhs)); - } else { - AffOp<OperatorT>().eval(m_lhs_array[index_value], std::get<DataT>(rhs)); - } - } - } - } -}; - template <typename OperatorT, typename ValueT, typename DataT> class AffectationProcessor final : public INodeProcessor { @@ -384,104 +225,6 @@ class AffectationProcessor final : public INodeProcessor using AffectationExecutorT = AffectationExecutor<OperatorT, ValueT, DataT>; return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ValueT>(value)); - } else if (lhs_node.is_type<language::subscript_expression>()) { - auto& array_expression = *lhs_node.children[0]; - Assert(array_expression.is_type<language::name>()); - - const std::string& symbol = array_expression.string(); - - auto [i_symbol, found] = lhs_node.m_symbol_table->find(symbol, lhs_node.begin()); - Assert(found); - DataVariant& value = i_symbol->attributes().value(); - - if (array_expression.m_data_type == ASTNodeDataType::vector_t) { - Assert(lhs_node.children.size() == 2); - - auto& index_expression = *lhs_node.children[1]; - - switch (array_expression.m_data_type.dimension()) { - case 1: { - using ArrayTypeT = TinyVector<1>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression); - } - case 2: { - using ArrayTypeT = TinyVector<2>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression); - } - case 3: { - using ArrayTypeT = TinyVector<3>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression); - } - // LCOV_EXCL_START - default: { - throw ParseError("unexpected error: invalid vector dimension", std::vector{lhs_node.begin()}); - } - // LCOV_EXCL_STOP - } - } else if (array_expression.m_data_type == ASTNodeDataType::matrix_t) { - Assert(lhs_node.children.size() == 3); - Assert(array_expression.m_data_type.numberOfRows() == array_expression.m_data_type.numberOfColumns()); - - auto& index0_expression = *lhs_node.children[1]; - auto& index1_expression = *lhs_node.children[2]; - - switch (array_expression.m_data_type.numberOfRows()) { - case 1: { - using ArrayTypeT = TinyMatrix<1>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression); - } - case 2: { - using ArrayTypeT = TinyMatrix<2>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression); - } - case 3: { - using ArrayTypeT = TinyMatrix<3>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - - return std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression); - } - // LCOV_EXCL_START - default: { - throw ParseError("unexpected error: invalid vector dimension", std::vector{lhs_node.begin()}); - } - // LCOV_EXCL_STOP - } - } else { - // LCOV_EXCL_START - throw UnexpectedError("invalid subscript expression"); - // LCOV_EXCL_STOP - } } else { // LCOV_EXCL_START throw ParseError("unexpected error: invalid lhs", std::vector{lhs_node.begin()}); @@ -866,111 +609,6 @@ class ListAffectationProcessor final : public INodeProcessor } m_affectation_executor_list.emplace_back(std::make_unique<AffectationExecutorT>(m_node, std::get<ValueT>(value))); - } else if (lhs_node.is_type<language::subscript_expression>()) { - auto& array_subscript_expression = lhs_node; - - auto& array_expression = *array_subscript_expression.children[0]; - Assert(array_expression.is_type<language::name>()); - - const std::string& symbol = array_expression.string(); - - auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, array_subscript_expression.begin()); - Assert(found); - DataVariant& value = i_symbol->attributes().value(); - - if (array_expression.m_data_type == ASTNodeDataType::vector_t) { - Assert(array_subscript_expression.children.size() == 2); - - auto& index_expression = *array_subscript_expression.children[1]; - - switch (array_expression.m_data_type.dimension()) { - case 1: { - using ArrayTypeT = TinyVector<1>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression)); - break; - } - case 2: { - using ArrayTypeT = TinyVector<2>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression)); - break; - } - case 3: { - using ArrayTypeT = TinyVector<3>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = VectorComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index_expression)); - break; - } - // LCOV_EXCL_START - default: { - throw ParseError("unexpected error: invalid vector dimension", - std::vector{array_subscript_expression.begin()}); - } - // LCOV_EXCL_STOP - } - } else if (array_expression.m_data_type == ASTNodeDataType::matrix_t) { - Assert(array_subscript_expression.children.size() == 3); - - auto& index0_expression = *array_subscript_expression.children[1]; - auto& index1_expression = *array_subscript_expression.children[2]; - - Assert(array_expression.m_data_type.numberOfRows() == array_expression.m_data_type.numberOfColumns()); - - switch (array_expression.m_data_type.numberOfRows()) { - case 1: { - using ArrayTypeT = TinyMatrix<1>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression)); - break; - } - case 2: { - using ArrayTypeT = TinyMatrix<2>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression)); - break; - } - case 3: { - using ArrayTypeT = TinyMatrix<3>; - if (not std::holds_alternative<ArrayTypeT>(value)) { - value = ArrayTypeT{}; - } - using AffectationExecutorT = MatrixComponentAffectationExecutor<OperatorT, ArrayTypeT, ValueT, DataT>; - m_affectation_executor_list.emplace_back( - std::make_unique<AffectationExecutorT>(lhs_node, std::get<ArrayTypeT>(value), index0_expression, - index1_expression)); - break; - } - // LCOV_EXCL_START - default: { - throw ParseError("unexpected error: invalid vector dimension", - std::vector{array_subscript_expression.begin()}); - } - // LCOV_EXCL_STOP - } - } } else { // LCOV_EXCL_START throw ParseError("unexpected error: invalid left hand side", std::vector{lhs_node.begin()}); diff --git a/tests/test_ASTBuilder.cpp b/tests/test_ASTBuilder.cpp index fdcf13315..262a0cd30 100644 --- a/tests/test_ASTBuilder.cpp +++ b/tests/test_ASTBuilder.cpp @@ -309,33 +309,6 @@ not not not false; } } - SECTION("subscript handling") - { - std::string_view data = R"( -u[a]; -u[f(c)]; -u[u[b]]; -)"; - - std::string_view result = R"( -(root) - +-(language::subscript_expression) - | +-(language::name:u) - | `-(language::name:a) - +-(language::subscript_expression) - | +-(language::name:u) - | `-(language::function_evaluation) - | +-(language::name:f) - | `-(language::name:c) - `-(language::subscript_expression) - +-(language::name:u) - `-(language::subscript_expression) - +-(language::name:u) - `-(language::name:b) -)"; - CHECK_AST(data, result); - } - SECTION("post incr/decr rearrangements") { std::string_view data = R"( diff --git a/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 2e3835024..5dcd6f57c 100644 --- a/tests/test_ASTNodeDataTypeBuilder.cpp +++ b/tests/test_ASTNodeDataTypeBuilder.cpp @@ -313,7 +313,7 @@ let (x,b,n,s) : R*B*N*string; SECTION("invalid array subscript") { std::string_view data = R"( -let x : R; x[2]; +let x:R, x = 1; let y:R, y = x[2]; )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -326,7 +326,7 @@ let x : R; x[2]; SECTION("invalid R^d subscript index list") { std::string_view data = R"( -let x : R^2; x[2,2]; +let x:R^2, x = 0; let y:R, y = x[2,2]; )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -339,7 +339,7 @@ let x : R^2; x[2,2]; SECTION("invalid R^dxd subscript index list 1") { std::string_view data = R"( -let x : R^2x2; x[2]; +let x:R^2x2, x = 0; let y:R, y = x[2]; )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; @@ -352,7 +352,7 @@ let x : R^2x2; x[2]; SECTION("invalid R^dxd subscript index list 2") { std::string_view data = R"( -let x : R^2x2; x[2,3,1]; +let x:R^2x2, x = 0; let y:R, y = x[2,3,1]; )"; TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; diff --git a/tests/test_ASTNodeExpressionBuilder.cpp b/tests/test_ASTNodeExpressionBuilder.cpp index 25a3d3a93..56af1db48 100644 --- a/tests/test_ASTNodeExpressionBuilder.cpp +++ b/tests/test_ASTNodeExpressionBuilder.cpp @@ -467,7 +467,7 @@ a--; { std::string_view data = R"( let x: R^3, x = (1, 2, 3); -x[2]; +let y: R, y = x[2]; )"; std::string result = R"( @@ -478,9 +478,11 @@ x[2]; | +-(language::integer:1:ValueProcessor) | +-(language::integer:2:ValueProcessor) | `-(language::integer:3:ValueProcessor) - `-(language::subscript_expression:ArraySubscriptProcessor<TinyVector<3ul, double> >) - +-(language::name:x:NameProcessor) - `-(language::integer:2:ValueProcessor) + `-(language::eq_op:AffectationProcessor<language::eq_op, double, double>) + +-(language::name:y:NameProcessor) + `-(language::subscript_expression:ArraySubscriptProcessor<TinyVector<3ul, double> >) + +-(language::name:x:NameProcessor) + `-(language::integer:2:ValueProcessor) )"; CHECK_AST(data, result); diff --git a/tests/test_ASTSymbolInitializationChecker.cpp b/tests/test_ASTSymbolInitializationChecker.cpp index d0475ee8c..b9bcef859 100644 --- a/tests/test_ASTSymbolInitializationChecker.cpp +++ b/tests/test_ASTSymbolInitializationChecker.cpp @@ -43,27 +43,6 @@ let p:N; REQUIRE(not symbol_p->attributes().isInitialized()); } - SECTION("Array subscript initialization") - { - std::string_view data = R"( -let x:R^3; -x[0] = 1; -)"; - - string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - - ASTSymbolTableBuilder{*ast}; - ASTSymbolInitializationChecker{*ast}; - - position position{internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - auto [symbol_m, found_m] = ast->m_symbol_table->find("x", position); - REQUIRE(found_m); - REQUIRE(symbol_m->attributes().isInitialized()); - } - SECTION("Declaration plus affectation") { std::string_view data = R"( @@ -238,27 +217,6 @@ let (x,y):R^3*R; } } - SECTION("Affectation") - { - std::string_view data = R"( -let x:R^3; -(x[2], x[1], x[0]) = (1, 2, 3); -)"; - - string_input input{data, "test.pgs"}; - auto ast = ASTBuilder::build(input); - - ASTSymbolTableBuilder{*ast}; - ASTSymbolInitializationChecker{*ast}; - - position position{internal::iterator{"fixture"}, "fixture"}; - position.byte = data.size(); // ensure that variables are declared at this point - - auto [symbol_x, found_x] = ast->m_symbol_table->find("x", position); - REQUIRE(found_x); - REQUIRE(symbol_x->attributes().isInitialized()); - } - SECTION("errors") { SECTION("used uninitialized") diff --git a/tests/test_AffectationProcessor.cpp b/tests/test_AffectationProcessor.cpp index b6f73afdb..42c0514f9 100644 --- a/tests/test_AffectationProcessor.cpp +++ b/tests/test_AffectationProcessor.cpp @@ -62,6 +62,12 @@ REQUIRE_THROWS_WITH(ASTNodeExpressionBuilder{*ast}, error_message); \ } +#define CHECK_BUILD_THROWS_WITH(data, error_message) \ + { \ + TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \ + REQUIRE_THROWS_WITH(ASTBuilder::build(input), error_message); \ + } + // clazy:excludeall=non-pod-global-static TEST_CASE("AffectationProcessor", "[language]") @@ -102,11 +108,6 @@ TEST_CASE("AffectationProcessor", "[language]") 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] = -1;", "x", (TinyVector<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1; x[0] = true;", "x", (TinyVector<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1; x[0] = false;", "x", (TinyVector<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1; x[0] = -2.3;", "x", (TinyVector<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = 0;", "x", (TinyVector<1>{zero})); } @@ -115,10 +116,6 @@ TEST_CASE("AffectationProcessor", "[language]") 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] = -1; x[1] = true;", "x", (TinyVector<2>{-1, true})); - CHECK_AFFECTATION_RESULT("let x : R^2; x[0] = true; x[1] = false;", "x", (TinyVector<2>{true, false})); - CHECK_AFFECTATION_RESULT("let x : R^2; x[0] = -0.3; x[1] = 12;", "x", (TinyVector<2>{-0.3, 12})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = 0;", "x", (TinyVector<2>{zero})); } @@ -126,10 +123,6 @@ TEST_CASE("AffectationProcessor", "[language]") { 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] = -1; x[1] = true; x[2] = false;", "x", - (TinyVector<3>{-1, true, false})); - CHECK_AFFECTATION_RESULT("let x : R^3; x[0] = -0.3; x[1] = 12; x[2] = 6.2;", "x", (TinyVector<3>{-0.3, 12, 6.2})); - CHECK_AFFECTATION_RESULT("let x : R^3; x = 0;", "x", (TinyVector<3>{zero})); } @@ -139,11 +132,6 @@ TEST_CASE("AffectationProcessor", "[language]") 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,0] = -1;", "x", (TinyMatrix<1>{-1})); - CHECK_AFFECTATION_RESULT("let x : R^1x1; x[0,0] = true;", "x", (TinyMatrix<1>{true})); - CHECK_AFFECTATION_RESULT("let x : R^1x1; x[0,0] = false;", "x", (TinyMatrix<1>{false})); - CHECK_AFFECTATION_RESULT("let x : R^1x1; x[0,0] = -2.3;", "x", (TinyMatrix<1>{-2.3})); - CHECK_AFFECTATION_RESULT("let x : R^1x1; x = 0;", "x", (TinyMatrix<1>{zero})); } @@ -153,13 +141,6 @@ TEST_CASE("AffectationProcessor", "[language]") 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,0] = -1; x[0,1] = true; x[1,0] = 2; x[1,1] = 3.3;", "x", - (TinyMatrix<2>{-1, true, 2, 3.3})); - CHECK_AFFECTATION_RESULT("let x : R^2x2; x[0,0] = true; x[0,1] = false; x[1,0] = 2.1; x[1,1] = -1;", "x", - (TinyMatrix<2>{true, false, 2.1, -1})); - CHECK_AFFECTATION_RESULT("let x : R^2x2; x[0,0] = -0.3; x[0,1] = 12; x[1,0] = 1.3; x[1,1] = 7;", "x", - (TinyMatrix<2>{-0.3, 12, 1.3, 7})); - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = 0;", "x", (TinyMatrix<2>{zero})); } @@ -169,10 +150,6 @@ TEST_CASE("AffectationProcessor", "[language]") (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,0] = -1; x[0,1] = true; x[0,2] = false; x[1,0] = -11; x[1,1] = 4; " - "x[1,2] = 3; x[2,0] = 6; x[2,1] = -3; x[2,2] = 5;", - "x", (TinyMatrix<3>{-1, true, false, -11, 4, 3, 6, -3, 5})); - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = 0;", "x", (TinyMatrix<3>{zero})); } } @@ -208,23 +185,18 @@ TEST_CASE("AffectationProcessor", "[language]") { CHECK_AFFECTATION_RESULT("let x : R^1, x = -1; let y : R^1, y = 1; x += y;", "x", (TinyVector<1>{-1} + TinyVector<1>{1})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = 2; x[0] += 1;", "x", (TinyVector<1>{2} + TinyVector<1>{1})); } SECTION("R^2") { CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); let y : R^2, y = (1,3); x += y;", "x", (TinyVector<2>{-1, true} + TinyVector<2>{1, 3})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); x[0] += 2; x[1] += 1;", "x", - (TinyVector<2>{-1, true} + TinyVector<2>{2, 1})); } SECTION("R^3") { CHECK_AFFECTATION_RESULT("let x : R^3, x = (-1, true, false); let y : R^3, y = (1,2,3); x += y;", "x", (TinyVector<3>{-1, true, false} + TinyVector<3>{1, 2, 3})); - CHECK_AFFECTATION_RESULT("let x : R^3, x = (-0.3, 12, 6.2); x[0] += 1; x[1] += -3; x[2] += 1;", "x", - (TinyVector<3>{-0.3, 12, 6.2} + TinyVector<3>{1, -3, 1})); } } @@ -259,23 +231,18 @@ TEST_CASE("AffectationProcessor", "[language]") { CHECK_AFFECTATION_RESULT("let x : R^1, x = -1; let y : R^1, y = 1; x -= y;", "x", (TinyVector<1>{-1} - TinyVector<1>{1})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = 2; x[0] -= 1;", "x", (TinyVector<1>{2} - TinyVector<1>{1})); } SECTION("R^2") { CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); let y : R^2, y = (1,3); x -= y;", "x", (TinyVector<2>{-1, true} - TinyVector<2>{1, 3})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); x[0] -= 2; x[1] -= 1;", "x", - (TinyVector<2>{-1, true} - TinyVector<2>{2, 1})); } SECTION("R^3") { CHECK_AFFECTATION_RESULT("let x : R^3, x = (-1, true, false); let y : R^3, y = (1,2,3); x-=y;", "x", (TinyVector<3>{-1, true, false} - TinyVector<3>{1, 2, 3})); - CHECK_AFFECTATION_RESULT("let x : R^3, x = (-0.3, 12, 6.2); x[0] -= 1; x[1] -= -3; x[2] -= 1;", "x", - (TinyVector<3>{-0.3, 12, 6.2} - TinyVector<3>{1, -3, 1})); } } @@ -309,46 +276,35 @@ TEST_CASE("AffectationProcessor", "[language]") SECTION("R^1") { CHECK_AFFECTATION_RESULT("let x : R^1, x = 2; x *= 2;", "x", (TinyVector<1>{TinyVector<1>{2} *= 2})); - CHECK_AFFECTATION_RESULT("let x : R^1, x = 2; x[0] *= 1.3;", "x", (TinyVector<1>{2 * 1.3})); } SECTION("R^2") { CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); x *= 3;", "x", (TinyVector<2>{TinyVector<2>{-1, true} *= 3})); - CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); x[0] *= 2; x[1] *= 3;", "x", - (TinyVector<2>{-1 * 2, true * 3})); } SECTION("R^3") { CHECK_AFFECTATION_RESULT("let x : R^3, x = (-1, true, false); x*=5.2;", "x", (TinyVector<3>{TinyVector<3>{-1, true, false} *= 5.2})); - CHECK_AFFECTATION_RESULT("let x : R^3, x = (-0.3, 12, 6.2); x[0] *= -1; x[1] *= -3; x[2] *= 2;", "x", - (TinyVector<3>{-0.3 * -1, 12 * -3, 6.2 * 2})); } SECTION("R^1x1") { CHECK_AFFECTATION_RESULT("let x : R^1x1, x = 2; x *= 2;", "x", (TinyMatrix<1>{TinyMatrix<1>{2} *= 2})); - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = 2; x[0,0] *= 1.3;", "x", (TinyMatrix<1>{2 * 1.3})); } SECTION("R^2x2") { CHECK_AFFECTATION_RESULT("let x : R^2x2, x = (-1, true, 3, 6); x *= 3;", "x", (TinyMatrix<2>{TinyMatrix<2>{-1, true, 3, 6} *= 3})); - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = (-1, true, 3, 6); x[0,0] *= 2; x[1,1] *= 3;", "x", - (TinyMatrix<2>{-1 * 2, true, 3, 6 * 3})); } SECTION("R^3x3") { CHECK_AFFECTATION_RESULT("let x : R^3x3, x = (-1, true, false, 2, -3, 11, 5, -4, 2); x*=5.2;", "x", (TinyMatrix<3>{TinyMatrix<3>{-1, true, false, 2, -3, 11, 5, -4, 2} *= 5.2})); - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = (-0.3, 12, 6.2, 2, -3, 11, 5, -4, 2); x[0,0] *= -1; x[0,1] *= -3; " - "x[0,2] *= 2; x[1,1] *= 2; x[2,1] *= 6; x[2,2] *= 2;", - "x", (TinyMatrix<3>{-0.3 * -1, 12 * -3, 6.2 * 2, 2, -3 * 2, 11, 5, (-4) * 6, 2 * 2})); } } @@ -375,45 +331,6 @@ TEST_CASE("AffectationProcessor", "[language]") CHECK_AFFECTATION_RESULT("let r : R, r = 1.1; r /= true;", "r", (1.1 / true)); CHECK_AFFECTATION_RESULT("let r : R, r = 2; r /= 1.1;", "r", (2. / 1.1)); } - - SECTION("R^1") - { - CHECK_AFFECTATION_RESULT("let x : R^1, x = 2; x[0] /= 1.3;", "x", (TinyVector<1>{2 / 1.3})); - } - - SECTION("R^2") - { - CHECK_AFFECTATION_RESULT("let x : R^2, x = (-1, true); x[0] /= 2; x[1] /= 3;", "x", - (TinyVector<2>{-1. / 2., true / 3.})); - } - - SECTION("R^3") - { - CHECK_AFFECTATION_RESULT("let x : R^3, x = (-0.3, 12, 6.2); x[0] /= -1.2; x[1] /= -3.1; x[2] /= 2.4;", "x", - (TinyVector<3>{-0.3 / -1.2, 12 / -3.1, 6.2 / 2.4})); - } - - SECTION("R^1x1") - { - CHECK_AFFECTATION_RESULT("let x : R^1x1, x = 2; x[0,0] /= 1.3;", "x", (TinyMatrix<1>{2 / 1.3})); - } - - SECTION("R^2x2") - { - CHECK_AFFECTATION_RESULT("let x : R^2x2, x = (-1, true, 3, 1); x[0,0] /= 2; x[0,1] /= 3; x[1,0] /= 0.5; x[1,1] " - "/= 4;", - "x", (TinyMatrix<2>{-1. / 2., true / 3., 3 / 0.5, 1. / 4})); - } - - SECTION("R^3x3") - { - CHECK_AFFECTATION_RESULT("let x : R^3x3, x = (-0.3, 12, 6.2, 1.2, 3, 5, 1, 11, 2); x[0,0] /= -1.2; x[0,1] /= " - "-3.1; x[0,2] /= 2.4; x[1,0] /= -1.6; x[1,1] /= -3.1; x[1,2] /= 2.4; x[2,0] /= 0.4; " - "x[2,1] /= -1.7; x[2,2] /= 1.2;", - "x", - (TinyMatrix<3>{-0.3 / -1.2, 12 / -3.1, 6.2 / 2.4, 1.2 / -1.6, 3 / -3.1, 5 / 2.4, 1 / 0.4, - 11 / -1.7, 2 / 1.2})); - } } SECTION("errors") @@ -518,8 +435,122 @@ TEST_CASE("AffectationProcessor", "[language]") "incompatible dimensions in affectation: expecting 3, but provided 4"); } + SECTION("-> R^n (affectation of components is forbidden)") + { + CHECK_BUILD_THROWS_WITH("let x : R^1; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1, x=0; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2, x=0; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3, x=0; x[0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1, x=0; x[0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2, x=0; x[0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3, x=0; x[0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1, x=0; x[0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2, x=0; x[0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3, x=0; x[0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1, x=0; x[0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2, x=0; x[0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3, x=0; x[0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = \"foobar\";", "undefined affectation type: R^2 = string"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = \"foobar\";", "undefined affectation type: R^3 = string"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 3.2;", "undefined affectation type: R^2 = R"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 2.3;", "undefined affectation type: R^3 = R"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1; let y : R^1x1, y = 1; x = y;", + "undefined affectation type: R^1 = R^1x1"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2; let y : R^2x2, y = (1,2,4,4); x = y;", + "undefined affectation type: R^2 = R^2x2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3; let y : R^3x3, y = (1,2,3,4,5,6,7,8,9); x = y;", + "undefined affectation type: R^3 = R^3x3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 4;", "invalid integral value (0 is the solely valid value)"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 3;", "invalid integral value (0 is the solely valid value)"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^2, y = x;", + "undefined affectation type: R^2 = R^1"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = 0; let y : R^3, y = x;", + "undefined affectation type: R^3 = R^1"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^1, y = x;", + "undefined affectation type: R^1 = R^2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = 0; let y : R^3, y = x;", + "undefined affectation type: R^3 = R^2"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^1, y = x;", + "undefined affectation type: R^1 = R^3"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = 0; let y : R^2, y = x;", + "undefined affectation type: R^2 = R^3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^1, x = (1,2);", "undefined affectation type: R^1 = list"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^2, x = (1,2,3);", + "incompatible dimensions in affectation: expecting 2, but provided 3"); + + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = (1,2);", + "incompatible dimensions in affectation: expecting 3, but provided 2"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^3, x = (1,2,3,4);", + "incompatible dimensions in affectation: expecting 3, but provided 4"); + } + SECTION("-> R^nxn") { + CHECK_BUILD_THROWS_WITH("let x : R^1x1; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2x2; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3x3; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1x1, x=0; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2x2, x=0; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3x3, x=0; x[0,0] = -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1x1, x=0; x[0,0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2x2, x=0; x[0,0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3x3, x=0; x[0,0] += -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1x1, x=0; x[0,0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2x2, x=0; x[0,0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3x3, x=0; x[0,0] -= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + + CHECK_BUILD_THROWS_WITH("let x : R^1x1, x=0; x[0,0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^2x2, x=0; x[0,0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_BUILD_THROWS_WITH("let x : R^3x3, x=0; x[0,0] *= -1;", + "parse error, using subscript expression as lvalue is not allowed"); + CHECK_AFFECTATION_THROWS_WITH("let x : R^2x2, x = \"foobar\";", "undefined affectation type: R^2x2 = string"); CHECK_AFFECTATION_THROWS_WITH("let x : R^3x3, x = \"foobar\";", "undefined affectation type: R^3x3 = string"); diff --git a/tests/test_ListAffectationProcessor.cpp b/tests/test_ListAffectationProcessor.cpp index 94dc1845c..f84ee471a 100644 --- a/tests/test_ListAffectationProcessor.cpp +++ b/tests/test_ListAffectationProcessor.cpp @@ -100,22 +100,5 @@ TEST_CASE("ListAffectationProcessor", "[language]") CHECK_AFFECTATION_RESULT(R"(let (x,y,z):R^3x3*R^2x2*R^1x1, (x,y,z) = (0,0,0);)", "y", (TinyMatrix<2>{zero})); CHECK_AFFECTATION_RESULT(R"(let (x,y,z):R^3x3*R^2x2*R^1x1, (x,y,z) = (0,0,0);)", "z", (TinyMatrix<1>{zero})); } - - SECTION("compound with subscript values") - { - CHECK_AFFECTATION_RESULT(R"(let x:R^3; (x[0], x[2], x[1]) = (4, 6, 5);)", "x", (TinyVector<3>{4, 5, 6})); - CHECK_AFFECTATION_RESULT(R"(let x:R^2; (x[1], x[0]) = (3, 6);)", "x", (TinyVector<2>{6, 3})); - CHECK_AFFECTATION_RESULT(R"(let x:R^1; let y:R; (y, x[0]) = (4, 2.3);)", "x", (TinyVector<1>{2.3})); - } - - SECTION("compound with subscript values") - { - CHECK_AFFECTATION_RESULT( - R"(let x:R^3x3; (x[0,0], x[1,0], x[1,2], x[2,0], x[0,1], x[0,2], x[1,1], x[2,1], x[2,2]) = (1, 4, 6, 7, 2, 3, 5, 8, 9);)", - "x", (TinyMatrix<3>{1, 2, 3, 4, 5, 6, 7, 8, 9})); - CHECK_AFFECTATION_RESULT(R"(let x:R^2x2; (x[1,1], x[0,0], x[1,0], x[0,1]) = (3, 6, 2, 4);)", "x", - (TinyMatrix<2>{6, 4, 2, 3})); - CHECK_AFFECTATION_RESULT(R"(let x:R^1x1; let y:R; (y, x[0,0]) = (4, 2.3);)", "x", (TinyMatrix<1>{2.3})); - } } } -- GitLab