diff --git a/doc/userdoc.org b/doc/userdoc.org index ba7cd798a6a7991d6451c405a5b9c81dfa2c0362..0ed26f5d8c495ab9b839e7fdf131c6cdc2f764d9 100644 --- a/doc/userdoc.org +++ b/doc/userdoc.org @@ -2160,6 +2160,10 @@ 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. +#+END_warning Let us give a few examples. #+NAME: R-to-R-function @@ -2184,6 +2188,15 @@ 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 +2221,16 @@ 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 + + **** Lifetime of function arguments The arguments used to define a function are *local* variables that exist @@ -2325,7 +2348,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. diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 8ee9225cd75b76d6aff8b82a7f853cb74c40bacc..0f8f1d287b88435c904c00557e7fc0dc729dcb56 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -175,6 +175,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>()); @@ -220,32 +241,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); @@ -520,6 +523,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(); } 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/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp index 656000c69cd45b85bcf72907850230c7e0f9615b..46ec44e1509ce607670b527d711284954a6670ac 100644 --- a/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeFunctionExpressionBuilder.cpp @@ -404,7 +404,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 +451,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 +1057,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 +1092,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 +1113,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 +1195,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/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/tests/test_ASTNodeDataTypeBuilder.cpp b/tests/test_ASTNodeDataTypeBuilder.cpp index 5c449d7abf9bc9f083bd7c8206d377360f0f229c..b6dc2cac85ab783eba86ba4b57a59a38edd6aac2 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") diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index 762202a671b1f7708b193ca8cd6c7aa599bfc780..1d3ef390960545ace5950c5c48f092f85c420b03 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,478 +1062,2892 @@ 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"( +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 --") + SECTION("tuples") + { + SECTION("from list of values") + { + SECTION("return a (B)") + { + SECTION("B argument") { - std::string_view data = R"( + 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!"}); + CHECK_EXPRESSION_BUILDER_THROWS_WITH(data, + std::string{ + "invalid function definition. Function data must be constant!"}); + } } } } diff --git a/tests/test_FunctionProcessor.cpp b/tests/test_FunctionProcessor.cpp index 97cc8d6be42199f684739dba21b1b3f9a2cab644..649cfe1af8baaa683e807662cc71873af24d4073 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,6 +834,991 @@ let x:R, x = g(f(3)); } } + SECTION("tuple functions") + { + SECTION("-> (B)") + { + SECTION("from B") + { + std::string_view data = R"( +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); + } + + 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("from (B)") + { + std::string_view data = R"( +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); + } + } + + 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("from N") + { + std::string_view data = R"( +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); + } + + 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("from (N)") + { + std::string_view data = R"( +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); + } + + 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("errors") { SECTION("negative value to N") @@ -871,5 +1867,40 @@ 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/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=()