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

Add multi-component function evaluation

``
let f : R -> R*R, x -> (x, x+1);
f(3);         // computes (3, 4)
``
parent 1b101ddf
No related branches found
No related tags found
1 merge request!37Feature/language
...@@ -320,8 +320,9 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const ...@@ -320,8 +320,9 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const
ASTNodeDataType data_type{ASTNodeDataType::undefined_t}; ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
if (image_domain_node.children.size() > 0) { if (image_domain_node.children.size() > 0) {
throw parse_error("compound data type is not implemented yet", image_domain_node.begin()); data_type = image_domain_node.m_data_type;
} else { } else {
#warning check if it is really useful to compute exact types here?
if (image_domain_node.is_type<language::B_set>()) { if (image_domain_node.is_type<language::B_set>()) {
data_type = ASTNodeDataType::bool_t; data_type = ASTNodeDataType::bool_t;
} else if (image_domain_node.is_type<language::Z_set>()) { } else if (image_domain_node.is_type<language::Z_set>()) {
......
...@@ -140,26 +140,30 @@ PUGS_INLINE ...@@ -140,26 +140,30 @@ PUGS_INLINE
std::unique_ptr<INodeProcessor> std::unique_ptr<INodeProcessor>
ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType expression_value_type, ASTNodeFunctionExpressionBuilder::_getFunctionProcessor(const ASTNodeDataType expression_value_type,
const ASTNodeDataType return_value_type, const ASTNodeDataType return_value_type,
ASTNode& node) ASTNode& node,
ASTNode& function_component_expression,
ASTNodeDataVariant& node_value)
{ {
auto get_function_processor_for_expression_value = [&](const auto& return_v) -> std::unique_ptr<INodeProcessor> { auto get_function_processor_for_expression_value = [&](const auto& return_v) -> std::unique_ptr<INodeProcessor> {
using ReturnT = std::decay_t<decltype(return_v)>; using ReturnT = std::decay_t<decltype(return_v)>;
switch (expression_value_type) { switch (expression_value_type) {
case ASTNodeDataType::bool_t: { case ASTNodeDataType::bool_t: {
return std::make_unique<FunctionExpressionProcessor<ReturnT, bool>>(node); return std::make_unique<FunctionExpressionProcessor<ReturnT, bool>>(function_component_expression, node_value);
} }
case ASTNodeDataType::unsigned_int_t: { case ASTNodeDataType::unsigned_int_t: {
return std::make_unique<FunctionExpressionProcessor<ReturnT, uint64_t>>(node); return std::make_unique<FunctionExpressionProcessor<ReturnT, uint64_t>>(function_component_expression,
node_value);
} }
case ASTNodeDataType::int_t: { case ASTNodeDataType::int_t: {
return std::make_unique<FunctionExpressionProcessor<ReturnT, int64_t>>(node); return std::make_unique<FunctionExpressionProcessor<ReturnT, int64_t>>(function_component_expression, node_value);
} }
case ASTNodeDataType::double_t: { case ASTNodeDataType::double_t: {
return std::make_unique<FunctionExpressionProcessor<ReturnT, double>>(node); return std::make_unique<FunctionExpressionProcessor<ReturnT, double>>(function_component_expression, node_value);
} }
case ASTNodeDataType::string_t: { case ASTNodeDataType::string_t: {
if constexpr (std::is_same_v<ReturnT, std::string>) { if constexpr (std::is_same_v<ReturnT, std::string>) {
return std::make_unique<FunctionExpressionProcessor<ReturnT, std::string>>(node); return std::make_unique<FunctionExpressionProcessor<ReturnT, std::string>>(function_component_expression,
node_value);
} else { } else {
throw parse_error("invalid string conversion", std::vector{node.children[1]->begin()}); throw parse_error("invalid string conversion", std::vector{node.children[1]->begin()});
} }
...@@ -211,21 +215,52 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node ...@@ -211,21 +215,52 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
FunctionDescriptor& function_descriptor = node.m_symbol_table->functionTable()[function_id]; FunctionDescriptor& function_descriptor = node.m_symbol_table->functionTable()[function_id];
if (function_descriptor.definitionNode().children[1]->is_type<language::expression_list>()) {
// LCOV_EXCL_START
throw parse_error("unexpected error: function expression list is not implemented yet",
std::vector{function_descriptor.definitionNode().children[1]->begin()});
// LCOV_EXCL_STOP
}
std::unique_ptr function_processor = std::make_unique<FunctionProcessor>(); std::unique_ptr function_processor = std::make_unique<FunctionProcessor>();
this->_buildArgumentProcessors(function_descriptor, node, *function_processor); this->_buildArgumentProcessors(function_descriptor, node, *function_processor);
const ASTNodeDataType expression_value_type = function_descriptor.definitionNode().children[1]->m_data_type; ASTNode& function_image_domain = *function_descriptor.domainMappingNode().children[1];
const ASTNodeDataType return_value_type = node.m_data_type; ASTNode& function_expression = *function_descriptor.definitionNode().children[1];
auto add_component_expression = [&](ASTNode& expression_node, ASTNode& domain_node, ASTNodeDataVariant& value) {
ASTNodeDataType expression_value_type = expression_node.m_data_type;
ASTNodeDataType return_value_type = ASTNodeDataType::undefined_t;
ASTNode& image_domain_node = domain_node;
if (image_domain_node.is_type<language::B_set>()) {
return_value_type = ASTNodeDataType::bool_t;
} else if (image_domain_node.is_type<language::Z_set>()) {
return_value_type = ASTNodeDataType::int_t;
} else if (image_domain_node.is_type<language::N_set>()) {
return_value_type = ASTNodeDataType::unsigned_int_t;
} else if (image_domain_node.is_type<language::R_set>()) {
return_value_type = ASTNodeDataType::double_t;
} else if (image_domain_node.is_type<language::string_type>()) {
return_value_type = ASTNodeDataType::string_t;
}
Assert(return_value_type != ASTNodeDataType::undefined_t);
function_processor->addFunctionExpressionProcessor( function_processor->addFunctionExpressionProcessor(
this->_getFunctionProcessor(expression_value_type, return_value_type, node)); this->_getFunctionProcessor(expression_value_type, return_value_type, node, expression_node, value));
};
if (function_expression.is_type<language::expression_list>()) {
Assert(function_image_domain.is_type<language::type_expression>());
ASTNode& image_domain_node = function_image_domain;
const size_t& nb_component = function_expression.children.size();
AggregateDataVariant aggregate_value(nb_component);
for (size_t i = 0; i < function_expression.children.size(); ++i) {
add_component_expression(*function_expression.children[i], *image_domain_node.children[i], aggregate_value[i]);
}
node.m_value = std::move(aggregate_value);
} else {
add_component_expression(function_expression, function_image_domain, node.m_value);
}
node.m_node_processor = std::move(function_processor); node.m_node_processor = std::move(function_processor);
} }
...@@ -27,7 +27,9 @@ class ASTNodeFunctionExpressionBuilder ...@@ -27,7 +27,9 @@ class ASTNodeFunctionExpressionBuilder
PUGS_INLINE PUGS_INLINE
std::unique_ptr<INodeProcessor> _getFunctionProcessor(const ASTNodeDataType expression_value_type, std::unique_ptr<INodeProcessor> _getFunctionProcessor(const ASTNodeDataType expression_value_type,
const ASTNodeDataType return_value_type, const ASTNodeDataType return_value_type,
ASTNode& node); ASTNode& node,
ASTNode& function_component_expression,
ASTNodeDataVariant& node_value);
public: public:
ASTNodeFunctionExpressionBuilder(ASTNode& node); ASTNodeFunctionExpressionBuilder(ASTNode& node);
......
...@@ -39,7 +39,7 @@ template <typename ReturnType, typename ExpressionValueType> ...@@ -39,7 +39,7 @@ template <typename ReturnType, typename ExpressionValueType>
class FunctionExpressionProcessor final : public INodeProcessor class FunctionExpressionProcessor final : public INodeProcessor
{ {
private: private:
ASTNode& m_node; ASTNodeDataVariant& m_value;
ASTNode& m_function_expression; ASTNode& m_function_expression;
public: public:
...@@ -49,23 +49,16 @@ class FunctionExpressionProcessor final : public INodeProcessor ...@@ -49,23 +49,16 @@ class FunctionExpressionProcessor final : public INodeProcessor
m_function_expression.execute(exec_policy); m_function_expression.execute(exec_policy);
if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) { if constexpr (std::is_same_v<ReturnType, ExpressionValueType>) {
m_node.m_value = m_function_expression.m_value; m_value = m_function_expression.m_value;
} else if constexpr (std::is_same_v<ReturnType, std::string>) { } else if constexpr (std::is_same_v<ReturnType, std::string>) {
m_node.m_value = std::to_string(std::get<ExpressionValueType>(m_function_expression.m_value)); m_value = std::to_string(std::get<ExpressionValueType>(m_function_expression.m_value));
} else { } else {
m_node.m_value = static_cast<ReturnType>(std::get<ExpressionValueType>(m_function_expression.m_value)); m_value = static_cast<ReturnType>(std::get<ExpressionValueType>(m_function_expression.m_value));
} }
} }
FunctionExpressionProcessor(ASTNode& node) FunctionExpressionProcessor(ASTNode& function_component_expression, ASTNodeDataVariant& value)
: m_node{node}, m_function_expression{[&]() -> ASTNode& { : m_value{value}, m_function_expression{function_component_expression}
auto [i_symbol, found] = m_node.m_symbol_table->find(m_node.children[0]->string(), m_node.begin());
Assert(found);
uint64_t function_id = std::get<uint64_t>(i_symbol->attributes().value());
FunctionDescriptor& function_descriptor = m_node.m_symbol_table->functionTable()[function_id];
return *function_descriptor.definitionNode().children[1];
}()}
{} {}
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment