diff --git a/src/language/ASTNodeBuiltinFunctionExpressionBuilder.cpp b/src/language/ASTNodeBuiltinFunctionExpressionBuilder.cpp index 13c1297bd3150b11d100ec46a2b46d1678249862..5b324f104a2a9c4906250281986adb65be67921d 100644 --- a/src/language/ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -38,6 +38,32 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } }; + auto get_function_argument_to_string_converter = [&]() -> std::unique_ptr<IFunctionArgumentConverter> { + switch (argument_node_sub_data_type.m_data_type) { + case ASTNodeDataType::bool_t: { + return std::make_unique<FunctionArgumentConverter<std::string, bool>>(argument_number); + } + case ASTNodeDataType::unsigned_int_t: { + return std::make_unique<FunctionArgumentConverter<std::string, uint64_t>>(argument_number); + } + case ASTNodeDataType::int_t: { + return std::make_unique<FunctionArgumentConverter<std::string, int64_t>>(argument_number); + } + case ASTNodeDataType::double_t: { + return std::make_unique<FunctionArgumentConverter<std::string, double>>(argument_number); + } + case ASTNodeDataType::string_t: { + return std::make_unique<FunctionArgumentConverter<std::string, std::string>>(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: { @@ -51,6 +77,9 @@ ASTNodeBuiltinFunctionExpressionBuilder::_getArgumentConverter(const ASTNodeData } case ASTNodeDataType::double_t: { return get_function_argument_converter_for(double{}); + } + case ASTNodeDataType::string_t: { + return get_function_argument_to_string_converter(); } // LCOV_EXCL_START default: { diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp index b779d7f2cfb10faf1fcb98a28e7bff3005caaf58..e2b1f30575ad297212cafefc1a7f5c4896e836e0 100644 --- a/src/language/ASTNodeDataType.cpp +++ b/src/language/ASTNodeDataType.cpp @@ -94,19 +94,19 @@ isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& tar if (data_type != ASTNodeDataType::type_id_t) { return true; } else { - return {data_type.typeName() == target_data_type.typeName()}; + return (data_type.typeName() == target_data_type.typeName()); } } else if (target_data_type == ASTNodeDataType::bool_t) { return false; } else if (target_data_type == ASTNodeDataType::unsigned_int_t) { - return {(data_type == ASTNodeDataType::int_t) or (data_type == ASTNodeDataType::bool_t)}; + return ((data_type == ASTNodeDataType::int_t) or (data_type == ASTNodeDataType::bool_t)); } else if (target_data_type == ASTNodeDataType::int_t) { - return {(data_type == ASTNodeDataType::unsigned_int_t) or (data_type == ASTNodeDataType::bool_t)}; + return ((data_type == ASTNodeDataType::unsigned_int_t) or (data_type == ASTNodeDataType::bool_t)); } else if (target_data_type == ASTNodeDataType::double_t) { - return {(data_type == ASTNodeDataType::unsigned_int_t) or (data_type == ASTNodeDataType::int_t) or - (data_type == ASTNodeDataType::bool_t)}; + return ((data_type == ASTNodeDataType::unsigned_int_t) or (data_type == ASTNodeDataType::int_t) or + (data_type == ASTNodeDataType::bool_t)); } else if (target_data_type == ASTNodeDataType::string_t) { - return {(data_type >= ASTNodeDataType::bool_t) and (data_type < ASTNodeDataType::string_t)}; + return ((data_type >= ASTNodeDataType::bool_t) and (data_type < ASTNodeDataType::string_t)); } return false; } diff --git a/src/language/ASTNodeDataType.hpp b/src/language/ASTNodeDataType.hpp index eb7e9b8d3fdcf0c9cc150df15bfa559c2d3305d4..7209d1c4f184dd4ebaf9cd835a940dba975699ec 100644 --- a/src/language/ASTNodeDataType.hpp +++ b/src/language/ASTNodeDataType.hpp @@ -78,18 +78,4 @@ ASTNodeDataType dataTypePromotion(const ASTNodeDataType& data_type_1, const ASTN bool isNaturalConversion(const ASTNodeDataType& data_type, const ASTNodeDataType& target_data_type); -// Traits ast_node_data_type_from_pod - -template <typename T> -inline ASTNodeDataType ast_node_data_type_from_pod = ASTNodeDataType::undefined_t; - -template <> -inline ASTNodeDataType ast_node_data_type_from_pod<bool> = ASTNodeDataType::bool_t; -template <> -inline ASTNodeDataType ast_node_data_type_from_pod<int64_t> = ASTNodeDataType::int_t; -template <> -inline ASTNodeDataType ast_node_data_type_from_pod<uint64_t> = ASTNodeDataType::unsigned_int_t; -template <> -inline ASTNodeDataType ast_node_data_type_from_pod<double> = ASTNodeDataType::double_t; - #endif // AST_NODE_DATA_TYPE_HPP diff --git a/src/language/BuiltinFunctionEmbedder.hpp b/src/language/BuiltinFunctionEmbedder.hpp index b9e4e96ca32b43f953eabb3297f5d6544b18d126..66c094587e1a67d1114e5da82ba8a6443270ec66 100644 --- a/src/language/BuiltinFunctionEmbedder.hpp +++ b/src/language/BuiltinFunctionEmbedder.hpp @@ -7,6 +7,22 @@ #include <ASTNodeDataType.hpp> #include <DataVariant.hpp> +#include <DataHandler.hpp> + +template <typename T> +inline ASTNodeDataType ast_node_data_type_from = ASTNodeDataType::undefined_t; + +template <> +inline ASTNodeDataType ast_node_data_type_from<bool> = ASTNodeDataType::bool_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<int64_t> = ASTNodeDataType::int_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<uint64_t> = ASTNodeDataType::unsigned_int_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<double> = ASTNodeDataType::double_t; +template <> +inline ASTNodeDataType ast_node_data_type_from<std::string> = ASTNodeDataType::string_t; + class IBuiltinFunctionEmbedder { public: @@ -36,6 +52,8 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder [&](auto v_i) { if constexpr (std::is_arithmetic_v<decltype(v_i)>) { std::get<I>(t) = v_i; + } else if constexpr (std::is_same_v<decltype(v_i), std::string>) { + throw std::runtime_error("NIY!"); } else { throw std::runtime_error("unexpected argument type!"); } @@ -55,7 +73,7 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder PUGS_INLINE ASTNodeDataType _getOneParameterDataType(ArgsTuple& t) const { - return ast_node_data_type_from_pod<std::decay_t<decltype(std::get<I>(t))>>; + return ast_node_data_type_from<std::decay_t<decltype(std::get<I>(t))>>; } template <size_t... I> @@ -71,7 +89,7 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder PUGS_INLINE ASTNodeDataType getReturnDataType() const final { - return ast_node_data_type_from_pod<FX>; + return ast_node_data_type_from<FX>; } PUGS_INLINE std::vector<ASTNodeDataType> @@ -90,6 +108,15 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder return sizeof...(Args); } + private: + template <typename T> + PUGS_INLINE std::shared_ptr<IDataHandler> + _createHandler(std::shared_ptr<T> data) const + { + return std::make_shared<DataHandler<T>>(data); + } + + public: PUGS_INLINE DataVariant apply(const std::vector<DataVariant>& x) const final @@ -99,7 +126,11 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder using IndexSequence = std::make_index_sequence<N>; this->_copy_from_vector(t, x, IndexSequence{}); - return {std::apply(m_f, t)}; + if constexpr (std::is_arithmetic_v<FX>) { + return {std::apply(m_f, t)}; + } else { + return EmbeddedData(_createHandler(std::apply(m_f, t))); + } } template <typename FX2, typename... Args2> diff --git a/src/language/DataHandler.hpp b/src/language/DataHandler.hpp index 78cf0587d3f99486be5d350fc3dfcadfe20d02b0..9a62a233ff57955c365b00db02b3e5dc9e2c7619 100644 --- a/src/language/DataHandler.hpp +++ b/src/language/DataHandler.hpp @@ -14,7 +14,7 @@ class IDataHandler }; template <typename DataT> -class DataHandler +class DataHandler : public IDataHandler { private: std::shared_ptr<DataT> m_data; diff --git a/src/language/MeshModule.cpp b/src/language/MeshModule.cpp index a145db0e72355d880422088cb00d16721fbd07ca..9c0862e013a64f7ff9d3787447ab27ce8f31203b 100644 --- a/src/language/MeshModule.cpp +++ b/src/language/MeshModule.cpp @@ -3,11 +3,17 @@ #include <BuiltinFunctionEmbedder.hpp> #include <TypeDescriptor.hpp> +class IMesh; + +template <> +inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<IMesh>> = {ASTNodeDataType::type_id_t, "mesh"}; + MeshModule::MeshModule() { - this->_addTypeDescriptor(std::make_shared<TypeDescriptor>(std::string{"mesh"})); + this->_addTypeDescriptor( + std::make_shared<TypeDescriptor>(ast_node_data_type_from<std::shared_ptr<IMesh>>.typeName())); - this->_addBuiltinFunction("readGmsh", std::make_shared<BuiltinFunctionEmbedder<double, std::string>>( - std::function<double(std::string)>{ - [](std::string filename) -> double { return filename.size(); }})); + this->_addBuiltinFunction("readGmsh", std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<IMesh>, std::string>>( + std::function<std::shared_ptr<IMesh>(std::string)>{ + [](std::string) -> std::shared_ptr<IMesh> { return {}; }})); } diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp index d8ea59f78810c4e56811a85cbc63512a39da95dc..1279d0cae75309bbb1ea660734cfe2828b9be296 100644 --- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -54,9 +54,8 @@ class BuiltinFunctionRegister std::function<bool(double, double)>{[](double x, double y) -> bool { return x > y; }}))); m_name_builtin_function_map.insert( - std::make_pair("StoB_invalid", - std::make_shared<BuiltinFunctionEmbedder<bool, std::string>>( - std::function<bool(std::string)>{[](std::string s) -> bool { return s.size() > 0; }}))); + std::make_pair("StoB", std::make_shared<BuiltinFunctionEmbedder<bool, std::string>>( + std::function<bool(std::string)>{[](std::string s) -> bool { return s.size() > 0; }}))); } public: @@ -339,6 +338,22 @@ R2toB(1., 0.); CHECK_AST(data, result); } + SECTION("string -> B") + { + std::string_view data = R"( +StoB("foo"); +)"; + + std::string_view result = R"( +(root:ASTNodeListProcessor) + `-(language::function_evaluation:BuiltinFunctionProcessor) + +-(language::name:StoB:NameProcessor) + `-(language::literal:"foo":ValueProcessor) +)"; + + CHECK_AST(data, result); + } + SECTION("errors") { SECTION("bad number of arguments") @@ -364,13 +379,5 @@ RtoR("foo"); )"; CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: string -> R"}); } - - SECTION("invalid function parameter type") - { - std::string_view data = R"( -StoB_invalid(3); -)"; - CHECK_AST_THROWS_WITH(data, std::string{"invalid implicit conversion: Z -> undefined"}); - } } }