Select Git revision
GmshReader.cpp
ASTNodeCFunctionExpressionBuilder.cpp 5.60 KiB
#include <ASTNodeCFunctionExpressionBuilder.hpp>
#include <PEGGrammar.hpp>
#include <SymbolTable.hpp>
#include <ASTNodeDataTypeFlattener.hpp>
#include <ASTNodeNaturalConversionChecker.hpp>
#include <node_processor/CFunctionProcessor.hpp>
PUGS_INLINE std::unique_ptr<IFunctionArgumentConverter>
ASTNodeCFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeDataType& parameter_type,
const ASTNodeSubDataType& argument_node_sub_data_type,
const size_t argument_number)
{
auto get_function_argument_converter_for =
[&](const auto& parameter_v) -> std::unique_ptr<IFunctionArgumentConverter> {
using ParameterT = std::decay_t<decltype(parameter_v)>;
switch (argument_node_sub_data_type.m_data_type) {
case ASTNodeDataType::bool_t: {
return std::make_unique<FunctionArgumentConverter<ParameterT, bool>>(argument_number);
}
case ASTNodeDataType::unsigned_int_t: {
return std::make_unique<FunctionArgumentConverter<ParameterT, uint64_t>>(argument_number);
}
case ASTNodeDataType::int_t: {
return std::make_unique<FunctionArgumentConverter<ParameterT, int64_t>>(argument_number);
}
case ASTNodeDataType::double_t: {
return std::make_unique<FunctionArgumentConverter<ParameterT, double>>(argument_number);
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: invalid argument type for function",
std::vector{argument_node_sub_data_type.m_parent_node.begin()});
}
// LCOV_EXCL_STOP
}
};
auto get_function_argument_converter_for_argument_type = [&]() {
switch (parameter_type) {
case ASTNodeDataType::bool_t: {
return get_function_argument_converter_for(bool{});
}
case ASTNodeDataType::unsigned_int_t: {
return get_function_argument_converter_for(uint64_t{});
}
case ASTNodeDataType::int_t: {
return get_function_argument_converter_for(int64_t{});
}
case ASTNodeDataType::double_t: {
return get_function_argument_converter_for(double{});
}
// LCOV_EXCL_START
default: {
throw parse_error("unexpected error: undefined parameter type for function",
std::vector{argument_node_sub_data_type.m_parent_node.begin()});
}
// LCOV_EXCL_STOP
}
};
ASTNodeNaturalConversionChecker{argument_node_sub_data_type.m_parent_node, argument_node_sub_data_type.m_data_type,
parameter_type};
return get_function_argument_converter_for_argument_type();
}
PUGS_INLINE
void
ASTNodeCFunctionExpressionBuilder::_storeArgumentProcessor(
const std::vector<ASTNodeDataType>& parameter_type_list,
const ASTNodeDataTypeFlattener::FlattenedDataTypeList& flattened_datatype_list,
const size_t argument_number,
CFunctionProcessor& c_function_processor)
{
c_function_processor.addArgumentConverter(this->_getArgumentConverter(parameter_type_list[argument_number],
flattened_datatype_list[argument_number],
argument_number));
}
PUGS_INLINE
void
ASTNodeCFunctionExpressionBuilder::_buildArgumentProcessors(const std::vector<ASTNodeDataType>& parameter_type_list,
ASTNode& node,
CFunctionProcessor& c_function_processor)
{
ASTNode& argument_nodes = *node.children[1];
ASTNodeDataTypeFlattener::FlattenedDataTypeList flattened_datatype_list;
ASTNodeDataTypeFlattener{argument_nodes, flattened_datatype_list};
const size_t arguments_number = flattened_datatype_list.size();
const size_t parameters_number = parameter_type_list.size();
if (arguments_number != parameters_number) {
std::ostringstream error_message;
error_message << "bad number of arguments: expecting " << rang::fgB::yellow << parameters_number
<< rang::style::reset << ", provided " << rang::fgB::yellow << arguments_number << rang::style::reset;
throw parse_error(error_message.str(), argument_nodes.begin());
}
if (arguments_number > 1) {
for (size_t i = 0; i < arguments_number; ++i) {
this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, i, c_function_processor);
}
} else {
this->_storeArgumentProcessor(parameter_type_list, flattened_datatype_list, 0, c_function_processor);
}
}
ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& node)
{
auto [i_function_symbol, found] = node.m_symbol_table->find(node.children[0]->string(), node.begin());
Assert(found);
Assert(i_function_symbol->attributes().dataType() == ASTNodeDataType::c_function_t);
uint64_t c_function_id = std::get<uint64_t>(i_function_symbol->attributes().value());
CFunctionEmbedderTable& c_function_embedder_table = node.m_symbol_table->cFunctionEbedderTable();
std::shared_ptr c_function_embedder = c_function_embedder_table[c_function_id];
std::vector<ASTNodeDataType> c_function_parameter_type_list = c_function_embedder->getParameterDataTypes();
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);
c_function_processor->setFunctionExpressionProcessor(
std::make_unique<CFunctionExpressionProcessor>(c_function_embedder));
node.m_node_processor = std::move(c_function_processor);
}