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 32c11c1..4ce7e3e 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 c218d30..a2a1331 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 59e09ba..8a0f897 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 73a33e2..66ea3f4 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 b161817..5609775 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 0000000..f6c7791 --- /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 1f71ad5..db853a0 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 5609775..293562c 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 8b75d3e..41192c1 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 }