From dd076908a2afc59a935122ba2e9428c52717f8ab Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Fri, 7 Feb 2020 11:11:26 +0100 Subject: [PATCH] Allow '0' to initialize R^d in function arguments and return For instance, the following code is now allowed `` // '0' argument interpreted as 0 in R^d let f0: R^3->R, x -> x[2]; R x0 = f0(0); let f1: R^3*R->R, (x,t) -> x[2]*t; R x1 = f1(0, 1); // '0' returned and interpreted as 0 in R^d let f2: R->R^3*R, x->(0, 2*x); R^3*R (x2,t2) = f2(2); let f3: R->R^3, x->0; R^3 x3 = f3(2.3); `` --- .../ASTNodeAffectationExpressionBuilder.cpp | 32 +---- .../ASTNodeCFunctionExpressionBuilder.cpp | 3 +- src/language/ASTNodeDataTypeBuilder.cpp | 16 +-- .../ASTNodeFunctionExpressionBuilder.cpp | 128 ++++++++++++------ .../ASTNodeFunctionExpressionBuilder.hpp | 3 +- ...STNodeListAffectationExpressionBuilder.cpp | 35 +---- .../ASTNodeNaturalConversionChecker.cpp | 64 ++++++++- .../ASTNodeNaturalConversionChecker.hpp | 15 +- .../node_processor/AffectationProcessor.hpp | 2 + .../FunctionArgumentConverter.hpp | 2 + .../node_processor/FunctionProcessor.hpp | 2 + 11 files changed, 181 insertions(+), 121 deletions(-) diff --git a/src/language/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ASTNodeAffectationExpressionBuilder.cpp index 1e5f911ff..8c4357ce4 100644 --- a/src/language/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeAffectationExpressionBuilder.cpp @@ -219,37 +219,7 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode } }; - if (n.m_data_type == ASTNodeDataType::vector_t) { - // Only real data are considered - const ASTNode& data_node = *n.children[1]; - switch (data_node.m_data_type) { - case ASTNodeDataType::list_t: { - if (data_node.children.size() != n.m_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()}); - } - for (const auto& child : data_node.children) { - ASTNodeNaturalConversionChecker{n, child->m_data_type, ASTNodeDataType::double_t}; - } - - break; - } - case ASTNodeDataType::vector_t: { - if (data_node.m_data_type.dimension() != n.m_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{n.begin()}); - } - break; - } - case ASTNodeDataType::int_t: { - // Nothing to check by now since the special value 0 is allowed - break; - } - default: { - ASTNodeNaturalConversionChecker{n, data_node.m_data_type, n.m_data_type}; - } - } - } else { - ASTNodeNaturalConversionChecker{n, n.children[1]->m_data_type, n.m_data_type}; - } + ASTNodeNaturalConversionChecker{*n.children[1], n.m_data_type}; set_affectation_processor_for_value(n.m_data_type); }; diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp index 6e93f998a..99a1c8ac0 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp @@ -61,8 +61,7 @@ ASTNodeCFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeDataType& } }; - ASTNodeNaturalConversionChecker{argument_node_sub_data_type.m_parent_node, argument_node_sub_data_type.m_data_type, - parameter_type}; + ASTNodeNaturalConversionChecker{argument_node_sub_data_type, parameter_type}; return get_function_argument_converter_for_argument_type(); } diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index f979a3768..d1400f8c3 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -74,7 +74,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const const ASTNode& test_node = *n.children[1]; if (not n.children[1]->is_type<language::for_test>()) { - ASTNodeNaturalConversionChecker{test_node, test_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t}; } // in the case of empty for_test (not simplified node), nothing to check! } @@ -100,7 +100,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const this->_buildNodeDataTypes(*child); } for (auto&& child : n.children) { - ASTNodeNaturalConversionChecker{*child, child->m_data_type, ASTNodeDataType::double_t}; + ASTNodeNaturalConversionChecker{*child, ASTNodeDataType::double_t}; } if (n.children.size() <= 3) { @@ -302,19 +302,19 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const n.m_data_type = ASTNodeDataType::void_t; const ASTNode& test_node = *n.children[0]; - ASTNodeNaturalConversionChecker{test_node, test_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t}; } else if (n.is_type<language::do_while_statement>()) { n.m_data_type = ASTNodeDataType::void_t; const ASTNode& test_node = *n.children[1]; - ASTNodeNaturalConversionChecker{test_node, test_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{test_node, ASTNodeDataType::bool_t}; } else if (n.is_type<language::unary_not>()) { n.m_data_type = ASTNodeDataType::bool_t; const ASTNode& operand_node = *n.children[0]; - ASTNodeNaturalConversionChecker{operand_node, operand_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{operand_node, ASTNodeDataType::bool_t}; } else if (n.is_type<language::lesser_op>() or n.is_type<language::lesser_or_eq_op>() or n.is_type<language::greater_op>() or n.is_type<language::greater_or_eq_op>() or @@ -324,10 +324,10 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const n.m_data_type = ASTNodeDataType::bool_t; const ASTNode& lhs_node = *n.children[0]; - ASTNodeNaturalConversionChecker{lhs_node, lhs_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{lhs_node, ASTNodeDataType::bool_t}; const ASTNode& rhs_node = *n.children[1]; - ASTNodeNaturalConversionChecker{rhs_node, rhs_node.m_data_type, ASTNodeDataType::bool_t}; + ASTNodeNaturalConversionChecker{rhs_node, ASTNodeDataType::bool_t}; } else if (n.is_type<language::unary_minus>()) { n.m_data_type = n.children[0]->m_data_type; @@ -414,7 +414,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const auto& array_expression = *n.children[0]; auto& index_expression = *n.children[1]; - ASTNodeNaturalConversionChecker{index_expression, index_expression.m_data_type, ASTNodeDataType::int_t}; + ASTNodeNaturalConversionChecker{index_expression, ASTNodeDataType::int_t}; if (array_expression.m_data_type != ASTNodeDataType::vector_t) { std::ostringstream message; message << "invalid types '" << rang::fgB::yellow << dataTypeName(array_expression.m_data_type) diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp index 69cdad7f1..414c7d9f7 100644 --- a/src/language/ASTNodeFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp @@ -17,8 +17,7 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy { const size_t parameter_id = std::get<size_t>(parameter_symbol.attributes().value()); - ASTNodeNaturalConversionChecker{node_sub_data_type.m_parent_node, node_sub_data_type.m_data_type, - parameter_symbol.attributes().dataType()}; + ASTNodeNaturalConversionChecker{node_sub_data_type, parameter_symbol.attributes().dataType()}; auto get_function_argument_converter_for = [&](const auto& parameter_v) -> std::unique_ptr<IFunctionArgumentConverter> { @@ -56,10 +55,19 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy ", provided " + std::to_string(node_sub_data_type.m_data_type.dimension()) + ")", std::vector{node_sub_data_type.m_parent_node.begin()}); } + } + case ASTNodeDataType::int_t: { + if (node_sub_data_type.m_parent_node.is_type<language::integer>()) { + if (std::stoi(node_sub_data_type.m_parent_node.string()) == 0) { + return std::make_unique<FunctionArgumentConverter<ParameterT, ZeroType>>(parameter_id); + } + } + [[fallthrough]]; } // 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 } @@ -118,10 +126,8 @@ ASTNodeFunctionExpressionBuilder::_getArgumentConverter(SymbolType& parameter_sy case 3: { return get_function_argument_converter_for_vector(TinyVector<3>{}); } - default: { - throw parse_error("unexpected error: invalid parameter dimension", std::vector{m_node.begin()}); - } } + [[fallthrough]]; } // LCOV_EXCL_START @@ -192,16 +198,15 @@ ASTNodeFunctionExpressionBuilder::_buildArgumentConverter(FunctionDescriptor& fu } std::unique_ptr<INodeProcessor> -ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType expression_value_type, - const ASTNodeDataType return_value_type, +ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType return_value_type, ASTNode& node, ASTNode& function_component_expression) { - ASTNodeNaturalConversionChecker{function_component_expression, expression_value_type, return_value_type}; + 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 (expression_value_type) { + switch (function_component_expression.m_data_type) { case ASTNodeDataType::bool_t: { return std::make_unique<FunctionExpressionProcessor<ReturnT, bool>>(function_component_expression); } @@ -234,18 +239,28 @@ ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType ex auto get_function_processor_for_expression_vector = [&](const auto& return_v) -> std::unique_ptr<INodeProcessor> { using ReturnT = std::decay_t<decltype(return_v)>; - switch (expression_value_type) { + switch (function_component_expression.m_data_type) { case ASTNodeDataType::vector_t: { - if (expression_value_type.dimension() == return_v.dimension()) { + 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 + 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<ReturnT, ZeroType>>(function_component_expression); + } + } + throw parse_error("unexpected error: undefined expression value type for function", + std::vector{function_component_expression.begin()}); + break; + } + // LCOV_EXCL_START default: { throw parse_error("unexpected error: undefined expression value type for function", - std::vector{node.children[1]->begin()}); + std::vector{function_component_expression.begin()}); } // LCOV_EXCL_STOP } @@ -329,8 +344,10 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node Assert(return_value_type != ASTNodeDataType::undefined_t); + ASTNodeNaturalConversionChecker{expression_node, return_value_type}; + function_processor->addFunctionExpressionProcessor( - this->_getFunctionProcessor(expression_value_type, return_value_type, node, expression_node)); + this->_getFunctionProcessor(return_value_type, node, expression_node)); }; ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1]; @@ -339,34 +356,67 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node if (function_image_domain.is_type<language::vector_type>()) { ASTNodeDataType vector_type = getVectorDataType(function_image_domain); - Assert(vector_type.dimension() == function_expression.children.size()); + ASTNodeNaturalConversionChecker{function_expression, vector_type}; + if (function_expression.is_type<language::expression_list>()) { + Assert(vector_type.dimension() == function_expression.children.size()); + + for (size_t i = 0; i < vector_type.dimension(); ++i) { + function_processor->addFunctionExpressionProcessor( + this->_getFunctionProcessor(ASTNodeDataType::double_t, node, *function_expression.children[i])); + } - for (size_t i = 0; i < vector_type.dimension(); ++i) { + 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)); + break; + } + case 3: { + node.m_node_processor = + std::make_unique<TupleToVectorProcessor<FunctionProcessor, 3>>(node, std::move(function_processor)); + break; + } + default: { + throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); + } + } + } else if (function_expression.is_type<language::integer>()) { + if (std::stoi(function_expression.string()) == 0) { + switch (vector_type.dimension()) { + case 1: { + node.m_node_processor = + std::make_unique<FunctionExpressionProcessor<TinyVector<1>, ZeroType>>(function_expression); + break; + } + case 2: { + node.m_node_processor = + std::make_unique<FunctionExpressionProcessor<TinyVector<2>, ZeroType>>(function_expression); + break; + } + case 3: { + node.m_node_processor = + std::make_unique<FunctionExpressionProcessor<TinyVector<3>, ZeroType>>(function_expression); + break; + } + default: { + throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); + } + } + } else { + throw parse_error("unexpected error: expecting 0", std::vector{function_expression.begin()}); + } + } else { function_processor->addFunctionExpressionProcessor( - this->_getFunctionProcessor(function_expression.children[i]->m_data_type, ASTNodeDataType::double_t, node, - *function_expression.children[i])); - } + this->_getFunctionProcessor(vector_type, node, function_expression)); - 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)); - break; - } - case 3: { - node.m_node_processor = - std::make_unique<TupleToVectorProcessor<FunctionProcessor, 3>>(node, std::move(function_processor)); - break; - } - default: { - throw parse_error("unexpected error: invalid vector_t dimension", std::vector{node.begin()}); - } + 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/ASTNodeFunctionExpressionBuilder.hpp b/src/language/ASTNodeFunctionExpressionBuilder.hpp index 54c3297c6..798c78897 100644 --- a/src/language/ASTNodeFunctionExpressionBuilder.hpp +++ b/src/language/ASTNodeFunctionExpressionBuilder.hpp @@ -25,8 +25,7 @@ class ASTNodeFunctionExpressionBuilder std::unique_ptr<FunctionProcessor> _buildArgumentConverter(FunctionDescriptor& function_descriptor, ASTNode& node); - std::unique_ptr<INodeProcessor> _getFunctionProcessor(const ASTNodeDataType expression_value_type, - const ASTNodeDataType return_value_type, + std::unique_ptr<INodeProcessor> _getFunctionProcessor(const ASTNodeDataType return_value_type, ASTNode& node, ASTNode& function_component_expression); diff --git a/src/language/ASTNodeListAffectationExpressionBuilder.cpp b/src/language/ASTNodeListAffectationExpressionBuilder.cpp index 3f88ad804..2c14148ec 100644 --- a/src/language/ASTNodeListAffectationExpressionBuilder.cpp +++ b/src/language/ASTNodeListAffectationExpressionBuilder.cpp @@ -145,40 +145,7 @@ ASTNodeListAffectationExpressionBuilder::_buildAffectationProcessor( } }; - if (value_node.m_data_type == ASTNodeDataType::vector_t) { - // Only real data are considered - const ASTNode& data_node = rhs_node_sub_data_type.m_parent_node; - switch (data_node.m_data_type) { - case ASTNodeDataType::list_t: { - if (data_node.children.size() != value_node.m_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{value_node.begin()}); - } - for (const auto& child : data_node.children) { - ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, child->m_data_type, - ASTNodeDataType::double_t}; - } - - break; - } - case ASTNodeDataType::vector_t: { - if (data_node.m_data_type.dimension() != value_node.m_data_type.dimension()) { - throw parse_error("incompatible dimensions in affectation", std::vector{value_node.begin()}); - } - break; - } - case ASTNodeDataType::int_t: { - // Nothing to check by now since the special value 0 is allowed - break; - } - default: { - ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, rhs_node_sub_data_type.m_data_type, - value_node.m_data_type}; - } - } - } else { - ASTNodeNaturalConversionChecker{rhs_node_sub_data_type.m_parent_node, rhs_node_sub_data_type.m_data_type, - value_node.m_data_type}; - } + ASTNodeNaturalConversionChecker{rhs_node_sub_data_type, value_node.m_data_type}; add_affectation_processor_for_value(value_node.m_data_type, rhs_node_sub_data_type); } diff --git a/src/language/ASTNodeNaturalConversionChecker.cpp b/src/language/ASTNodeNaturalConversionChecker.cpp index abf672e0d..f7c5fa95e 100644 --- a/src/language/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ASTNodeNaturalConversionChecker.cpp @@ -1,8 +1,11 @@ #include <ASTNodeNaturalConversionChecker.hpp> -ASTNodeNaturalConversionChecker::ASTNodeNaturalConversionChecker(const ASTNode& node, - const ASTNodeDataType& data_type, - const ASTNodeDataType& target_data_type) +#include <PEGGrammar.hpp> + +void +ASTNodeNaturalConversionChecker::_checkIsNaturalTypeConversion(const ASTNode& node, + const ASTNodeDataType& data_type, + const ASTNodeDataType& target_data_type) const { if (not isNaturalConversion(data_type, target_data_type)) { std::ostringstream error_message; @@ -12,3 +15,58 @@ ASTNodeNaturalConversionChecker::ASTNodeNaturalConversionChecker(const ASTNode& throw parse_error(error_message.str(), node.begin()); } } + +void +ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNode& node, + const ASTNodeDataType& data_type, + const ASTNodeDataType& target_data_type) const +{ + if (target_data_type == ASTNodeDataType::vector_t) { + // Only R^d data is considered + switch (node.m_data_type) { + case ASTNodeDataType::list_t: { + if (node.children.size() != target_data_type.dimension()) { + throw parse_error("incompatible dimensions in affectation", std::vector{node.begin()}); + } + for (const auto& child : node.children) { + this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, ASTNodeDataType::double_t); + } + + break; + } + case ASTNodeDataType::vector_t: { + if (data_type.dimension() != target_data_type.dimension()) { + throw parse_error("incompatible dimensions in affectation", std::vector{node.begin()}); + } + break; + } + case ASTNodeDataType::int_t: { + if (node.is_type<language::integer>()) { + if (std::stoi(node.string()) == 0) { + break; + } + } + this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + break; + } + default: { + this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + } + } + } else { + this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + } +} + +ASTNodeNaturalConversionChecker::ASTNodeNaturalConversionChecker(const ASTNode& data_node, + const ASTNodeDataType& target_data_type) +{ + this->_checkIsNaturalExpressionConversion(data_node, data_node.m_data_type, target_data_type); +} + +ASTNodeNaturalConversionChecker::ASTNodeNaturalConversionChecker(const ASTNodeSubDataType& data_node_sub_data_type, + const ASTNodeDataType& target_data_type) +{ + this->_checkIsNaturalExpressionConversion(data_node_sub_data_type.m_parent_node, data_node_sub_data_type.m_data_type, + target_data_type); +} diff --git a/src/language/ASTNodeNaturalConversionChecker.hpp b/src/language/ASTNodeNaturalConversionChecker.hpp index fb2391895..bccd180b5 100644 --- a/src/language/ASTNodeNaturalConversionChecker.hpp +++ b/src/language/ASTNodeNaturalConversionChecker.hpp @@ -3,12 +3,23 @@ #include <ASTNode.hpp> #include <ASTNodeDataType.hpp> +#include <ASTNodeSubDataType.hpp> class ASTNodeNaturalConversionChecker { + private: + void _checkIsNaturalTypeConversion(const ASTNode& ast_node, + const ASTNodeDataType& data_type, + const ASTNodeDataType& target_data_type) const; + + void _checkIsNaturalExpressionConversion(const ASTNode& ast_node, + const ASTNodeDataType& data_type, + const ASTNodeDataType& target_data_type) const; + public: - ASTNodeNaturalConversionChecker(const ASTNode& ast_node, - const ASTNodeDataType& data_type, + ASTNodeNaturalConversionChecker(const ASTNode& data_node, const ASTNodeDataType& target_data_type); + + ASTNodeNaturalConversionChecker(const ASTNodeSubDataType& data_node_sub_data_type, const ASTNodeDataType& target_data_type); }; diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index c9e91663f..4449fd8ce 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -117,6 +117,8 @@ class AffectationExecutor final : public IAffectationExecutor } } else if (std::is_same_v<OperatorT, language::eq_op>) { m_lhs = ValueT{zero}; + } else { + static_assert(std::is_same_v<OperatorT, language::eq_op>, "unexpected operator type"); } } } diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index 48455d0bd..fd05ca24b 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -26,6 +26,8 @@ class FunctionArgumentConverter final : public IFunctionArgumentConverter exec_policy.currentContext()[m_argument_id] = std::move(value); } else if constexpr (std::is_same_v<ExpectedValueType, std::string>) { exec_policy.currentContext()[m_argument_id] = std::move(std::to_string(std::get<ProvidedValueType>(value))); + } else if constexpr (std::is_same_v<ProvidedValueType, ZeroType>) { + exec_policy.currentContext()[m_argument_id] = ExpectedValueType{ZeroType::zero}; } else { exec_policy.currentContext()[m_argument_id] = std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value))); diff --git a/src/language/node_processor/FunctionProcessor.hpp b/src/language/node_processor/FunctionProcessor.hpp index c45faaa39..a393117ba 100644 --- a/src/language/node_processor/FunctionProcessor.hpp +++ b/src/language/node_processor/FunctionProcessor.hpp @@ -26,6 +26,8 @@ class FunctionExpressionProcessor final : public INodeProcessor return m_function_expression.execute(exec_policy); } else if constexpr (std::is_same_v<ReturnType, std::string>) { return std::to_string(std::get<ExpressionValueType>(m_function_expression.execute(exec_policy))); + } else if constexpr (std::is_same_v<ExpressionValueType, ZeroType>) { + return ReturnType{ZeroType::zero}; } else { return static_cast<ReturnType>(std::get<ExpressionValueType>(m_function_expression.execute(exec_policy))); } -- GitLab