diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp index 27410d7378fb6bd196d752def592b716f0f1af94..4517f30a0fc15b6c4da9f00d847e440a58feb579 100644 --- a/src/language/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp @@ -37,7 +37,8 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy } // LCOV_EXCL_START default: { - throw parse_error("invalid argument type", std::vector{node_sub_data_type.m_parent_node.begin()}); + throw parse_error("unexpected error: invalid argument type", + std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -51,9 +52,10 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy if (node_sub_data_type.m_data_type.dimension() == parameter_v.dimension()) { return std::make_unique<FunctionArgumentConverter<ParameterT, ParameterT>>(parameter_id); } else { - throw parse_error("invalid argument dimension (expected " + std::to_string(parameter_v.dimension()) + - ", provided " + std::to_string(node_sub_data_type.m_data_type.dimension()) + ")", + // LCOV_EXCL_START + throw parse_error("unexpected error: invalid argument dimension", std::vector{node_sub_data_type.m_parent_node.begin()}); + // LCOV_EXCL_STOP } } case ASTNodeDataType::int_t: { @@ -92,7 +94,8 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy } // LCOV_EXCL_START default: { - throw parse_error("invalid argument type", std::vector{node_sub_data_type.m_parent_node.begin()}); + throw parse_error("unexpected error: invalid argument type", + std::vector{node_sub_data_type.m_parent_node.begin()}); } // LCOV_EXCL_STOP } @@ -202,8 +205,6 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType re ASTNode& node, ASTNode& function_component_expression) { - ASTNodeNaturalConversionChecker{function_component_expression, return_value_type}; - auto get_function_processor_for_expression_value = [&](const auto& return_v) -> std::unique_ptr<INodeProcessor> { using ReturnT = std::decay_t<decltype(return_v)>; switch (function_component_expression.m_data_type) { @@ -244,7 +245,10 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType re if (function_component_expression.m_data_type.dimension() == return_v.dimension()) { return std::make_unique<FunctionExpressionProcessor<ReturnT, ReturnT>>(function_component_expression); } else { - throw parse_error("invalid dimension for returned vector", std::vector{function_component_expression.begin()}); + // LCOV_EXCL_START + throw parse_error("unexpected error: invalid dimension for returned vector", + std::vector{function_component_expression.begin()}); + // LCOV_EXCL_STOP } } case ASTNodeDataType::int_t: { @@ -253,9 +257,10 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType re return std::make_unique<FunctionExpressionProcessor<ReturnT, ZeroType>>(function_component_expression); } } + // LCOV_EXCL_START throw parse_error("unexpected error: undefined expression value type for function", std::vector{function_component_expression.begin()}); - break; + // LCOV_EXCL_STOP } // LCOV_EXCL_START default: { @@ -283,7 +288,11 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType re case ASTNodeDataType::vector_t: { switch (return_value_type.dimension()) { case 1: { - return get_function_processor_for_expression_vector(TinyVector<1>{}); + if (function_component_expression.m_data_type == ASTNodeDataType::vector_t) { + return get_function_processor_for_expression_vector(TinyVector<1>{}); + } else { + return get_function_processor_for_expression_value(TinyVector<1>{}); + } } case 2: { return get_function_processor_for_expression_vector(TinyVector<2>{}); @@ -291,9 +300,11 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType re case 3: { return get_function_processor_for_expression_vector(TinyVector<3>{}); } + // LCOV_EXCL_START default: { throw parse_error("unexpected error: invalid dimension in returned type", std::vector{node.begin()}); } + // LCOV_EXCL_STOP } } case ASTNodeDataType::string_t: { @@ -323,7 +334,7 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node std::unique_ptr function_processor = this->_buildArgumentConverter(function_descriptor, node); auto add_component_expression = [&](ASTNode& expression_node, ASTNode& domain_node) { - ASTNodeDataType return_value_type = ASTNodeDataType::undefined_t; + ASTNodeDataType return_value_type = ASTNodeDataType::undefined_t; ASTNode& image_domain_node = domain_node; @@ -343,7 +354,11 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node Assert(return_value_type != ASTNodeDataType::undefined_t); - ASTNodeNaturalConversionChecker{expression_node, return_value_type}; + if ((return_value_type == ASTNodeDataType::vector_t) and (return_value_type.dimension() == 1)) { + ASTNodeNaturalConversionChecker{expression_node, ASTNodeDataType::double_t}; + } else { + ASTNodeNaturalConversionChecker{expression_node, return_value_type}; + } function_processor->addFunctionExpressionProcessor( this->_getFunctionProcessor(return_value_type, node, expression_node)); @@ -355,7 +370,11 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node if (function_image_domain.is_type<language::vector_type>()) { ASTNodeDataType vector_type = getVectorDataType(function_image_domain); - ASTNodeNaturalConversionChecker{function_expression, vector_type}; + if ((vector_type.dimension() == 1) and (function_expression.m_data_type != ASTNodeDataType::vector_t)) { + ASTNodeNaturalConversionChecker{function_expression, ASTNodeDataType::double_t}; + } else { + ASTNodeNaturalConversionChecker{function_expression, vector_type}; + } if (function_expression.is_type<language::expression_list>()) { Assert(vector_type.dimension() == function_expression.children.size()); @@ -365,11 +384,6 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node } switch (vector_type.dimension()) { - case 1: { - node.m_node_processor = - std::make_unique<TupleToVectorProcessor<FunctionProcessor, 1>>(node, std::move(function_processor)); - break; - } case 2: { node.m_node_processor = std::make_unique<TupleToVectorProcessor<FunctionProcessor, 2>>(node, std::move(function_processor)); @@ -380,9 +394,11 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node std::make_unique<TupleToVectorProcessor<FunctionProcessor, 3>>(node, std::move(function_processor)); break; } + // LCOV_EXCL_START default: { throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); } + // LCOV_EXCL_STOP } } else if (function_expression.is_type<language::integer>()) { if (std::stoi(function_expression.string()) == 0) { @@ -402,12 +418,16 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node std::make_unique<FunctionExpressionProcessor<TinyVector<3>, ZeroType>>(function_expression); break; } + // LCOV_EXCL_START default: { throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); } + // LCOV_EXCL_STOP } } else { + // LCOV_EXCL_START throw parse_error("unexpected error: expecting 0", std::vector{function_expression.begin()}); + // LCOV_EXCL_STOP } } else { function_processor->addFunctionExpressionProcessor( diff --git a/tests/test_ASTNodeFunctionExpressionBuilder.cpp b/tests/test_ASTNodeFunctionExpressionBuilder.cpp index f773fbaa073ef36ed2b14633aec0d8dbdde5af04..806ce8b806d558a03c1e6d8de1b67720811698b2 100644 --- a/tests/test_ASTNodeFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeFunctionExpressionBuilder.cpp @@ -330,6 +330,260 @@ cat("foo", 2.5e-3); CHECK_AST(data, result); } + + SECTION("Return R^1 -> R^1") + { + std::string_view data = R"( +let f : R^1 -> R^1, x -> x+x; +R^1 x = 1; +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 R^2 -> R^2") + { + std::string_view data = R"( +let f : R^2 -> R^2, x -> x+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 R^3 -> R^3") + { + std::string_view data = R"( +let f : R^3 -> R^3, x -> x+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 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 tuple -> 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:TupleToVectorProcessor<FunctionProcessor, 2ul>) + +-(language::name:f:NameProcessor) + `-(language::function_argument_list:ASTNodeExpressionListProcessor) + +-(language::integer:1:ValueProcessor) + `-(language::integer:2:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + SECTION("Return tuple -> 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:TupleToVectorProcessor<FunctionProcessor, 3ul>) + +-(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 '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"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionExpressionProcessor<TinyVector<2ul, double>, ZeroType>) + +-(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:FunctionExpressionProcessor<TinyVector<3ul, double>, ZeroType>) + +-(language::name:f:NameProcessor) + `-(language::integer:1:ValueProcessor) +)"; + + 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); +)"; + + 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 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); +)"; + + 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("Arguments '0' -> R^1") + { + std::string_view data = R"( +let f : R^1 -> R^1, x -> x; +f(0); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:0:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + 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"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:0:ValueProcessor) +)"; + + CHECK_AST(data, result); + } + + 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"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:FunctionProcessor) + +-(language::name:f:NameProcessor) + `-(language::integer:0:ValueProcessor) +)"; + + CHECK_AST(data, result); + } } SECTION("errors")