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

Fix return type value checking for BuiltinFunctionEmbedder

Actually, in the case of single returned value (non-tuple), the
constness of data type in shared_ptr's was not checked at compile
time.
parent 0f70cfb8
No related branches found
No related tags found
1 merge request!162Fix return type value checking for BuiltinFunctionEmbedder
......@@ -40,19 +40,25 @@ template <typename FX, typename... Args>
class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder
{
protected:
template <size_t I>
PUGS_INLINE void constexpr _check_value() const
template <typename ValueT>
PUGS_INLINE void constexpr _check_value_type() const
{
using ValueN_T = std::tuple_element_t<I, FX>;
if constexpr (std::is_lvalue_reference_v<ValueN_T>) {
static_assert(std::is_const_v<std::remove_reference_t<ValueN_T>>,
if constexpr (std::is_lvalue_reference_v<ValueT>) {
static_assert(std::is_const_v<std::remove_reference_t<ValueT>>,
"builtin function return values are non mutable use 'const' when passing references");
}
if constexpr (is_std_ptr_v<ValueN_T>) {
static_assert(std::is_const_v<typename ValueN_T::element_type>,
if constexpr (is_std_ptr_v<ValueT>) {
static_assert(std::is_const_v<typename ValueT::element_type>,
"builtin function return values are non mutable. For instance use std::shared_ptr<const T>");
}
}
template <size_t I>
PUGS_INLINE void constexpr _check_value() const
{
using ValueN_T = std::tuple_element_t<I, FX>;
_check_value_type<ValueN_T>();
if (ast_node_data_type_from<std::remove_cv_t<std::remove_reference_t<ValueN_T>>> == ASTNodeDataType::undefined_t) {
throw std::invalid_argument(std::string{"cannot bind C++ to language.\nnote: return value number "} +
......@@ -79,6 +85,7 @@ class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder
std::string{"cannot bind C++ to language.\nnote: return value has no associated language type: "} +
demangle<FX>());
}
_check_value_type<FX>();
}
}
......@@ -99,8 +106,7 @@ class BuiltinFunctionEmbedderBase<FX(Args...)> : public IBuiltinFunctionEmbedder
}
template <size_t... I>
PUGS_INLINE std::vector<std::shared_ptr<const ASTNodeDataType>>
_getCompoundDataTypes(std::index_sequence<I...>) const
PUGS_INLINE std::vector<std::shared_ptr<const ASTNodeDataType>> _getCompoundDataTypes(std::index_sequence<I...>) const
{
std::vector<std::shared_ptr<const ASTNodeDataType>> compound_type_list;
(compound_type_list.push_back(std::make_shared<ASTNodeDataType>(this->_getOneElementDataType<FX, I>())), ...);
......@@ -266,8 +272,7 @@ class BuiltinFunctionEmbedder<FX(Args...)> : public BuiltinFunctionEmbedderBase<
}
template <size_t... I>
PUGS_INLINE std::vector<ASTNodeDataType>
_getParameterDataTypes(std::index_sequence<I...>) const
PUGS_INLINE std::vector<ASTNodeDataType> _getParameterDataTypes(std::index_sequence<I...>) const
{
std::vector<ASTNodeDataType> parameter_type_list;
(parameter_type_list.push_back(this->template _getOneElementDataType<ArgsTuple, I>()), ...);
......
......@@ -10,12 +10,8 @@ inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> =
ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_double");
template <>
inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<double>> =
ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_double");
template <>
inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<uint64_t>> =
ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_uint64_t");
inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const uint64_t>> =
ASTNodeDataType::build<ASTNodeDataType::type_id_t>("shared_const_uint64_t");
TEST_CASE("BuiltinFunctionEmbedder", "[language]")
{
......@@ -177,7 +173,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
REQUIRE(*data.data_ptr() == (2.3 + 4ul));
}
SECTION("double(std::shared_ptr<double>) BuiltinFunctionEmbedder")
SECTION("double(std::shared_ptr<const double>) BuiltinFunctionEmbedder")
{
std::function abs = [&](std::shared_ptr<const double> x) -> double { return std::abs(*x); };
......@@ -237,7 +233,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
SECTION("uint64_t(std::vector<EmbeddedData>) BuiltinFunctionEmbedder")
{
std::function sum = [&](const std::vector<std::shared_ptr<uint64_t>>& x) -> uint64_t {
std::function sum = [&](const std::vector<std::shared_ptr<const uint64_t>>& x) -> uint64_t {
uint64_t sum = 0;
for (size_t i = 0; i < x.size(); ++i) {
sum += *x[i];
......@@ -246,7 +242,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
};
std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<uint64_t>>&)>>(sum);
std::make_unique<BuiltinFunctionEmbedder<uint64_t(const std::vector<std::shared_ptr<const uint64_t>>&)>>(sum);
REQUIRE(i_embedded_c->numberOfParameters() == 1);
REQUIRE(i_embedded_c->getParameterDataTypes().size() == 1);
......@@ -255,21 +251,21 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
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)));
embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const uint64_t>(1)));
embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const uint64_t>(2)));
embedded_data.emplace_back(std::make_shared<DataHandler<const uint64_t>>(std::make_shared<const 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)));
embedded_data.emplace_back(std::make_shared<DataHandler<const double>>(std::make_shared<const 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>>());
demangle<DataHandler<const 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>>>() + '"');
"\" to \"" + demangle<std::vector<std::shared_ptr<const uint64_t>>>() + '"');
}
SECTION("double(void) BuiltinFunctionEmbedder")
......@@ -286,9 +282,9 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
REQUIRE(i_embedded_c->getReturnDataType() == ASTNodeDataType::double_t);
}
SECTION("R*R -> R*R^2*shared_double BuiltinFunctionEmbedder")
SECTION("R*R -> R*R^2*shared_const_double BuiltinFunctionEmbedder")
{
std::function c = [](double a, double b) -> std::tuple<double, TinyVector<2>, std::shared_ptr<double>> {
std::function c = [](double a, double b) -> std::tuple<double, TinyVector<2>, std::shared_ptr<const double>> {
return std::make_tuple(a + b, TinyVector<2>{b, -a}, std::make_shared<double>(a - b));
};
......@@ -311,15 +307,15 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
REQUIRE(*data_type.contentTypeList()[0] == ASTNodeDataType::double_t);
REQUIRE(*data_type.contentTypeList()[1] == ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<double>>);
REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<const double>>);
}
SECTION("void -> N*R*shared_double BuiltinFunctionEmbedder")
SECTION("void -> N*R*shared_const_double BuiltinFunctionEmbedder")
{
std::function c = [](void) -> std::tuple<uint64_t, double, std::shared_ptr<double>> {
std::function c = [](void) -> std::tuple<uint64_t, double, std::shared_ptr<const double>> {
uint64_t a = 1;
double b = 3.5;
return std::make_tuple(a, b, std::make_shared<double>(a + b));
return std::make_tuple(a, b, std::make_shared<const double>(a + b));
};
std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
......@@ -357,19 +353,19 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
SECTION("EmbeddedData(void) BuiltinFunctionEmbedder")
{
std::function c = [](void) -> std::shared_ptr<double> { return std::make_shared<double>(1.5); };
std::function c = [](void) -> std::shared_ptr<const double> { return std::make_shared<const double>(1.5); };
std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<double>(void)>>(c);
std::make_unique<BuiltinFunctionEmbedder<std::shared_ptr<const double>(void)>>(c);
REQUIRE(i_embedded_c->numberOfParameters() == 0);
REQUIRE(i_embedded_c->getParameterDataTypes().size() == 0);
REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<double>>);
REQUIRE(i_embedded_c->getReturnDataType() == ast_node_data_type_from<std::shared_ptr<const double>>);
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);
const DataHandler<const double>& data = dynamic_cast<const DataHandler<const double>&>(handled_data);
REQUIRE(*data.data_ptr() == 1.5);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment