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

Rework CFunction arguments treatment

It now uses FunctionArgumentConverter and ASTNodeDataTypeFlattener. This leads
to a more consistent implementation and use of CFunction along with
FunctionExpression.

Now one can write
``
import math;
let x_and_3: R->R*R, x->(x,3);
R x = pow(x_and_3(2));
``
the novelty is that `pow` acts (has one could expect) as a `R*R->R` function
expression which makes is more natural (even if this example may not show its
relevance)
parent 3a5b2816
No related branches found
No related tags found
1 merge request!37Feature/language
...@@ -3,64 +3,73 @@ ...@@ -3,64 +3,73 @@
#include <SymbolTable.hpp> #include <SymbolTable.hpp>
#include <ASTNodeDataTypeFlattener.hpp>
#include <node_processor/CFunctionProcessor.hpp> #include <node_processor/CFunctionProcessor.hpp>
PUGS_INLINE std::unique_ptr<INodeProcessor> PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter>
ASTNodeCFunctionExpressionBuilder::_getArgumentProcessor(const ASTNodeDataType& parameter_type, ASTNode& argument_node) 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)>; 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: { 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: { 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: { 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: { case ASTNodeDataType::double_t: {
return std::make_unique<CFunctionArgumentProcessor<ParameterT, double>>(argument_node); return std::make_unique<FunctionArgumentConverter<ParameterT, double>>(argument_number);
} }
default: { 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) { switch (parameter_type) {
case ASTNodeDataType::bool_t: { case ASTNodeDataType::bool_t: {
return get_function_argument_processor_for(bool{}); return get_function_argument_converter_for(bool{});
} }
case ASTNodeDataType::unsigned_int_t: { 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: { case ASTNodeDataType::int_t: {
return get_function_argument_processor_for(int64_t{}); return get_function_argument_converter_for(int64_t{});
} }
case ASTNodeDataType::double_t: { case ASTNodeDataType::double_t: {
return get_function_argument_processor_for(double{}); return get_function_argument_converter_for(double{});
} }
default: { 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 PUGS_INLINE
void void
ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list, ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(
const std::vector<ASTNodeDataType>& parameter_type_list,
const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list,
const size_t argument_number, const size_t argument_number,
ASTNode& argument_node,
CFunctionProcessor& c_function_processor) CFunctionProcessor& c_function_processor)
{ {
c_function_processor.addArgumentProcessor( c_function_processor.addArgumentConverter(this->_getArgumentConverter(parameter_type_list[argument_number],
this->_getArgumentProcessor(parameter_type_list[argument_number], argument_node)); flattened_datatype_list[argument_number],
argument_number));
} }
PUGS_INLINE PUGS_INLINE
...@@ -71,9 +80,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS ...@@ -71,9 +80,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS
{ {
ASTNode& argument_nodes = *node.children[1]; ASTNode& argument_nodes = *node.children[1];
const size_t arguments_number = ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list;
argument_nodes.is_type<language::function_argument_list>() ? argument_nodes.children.size() : 1; ASTNodeDataTypeFlattener{argument_nodes, flattened_datatype_list};
const size_t arguments_number = flattened_datatype_list.size();
const size_t parameters_number = parameter_type_list.size(); const size_t parameters_number = parameter_type_list.size();
if (arguments_number != parameters_number) { if (arguments_number != parameters_number) {
...@@ -85,11 +95,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS ...@@ -85,11 +95,10 @@ ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<AS
if (arguments_number > 1) { if (arguments_number > 1) {
for (size_t i = 0; i < arguments_number; ++i) { for (size_t i = 0; i < arguments_number; ++i) {
ASTNode& argument_node = *argument_nodes.children[i]; this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, i, c_function_processor);
this->_storeArgumentProcessor(parameter_type_list, i, argument_node, c_function_processor);
} }
} else { } 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 ...@@ -106,7 +115,8 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no
std::vector<ASTNodeDataType> c_function_parameter_type_list = c_function_embedder->getParameterDataTypes(); 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); this->_buildArgumentProcessors(c_function_parameter_type_list, node, *c_function_processor);
......
...@@ -4,18 +4,23 @@ ...@@ -4,18 +4,23 @@
#include <ASTNode.hpp> #include <ASTNode.hpp>
#include <node_processor/INodeProcessor.hpp> #include <node_processor/INodeProcessor.hpp>
#include <ASTNodeDataTypeFlattener.hpp>
class CFunctionProcessor; class CFunctionProcessor;
class IFunctionArgumentConverter;
class ASTNodeCFunctionExpressionBuilder class ASTNodeCFunctionExpressionBuilder
{ {
private: private:
PUGS_INLINE std::unique_ptr<INodeProcessor> _getArgumentProcessor(const ASTNodeDataType& parameter_type, PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter> _getArgumentConverter(
ASTNode& argument_node); const ASTNodeDataType& parameter_type,
const ASTNodeSubDataType& argument_node_sub_data_type,
const size_t argument_number);
PUGS_INLINE PUGS_INLINE
void _storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list, void _storeArgumentProcessor(const std::vector<ASTNodeDataType>& parameter_type_list,
const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list,
const size_t argument_number, const size_t argument_number,
ASTNode& argument_node,
CFunctionProcessor& c_function_processor); CFunctionProcessor& c_function_processor);
PUGS_INLINE PUGS_INLINE
......
...@@ -7,25 +7,7 @@ ...@@ -7,25 +7,7 @@
#include <CFunctionEmbedder.hpp> #include <CFunctionEmbedder.hpp>
template <typename ExpectedValueType, typename ProvidedValueType> #include <node_processor/FunctionArgumentConverter.hpp>
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} {}
};
class CFunctionExpressionProcessor final : public INodeProcessor class CFunctionExpressionProcessor final : public INodeProcessor
{ {
...@@ -47,15 +29,17 @@ class CFunctionExpressionProcessor final : public INodeProcessor ...@@ -47,15 +29,17 @@ class CFunctionExpressionProcessor final : public INodeProcessor
class CFunctionProcessor : public INodeProcessor class CFunctionProcessor : public INodeProcessor
{ {
private: private:
ASTNode& m_argument_node;
std::unique_ptr<INodeProcessor> m_function_expression_processor; 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: public:
void 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 void
...@@ -69,17 +53,22 @@ class CFunctionProcessor : public INodeProcessor ...@@ -69,17 +53,22 @@ class CFunctionProcessor : public INodeProcessor
{ {
ExecutionPolicy context_exec_policy{exec_policy, ExecutionPolicy context_exec_policy{exec_policy,
ExecutionPolicy::Context{-1, std::make_shared<ExecutionPolicy::Context::Values>( ExecutionPolicy::Context{-1, std::make_shared<ExecutionPolicy::Context::Values>(
m_argument_processors.size())}}; m_argument_converters.size())}};
auto& argument_values = context_exec_policy.currentContext(); 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) { for (size_t i = 0; i < m_argument_converters.size(); ++i) {
argument_values[i] = m_argument_processors[i]->execute(context_exec_policy); m_argument_converters[i]->convert(context_exec_policy, std::move(argument_values[i]));
}
} }
return m_function_expression_processor->execute(context_exec_policy); return m_function_expression_processor->execute(context_exec_policy);
} }
CFunctionProcessor() = default; CFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {}
}; };
#endif // CFUNCTION_PROCESSOR_HPP #endif // CFUNCTION_PROCESSOR_HPP
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment