Skip to content
Snippets Groups Projects
Commit f64135a2 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Add support for multiple argument C functions

It remains a bunch of types checking and validation

Functions such as `min`, `max` and maybe `abs` should probably not be defined as
math C functions: these functions should compute their returned type according
to their arguments and not be only real function. Moreover, `min` and `max`
should conveniently allow more than 2 arguments.
parent 3f412d77
No related branches found
No related tags found
1 merge request!37Feature/language
......@@ -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);
}
......@@ -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);
......
......@@ -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;
......
......@@ -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); }}));
}
......@@ -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,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment