From 1dc79eaf1f8acfa3461a5bd3041eccf5b66c3428 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Mon, 14 Oct 2019 18:00:41 +0200 Subject: [PATCH] Provide sin function to the math module `sin` is now functional, but it is hard coded, it is just some kind of proof of concept. --- .../ASTNodeCFunctionExpressionBuilder.cpp | 21 +++-- .../ASTNodeCFunctionExpressionBuilder.hpp | 7 +- .../node_processor/CFunctionProcessor.hpp | 76 +++++++++++++++---- 3 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp index ca9f36e6a..6fc40f2f9 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp @@ -6,18 +6,22 @@ #include <node_processor/CFunctionProcessor.hpp> PUGS_INLINE std::unique_ptr<INodeProcessor> -ASTNodeCFunctionExpressionBuilder::_getArgumentProcessor(ASTNode& argument_node) +ASTNodeCFunctionExpressionBuilder::_getArgumentProcessor(ASTNode& argument_node, ASTNodeDataVariant& argument_value) { #warning use correct types - return std::make_unique<CFunctionArgumentProcessor<double, double>>(argument_node); + return std::make_unique<CFunctionArgumentProcessor<double, double>>(argument_node, argument_value); } PUGS_INLINE void -ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(ASTNode& argument_node, +ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(const size_t argument_number, + ASTNode& argument_node, CFunctionProcessor& c_function_processor) { - c_function_processor.addArgumentProcessor(this->_getArgumentProcessor(argument_node)); + auto& argument_values = c_function_processor.argumentValues(); + + c_function_processor.addArgumentProcessor( + this->_getArgumentProcessor(argument_node, argument_values[argument_number])); } PUGS_INLINE @@ -28,6 +32,8 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(ASTNode& node, CFunc const size_t arguments_number = argument_nodes.is<language::expression_list>() ? argument_nodes.children.size() : 1; + c_function_processor.setNumberOfArguments(arguments_number); + #warning use the correct number of parameters_domain_node const size_t parameters_number = 1; @@ -41,10 +47,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(ASTNode& node, CFunc if (arguments_number > 1) { for (size_t i = 0; i < arguments_number; ++i) { ASTNode& argument_node = *argument_nodes.children[i]; - this->_storeArgumentProcessor(argument_node, c_function_processor); + this->_storeArgumentProcessor(i, argument_node, c_function_processor); } } else { - this->_storeArgumentProcessor(argument_nodes, c_function_processor); + this->_storeArgumentProcessor(0, argument_nodes, c_function_processor); } } @@ -61,6 +67,9 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no this->_buildArgumentProcessors(node, *c_function_processor); + c_function_processor->setFunctionExpressionProcessor( + std::make_unique<CFunctionExpressionProcessor<double, double>>(node, c_function_processor->argumentValues())); + ASTNodeDataType c_function_return_type = ASTNodeDataType::double_t; node.m_node_processor = std::move(c_function_processor); diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.hpp b/src/language/ASTNodeCFunctionExpressionBuilder.hpp index f8d195100..f3b78a8ed 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.hpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.hpp @@ -8,10 +8,13 @@ class CFunctionProcessor; class ASTNodeCFunctionExpressionBuilder { - PUGS_INLINE std::unique_ptr<INodeProcessor> _getArgumentProcessor(ASTNode& argument_node); + PUGS_INLINE std::unique_ptr<INodeProcessor> _getArgumentProcessor(ASTNode& argument_node, + ASTNodeDataVariant& argument_value); PUGS_INLINE - void _storeArgumentProcessor(ASTNode& argument_node, CFunctionProcessor& c_function_processor); + void _storeArgumentProcessor(const size_t argument_number, + ASTNode& argument_node, + CFunctionProcessor& c_function_processor); PUGS_INLINE void _buildArgumentProcessors(ASTNode& node, CFunctionProcessor& c_function_processor); diff --git a/src/language/node_processor/CFunctionProcessor.hpp b/src/language/node_processor/CFunctionProcessor.hpp index 241196bf4..ca2fb3b33 100644 --- a/src/language/node_processor/CFunctionProcessor.hpp +++ b/src/language/node_processor/CFunctionProcessor.hpp @@ -5,11 +5,14 @@ #include <node_processor/INodeProcessor.hpp> +#include <cmath> + template <typename ProvidedValueType, typename ExpectedValueType> class CFunctionArgumentProcessor final : public INodeProcessor { private: ASTNode& m_provided_value_node; + ASTNodeDataVariant& m_argument_value; public: void @@ -17,14 +20,16 @@ class CFunctionArgumentProcessor final : public INodeProcessor { m_provided_value_node.execute(exec_policy); - // if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) { - // m_symbol_value = m_provided_value_node.m_value; - // } else { - // m_symbol_value = static_cast<ExpectedValueType>(std::get<ProvidedValueType>(m_provided_value_node.m_value)); - // } + if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) { + m_argument_value = m_provided_value_node.m_value; + } else { + m_argument_value = static_cast<ExpectedValueType>(std::get<ProvidedValueType>(m_provided_value_node.m_value)); + } } - CFunctionArgumentProcessor(ASTNode& provided_value_node) : m_provided_value_node{provided_value_node} {} + CFunctionArgumentProcessor(ASTNode& provided_value_node, ASTNodeDataVariant& argument_value) + : m_provided_value_node{provided_value_node}, m_argument_value{argument_value} + {} }; template <typename ReturnType, typename ExpressionValueType> @@ -33,42 +38,83 @@ class CFunctionExpressionProcessor final : public INodeProcessor private: ASTNode& m_node; + std::vector<ASTNodeDataVariant>& m_argument_values; + public: void execute(ExecUntilBreakOrContinue& exec_policy) { - // if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) { - // m_node.m_value = m_function_expression.m_value; - // } else { - // m_node.m_value = static_cast<ReturnType>(std::get<ExpressionValueType>(m_function_expression.m_value)); - // } + if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) { + std::visit( + [&](auto v) { + if constexpr (std::is_arithmetic_v<decltype(v)>) { + m_node.m_value = std::sin(v); + } else { + throw parse_error("invalid C function evaluation", m_node.begin()); + } + }, + m_argument_values[0]); + } else { + std::visit( + [&](auto v) { + if constexpr (std::is_arithmetic_v<decltype(v)>) { + m_node.m_value = static_cast<ReturnType>(std::sin(v)); + } else { + throw parse_error("invalid C function evaluation", m_node.begin()); + } + }, + m_argument_values[0]); + } } - CFunctionExpressionProcessor(ASTNode& node) : m_node{node} {} + CFunctionExpressionProcessor(ASTNode& node, std::vector<ASTNodeDataVariant>& argument_values) + : m_node{node}, m_argument_values{argument_values} + {} }; class CFunctionProcessor : public INodeProcessor { private: + std::unique_ptr<INodeProcessor> m_function_expression_processor; + std::vector<std::unique_ptr<INodeProcessor>> m_argument_processors; + std::vector<ASTNodeDataVariant> m_argument_values; public: + void + setNumberOfArguments(const size_t& number_of_arguments) + { + Assert(m_argument_values.size() == 0, "argument number has already been provided"); + m_argument_values.resize(number_of_arguments); + } + + std::vector<ASTNodeDataVariant>& + argumentValues() + { + return m_argument_values; + } + void addArgumentProcessor(std::unique_ptr<INodeProcessor>&& argument_processor) { m_argument_processors.emplace_back(std::move(argument_processor)); } + void + setFunctionExpressionProcessor(std::unique_ptr<INodeProcessor>&& function_processor) + { + m_function_expression_processor = std::move(function_processor); + } + void execute(ExecUntilBreakOrContinue& exec_policy) { + Assert(m_argument_processors.size() == m_argument_values.size()); for (auto& argument_processor : m_argument_processors) { argument_processor->execute(exec_policy); } - std::cerr << __FILE__ << ':' << __LINE__ << ": " << rang::fgB::red - << "execution of CFunctionProcessor not finished!" << rang::style::reset << '\n'; - std::exit(1); + m_function_expression_processor->execute(exec_policy); } CFunctionProcessor() = default; -- GitLab