diff --git a/src/language/ast/ASTNodeExpressionBuilder.cpp b/src/language/ast/ASTNodeExpressionBuilder.cpp index f8d26d197e94ae33fef09eed675bfdd688c6cc44..d9b3b4e439183e1f3a205a7c94e47252ac7a42f2 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeExpressionBuilder.cpp @@ -25,6 +25,19 @@ #include <language/node_processor/WhileProcessor.hpp> #include <language/utils/ParseError.hpp> +void +ASTNodeExpressionBuilder::_checkIsPureFunction(const ASTNode& node) const +{ + if (node.is_type<language::unary_plusplus>() or node.is_type<language::unary_minusminus>() or + node.is_type<language::post_plusplus>() or node.is_type<language::post_minusminus>()) { + throw ParseError("invalid function definition. Function data must be constant!", node.begin()); + } + + for (auto&& child : node.children) { + this->_checkIsPureFunction(*child); + } +} + void ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) { @@ -42,6 +55,8 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) } else if (n.is_type<language::tuple_expression>()) { n.m_node_processor = std::make_unique<TupleToVectorProcessor<ASTNodeExpressionListProcessor>>(n); } else if (n.is_type<language::function_definition>()) { + this->_checkIsPureFunction(n); + n.m_node_processor = std::make_unique<FakeProcessor>(); } else if (n.is_type<language::function_evaluation>()) { diff --git a/src/language/ast/ASTNodeExpressionBuilder.hpp b/src/language/ast/ASTNodeExpressionBuilder.hpp index 74a2f720970df49a6ca5315dfd0b20fb2905f7d7..0e36b65289593d8f59074b7dcc9e8fbd1faeaef2 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.hpp +++ b/src/language/ast/ASTNodeExpressionBuilder.hpp @@ -5,7 +5,9 @@ class ASTNodeExpressionBuilder { + private: void _buildExpression(ASTNode& n); + void _checkIsPureFunction(const ASTNode& n) const; public: ASTNodeExpressionBuilder(ASTNode& n); diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index a8c2e0f15525c78dfd9e35df0672761d3df3b1f0..d10d243a8de7b16b3b6c33bc81d55343b2298953 100644 --- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp @@ -1141,5 +1141,98 @@ 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 : R -> R, 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 : R -> R, 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 : R -> R, 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 : R -> R, 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:R, a = 4; +let non_pure : R -> R, 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:R, a = 4; +let non_pure : R -> R, 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:R, a = 4; +let non_pure : R -> R, 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:R, a = 4; +let non_pure : R -> R, x -> x + a--; +)"; + + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, std::string{ + "invalid function definition. Function data must be constant!"}); + } + } + } } }