From 71245aa70306a24eebc3c7c6801b52ee482e929a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 17 Apr 2015 20:02:09 -0600 Subject: [PATCH 1/2] Add array type support #167 --- include/chaiscript/dispatchkit/bootstrap.hpp | 37 +++++++++++++++++++ .../dispatchkit/boxed_cast_helper.hpp | 3 +- .../chaiscript/language/chaiscript_eval.hpp | 2 +- .../chaiscript/language/chaiscript_parser.hpp | 4 +- src/test_module.cpp | 10 +++++ unittests/array_types.chai | 12 ++++++ 6 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 unittests/array_types.chai diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 32c11c15..4ce7e3e1 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -52,6 +52,43 @@ namespace chaiscript } } + template::value>::type > + ModulePtr array(const std::string &type, ModulePtr m = ModulePtr(new Module())) + { + typedef typename std::remove_extent::type ReturnType; + const auto extent = std::extent::value; + m->add(user_type(), type); + m->add(fun( + [extent](T& t, size_t index)->ReturnType &{ + if (extent > 0 && index >= extent) { + throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); + } else { + return t[index]; + } + } + ), "[]" + ); + + m->add(fun( + [extent](const T &t, size_t index)->const ReturnType &{ + if (extent > 0 && index >= extent) { + throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent)); + } else { + return t[index]; + } + } + ), "[]" + ); + + m->add(fun( + [extent](const T &) { + return extent; + }), "size"); + + + return m; + } + /// \brief Adds a copy constructor for the given type to the given Model /// \param[in] type The name of the type. The copy constructor will be named "type". /// \param[in,out] m The Module to add the copy constructor to diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index c218d30f..a2a13318 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -40,7 +40,8 @@ namespace chaiscript { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { - return *(static_cast(throw_if_null(ob.get_const_ptr()))); + auto p = throw_if_null(ob.get_const_ptr()); + return std::cref(*static_cast(p)); } else { throw chaiscript::detail::exception::bad_any_cast(); } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 59e09baa..8a0f897a 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -712,7 +712,7 @@ namespace chaiscript fpp.save_params(params); - std::string fun_name = [&](){ + std::string fun_name = [&]()->std::string{ if ((this->children[i]->identifier == AST_Node_Type::Fun_Call) || (this->children[i]->identifier == AST_Node_Type::Array_Call)) { return this->children[i]->children[0]->text; } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 73a33e20..66ea3f4e 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -617,7 +617,7 @@ namespace chaiscript } - const size_t size = [&](){ + const size_t size = [&]()->size_t{ if (longlong_) { return sizeof(int64_t) * 8; @@ -800,7 +800,7 @@ namespace chaiscript const auto prev_line = m_line; if (Id_()) { m_match_stack.push_back(std::make_shared( - [&](){ + [&]()->std::string{ if (*start == '`') { //Id Literal return std::string(start+1, m_input_pos-1); diff --git a/src/test_module.cpp b/src/test_module.cpp index b1618175..56097755 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -1,5 +1,6 @@ #include +#include #include @@ -21,6 +22,8 @@ class TestBaseType int val; const int const_val; + int mdarray[2][3][5]; + private: TestBaseType &operator=(const TestBaseType &); }; @@ -159,6 +162,13 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); + // Array types + m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray"); + m->add(chaiscript::bootstrap::array("IntArray_2_3_5")); + m->add(chaiscript::bootstrap::array("IntArray_3_5")); + m->add(chaiscript::bootstrap::array("IntArray_5")); + // end array types + m->add(chaiscript::fun(&get_new_int), "get_new_int"); diff --git a/unittests/array_types.chai b/unittests/array_types.chai new file mode 100644 index 00000000..f6c77919 --- /dev/null +++ b/unittests/array_types.chai @@ -0,0 +1,12 @@ +load_module("test_module") + +auto t0 = TestBaseType() + +assert_true(t0.mdarray.size() == 2) +assert_true(t0.mdarray[0].size() == 3) +assert_true(t0.mdarray[0][0].size() == 5) + +t0.mdarray[1][2][4] = 15; + +assert_true(t0.mdarray[1][2][4] == 15) + From db348992252917a5dd3dd17d570b71abd2b67423 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 18 Apr 2015 20:51:45 -0600 Subject: [PATCH 2/2] Address msvc issues with #167 #165 The best we can get it down to is 2 moves in MSVC, it does not elide the moves/copies as well as GCC and Clang do It's not possible for us to support registering of array types in MSVC12, but we can in MSVC14 with the latest release of the compiler. --- include/chaiscript/dispatchkit/proxy_functions.hpp | 11 ++++++++++- src/test_module.cpp | 4 ++++ unittests/object_copy_count_test.cpp | 9 +++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 1f71ad54..db853a03 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -490,8 +490,17 @@ namespace chaiscript std::vector types = t_f->get_param_types(); assert(types.size() == t_args.size() + 1); +#ifdef CHAISCRIPT_MSVC_12 +#pragma warning(push) +#pragma warning(disable : 6011) +#endif + // this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14 std::vector retval{types[0]}; - for (size_t i = 0; i < types.size()-1; ++i) +#ifdef CHAISCRIPT_MSVC_12 +#pragma warning(pop) +#endif + + for (size_t i = 0; i < types.size() - 1; ++i) { if (t_args[i].get_type_info() == chaiscript::detail::Get_Type_Info::get()) { diff --git a/src/test_module.cpp b/src/test_module.cpp index 56097755..293562ca 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -162,12 +162,16 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); +#ifndef CHAISCRIPT_MSVC_12 + // we cannot support these in MSVC_12 because of a bug in the implementation of + // std::reference_wrapper // Array types m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray"); m->add(chaiscript::bootstrap::array("IntArray_2_3_5")); m->add(chaiscript::bootstrap::array("IntArray_3_5")); m->add(chaiscript::bootstrap::array("IntArray_5")); // end array types +#endif m->add(chaiscript::fun(&get_new_int), "get_new_int"); diff --git a/unittests/object_copy_count_test.cpp b/unittests/object_copy_count_test.cpp index 8b75d3e6..41192c10 100644 --- a/unittests/object_copy_count_test.cpp +++ b/unittests/object_copy_count_test.cpp @@ -71,10 +71,19 @@ int main() chai.eval(" { auto i = create(); } "); +#ifdef CHAISCRIPT_MSVC + if (Test::destructcount() == 3 && Test::copycount() == 0 && Test::movecount() == 2 && Test::constructcount() == 1) + { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } +#else if (Test::destructcount() == 2 && Test::copycount() == 0 && Test::movecount() == 1 && Test::constructcount() == 1) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } +#endif }