From fcca453223c6d22f7543253d01ba3b20be8ef662 Mon Sep 17 00:00:00 2001 From: Viktor Rennert Date: Tue, 26 Jan 2016 00:06:57 +0100 Subject: [PATCH 1/2] Added initializer_list conversion as possible function call argument or return type. --- .../dispatchkit/type_conversions.hpp | 61 ++++++++++++++++++- .../chaiscript/language/chaiscript_eval.hpp | 1 + unittests/compiled_tests.cpp | 42 +++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 602d4d9..fe181d0 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -310,7 +310,48 @@ namespace chaiscript private: Callable m_func; }; - +#ifndef CHAISCRIPT_MSVC_12 + //http://stackoverflow.com/questions/18895583/convert-a-vectort-to-initializer-listt + constexpr size_t DEFAULT_MAX_LENGTH = 128; + + template struct backingValue { static V value; }; + template V backingValue::value; + + template struct backingList { static std::initializer_list list; }; + template + std::initializer_list backingList::list = { (Vcount)backingValue::value... }; + + template + static typename std::enable_if< sizeof...(Vcount) >= maxLength, + std::initializer_list >::type generate_n(It begin, It end, It current) + { + throw std::length_error("More than maxLength elements in range."); + } + + template + static typename std::enable_if< sizeof...(Vcount) < maxLength, + std::initializer_list >::type generate_n(It begin, It end, It current) + { + if (current != end) + { + return generate_n(begin, end, ++current); + } + + current = begin; + for (auto it = backingList::list.begin(); + it != backingList::list.end(); + ++current, ++it) + *const_cast(&*it) = *current; + + return backingList::list; + } + + template + std::initializer_list range_to_initializer_list(It begin, It end) + { + return detail::generate_n(begin, end, begin); + } +#endif } class Type_Conversions @@ -593,6 +634,24 @@ namespace chaiscript return chaiscript::make_shared>(user_type>(), user_type(), func); } +#ifndef CHAISCRIPT_MSVC_12 + template + Type_Conversion initializer_list_conversion() { + auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { + const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); + + std::vector vec; + vec.reserve(from_vec.size()); + for (const auto &bv : from_vec) { + vec.push_back(detail::Cast_Helper::cast(bv, nullptr)); + } + + return Boxed_Value(detail::range_to_initializer_list(vec.begin(), vec.end())); + }; + auto ret = chaiscript::make_shared>(user_type>(), user_type(), func); + return ret; + } +#endif } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index aa01de9..c3391b5 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1005,6 +1005,7 @@ namespace chaiscript try { std::vector vec; if (!children.empty()) { + vec.reserve(children[0]->children.size()); for (const auto &child : children[0]->children) { auto obj = child->eval(t_ss); if (!obj.is_return_value()) { diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 9a9a4a5..2da054a 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -913,3 +913,45 @@ TEST_CASE("Return of converted type from script") chai.add(chaiscript::user_type(), "Returned_Converted_Config"); } +#ifndef CHAISCRIPT_MSVC_12 +TEST_CASE("Return initializer_list") +{ + chaiscript::ChaiScript chai; + + chai.add(chaiscript::initializer_list_conversion>()); + + auto initlist = chai.eval>(R"( + return [11, 22, 33, 44]; + )"); + + CHECK(initlist.size() == 4); + CHECK(typeid(decltype(initlist)) == typeid(std::initializer_list)); +} + +bool initializer_list_of_enums_interface(std::initializer_list initlist) { + return initlist.size() == 3 && *initlist.begin() == THREE; +} + +TEST_CASE("Call from script with initializer_list argument") +{ + chaiscript::ChaiScript chai; + + chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module()); + chaiscript::utility::add_class(*m, + "Utility_Test_Numbers", + { { ONE, "ONE" }, + { TWO, "TWO" }, + { THREE, "THREE" } + } + ); + chai.add(m); + + chai.add(chaiscript::initializer_list_conversion>()); + chai.add(chaiscript::fun(&initializer_list_of_enums_interface), "initializer_list_of_enums_interface"); + + auto interface_result = chai.eval("return initializer_list_of_enums_interface([THREE, TWO, ONE]);"); + + CHECK(interface_result == true); +} +#endif + From af1eba1b0e9b4e672199f68f5c33f695f3c1905f Mon Sep 17 00:00:00 2001 From: Viktor Rennert Date: Tue, 26 Jan 2016 18:36:45 +0100 Subject: [PATCH 2/2] Added type fix for gcc/clang and tiny formating fixes. --- include/chaiscript/dispatchkit/type_conversions.hpp | 10 ++++++---- unittests/compiled_tests.cpp | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index fe181d0..962d7f3 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -623,7 +623,7 @@ namespace chaiscript const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); To vec; - + vec.reserve(from_vec.size()); for (const Boxed_Value &bv : from_vec) { vec.push_back(detail::Cast_Helper::cast(bv, nullptr)); } @@ -636,13 +636,15 @@ namespace chaiscript #ifndef CHAISCRIPT_MSVC_12 template - Type_Conversion initializer_list_conversion() { + Type_Conversion initializer_list_conversion() + { auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); - std::vector vec; + std::vector vec; vec.reserve(from_vec.size()); - for (const auto &bv : from_vec) { + for (const auto &bv : from_vec) + { vec.push_back(detail::Cast_Helper::cast(bv, nullptr)); } diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 2da054a..7c4d769 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -928,7 +928,8 @@ TEST_CASE("Return initializer_list") CHECK(typeid(decltype(initlist)) == typeid(std::initializer_list)); } -bool initializer_list_of_enums_interface(std::initializer_list initlist) { +bool initializer_list_of_enums_interface(std::initializer_list initlist) +{ return initlist.size() == 3 && *initlist.begin() == THREE; }