diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp index d42420b70640364567109eac8c92782f776158f1..24821a00420590b776b67674414a89630a1b39a1 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp @@ -26,7 +26,9 @@ ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(const size_t argument PUGS_INLINE void -ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(ASTNode& node, CFunctionProcessor& c_function_processor) +ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(ASTNode& node, + const std::vector<ASTNodeDataType>& argument_type_list, + CFunctionProcessor& c_function_processor) { ASTNode& argument_nodes = *node.children[1]; @@ -34,8 +36,7 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(ASTNode& node, CFunc c_function_processor.setNumberOfArguments(arguments_number); -#warning use the correct number of parameters_domain_node - const size_t parameters_number = 1; + const size_t parameters_number = argument_type_list.size(); if (arguments_number != parameters_number) { std::ostringstream error_message; @@ -60,22 +61,21 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no Assert(found); Assert(i_function_symbol->attributes().dataType() == ASTNodeDataType::c_function_t); -#warning use the correct arguments type - const ASTNodeDataType c_function_argument_type = ASTNodeDataType::double_t; + uint64_t c_function_id = std::get<uint64_t>(i_function_symbol->attributes().value()); - std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>(); + CFunctionEmbedderTable& c_function_embedder_table = node.m_symbol_table->cFunctionEbedderTable(); + std::shared_ptr c_function_embedder = c_function_embedder_table[c_function_id]; - this->_buildArgumentProcessors(node, *c_function_processor); + std::vector<ASTNodeDataType> c_function_argument_type_list = c_function_embedder->getArgumentDataTypes(); - uint64_t c_function_id = std::get<uint64_t>(i_function_symbol->attributes().value()); + std::unique_ptr c_function_processor = std::make_unique<CFunctionProcessor>(); - CFunctionEmbedderTable& c_function_embedder_table = node.m_symbol_table->cFunctionEbedderTable(); + this->_buildArgumentProcessors(node, c_function_argument_type_list, *c_function_processor); c_function_processor->setFunctionExpressionProcessor( - std::make_unique<CFunctionExpressionProcessor<double, double>>(node, c_function_embedder_table[c_function_id], - c_function_processor->argumentValues())); + std::make_unique<CFunctionExpressionProcessor>(node, c_function_embedder, c_function_processor->argumentValues())); - ASTNodeDataType c_function_return_type = ASTNodeDataType::double_t; + ASTNodeDataType c_function_return_type = c_function_embedder->getReturnDataType(); node.m_node_processor = std::move(c_function_processor); } diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.hpp b/src/language/ASTNodeCFunctionExpressionBuilder.hpp index f3b78a8edadf4ea56845120ff59eb72fda2fb1ea..82b37ec7c7665c9df871338dec736a3a23ee143b 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.hpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.hpp @@ -17,7 +17,9 @@ class ASTNodeCFunctionExpressionBuilder CFunctionProcessor& c_function_processor); PUGS_INLINE - void _buildArgumentProcessors(ASTNode& node, CFunctionProcessor& c_function_processor); + void _buildArgumentProcessors(ASTNode& node, + const std::vector<ASTNodeDataType>& argument_type_list, + CFunctionProcessor& c_function_processor); public: ASTNodeCFunctionExpressionBuilder(ASTNode& node); diff --git a/src/language/CFunctionEmbedder.hpp b/src/language/CFunctionEmbedder.hpp index e5208d9016ea97356070f5827b2aa41ee01c8bcf..3ba93bbb4f056b9b6e6b620b63b002a701ae8510 100644 --- a/src/language/CFunctionEmbedder.hpp +++ b/src/language/CFunctionEmbedder.hpp @@ -4,6 +4,7 @@ #include <PugsAssert.hpp> #include <PugsMacros.hpp> +#include <ASTNodeDataType.hpp> #include <ASTNodeDataVariant.hpp> #include <cmath> @@ -12,10 +13,16 @@ #include <tuple> #include <vector> +#include <type_traits> + class ICFunctionEmbedder { public: - virtual void apply(const std::vector<ASTNodeDataVariant>& x, double& f_x) = 0; + virtual void apply(const std::vector<ASTNodeDataVariant>& x, ASTNodeDataVariant& f_x) = 0; + + virtual ASTNodeDataType getReturnDataType() const = 0; + + virtual std::vector<ASTNodeDataType> getArgumentDataTypes() const = 0; virtual ~ICFunctionEmbedder() = default; }; @@ -51,9 +58,57 @@ class CFunctionEmbedder : public ICFunctionEmbedder (_copy_value<I>(t, v), ...); } + template <typename T> + [[deprecated("displace this code along with ASTNodeDataType definition")]] ASTNodeDataType + _getASTNodeDataTypeFromPOD() const + { + if constexpr (std::is_same_v<bool, std::decay<T>>) { + return ASTNodeDataType::bool_t; + } else if constexpr (std::is_same_v<int64_t, std::decay<T>>) { + return ASTNodeDataType::int_t; + } else if constexpr (std::is_same_v<uint64_t, std::decay<T>>) { + return ASTNodeDataType::unsigned_int_t; + } else if constexpr (std::is_same_v<double, std::decay<T>>) { + return ASTNodeDataType::double_t; + } else { + return ASTNodeDataType::undefined_t; + } + } + + template <size_t I> + PUGS_INLINE ASTNodeDataType + _getOneArgumentDataType(ArgsTuple& t) const + { + return _getASTNodeDataTypeFromPOD<std::decay<decltype(std::get<I>(t))>>(); + } + + template <size_t... I> + PUGS_INLINE std::vector<ASTNodeDataType> + _getArgumentDataTypes(ArgsTuple t, std::index_sequence<I...>) const + { + std::vector<ASTNodeDataType> argument_type_list; + (argument_type_list.push_back(this->_getOneArgumentDataType<I>(t)), ...); + return argument_type_list; + } + public: - PUGS_INLINE - size_t + ASTNodeDataType + getReturnDataType() const + { + return this->_getASTNodeDataTypeFromPOD<FX>(); + } + + std::vector<ASTNodeDataType> + getArgumentDataTypes() const final + { + constexpr size_t N = std::tuple_size_v<ArgsTuple>; + ArgsTuple t; + using IndexSequence = std::make_index_sequence<N>; + + return this->_getArgumentDataTypes(t, IndexSequence{}); + } + + PUGS_INLINE constexpr size_t numberOfArguments() const { return sizeof...(Args); @@ -61,7 +116,7 @@ class CFunctionEmbedder : public ICFunctionEmbedder PUGS_INLINE void - apply(const std::vector<ASTNodeDataVariant>& x, FX& f_x) final + apply(const std::vector<ASTNodeDataVariant>& x, ASTNodeDataVariant& f_x) final { constexpr size_t N = std::tuple_size_v<ArgsTuple>; ArgsTuple t; diff --git a/src/language/CMathModule.cpp b/src/language/CMathModule.cpp index ec37707b96f8d15d68cda6234c010e321a5a44cb..46d2f1f94faf2ef674f626501925603be50f20a7 100644 --- a/src/language/CMathModule.cpp +++ b/src/language/CMathModule.cpp @@ -16,9 +16,37 @@ CMathModule::_addFunction(const std::string& name, std::shared_ptr<ICFunctionEmb CMathModule::CMathModule() { + this->_addFunction("sqrt", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::sqrt(x); }})); + + this->_addFunction("abs", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::abs(x); }})); + this->_addFunction("sin", std::make_shared<CFunctionEmbedder<double, double>>( std::function<double(double)>{[](double x) -> double { return std::sin(x); }})); this->_addFunction("cos", std::make_shared<CFunctionEmbedder<double, double>>( std::function<double(double)>{[](double x) -> double { return std::cos(x); }})); + + this->_addFunction("tan", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::tan(x); }})); + + this->_addFunction("asin", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::asin(x); }})); + + this->_addFunction("acos", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::acos(x); }})); + + this->_addFunction("atan", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::atan(x); }})); + + this->_addFunction("exp", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::exp(x); }})); + + this->_addFunction("log", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::log(x); }})); + + this->_addFunction("pow", + std::make_shared<CFunctionEmbedder<double, double, double>>(std::function<double(double, double)>{ + [](double x, double y) -> double { return std::pow(x, y); }})); } diff --git a/src/language/node_processor/CFunctionProcessor.hpp b/src/language/node_processor/CFunctionProcessor.hpp index 0b587afed45d8e991bd355ab6c5c4edc9d55dad4..a5b253072f98e78345700f37905ce52e51adf4eb 100644 --- a/src/language/node_processor/CFunctionProcessor.hpp +++ b/src/language/node_processor/CFunctionProcessor.hpp @@ -32,7 +32,6 @@ class CFunctionArgumentProcessor final : public INodeProcessor {} }; -template <typename ReturnType, typename ExpressionValueType> class CFunctionExpressionProcessor final : public INodeProcessor { private: @@ -45,13 +44,7 @@ class CFunctionExpressionProcessor final : public INodeProcessor void execute(ExecUntilBreakOrContinue&) { - ReturnType result; - m_embedded_c_function->apply(m_argument_values, result); - if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) { - m_node.m_value = result; - } else { - m_node.m_value = static_cast<ExpressionValueType>(result); - } + m_embedded_c_function->apply(m_argument_values, m_node.m_value); } CFunctionExpressionProcessor(ASTNode& node,