diff --git a/src/language/modules/MathModule.cpp b/src/language/modules/MathModule.cpp index 7064dc33c1cc8eb0753edccb45ddae6ef988a2c5..e774284b385e7e74b8cb715f73b5ebec6f81b02e 100644 --- a/src/language/modules/MathModule.cpp +++ b/src/language/modules/MathModule.cpp @@ -4,78 +4,69 @@ MathModule::MathModule() { - this->_addBuiltinFunction("sqrt", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sqrt(x); }})); + this->_addBuiltinFunction("sqrt", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::sqrt(x); })); - this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::abs(x); }})); + this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::abs(x); })); - this->_addBuiltinFunction("sin", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sin(x); }})); + this->_addBuiltinFunction("sin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::sin(x); })); - this->_addBuiltinFunction("cos", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::cos(x); }})); + this->_addBuiltinFunction("cos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::cos(x); })); - this->_addBuiltinFunction("tan", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::tan(x); }})); + this->_addBuiltinFunction("tan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::tan(x); })); - this->_addBuiltinFunction("asin", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::asin(x); }})); + this->_addBuiltinFunction("asin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::asin(x); })); - this->_addBuiltinFunction("acos", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::acos(x); }})); + this->_addBuiltinFunction("acos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::acos(x); })); - this->_addBuiltinFunction("atan", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::atan(x); }})); + this->_addBuiltinFunction("atan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::atan(x); })); - this->_addBuiltinFunction("atan2", std::make_shared<BuiltinFunctionEmbedder<double, double, double>>( - std::function<double(double, double)>{ - [](double x, double y) -> double { return std::atan2(x, y); }})); + this->_addBuiltinFunction("atan2", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>( + [](double x, double y) -> double { return std::atan2(x, y); })); - this->_addBuiltinFunction("sinh", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sinh(x); }})); + this->_addBuiltinFunction("sinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::sinh(x); })); - this->_addBuiltinFunction("cosh", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::cosh(x); }})); + this->_addBuiltinFunction("cosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::cosh(x); })); - this->_addBuiltinFunction("tanh", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::tanh(x); }})); + this->_addBuiltinFunction("tanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::tanh(x); })); - this->_addBuiltinFunction("asinh", - std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::asinh(x); }})); + this->_addBuiltinFunction("asinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::asinh(x); })); - this->_addBuiltinFunction("acosh", - std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::acosh(x); }})); + this->_addBuiltinFunction("acosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::acosh(x); })); - this->_addBuiltinFunction("atanh", - std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::atanh(x); }})); + this->_addBuiltinFunction("atanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::atanh(x); })); - this->_addBuiltinFunction("exp", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::exp(x); }})); + this->_addBuiltinFunction("exp", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::exp(x); })); - this->_addBuiltinFunction("log", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::log(x); }})); + this->_addBuiltinFunction("log", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return std::log(x); })); - this->_addBuiltinFunction("pow", std::make_shared<BuiltinFunctionEmbedder<double, double, double>>( - std::function<double(double, double)>{ - [](double x, double y) -> double { return std::pow(x, y); }})); + this->_addBuiltinFunction("pow", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>( + [](double x, double y) -> double { return std::pow(x, y); })); - this->_addBuiltinFunction("ceil", - std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::ceil(x); }})); + this->_addBuiltinFunction("ceil", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>( + [](double x) -> int64_t { return std::ceil(x); })); - this->_addBuiltinFunction("floor", - std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::floor(x); }})); + this->_addBuiltinFunction("floor", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>( + [](double x) -> int64_t { return std::floor(x); })); - this->_addBuiltinFunction("trunc", - std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::trunc(x); }})); + this->_addBuiltinFunction("trunc", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>( + [](double x) -> int64_t { return std::trunc(x); })); - this->_addBuiltinFunction("round", - std::make_shared<BuiltinFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::lround(x); }})); + this->_addBuiltinFunction("round", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>( + [](double x) -> int64_t { return std::lround(x); })); } diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp index 0236d8d7995bedb254062d6dd29f26bd064b04b1..8394d940dfd774f58fcd7a16f54c91e0eb5334ea 100644 --- a/src/language/modules/MeshModule.cpp +++ b/src/language/modules/MeshModule.cpp @@ -64,21 +64,18 @@ MeshModule::MeshModule() this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IMesh>>); this->_addBuiltinFunction("readGmsh", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, std::string>>( - std::function<std::shared_ptr<const IMesh>(std::string)>{ + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>(const std::string&)>>( - [](const std::string& file_name) -> std::shared_ptr<const IMesh> { - GmshReader gmsh_reader(file_name); - return gmsh_reader.mesh(); - }} + [](const std::string& file_name) -> std::shared_ptr<const IMesh> { + GmshReader gmsh_reader(file_name); + return gmsh_reader.mesh(); + } )); - this - ->_addBuiltinFunction("transform", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, - std::shared_ptr<const IMesh>, FunctionSymbolId>>( - std::function<std::shared_ptr<const IMesh>(std::shared_ptr<const IMesh>, FunctionSymbolId)>{ + this->_addBuiltinFunction("transform", + std::make_shared<BuiltinFunctionEmbedder< + std::shared_ptr<const IMesh>(std::shared_ptr<const IMesh>, const FunctionSymbolId&)>>( [](std::shared_ptr<const IMesh> p_mesh, const FunctionSymbolId& function_id) -> std::shared_ptr<const IMesh> { @@ -99,97 +96,88 @@ MeshModule::MeshModule() throw UnexpectedError("invalid mesh dimension"); } } - }} + } - )); + )); this->_addBuiltinFunction("cartesian1dMesh", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<1>, - TinyVector<1>, std::vector<uint64_t>>>( + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IMesh>(const TinyVector<1>, const TinyVector<1>, const std::vector<uint64_t>&)>>( - std::function<std::shared_ptr<const IMesh>(TinyVector<1>, TinyVector<1>, - std::vector<uint64_t>)>{ + [&](const TinyVector<1> a, const TinyVector<1> b, + const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { + constexpr uint64_t dimension = 1; - [&](const TinyVector<1> a, const TinyVector<1> b, - const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { - constexpr uint64_t dimension = 1; + if (box_sizes.size() != dimension) { + throw NormalError("expecting " + std::to_string(dimension) + + " dimensions, provided " + std::to_string(box_sizes.size())); + } - if (box_sizes.size() != dimension) { - throw NormalError("expecting " + std::to_string(dimension) + - " dimensions, provided " + std::to_string(box_sizes.size())); + const TinyVector<dimension, uint64_t> sizes = [&]() { + TinyVector<dimension, uint64_t> s; + for (size_t i = 0; i < dimension; ++i) { + s[i] = box_sizes[i]; } + return s; + }(); - const TinyVector<dimension, uint64_t> sizes = [&]() { - TinyVector<dimension, uint64_t> s; - for (size_t i = 0; i < dimension; ++i) { - s[i] = box_sizes[i]; - } - return s; - }(); - - CartesianMeshBuilder builder{a, b, sizes}; - return builder.mesh(); - }} + CartesianMeshBuilder builder{a, b, sizes}; + return builder.mesh(); + } )); this->_addBuiltinFunction("cartesian2dMesh", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<2>, - TinyVector<2>, std::vector<uint64_t>>>( + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IMesh>(const TinyVector<2>, const TinyVector<2>, const std::vector<uint64_t>&)>>( - std::function<std::shared_ptr<const IMesh>(TinyVector<2>, TinyVector<2>, - std::vector<uint64_t>)>{ + [&](const TinyVector<2> a, const TinyVector<2> b, + const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { + constexpr uint64_t dimension = 2; - [&](const TinyVector<2> a, const TinyVector<2> b, - const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { - constexpr uint64_t dimension = 2; + if (box_sizes.size() != dimension) { + throw NormalError("expecting " + std::to_string(dimension) + + " dimensions, provided " + std::to_string(box_sizes.size())); + } - if (box_sizes.size() != dimension) { - throw NormalError("expecting " + std::to_string(dimension) + - " dimensions, provided " + std::to_string(box_sizes.size())); + const TinyVector<dimension, uint64_t> sizes = [&]() { + TinyVector<dimension, uint64_t> s; + for (size_t i = 0; i < dimension; ++i) { + s[i] = box_sizes[i]; } + return s; + }(); - const TinyVector<dimension, uint64_t> sizes = [&]() { - TinyVector<dimension, uint64_t> s; - for (size_t i = 0; i < dimension; ++i) { - s[i] = box_sizes[i]; - } - return s; - }(); - - CartesianMeshBuilder builder{a, b, sizes}; - return builder.mesh(); - }} + CartesianMeshBuilder builder{a, b, sizes}; + return builder.mesh(); + } )); this->_addBuiltinFunction("cartesian3dMesh", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>, TinyVector<3>, - TinyVector<3>, std::vector<uint64_t>>>( + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr< + const IMesh>(const TinyVector<3>&, const TinyVector<3>&, const std::vector<uint64_t>&)>>( - std::function<std::shared_ptr<const IMesh>(TinyVector<3>, TinyVector<3>, - std::vector<uint64_t>)>{ + [&](const TinyVector<3>& a, const TinyVector<3>& b, + const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { + constexpr uint64_t dimension = 3; - [&](const TinyVector<3>& a, const TinyVector<3>& b, - const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> { - constexpr uint64_t dimension = 3; + if (box_sizes.size() != dimension) { + throw NormalError("expecting " + std::to_string(dimension) + + " dimensions, provided " + std::to_string(box_sizes.size())); + } - if (box_sizes.size() != dimension) { - throw NormalError("expecting " + std::to_string(dimension) + - " dimensions, provided " + std::to_string(box_sizes.size())); + const TinyVector<dimension, uint64_t> sizes = [&]() { + TinyVector<dimension, uint64_t> s; + for (size_t i = 0; i < dimension; ++i) { + s[i] = box_sizes[i]; } + return s; + }(); - const TinyVector<dimension, uint64_t> sizes = [&]() { - TinyVector<dimension, uint64_t> s; - for (size_t i = 0; i < dimension; ++i) { - s[i] = box_sizes[i]; - } - return s; - }(); - - CartesianMeshBuilder builder{a, b, sizes}; - return builder.mesh(); - }} + CartesianMeshBuilder builder{a, b, sizes}; + return builder.mesh(); + } )); } diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp index fc9eae90669693c784f204744e93f0d61c3be119..a1fedff2f0168da1d2fe58c97a5bfc91cd6d4154 100644 --- a/src/language/modules/SchemeModule.cpp +++ b/src/language/modules/SchemeModule.cpp @@ -208,72 +208,65 @@ SchemeModule::SchemeModule() this->_addBuiltinFunction("boundaryName", std::make_shared< - BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>, std::string>>( - std::function<std::shared_ptr<const IBoundaryDescriptor>(std::string)>{ + BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(const std::string&)>>( - [](const std::string& boundary_name) -> std::shared_ptr<const IBoundaryDescriptor> { - return std::make_shared<NamedBoundaryDescriptor>(boundary_name); - }} + [](const std::string& boundary_name) -> std::shared_ptr<const IBoundaryDescriptor> { + return std::make_shared<NamedBoundaryDescriptor>(boundary_name); + } )); this->_addBuiltinFunction("boundaryTag", std::make_shared< - BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>, int64_t>>( - std::function<std::shared_ptr<const IBoundaryDescriptor>(int64_t)>{ + BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(int64_t)>>( - [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> { - return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag); - }} + [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> { + return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag); + } )); this ->_addBuiltinFunction("symmetry", - std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>, - std::shared_ptr<const IBoundaryDescriptor>>>( - std::function<std::shared_ptr<const IBoundaryConditionDescriptor>( - std::shared_ptr<const IBoundaryDescriptor>)>{ + std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>( + std::shared_ptr<const IBoundaryDescriptor>)>>( - [](std::shared_ptr<const IBoundaryDescriptor> boundary) - -> std::shared_ptr<const IBoundaryConditionDescriptor> { - return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary); - }} + [](std::shared_ptr<const IBoundaryDescriptor> boundary) + -> std::shared_ptr<const IBoundaryConditionDescriptor> { + return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary); + } )); this->_addBuiltinFunction("glace", - std::make_shared< - BuiltinFunctionEmbedder<void, std::shared_ptr<const IMesh>, - std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>, - FunctionSymbolId, FunctionSymbolId, FunctionSymbolId>>( - std::function<void(std::shared_ptr<const IMesh>, - std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>, - FunctionSymbolId, FunctionSymbolId, FunctionSymbolId)>{ - - [](std::shared_ptr<const IMesh> p_mesh, - const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& - bc_descriptor_list, - const FunctionSymbolId& rho_id, const FunctionSymbolId& u_id, - const FunctionSymbolId& p_id) -> void { - switch (p_mesh->dimension()) { - case 1: { - GlaceScheme<1>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; - break; - } - case 2: { - GlaceScheme<2>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; - break; - } - case 3: { - GlaceScheme<3>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; - break; - } - default: { - throw UnexpectedError("invalid mesh dimension"); - } - } + std::make_shared<BuiltinFunctionEmbedder< + void(std::shared_ptr<const IMesh>, + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&, + const FunctionSymbolId&, const FunctionSymbolId&, const FunctionSymbolId&)>>( + + [](std::shared_ptr<const IMesh> p_mesh, + const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& + bc_descriptor_list, + const FunctionSymbolId& rho_id, const FunctionSymbolId& u_id, + const FunctionSymbolId& p_id) -> void { + switch (p_mesh->dimension()) { + case 1: { + GlaceScheme<1>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; + break; + } + case 2: { + GlaceScheme<2>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; + break; + } + case 3: { + GlaceScheme<3>{*p_mesh, bc_descriptor_list, rho_id, u_id, p_id}; + break; } + default: { + throw UnexpectedError("invalid mesh dimension"); + } + } + } - })); + )); } diff --git a/src/language/modules/VTKModule.cpp b/src/language/modules/VTKModule.cpp index aafe8d2abbe0a8167e96e686ffc54e7184645585..30d2c11e48b580622ae24e30c9d71bb2d46b007d 100644 --- a/src/language/modules/VTKModule.cpp +++ b/src/language/modules/VTKModule.cpp @@ -10,40 +10,40 @@ VTKModule::VTKModule() { this->_addBuiltinFunction("writeVTK", - std::make_shared<BuiltinFunctionEmbedder<void, std::shared_ptr<const IMesh>, std::string>>( - std::function<void(std::shared_ptr<const IMesh>, std::string)>{ - - [](std::shared_ptr<const IMesh> p_mesh, const std::string& filename) -> void { - VTKWriter writer(filename, 0.1); - - static double time = 0; - - switch (p_mesh->dimension()) { - case 1: { - using MeshType = Mesh<Connectivity<1>>; - const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); - - writer.write(mesh, OutputNamedItemValueSet{}, time, true); - break; - } - case 2: { - using MeshType = Mesh<Connectivity<2>>; - const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); - - writer.write(mesh, OutputNamedItemValueSet{}, time, true); - break; - } - case 3: { - using MeshType = Mesh<Connectivity<3>>; - const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); - - writer.write(mesh, OutputNamedItemValueSet{}, time, true); - break; - } - } - - time++; + std::make_shared< + BuiltinFunctionEmbedder<void(std::shared_ptr<const IMesh>, const std::string&)>>( + + [](std::shared_ptr<const IMesh> p_mesh, const std::string& filename) -> void { + VTKWriter writer(filename, 0.1); + + static double time = 0; + + switch (p_mesh->dimension()) { + case 1: { + using MeshType = Mesh<Connectivity<1>>; + const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); + + writer.write(mesh, OutputNamedItemValueSet{}, time, true); + break; + } + case 2: { + using MeshType = Mesh<Connectivity<2>>; + const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); + + writer.write(mesh, OutputNamedItemValueSet{}, time, true); + break; + } + case 3: { + using MeshType = Mesh<Connectivity<3>>; + const MeshType& mesh = dynamic_cast<const MeshType&>(*p_mesh); + + writer.write(mesh, OutputNamedItemValueSet{}, time, true); + break; } + } + + time++; + } - })); + )); } diff --git a/src/language/utils/BuiltinFunctionEmbedder.hpp b/src/language/utils/BuiltinFunctionEmbedder.hpp index 9a77fec82e6bfa3b9496a2e600144d014753f67c..4870ab0028bc1c1bc82f13b7b4b20d5d989ecce9 100644 --- a/src/language/utils/BuiltinFunctionEmbedder.hpp +++ b/src/language/utils/BuiltinFunctionEmbedder.hpp @@ -34,11 +34,22 @@ class IBuiltinFunctionEmbedder }; template <typename FX, typename... Args> -class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder +class BuiltinFunctionEmbedder +{ + static_assert(std::is_class_v<BuiltinFunctionEmbedder<FX, Args...>>, + "wrong template parameters do not use <FX, Args...>, use <FX(Args...)>"); +}; + +template <typename T> +inline constexpr bool is_const_ref_or_non_ref = (std::is_const_v<T> and std::is_lvalue_reference_v<T>) or + (not std::is_lvalue_reference_v<T>); + +template <typename FX, typename... Args> +class BuiltinFunctionEmbedder<FX(Args...)> : public IBuiltinFunctionEmbedder { private: std::function<FX(Args...)> m_f; - using ArgsTuple = std::tuple<Args...>; + using ArgsTuple = std::tuple<std::decay_t<Args>...>; template <size_t I> PUGS_INLINE void @@ -56,8 +67,15 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder std::get<I>(t) = v_i; } else if constexpr (is_shared_ptr_v<Ti_Type>) { if constexpr (std::is_same_v<Vi_Type, EmbeddedData>) { - auto& data_handler = static_cast<const DataHandler<typename Ti_Type::element_type>&>(v_i.get()); - std::get<I>(t) = data_handler.data_ptr(); + using Ti_handeled_type = typename Ti_Type::element_type; + try { + auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i.get()); + std::get<I>(t) = data_handler.data_ptr(); + } + catch (std::bad_cast&) { + throw UnexpectedError("unexpected argument types while casting: invalid EmbeddedData type, expecting " + + demangle<DataHandler<Ti_handeled_type>>()); + } } else { throw UnexpectedError("unexpected argument types while casting: expecting EmbeddedData"); } @@ -70,20 +88,27 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder 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(); + try { + auto& data_handler = dynamic_cast<const DataHandler<Ti_handeled_type>&>(v_i[j].get()); + std::get<I>(t)[j] = data_handler.data_ptr(); + } + catch (std::bad_cast&) { + throw UnexpectedError( + "unexpected argument types while casting: invalid EmbeddedData type, expecting " + + demangle<DataHandler<Ti_handeled_type>>()); + } } } else { - throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " + - demangle<Ti_Type>()); + throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + + demangle<Ti_Type>() + '"'); } } else { - throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " + - demangle<Ti_Type>()); + throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + + demangle<Ti_Type>() + '"'); } } else { - throw UnexpectedError("Unexpected argument types while casting " + demangle<Vi_Type>() + " -> " + - demangle<Ti_Type>()); + throw UnexpectedError("unexpected argument types while casting \"" + demangle<Vi_Type>() + "\" to \"" + + demangle<Ti_Type>() + '"'); } }, v[I]); @@ -101,7 +126,14 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder PUGS_INLINE ASTNodeDataType _getOneParameterDataType(ArgsTuple& t) const { - return ast_node_data_type_from<std::decay_t<decltype(std::get<I>(t))>>; + using ArgN_T = std::decay_t<decltype(std::get<I>(t))>; + if constexpr (is_data_variant_v<ArgN_T>) { + return ast_node_data_type_from<ArgN_T>; + } else if constexpr (std::is_same_v<void, ArgN_T>) { + return ASTNodeDataType::void_t; + } else { + return ASTNodeDataType::type_id_t; + } } template <size_t... I> @@ -113,11 +145,45 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder return parameter_type_list; } + template <typename T> + PUGS_INLINE std::shared_ptr<IDataHandler> + _createHandler(std::shared_ptr<T> data) const + { + return std::make_shared<DataHandler<T>>(data); + } + + template <size_t I> + PUGS_INLINE void constexpr _check_arg() const + { + using ArgN_T = std::tuple_element_t<I, std::tuple<Args...>>; + if constexpr (std::is_lvalue_reference_v<ArgN_T>) { + static_assert(std::is_const_v<std::remove_reference_t<ArgN_T>>, + "builtin function arguments are non mutable use 'const' when passing references"); + } + + if constexpr (is_std_ptr_v<ArgN_T>) { + static_assert(std::is_const_v<typename ArgN_T::element_type>, + "builtin function arguments are non mutable. For instance use std::shared_ptr<const T>"); + } + } + + template <size_t... I> + PUGS_INLINE void constexpr _check_arg_list(std::index_sequence<I...>) const + { + (_check_arg<I>(), ...); + } + public: PUGS_INLINE ASTNodeDataType getReturnDataType() const final { - return ast_node_data_type_from<FX>; + if constexpr (is_data_variant_v<FX>) { + return ast_node_data_type_from<FX>; + } else if constexpr (std::is_same_v<void, FX>) { + return ASTNodeDataType::void_t; + } else { + return ASTNodeDataType::type_id_t; + } } PUGS_INLINE std::vector<ASTNodeDataType> @@ -136,14 +202,6 @@ 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 @@ -154,7 +212,7 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder using IndexSequence = std::make_index_sequence<N>; this->_copyFromVector(t, x, IndexSequence{}); - if constexpr (std::is_arithmetic_v<FX>) { + if constexpr (is_data_variant_v<FX>) { return {std::apply(m_f, t)}; } else if constexpr (std::is_same_v<FX, void>) { std::apply(m_f, t); @@ -164,27 +222,51 @@ class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder } } - template <typename FX2, typename... Args2> - BuiltinFunctionEmbedder(std::function<FX2(Args2...)> f) : m_f{f} + BuiltinFunctionEmbedder(std::function<FX(Args...)> f) : m_f{f} { - static_assert(std::is_same_v<FX, FX2>, "incorrect return type"); - static_assert(sizeof...(Args) == sizeof...(Args2), "invalid number of arguments"); - using Args2Tuple = std::tuple<Args2...>; - static_assert(std::is_same_v<ArgsTuple, Args2Tuple>, "invalid arguments type"); + using IndexSequence = std::make_index_sequence<std::tuple_size_v<ArgsTuple>>; + this->_check_arg_list(IndexSequence{}); + + static_assert((std::is_same_v<Args, Args> and ...)); } + + BuiltinFunctionEmbedder(const BuiltinFunctionEmbedder&) = delete; + BuiltinFunctionEmbedder(BuiltinFunctionEmbedder&&) = delete; + + ~BuiltinFunctionEmbedder() = default; +}; + +template <typename FX> +class BuiltinFunctionEmbedder<FX, void> +{ + static_assert(std::is_class_v<BuiltinFunctionEmbedder<FX, void>>, + "wrong template parameters do not use <FX, void>, use <FX(void)>"); }; template <typename FX> -class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder +class BuiltinFunctionEmbedder<FX(void)> : public IBuiltinFunctionEmbedder { private: std::function<FX(void)> m_f; + 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 ASTNodeDataType getReturnDataType() const final { - return ast_node_data_type_from<FX>; + if constexpr (is_data_variant_v<FX>) { + return ast_node_data_type_from<FX>; + } else if constexpr (std::is_same_v<void, FX>) { + return ASTNodeDataType::void_t; + } else { + return ASTNodeDataType::type_id_t; + } } PUGS_INLINE std::vector<ASTNodeDataType> @@ -199,12 +281,11 @@ class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder return 0; } - public: PUGS_INLINE DataVariant apply(const std::vector<DataVariant>&) const final { - if constexpr (std::is_arithmetic_v<FX>) { + if constexpr (is_data_variant_v<FX>) { return {m_f()}; } else if constexpr (std::is_same_v<FX, void>) { m_f(); @@ -214,7 +295,12 @@ class BuiltinFunctionEmbedder<FX, void> : public IBuiltinFunctionEmbedder } } - BuiltinFunctionEmbedder(const std::function<void(void)>& f) : m_f{f} {} + BuiltinFunctionEmbedder(std::function<FX(void)> f) : m_f{f} {} + + BuiltinFunctionEmbedder(const BuiltinFunctionEmbedder&) = delete; + BuiltinFunctionEmbedder(BuiltinFunctionEmbedder&&) = delete; + + ~BuiltinFunctionEmbedder() = default; }; #endif // BUILTIN_FUNCTION_EMBEDDER_HPP diff --git a/src/language/utils/DataVariant.hpp b/src/language/utils/DataVariant.hpp index b8d45704d08e4a8c3d6f91b22e7d3f34c5f6964f..13744172a73c2e3c54d97412cd654ae7211ad42c 100644 --- a/src/language/utils/DataVariant.hpp +++ b/src/language/utils/DataVariant.hpp @@ -4,6 +4,7 @@ #include <algebra/TinyVector.hpp> #include <language/utils/EmbeddedData.hpp> #include <language/utils/FunctionSymbolId.hpp> +#include <utils/PugsTraits.hpp> #include <iostream> #include <tuple> @@ -34,6 +35,9 @@ using DataVariant = std::variant<std::monostate, AggregateDataVariant, FunctionSymbolId>; +template <typename T, typename...> +inline constexpr bool is_data_variant_v = is_variant<T, DataVariant>::value; + std::ostream& operator<<(std::ostream& os, const DataVariant& v); class AggregateDataVariant // LCOV_EXCL_LINE diff --git a/src/utils/PugsTraits.hpp b/src/utils/PugsTraits.hpp index cb934a2ab2cf1e4d563a8703b4751d3799a753ae..52acae2bb0c80aecab29fb125604b7b869fc5f3c 100644 --- a/src/utils/PugsTraits.hpp +++ b/src/utils/PugsTraits.hpp @@ -4,6 +4,7 @@ #include <cstddef> #include <memory> #include <type_traits> +#include <variant> #include <vector> template <size_t N, typename T> @@ -83,4 +84,15 @@ inline constexpr bool is_tiny_vector_v = false; template <size_t N, typename T> inline constexpr bool is_tiny_vector_v<TinyVector<N, T>> = true; +// Traits is_tiny_vector +// helper to check if a type is part of a variant + +template <typename T, typename V> +struct is_variant; + +template <typename T, typename... ALL_T> +struct is_variant<T, std::variant<ALL_T...>> : public std::disjunction<std::is_same<T, ALL_T>...> +{ +}; + #endif // PUGS_TRAITS_HPP diff --git a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp index b9f7a9af1170c146df66456a794c7c3ace6a3eee..668a77696363a23b01c01663cf9229fa3281fd45 100644 --- a/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeBuiltinFunctionExpressionBuilder.cpp @@ -27,31 +27,27 @@ class BuiltinFunctionRegister void _populateNameBuiltinFunctionMap() { - m_name_builtin_function_map.insert( - std::make_pair("RtoR", std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return x + 1; }}))); + m_name_builtin_function_map.insert(std::make_pair("RtoR", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( + [](double x) -> double { return x + 1; }))); m_name_builtin_function_map.insert( - std::make_pair("ZtoR", std::make_shared<BuiltinFunctionEmbedder<double, int64_t>>( - std::function<double(int64_t)>{[](int64_t z) -> double { return 0.5 * z; }}))); + std::make_pair("ZtoR", std::make_shared<BuiltinFunctionEmbedder<double(int64_t)>>( + [](int64_t z) -> double { return 0.5 * z; }))); m_name_builtin_function_map.insert( - std::make_pair("NtoR", std::make_shared<BuiltinFunctionEmbedder<double, uint64_t>>( - std::function<double(uint64_t)>{[](uint64_t n) -> double { return 0.5 * n; }}))); + std::make_pair("NtoR", std::make_shared<BuiltinFunctionEmbedder<double(uint64_t)>>( + [](uint64_t n) -> double { return 0.5 * n; }))); - m_name_builtin_function_map.insert( - std::make_pair("BtoR", std::make_shared<BuiltinFunctionEmbedder<double, bool>>( - std::function<double(bool)>{[](bool b) -> double { return b; }}))); + m_name_builtin_function_map.insert(std::make_pair("BtoR", std::make_shared<BuiltinFunctionEmbedder<double(bool)>>( + [](bool b) -> double { return b; }))); m_name_builtin_function_map.insert( - std::make_pair("R2toB", - std::make_shared<BuiltinFunctionEmbedder<bool, double, double>>( - std::function<bool(double, double)>{[](double x, double y) -> bool { return x > y; }}))); + std::make_pair("R2toB", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>( + [](double x, double y) -> bool { return x > y; }))); m_name_builtin_function_map.insert( - std::make_pair("StoB", - std::make_shared<BuiltinFunctionEmbedder<bool, std::string>>( - std::function<bool(std::string)>{[](const std::string& s) -> bool { return s.size() > 0; }}))); + std::make_pair("StoB", std::make_shared<BuiltinFunctionEmbedder<bool(std::string)>>( + [](const std::string& s) -> bool { return s.size() > 0; }))); } public: diff --git a/tests/test_BuiltinFunctionEmbedder.cpp b/tests/test_BuiltinFunctionEmbedder.cpp index f5172381c23409e416df26221f969f23bb40d2e5..052ac6fe06b8ea4c117fcdd747678c386c56cf9f 100644 --- a/tests/test_BuiltinFunctionEmbedder.cpp +++ b/tests/test_BuiltinFunctionEmbedder.cpp @@ -10,8 +10,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") SECTION("math") { - BuiltinFunctionEmbedder<double, double> embedded_sin{ - std::function<double(double)>{[](double x) -> double { return std::sin(x); }}}; + BuiltinFunctionEmbedder<double(double)> embedded_sin{[](double x) -> double { return std::sin(x); }}; double arg = 2; DataVariant arg_variant = arg; @@ -27,9 +26,9 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") SECTION("multiple variant args") { - std::function<bool(double, uint64_t)> c = [](double x, uint64_t i) -> bool { return x > i; }; + std::function c = [](double x, uint64_t i) -> bool { return x > i; }; - BuiltinFunctionEmbedder<bool, double, uint64_t> embedded_c{c}; + BuiltinFunctionEmbedder<bool(double, uint64_t)> embedded_c{c}; double d_arg = 2.3; uint64_t i_arg = 3; @@ -48,12 +47,12 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") REQUIRE(embedded_c.getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t); } - SECTION("IBuiltinFunctionEmbedder") + SECTION("POD BuiltinFunctionEmbedder") { - std::function<bool(double, uint64_t)> c = [](double x, uint64_t i) -> bool { return x > i; }; + std::function c = [](double x, uint64_t i) -> bool { return x > i; }; std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = - std::make_unique<BuiltinFunctionEmbedder<bool, double, uint64_t>>(c); + std::make_unique<BuiltinFunctionEmbedder<bool(double, uint64_t)>>(c); double d_arg = 2.3; uint64_t i_arg = 3; @@ -72,11 +71,196 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]") REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::unsigned_int_t); } + SECTION("void(double) BuiltinFunctionEmbedder") + { + double y = 1; + + std::function add_to_y = [&](double x) -> void { y += x; }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<void(double)>>(add_to_y); + + double x = 0.5; + i_embedded_c->apply(std::vector<DataVariant>{x}); + REQUIRE(y == 1.5); + REQUIRE(i_embedded_c->numberOfParameters() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1); + + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t); + + REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}), + "unexpected error: unexpected argument types while casting \"" + + demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<double>() + '"'); + } + + SECTION("EmbeddedData(double, double) BuiltinFunctionEmbedder") + { + std::function sum = [&](double x, double y) -> std::shared_ptr<double> { return std::make_shared<double>(x + y); }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(double, double)>>(sum); + + // using 4ul enforces cast test + REQUIRE(i_embedded_c->numberOfParameters() == 2); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 2); + REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::double_t); + REQUIRE(i_embedded_c->getParameterDataTypes()[1] == ASTNodeDataType::double_t); + + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::type_id_t); + + DataVariant result = i_embedded_c->apply(std::vector<DataVariant>{2.3, 4ul}); + EmbeddedData embedded_data = std::get<EmbeddedData>(result); + + const IDataHandler& handled_data = embedded_data.get(); + const DataHandler<double>& data = dynamic_cast<const DataHandler<double>&>(handled_data); + REQUIRE(*data.data_ptr() == (2.3 + 4ul)); + } + + SECTION("double(std::shared_ptr<double>) BuiltinFunctionEmbedder") + { + std::function abs = [&](std::shared_ptr<const double> x) -> double { return std::abs(*x); }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<double(std::shared_ptr<const double>)>>(abs); + + REQUIRE(i_embedded_c->numberOfParameters() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::type_id_t); + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t); + + EmbeddedData data(std::make_shared<DataHandler<const double>>(std::make_shared<const double>(-2.3))); + DataVariant result = i_embedded_c->apply({data}); + + REQUIRE(std::get<double>(result) == 2.3); + + REQUIRE_THROWS_WITH(i_embedded_c->apply({2.3}), + "unexpected error: unexpected argument types while casting: expecting EmbeddedData"); + + EmbeddedData wrong_embedded_data_type( + std::make_shared<DataHandler<const TinyVector<2>>>(std::make_shared<const TinyVector<2>>(-2, -2))); + REQUIRE_THROWS_WITH(i_embedded_c->apply({wrong_embedded_data_type}), + "unexpected error: unexpected argument types while casting: " + "invalid EmbeddedData type, expecting " + + demangle<DataHandler<const double>>()); + } + + SECTION("uint64_t(std::vector<uint64_t>) BuiltinFunctionEmbedder") + { + std::function sum = [&](const std::vector<uint64_t>& x) -> uint64_t { + uint64_t sum = 0; + for (size_t i = 0; i < x.size(); ++i) { + sum += x[i]; + } + return sum; + }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<uint64_t>&)>>(sum); + + REQUIRE(i_embedded_c->numberOfParameters() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::tuple_t); + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t); + + REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul}})) == 6); + REQUIRE(std::get<uint64_t>(i_embedded_c->apply({std::vector{1ul, 2ul, 3ul, 4ul}})) == 10); + + REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector{1.2, 2.3, 3.1, 4.4}}), + "unexpected error: unexpected argument types while casting \"" + + demangle<std::vector<double>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"'); + + REQUIRE_THROWS_WITH(i_embedded_c->apply({std::vector<EmbeddedData>{}}), + "unexpected error: unexpected argument types while casting \"" + + demangle<std::vector<EmbeddedData>>() + "\" to \"" + demangle<std::vector<uint64_t>>() + '"'); + } + + SECTION("uint64_t(std::vector<EmbeddedData>) BuiltinFunctionEmbedder") + { + std::function sum = [&](const std::vector<std::shared_ptr<uint64_t>>& x) -> uint64_t { + uint64_t sum = 0; + for (size_t i = 0; i < x.size(); ++i) { + sum += *x[i]; + } + return sum; + }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<uint64_t>>&)>>(sum); + + REQUIRE(i_embedded_c->numberOfParameters() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1); + REQUIRE(i_embedded_c->getParameterDataTypes()[0] == ASTNodeDataType::type_id_t); + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::unsigned_int_t); + + std::vector<EmbeddedData> embedded_data; + REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 0); + embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(1))); + embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(2))); + embedded_data.emplace_back(std::make_shared<DataHandler<uint64_t>>(std::make_shared<uint64_t>(3))); + + REQUIRE(std::get<uint64_t>(i_embedded_c->apply({embedded_data})) == 6); + + embedded_data.emplace_back(std::make_shared<DataHandler<double>>(std::make_shared<double>(4))); + REQUIRE_THROWS_WITH(i_embedded_c->apply({embedded_data}), + "unexpected error: unexpected argument types while casting: invalid" + " EmbeddedData type, expecting " + + demangle<DataHandler<uint64_t>>()); + + REQUIRE_THROWS_WITH(i_embedded_c->apply({TinyVector<1>{13}}), + "unexpected error: unexpected argument types while casting \"" + demangle<TinyVector<1>>() + + "\" to \"" + demangle<std::vector<std::shared_ptr<uint64_t>>>() + '"'); + } + + SECTION("double(void) BuiltinFunctionEmbedder") + { + std::function c = [](void) -> double { return 1.5; }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<double(void)>>(c); + + REQUIRE(1.5 == c()); + REQUIRE(std::get<double>(i_embedded_c->apply(std::vector<DataVariant>{})) == c()); + REQUIRE(i_embedded_c->numberOfParameters() == 0); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0); + + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t); + } + + SECTION("void(void) BuiltinFunctionEmbedder") + { + std::function c = [](void) -> void {}; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<BuiltinFunctionEmbedder<void(void)>>(c); + + REQUIRE_NOTHROW(std::get<std::monostate>(i_embedded_c->apply(std::vector<DataVariant>{}))); + REQUIRE(i_embedded_c->numberOfParameters() == 0); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0); + + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::void_t); + } + + SECTION("EmbeddedData(void) BuiltinFunctionEmbedder") + { + std::function c = [](void) -> std::shared_ptr<double> { return std::make_shared<double>(1.5); }; + + std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = + std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(void)>>(c); + + REQUIRE(i_embedded_c->numberOfParameters() == 0); + REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0); + + REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::type_id_t); + + const auto embedded_data = std::get<EmbeddedData>(i_embedded_c->apply(std::vector<DataVariant>{})); + const IDataHandler& handled_data = embedded_data.get(); + const DataHandler<double>& data = dynamic_cast<const DataHandler<double>&>(handled_data); + REQUIRE(*data.data_ptr() == 1.5); + } + SECTION("error") { - std::function<bool(double)> positive = [](double x) -> bool { return x >= 0; }; + std::function positive = [](double x) -> bool { return x >= 0; }; - BuiltinFunctionEmbedder<bool, double> embedded_positive{positive}; + BuiltinFunctionEmbedder<bool(double)> embedded_positive{positive}; std::string arg = std::string{"2.3"}; diff --git a/tests/test_BuiltinFunctionEmbedderTable.cpp b/tests/test_BuiltinFunctionEmbedderTable.cpp index 09b9d7c1f7beafa7ef26cfd288f4a8746b530e0c..5cc254f190a07c6162053ea522627ac0eeb49586 100644 --- a/tests/test_BuiltinFunctionEmbedderTable.cpp +++ b/tests/test_BuiltinFunctionEmbedderTable.cpp @@ -13,15 +13,14 @@ TEST_CASE("BuiltinFunctionEmbedderTable", "[language]") REQUIRE(table.size() == 0); - std::shared_ptr<IBuiltinFunctionEmbedder> embedded_sin = std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sin(x); }}); + std::shared_ptr<IBuiltinFunctionEmbedder> embedded_sin = + std::make_shared<BuiltinFunctionEmbedder<double(double)>>([](double x) -> double { return std::sin(x); }); table.add(embedded_sin); REQUIRE(table.size() == 1); std::shared_ptr<IBuiltinFunctionEmbedder> embedded_greater = - std::make_shared<BuiltinFunctionEmbedder<bool, int, int>>( - std::function<bool(int, int)>{[](int i, int j) -> bool { return i > j; }}); + std::make_shared<BuiltinFunctionEmbedder<bool(int, int)>>([](int i, int j) -> bool { return i > j; }); table.add(embedded_greater); REQUIRE(table.size() == 2); diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp index 7eadfc31426ac7cc7154a60d1d0d4c6a4e8649c5..bb80c4999781e59f3585f1ff64eba3ac3b71bcac 100644 --- a/tests/test_SymbolTable.cpp +++ b/tests/test_SymbolTable.cpp @@ -213,8 +213,8 @@ TEST_CASE("SymbolTable", "[language]") const auto& const_builtin_function_table = static_cast<const SymbolTable&>(*root_st).builtinFunctionEmbedderTable(); REQUIRE(const_builtin_function_table.size() == 0); - builtin_function_table.add(std::make_shared<BuiltinFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double) -> double { return 0; }})); + builtin_function_table.add( + std::make_shared<BuiltinFunctionEmbedder<double(double)>>([](double) -> double { return 0; })); REQUIRE(builtin_function_table.size() == 1); REQUIRE(const_builtin_function_table.size() == 1);