diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index b68a1dd76592987a57990e6dfbf3cac602592b3f..d2cd7c480bb635a83b3f60a4c49b5cf7cae6815b 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -50,6 +50,9 @@ struct real struct escaped_c : one< '\'', '"', '?', '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v' > {}; struct character : if_must_else< one< '\\' >, escaped_c, ascii::any> {}; +struct open_parent : seq< one< '(' >, ignored > {}; +struct close_parent : seq< one< ')' >, ignored > {}; + struct literal : if_must< one< '"' >, until< one< '"' >, character > > {}; struct import_kw : TAO_PEGTL_KEYWORD("import") {}; @@ -72,11 +75,13 @@ struct vector_type : seq< R_set, ignored, one< '^' >, ignored, integer >{}; struct basic_type : sor< scalar_type, string_type >{}; struct type_name_id; -struct type_specifier : sor< vector_type, basic_type, type_name_id >{}; +struct simple_type_specifier : sor< vector_type, basic_type, type_name_id >{}; + +struct tuple_type_specifier : seq<open_parent, simple_type_specifier, ignored, close_parent>{}; -struct TYPE_SPECIFIER : seq< type_specifier, ignored >{}; +struct TYPE_SPECIFIER : seq< sor<simple_type_specifier, tuple_type_specifier>, ignored >{}; -struct type_expression : list_must< type_specifier, seq< ignored, one< '*' >, ignored > >{}; +struct type_expression : list_must< TYPE_SPECIFIER, seq< ignored, one< '*' >, ignored > >{}; struct TYPE_EXPRESSION : seq< type_expression, ignored >{}; struct and_kw : TAO_PEGTL_KEYWORD("and") {}; @@ -142,9 +147,6 @@ struct COLUMN : seq< column , ignored > {}; struct comma : one< ',' > {}; struct COMMA : seq< comma , ignored > {}; -struct open_parent : seq< one< '(' >, ignored > {}; -struct close_parent : seq< one< ')' >, ignored > {}; - struct expression; struct parented_expression : if_must< open_parent, expression, close_parent >{}; diff --git a/src/language/ast/ASTBuilder.cpp b/src/language/ast/ASTBuilder.cpp index b0969abbb5d19f3c55fadf21a1d518621e9b6a7d..cef779ffce63b9c2ad808ca94b993e7eff59d4ff 100644 --- a/src/language/ast/ASTBuilder.cpp +++ b/src/language/ast/ASTBuilder.cpp @@ -275,6 +275,7 @@ using selector = parse_tree::selector< language::unary_plus, language::unary_not, language::subscript_expression, + language::tuple_type_specifier, language::type_expression, language::unary_expression, language::name_subscript_expression>, diff --git a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp index b0b9455dba6e7339a5ea5a6caebbcf60c07e9a98..1295383c4df4b97e784a3862bfb502c95564c0ba 100644 --- a/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeAffectationExpressionBuilder.cpp @@ -5,6 +5,8 @@ #include <language/ast/ASTNodeNaturalConversionChecker.hpp> #include <language/node_processor/AffectationProcessor.hpp> +#include <utils/Exceptions.hpp> + ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode& n) { auto set_affectation_processor = [](ASTNode& n, const auto& operator_v) { @@ -206,6 +208,31 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode break; } // LCOV_EXCL_START + default: { + throw parse_error("unexpected error: undefined operand type for embedded data affectation", + std::vector{n.children[1]->begin()}); + } + // LCOV_EXCL_STOP + } + } else { + throw parse_error("invalid operator for '" + data_type.typeName() + "' affectation", std::vector{n.begin()}); + } + }; + + auto set_affectation_processor_for_tuple_data = [&](const ASTNodeDataType& content_data_type, + const ASTNodeDataType& data_type) { + if (content_data_type != ASTNodeDataType::type_id_t) { + throw NotImplementedError(dataTypeName(content_data_type) + " argument to tuple "); + } + + using OperatorT = std::decay_t<decltype(operator_v)>; + if constexpr (std::is_same_v<OperatorT, language::eq_op>) { + switch (data_type) { + case ASTNodeDataType::list_t: { + n.m_node_processor = std::make_unique<AffectationFromListProcessor<OperatorT, EmbeddedData>>(n); + break; + } + // LCOV_EXCL_START default: { throw parse_error("unexpected error: undefined operand type for string affectation", std::vector{n.children[1]->begin()}); @@ -267,6 +294,11 @@ ASTNodeAffectationExpressionBuilder::ASTNodeAffectationExpressionBuilder(ASTNode set_affectation_processor_for_embedded_data(data_type); break; } + case ASTNodeDataType::tuple_t: { + const ASTNodeDataType& content_type = value_type.contentType(); + set_affectation_processor_for_tuple_data(content_type, data_type); + break; + } default: { throw parse_error("unexpected error: undefined value type for affectation", std::vector{n.children[0]->begin()}); diff --git a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp index cda5d08cd26517038b3fa6969191806a68ccea3e..0ccb025730f0605af9119589f37ac71da5ae37da 100644 --- a/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -76,6 +76,20 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } }; + auto get_function_argument_to_tuple_converter = [&]() -> std::unique_ptr<IFunctionArgumentConverter> { + switch (argument_node_sub_data_type.m_data_type) { + case ASTNodeDataType::tuple_t: { + return std::make_unique<FunctionArgumentConverter<EmbeddedData, EmbeddedData>>(argument_number); + } + case ASTNodeDataType::list_t: { + return std::make_unique<FunctionListArgumentConverter<EmbeddedData, EmbeddedData>>(argument_number); + } + default: { + throw UnexpectedError(dataTypeName(argument_node_sub_data_type.m_data_type) + " argument to tuple "); + } + } + }; + auto get_function_argument_to_function_id_converter = [&]() -> std::unique_ptr<IFunctionArgumentConverter> { switch (argument_node_sub_data_type.m_data_type) { case ASTNodeDataType::function_t: { @@ -115,6 +129,12 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::function_t: { return get_function_argument_to_function_id_converter(); + } + case ASTNodeDataType::tuple_t: { + if (parameter_type.contentType() != ASTNodeDataType::type_id_t) { + throw NotImplementedError(dataTypeName(parameter_type.contentType()) + " argument to tuple "); + } + return get_function_argument_to_tuple_converter(); } // LCOV_EXCL_START default: { diff --git a/src/language/ast/ASTNodeDataType.cpp b/src/language/ast/ASTNodeDataType.cpp index 0befade165ce5812e0a3fb78f700481b99cfe867..923c751f8c858674123d99458f7322b8c80652b4 100644 --- a/src/language/ast/ASTNodeDataType.cpp +++ b/src/language/ast/ASTNodeDataType.cpp @@ -41,6 +41,12 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::vector_t: name = "R^" + std::to_string(data_type.dimension()); break; + case ASTNodeDataType::tuple_t: + name = "tuple(" + dataTypeName(data_type.contentType()) + ')'; + break; + case ASTNodeDataType::list_t: + name = "list"; + break; case ASTNodeDataType::string_t: name = "string"; break; @@ -62,9 +68,6 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::void_t: name = "void"; break; - case ASTNodeDataType::list_t: - name = "list"; - break; } return name; } diff --git a/src/language/ast/ASTNodeDataType.hpp b/src/language/ast/ASTNodeDataType.hpp index 7209d1c4f184dd4ebaf9cd835a940dba975699ec..3c65905181878ab0d05887ddd92128003aa5cfcc 100644 --- a/src/language/ast/ASTNodeDataType.hpp +++ b/src/language/ast/ASTNodeDataType.hpp @@ -1,7 +1,10 @@ #ifndef AST_NODE_DATA_TYPE_HPP #define AST_NODE_DATA_TYPE_HPP +#include <utils/PugsAssert.hpp> + #include <limits> +#include <memory> #include <string> class ASTNode; @@ -17,8 +20,9 @@ class ASTNodeDataType unsigned_int_t = 2, double_t = 3, vector_t = 4, - list_t = 5, - string_t = 6, + tuple_t = 5, + list_t = 6, + string_t = 7, typename_t = 10, type_name_id_t = 11, type_id_t = 21, @@ -29,6 +33,7 @@ class ASTNodeDataType private: DataType m_data_type; + std::shared_ptr<ASTNodeDataType> m_content_type; size_t m_dimension; std::string m_type_name; @@ -39,13 +44,20 @@ class ASTNodeDataType return m_dimension; } + const ASTNodeDataType& + contentType() const + { + Assert(m_content_type); + return *m_content_type; + } + const std::string& typeName() const { return m_type_name; } - operator DataType() const + operator const DataType&() const { return m_data_type; } @@ -53,14 +65,23 @@ class ASTNodeDataType ASTNodeDataType& operator=(const ASTNodeDataType&) = default; ASTNodeDataType& operator=(ASTNodeDataType&&) = default; - ASTNodeDataType(DataType data_type) : m_data_type{data_type}, m_dimension{1}, m_type_name{"unknown"} {} + ASTNodeDataType(DataType data_type) + : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{1}, m_type_name{"unknown"} + {} + + ASTNodeDataType(DataType data_type, const ASTNodeDataType& content_type) + : m_data_type{data_type}, + m_content_type{std::make_shared<ASTNodeDataType>(content_type)}, + m_dimension{1}, + m_type_name{"unknown"} + {} ASTNodeDataType(DataType data_type, size_t dimension) - : m_data_type{data_type}, m_dimension{dimension}, m_type_name{"unknown"} + : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{dimension}, m_type_name{"unknown"} {} ASTNodeDataType(DataType data_type, const std::string& type_name) - : m_data_type{data_type}, m_dimension{1}, m_type_name{type_name} + : m_data_type{data_type}, m_content_type{nullptr}, m_dimension{1}, m_type_name{type_name} {} ASTNodeDataType(const ASTNodeDataType&) = default; diff --git a/src/language/ast/ASTNodeDataTypeBuilder.cpp b/src/language/ast/ASTNodeDataTypeBuilder.cpp index 973d0fc99b74f90e1f069dff6de78346f2c6e772..ba69d9d89959ec630a414ac5a0ddac701dd4bb87 100644 --- a/src/language/ast/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ast/ASTNodeDataTypeBuilder.cpp @@ -37,6 +37,43 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo data_type = ASTNodeDataType::double_t; } else if (type_node.is_type<language::vector_type>()) { data_type = getVectorDataType(type_node); + } else if (type_node.is_type<language::tuple_type_specifier>()) { + auto& content_node = type_node.children[0]; + + if (content_node->is_type<language::type_name_id>()) { + const std::string& type_name_id = content_node->string(); + + auto& symbol_table = *type_node.m_symbol_table; + + auto [i_type_symbol, found] = symbol_table.find(type_name_id, content_node->begin()); + if (not found) { + throw parse_error("undefined type identifier", std::vector{content_node->begin()}); + } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { + std::ostringstream os; + os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" + << dataTypeName(i_type_symbol->attributes().dataType()) << "'" << std::ends; + throw parse_error(os.str(), std::vector{content_node->begin()}); + } + + content_node->m_data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_name_id}; + i_type_symbol->attributes().setDataType(content_node->m_data_type); + } else if (content_node->is_type<language::B_set>()) { + data_type = ASTNodeDataType::bool_t; + } else if (content_node->is_type<language::Z_set>()) { + data_type = ASTNodeDataType::int_t; + } else if (content_node->is_type<language::N_set>()) { + data_type = ASTNodeDataType::unsigned_int_t; + } else if (content_node->is_type<language::R_set>()) { + data_type = ASTNodeDataType::double_t; + } else if (content_node->is_type<language::vector_type>()) { + data_type = getVectorDataType(type_node); + } else if (content_node->is_type<language::string_type>()) { + data_type = ASTNodeDataType::string_t; + } else { + throw UnexpectedError("unexpected content type in tuple"); + } + + data_type = ASTNodeDataType{ASTNodeDataType::tuple_t, content_node->m_data_type}; } else if (type_node.is_type<language::string_type>()) { data_type = ASTNodeDataType::string_t; } else if (type_node.is_type<language::type_name_id>()) { diff --git a/src/language/ast/ASTNodeExpressionBuilder.cpp b/src/language/ast/ASTNodeExpressionBuilder.cpp index 48b807c2f841166371bf3d5d977216e0a081746d..1f73444e167a5524e6d4cb818ca76fe3885ece80 100644 --- a/src/language/ast/ASTNodeExpressionBuilder.cpp +++ b/src/language/ast/ASTNodeExpressionBuilder.cpp @@ -19,6 +19,7 @@ #include <language/node_processor/NameProcessor.hpp> #include <language/node_processor/OStreamProcessor.hpp> #include <language/node_processor/TupleToTinyVectorProcessor.hpp> +#include <language/node_processor/TupleToVectorProcessor.hpp> #include <language/node_processor/ValueProcessor.hpp> #include <language/node_processor/WhileProcessor.hpp> @@ -49,11 +50,9 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n) n.m_node_processor = std::make_unique<TupleToTinyVectorProcessor<ASTNodeExpressionListProcessor, 3>>(n); break; } - // LCOV_EXCL_START default: { - throw parse_error("unexpected error: invalid tuple size", n.begin()); + n.m_node_processor = std::make_unique<TupleToVectorProcessor<ASTNodeExpressionListProcessor>>(n); } - // LCOV_EXCL_STOP } } else if (n.is_type<language::function_definition>()) { n.m_node_processor = std::make_unique<FakeProcessor>(); diff --git a/src/language/ast/ASTNodeNaturalConversionChecker.cpp b/src/language/ast/ASTNodeNaturalConversionChecker.cpp index c32f77d3078a36ca29ed94166dae1be97b8e9993..8a6820d189ade9907e217d499b544e510d5f41b8 100644 --- a/src/language/ast/ASTNodeNaturalConversionChecker.cpp +++ b/src/language/ast/ASTNodeNaturalConversionChecker.cpp @@ -58,6 +58,15 @@ ASTNodeNaturalConversionChecker::_checkIsNaturalExpressionConversion(const ASTNo this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); } } + } else if (target_data_type == ASTNodeDataType::tuple_t) { + const ASTNodeDataType& target_content_type = target_data_type.contentType(); + if (node.m_data_type == ASTNodeDataType::list_t) { + for (const auto& child : node.children) { + this->_checkIsNaturalExpressionConversion(*child, child->m_data_type, target_content_type); + } + } else { + this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); + } } else { this->_checkIsNaturalTypeConversion(node, data_type, target_data_type); } diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index 651516402260052ca69947415aaaea281af72f7e..176489a7f9d4e9520b1822108b0cee4f8e0ef493 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -26,24 +26,10 @@ struct GlaceScheme const MeshType& m_mesh; - GlaceScheme(const IMesh& mesh, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_0, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_1, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_2, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_3, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_4, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_5) + GlaceScheme(const IMesh& mesh, std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>> bc_descriptor_list) : m_mesh{dynamic_cast<const MeshType&>(mesh)} { MeshDataType mesh_data(m_mesh); - std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>> bc_descriptor_list; - if constexpr (Dimension == 1) { - bc_descriptor_list = {boundary_0, boundary_1}; - } else if constexpr (Dimension == 2) { - bc_descriptor_list = {boundary_0, boundary_1, boundary_2, boundary_3}; - } else if constexpr (Dimension == 3) { - bc_descriptor_list = {boundary_0, boundary_1, boundary_2, boundary_3, boundary_4, boundary_5}; - } std::cout << "number of bc descr = " << bc_descriptor_list.size() << '\n'; @@ -177,50 +163,35 @@ SchemeModule::SchemeModule() )); - this->_addBuiltinFunction("glace", - std::make_shared<BuiltinFunctionEmbedder< - void, std::shared_ptr<const IMesh>, std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>>>( - std::function<void(std::shared_ptr<const IMesh>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryConditionDescriptor>)>{ - - [](std::shared_ptr<const IMesh> p_mesh, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_0, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_1, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_2, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_3, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_4, - std::shared_ptr<const IBoundaryConditionDescriptor> boundary_5) -> void { - switch (p_mesh->dimension()) { - case 1: { - GlaceScheme<1>{*p_mesh, boundary_0, boundary_1, boundary_2, - boundary_3, boundary_4, boundary_5}; - break; - } - case 2: { - GlaceScheme<2>{*p_mesh, boundary_0, boundary_1, boundary_2, - boundary_3, boundary_4, boundary_5}; - break; - } - case 3: { - GlaceScheme<3>{*p_mesh, boundary_0, boundary_1, boundary_2, - boundary_3, boundary_4, boundary_5}; - break; - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } - }} - - )); + this + ->_addBuiltinFunction("glace", + std::make_shared< + BuiltinFunctionEmbedder<void, std::shared_ptr<const IMesh>, + std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>>>( + std::function<void(std::shared_ptr<const IMesh>, + std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>)>{ + + [](std::shared_ptr<const IMesh> p_mesh, + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& + bc_descriptor_list) -> void { + switch (p_mesh->dimension()) { + case 1: { + GlaceScheme<1>{*p_mesh, bc_descriptor_list}; + break; + } + case 2: { + GlaceScheme<2>{*p_mesh, bc_descriptor_list}; + break; + } + case 3: { + GlaceScheme<3>{*p_mesh, bc_descriptor_list}; + break; + } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } + + })); } diff --git a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp index e75992ee7e5670e948a9c064a76b0610f4b75cf4..ec37d74ee5c815695c229d3b93d5d0acdb79bc9d 100644 --- a/src/language/node_processor/ASTNodeExpressionListProcessor.hpp +++ b/src/language/node_processor/ASTNodeExpressionListProcessor.hpp @@ -20,8 +20,12 @@ class ASTNodeExpressionListProcessor final : public INodeProcessor [&](auto&& v) { using ValueT = std::decay_t<decltype(v)>; if constexpr (std::is_same_v<ValueT, AggregateDataVariant>) { - for (size_t i = 0; i < v.size(); ++i) { - _flattenResults(std::move(v[i]), list_values); + if (v.isFlattenable()) { + for (size_t i = 0; i < v.size(); ++i) { + _flattenResults(std::move(v[i]), list_values); + } + } else { + list_values.emplace_back(v); } } else { list_values.emplace_back(v); diff --git a/src/language/node_processor/AffectationProcessor.hpp b/src/language/node_processor/AffectationProcessor.hpp index bd0431e5da9424d9bb184d7976caa1c30be1770a..93d1396afc97da5eb39a24b7b25dc3ad6506b665 100644 --- a/src/language/node_processor/AffectationProcessor.hpp +++ b/src/language/node_processor/AffectationProcessor.hpp @@ -361,6 +361,52 @@ class AffectationFromListProcessor final : public INodeProcessor } }; +template <typename OperatorT> +class AffectationFromListProcessor<OperatorT, EmbeddedData> final : public INodeProcessor +{ + private: + ASTNode& m_node; + + DataVariant* m_lhs; + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + AggregateDataVariant children_values = std::get<AggregateDataVariant>(m_node.children[1]->execute(exec_policy)); + + static_assert(std::is_same_v<OperatorT, language::eq_op>, "forbidden affection operator for list to vectors"); + + std::vector<EmbeddedData> tuple_value(children_values.size()); + for (size_t i = 0; i < children_values.size(); ++i) { + std::visit( + [&](auto&& child_value) { + using T = std::decay_t<decltype(child_value)>; + if constexpr (std::is_same_v<T, EmbeddedData>) { + tuple_value[i] = child_value; + } else { + // LCOV_EXCL_START + throw parse_error("unexpected error: unexpected right hand side type in affectation", m_node.begin()); + // LCOV_EXCL_STOP + } + }, + children_values[i]); + } + + *m_lhs = std::move(tuple_value); + return {}; + } + + AffectationFromListProcessor(ASTNode& node) : m_node{node} + { + const std::string& symbol = m_node.children[0]->string(); + auto [i_symbol, found] = m_node.m_symbol_table->find(symbol, m_node.children[0]->begin()); + Assert(found); + + m_lhs = &i_symbol->attributes().value(); + } +}; + template <typename ValueT> class AffectationFromZeroProcessor final : public INodeProcessor { diff --git a/src/language/node_processor/FunctionArgumentConverter.hpp b/src/language/node_processor/FunctionArgumentConverter.hpp index 8733211dcefd7f25deb31345c6b66800de971ec2..445bf7ea975aaa2409a2ee0691613a1b2911dadc 100644 --- a/src/language/node_processor/FunctionArgumentConverter.hpp +++ b/src/language/node_processor/FunctionArgumentConverter.hpp @@ -3,6 +3,7 @@ #include <language/node_processor/ExecutionPolicy.hpp> #include <language/utils/DataVariant.hpp> +#include <utils/Exceptions.hpp> class IFunctionArgumentConverter { @@ -43,6 +44,40 @@ class FunctionArgumentConverter final : public IFunctionArgumentConverter FunctionArgumentConverter(size_t argument_id) : m_argument_id{argument_id} {} }; +template <typename ExpectedValueType, typename ProvidedValueType> +class FunctionListArgumentConverter final : public IFunctionArgumentConverter +{ + private: + size_t m_argument_id; + + public: + DataVariant + convert(ExecutionPolicy& exec_policy, DataVariant&& value) + { + if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) { + std::visit( + [&](auto&& v) { + using Value_T = std::decay_t<decltype(v)>; + if constexpr (std::is_same_v<Value_T, AggregateDataVariant>) { + std::vector<ExpectedValueType> list_value; + for (size_t i = 0; i < v.size(); ++i) { + list_value.emplace_back(std::get<ProvidedValueType>(v[i])); + } + exec_policy.currentContext()[m_argument_id] = std::move(list_value); + } else { + throw UnexpectedError("unexpected value type"); + } + }, + value); + } + static_assert(std::is_same_v<ExpectedValueType, ProvidedValueType>, "conversion is not implemented"); + + return {}; + } + + FunctionListArgumentConverter(size_t argument_id) : m_argument_id{argument_id} {} +}; + class FunctionArgumentToFunctionSymbolIdConverter final : public IFunctionArgumentConverter { private: diff --git a/src/language/node_processor/OStreamProcessor.hpp b/src/language/node_processor/OStreamProcessor.hpp index bc5778bc02a64aa32083c81e8675b331384e361b..43d07364c645385f54080ae563eec41e47ae4c9d 100644 --- a/src/language/node_processor/OStreamProcessor.hpp +++ b/src/language/node_processor/OStreamProcessor.hpp @@ -21,6 +21,15 @@ class OStreamProcessor final : public INodeProcessor if constexpr (not std::is_same_v<std::monostate, ValueT>) { if constexpr (std::is_same_v<bool, ValueT>) { m_os << std::boolalpha << value; + } else if constexpr (std::is_same_v<std::vector<EmbeddedData>, ValueT>) { + m_os << '('; + if (value.size() > 0) { + m_os << value[0]; + } + for (size_t i = 1; i < value.size(); ++i) { + m_os << ", " << value[i]; + } + m_os << ')'; } else { m_os << value; } diff --git a/src/language/node_processor/TupleToVectorProcessor.hpp b/src/language/node_processor/TupleToVectorProcessor.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4908bfaa58d582e441cd2500e16da8b5c685582b --- /dev/null +++ b/src/language/node_processor/TupleToVectorProcessor.hpp @@ -0,0 +1,32 @@ +#ifndef TUPLE_TO_VECTOR_PROCESSOR_HPP +#define TUPLE_TO_VECTOR_PROCESSOR_HPP + +#include <language/ast/ASTNode.hpp> +#include <language/node_processor/INodeProcessor.hpp> + +template <typename TupleProcessorT> +class TupleToVectorProcessor final : public INodeProcessor +{ + private: + ASTNode& m_node; + + std::unique_ptr<TupleProcessorT> m_tuple_processor; + + public: + DataVariant + execute(ExecutionPolicy& exec_policy) + { + AggregateDataVariant v = std::get<AggregateDataVariant>(m_tuple_processor->execute(exec_policy)); + + v.setIsFlattenable(false); + return DataVariant{std::move(v)}; + } + + TupleToVectorProcessor(ASTNode& node) : m_node{node}, m_tuple_processor{std::make_unique<TupleProcessorT>(node)} {} + + TupleToVectorProcessor(ASTNode& node, std::unique_ptr<TupleProcessorT>&& tuple_processor) + : m_node{node}, m_tuple_processor{std::move(tuple_processor)} + {} +}; + +#endif // TUPLE_TO_TINY_VECTOR_PROCESSOR_HPP diff --git a/src/language/utils/ASTNodeDataTypeTraits.hpp b/src/language/utils/ASTNodeDataTypeTraits.hpp index 44d40a771edc24c189331a491d3ac0652708f4fa..1956f2bc2bf5dc9e1d2c137bd877ef99bba1dadb 100644 --- a/src/language/utils/ASTNodeDataTypeTraits.hpp +++ b/src/language/utils/ASTNodeDataTypeTraits.hpp @@ -25,4 +25,8 @@ inline ASTNodeDataType ast_node_data_type_from<FunctionSymbolId> = ASTNodeDataTy template <size_t N> inline ASTNodeDataType ast_node_data_type_from<TinyVector<N>> = {ASTNodeDataType::vector_t, N}; +template <typename T> +inline ASTNodeDataType ast_node_data_type_from<std::vector<T>> = + ASTNodeDataType{ASTNodeDataType::tuple_t, ast_node_data_type_from<T>}; + #endif // AST_NODE_DATA_TYPE_TRAITS_H diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index 78efd7d30f96f83b8ff65dced9d56d546fa5409d..4df112ac258f7aea6e673c4395d8aece63723502 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -61,6 +61,21 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder } else { throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData"); } + } else if constexpr (std::is_same_v<Vi_Type, std::vector<EmbeddedData>>) { + if constexpr (is_vector_v<Ti_Type>) { + using Ti_value_type = typename Ti_Type::value_type; + static_assert(is_shared_ptr_v<Ti_value_type>, "expecting shared_ptr"); + + using Ti_handeled_type = typename Ti_value_type::element_type; + std::get<I>(t).resize(v_i.size()); + for (size_t j = 0; j < v_i.size(); ++j) { + auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get()); + std::get<I>(t)[j] = data_handler.data_ptr(); + } + } else { + throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " + + demangle<Ti_Type>()); + } } else { throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " + demangle<Ti_Type>()); diff --git a/src/language/utils/DataVariant.hpp b/src/language/utils/DataVariant.hpp index 1ca8a869d0b63348a735e1f5aa0c43fa2a32d80a..0bb9a656cf5c78acf700fe9752aebb0b8a27ac17 100644 --- a/src/language/utils/DataVariant.hpp +++ b/src/language/utils/DataVariant.hpp @@ -19,6 +19,7 @@ using DataVariant = std::variant<std::monostate, double, std::string, EmbeddedData, + std::vector<EmbeddedData>, AggregateDataVariant, FunctionSymbolId, TinyVector<1>, @@ -29,6 +30,7 @@ class AggregateDataVariant // LCOV_EXCL_LINE { private: std::vector<DataVariant> m_data_vector; + bool m_is_flattenable = true; std::ostream& _printComponent(std::ostream& os, const DataVariant& value) const @@ -37,6 +39,15 @@ class AggregateDataVariant // LCOV_EXCL_LINE [&](auto&& v) { if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::monostate>) { os << " -- "; + } else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<EmbeddedData>>) { + os << '('; + if (v.size() > 0) { + os << v[0]; + } + for (size_t i = 1; i < v.size(); ++i) { + os << ", " << v[i]; + } + os << ')'; } else { os << v; } @@ -66,6 +77,18 @@ class AggregateDataVariant // LCOV_EXCL_LINE return compound._print(os); } + void + setIsFlattenable(bool is_flattenable) + { + m_is_flattenable = is_flattenable; + } + + bool + isFlattenable() const + { + return m_is_flattenable; + } + PUGS_INLINE size_t size() const @@ -90,7 +113,7 @@ class AggregateDataVariant // LCOV_EXCL_LINE AggregateDataVariant& operator=(const AggregateDataVariant&) = default; AggregateDataVariant& operator=(AggregateDataVariant&&) = default; - AggregateDataVariant(std::vector<DataVariant>&& data_vector) : m_data_vector(data_vector) {} + AggregateDataVariant(std::vector<DataVariant>&& data_vector) : m_data_vector{data_vector} {} AggregateDataVariant(const AggregateDataVariant&) = default; AggregateDataVariant(AggregateDataVariant&&) = default; diff --git a/src/language/utils/SymbolTable.hpp b/src/language/utils/SymbolTable.hpp index 957251371b7393caebf0ce445c528d57a962fc1f..75baa7e7303b2aa05bb0e6156932d5a00130bafc 100644 --- a/src/language/utils/SymbolTable.hpp +++ b/src/language/utils/SymbolTable.hpp @@ -92,12 +92,23 @@ class SymbolTable os << "type_name_id:"; } else if (attributes.m_data_type == ASTNodeDataType::type_id_t) { os << attributes.m_data_type.typeName() << ':'; + } else if (attributes.m_data_type == ASTNodeDataType::tuple_t) { + os << attributes.m_data_type.typeName() << ':'; } std::visit( - [&](const auto& value) { + [&](auto&& value) { using T = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<T, std::monostate>) { os << "--"; + } else if constexpr (std::is_same_v<T, std::vector<EmbeddedData>>) { + os << '('; + if (value.size() > 0) { + os << value[0]; + } + for (size_t i = 1; i < value.size(); ++i) { + os << ", " << value[i]; + } + os << ')'; } else { os << value; } diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp index 60316bfe4239a8427840da5853db8bf3bab78cb4..b6e627200725198a1fb0c088b81779cf478c6521 100644 --- a/src/utils/PugsTraits.hpp +++ b/src/utils/PugsTraits.hpp @@ -4,6 +4,7 @@ #include <cstddef> #include <memory> #include <type_traits> +#include <vector> template <size_t N, typename T> class TinyVector; @@ -38,4 +39,12 @@ inline constexpr bool is_shared_ptr_v = false; template <typename T> inline constexpr bool is_shared_ptr_v<std::shared_ptr<T>> = true; +// Traits is_vector + +template <typename T> +inline constexpr bool is_vector_v = false; + +template <typename T> +inline constexpr bool is_vector_v<std::vector<T>> = true; + #endif // PUGS_TRAITS_HPP