diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp index b958907ab7f9d2c1e5f1852cd27977ec404a7e5b..936236d1c3dd1fd3e25c739fc7edc53e287293c4 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp @@ -3,64 +3,73 @@ #include <SymbolTable.hpp> +#include <ASTNodeDataTypeFlattener.hpp> + #include <node_processor/CFunctionProcessor.hpp> -PUGS_INLINE std::unique_ptr<INodeProcessor> -ASTNodeCFunctionExpressionBuilder::_getArgumentProcessor(const ASTNodeDataType& parameter_type, ASTNode& argument_node) +PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter> +ASTNodeCFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeDataType& parameter_type, + const ASTNodeSubDataType& argument_node_sub_data_type, + const size_t argument_number) { - auto get_function_argument_processor_for = [&](const auto& parameter_v) -> std::unique_ptr<INodeProcessor> { + auto get_function_argument_converter_for = + [&](const auto& parameter_v) -> std::unique_ptr<IFunctionArgumentConverter> { using ParameterT = std::decay_t<decltype(parameter_v)>; - switch (argument_node.m_data_type) { + switch (argument_node_sub_data_type.m_data_type) { case ASTNodeDataType::bool_t: { - return std::make_unique<CFunctionArgumentProcessor<ParameterT, bool>>(argument_node); + return std::make_unique<FunctionArgumentConverter<ParameterT, bool>>(argument_number); } case ASTNodeDataType::unsigned_int_t: { - return std::make_unique<CFunctionArgumentProcessor<ParameterT, uint64_t>>(argument_node); + return std::make_unique<FunctionArgumentConverter<ParameterT, uint64_t>>(argument_number); } case ASTNodeDataType::int_t: { - return std::make_unique<CFunctionArgumentProcessor<ParameterT, int64_t>>(argument_node); + return std::make_unique<FunctionArgumentConverter<ParameterT, int64_t>>(argument_number); } case ASTNodeDataType::double_t: { - return std::make_unique<CFunctionArgumentProcessor<ParameterT, double>>(argument_node); + return std::make_unique<FunctionArgumentConverter<ParameterT, double>>(argument_number); } default: { - throw parse_error("invalid argument type for function", std::vector{argument_node.begin()}); + throw parse_error("invalid argument type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } } }; - auto get_function_argument_processor_for_argument_type = [&]() { + auto get_function_argument_converter_for_argument_type = [&]() { switch (parameter_type) { case ASTNodeDataType::bool_t: { - return get_function_argument_processor_for(bool{}); + return get_function_argument_converter_for(bool{}); } case ASTNodeDataType::unsigned_int_t: { - return get_function_argument_processor_for(uint64_t{}); + return get_function_argument_converter_for(uint64_t{}); } case ASTNodeDataType::int_t: { - return get_function_argument_processor_for(int64_t{}); + return get_function_argument_converter_for(int64_t{}); } case ASTNodeDataType::double_t: { - return get_function_argument_processor_for(double{}); + return get_function_argument_converter_for(double{}); } default: { - throw parse_error("unexpected error: undefined parameter type for function", std::vector{argument_node.begin()}); + throw parse_error("unexpected error: undefined parameter type for function", + std::vector{argument_node_sub_data_type.m_parent_node.begin()}); } } }; - return get_function_argument_processor_for_argument_type(); + return get_function_argument_converter_for_argument_type(); } PUGS_INLINE void -ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list, - const size_t argument_number, - ASTNode& argument_node, - CFunctionProcessor& c_function_processor) +ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor( + const std::vector<ASTNodeDataType>& parameter_type_list, + const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list, + const size_t argument_number, + CFunctionProcessor& c_function_processor) { - c_function_processor.addArgumentProcessor( - this->_getArgumentProcessor(parameter_type_list[argument_number], argument_node)); + c_function_processor.addArgumentConverter(this->_getArgumentConverter(parameter_type_list[argument_number], + flattened_datatype_list[argument_number], + argument_number)); } PUGS_INLINE @@ -71,9 +80,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS { ASTNode& argument_nodes = *node.children[1]; - const size_t arguments_number = - argument_nodes.is_type<language::function_argument_list>() ? argument_nodes.children.size() : 1; + ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list; + ASTNodeDataTypeFlattener{argument_nodes, flattened_datatype_list}; + const size_t arguments_number = flattened_datatype_list.size(); const size_t parameters_number = parameter_type_list.size(); if (arguments_number != parameters_number) { @@ -85,11 +95,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS if (arguments_number > 1) { for (size_t i = 0; i < arguments_number; ++i) { - ASTNode& argument_node = *argument_nodes.children[i]; - this->_storeArgumentProcessor(parameter_type_list, i, argument_node, c_function_processor); + this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, i, c_function_processor); } } else { - this->_storeArgumentProcessor(parameter_type_list, 0, argument_nodes, c_function_processor); + this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, 0, c_function_processor); } } @@ -106,7 +115,8 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no std::vector<ASTNodeDataType> c_function_parameter_type_list = c_function_embedder->getParameterDataTypes(); - std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>(); + ASTNode& argument_nodes = *node.children[1]; + std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>(argument_nodes); this->_buildArgumentProcessors(c_function_parameter_type_list, node, *c_function_processor); diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.hpp b/src/language/ASTNodeCFunctionExpressionBuilder.hpp index db4533bdb16dbe4ce332476ac1d768ccf43097eb..267e4223868eed72c63dd7c19b7f0c1f75ffb6fb 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.hpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.hpp @@ -4,18 +4,23 @@ #include <ASTNode.hpp> #include <node_processor/INodeProcessor.hpp> +#include <ASTNodeDataTypeFlattener.hpp> + class CFunctionProcessor; +class IFunctionArgumentConverter; class ASTNodeCFunctionExpressionBuilder { private: - PUGS_INLINE std::unique_ptr<INodeProcessor> _getArgumentProcessor(const ASTNodeDataType& parameter_type, - ASTNode& argument_node); + PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter> _getArgumentConverter( + const ASTNodeDataType& parameter_type, + const ASTNodeSubDataType& argument_node_sub_data_type, + const size_t argument_number); PUGS_INLINE void _storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list, + const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list, const size_t argument_number, - ASTNode& argument_node, CFunctionProcessor& c_function_processor); PUGS_INLINE diff --git a/src/language/node_processor/CFunctionProcessor.hpp b/src/language/node_processor/CFunctionProcessor.hpp index 5c5f3c82be16563435fb4e8485c4502f53b941cc..e41eb2ca456fab00138cb0df4b6b279c04be6124 100644 --- a/src/language/node_processor/CFunctionProcessor.hpp +++ b/src/language/node_processor/CFunctionProcessor.hpp @@ -7,25 +7,7 @@ #include <CFunctionEmbedder.hpp> -template <typename ExpectedValueType, typename ProvidedValueType> -class CFunctionArgumentProcessor final : public INodeProcessor -{ - private: - ASTNode& m_provided_value_node; - - public: - DataVariant - execute(ExecutionPolicy& exec_policy) - { - if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) { - return m_provided_value_node.execute(exec_policy); - } else { - return static_cast<ExpectedValueType>(std::get<ProvidedValueType>(m_provided_value_node.execute(exec_policy))); - } - } - - CFunctionArgumentProcessor(ASTNode& provided_value_node) : m_provided_value_node{provided_value_node} {} -}; +#include <node_processor/FunctionArgumentConverter.hpp> class CFunctionExpressionProcessor final : public INodeProcessor { @@ -47,15 +29,17 @@ class CFunctionExpressionProcessor final : public INodeProcessor class CFunctionProcessor : public INodeProcessor { private: + ASTNode& m_argument_node; + std::unique_ptr<INodeProcessor> m_function_expression_processor; - std::vector<std::unique_ptr<INodeProcessor>> m_argument_processors; + std::vector<std::unique_ptr<IFunctionArgumentConverter>> m_argument_converters; public: void - addArgumentProcessor(std::unique_ptr<INodeProcessor>&& argument_processor) + addArgumentConverter(std::unique_ptr<IFunctionArgumentConverter>&& argument_converter) { - m_argument_processors.emplace_back(std::move(argument_processor)); + m_argument_converters.emplace_back(std::move(argument_converter)); } void @@ -69,17 +53,22 @@ class CFunctionProcessor : public INodeProcessor { ExecutionPolicy context_exec_policy{exec_policy, ExecutionPolicy::Context{-1, std::make_shared<ExecutionPolicy::Context::Values>( - m_argument_processors.size())}}; - auto& argument_values = context_exec_policy.currentContext(); + m_argument_converters.size())}}; + if (m_argument_converters.size() == 1) { + m_argument_converters[0]->convert(context_exec_policy, m_argument_node.execute(context_exec_policy)); + } else { + AggregateDataVariant argument_values{ + std::get<AggregateDataVariant>(m_argument_node.execute(context_exec_policy))}; - for (size_t i = 0; i < argument_values.size(); ++i) { - argument_values[i] = m_argument_processors[i]->execute(context_exec_policy); + for (size_t i = 0; i < m_argument_converters.size(); ++i) { + m_argument_converters[i]->convert(context_exec_policy, std::move(argument_values[i])); + } } return m_function_expression_processor->execute(context_exec_policy); } - CFunctionProcessor() = default; + CFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {} }; #endif // CFUNCTION_PROCESSOR_HPP