From ef92b6619e51d8e0f155207bb86b541f11ff16c6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 6 May 2015 14:18:28 -0600 Subject: [PATCH 001/116] Increment develop to 5.7.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f842591..9cb63dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 7) -set(CPACK_PACKAGE_VERSION_PATCH 0) +set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") From c21c21dfda816cde179e7e23e50780919242a6f3 Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Fri, 8 May 2015 15:57:59 +0200 Subject: [PATCH 002/116] Fixed minor typos in cheatsheet --- cheatsheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index 8ec408a..16bed0a 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -152,7 +152,7 @@ p(5, 6); // calls chaiscript's '+' function, returning 11 ``` ``` -auto p = chai.eval>(fun(x,y) { to_string(x) + to_string(y); }); +auto p = chai.eval>("fun(x,y) { to_string(x) + to_string(y); }"); p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++ ``` @@ -183,7 +183,7 @@ var m = ["a":1, "b":2]; // map of string:value pairs ``` Floating point values default to `double` type and integers default to `int` type. All C++ suffixes -such as `f`, `ll`, `u` as well as scientific notion is supported +such as `f`, `ll`, `u` as well as scientific notation are supported ``` 1.0 // double From f35c2fdb033b75a6a6c0849f96f9d39d798aaea1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 8 May 2015 14:12:51 -0600 Subject: [PATCH 003/116] Update readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index f4446e7..cc3af26 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ -Master Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=master)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master) +Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=master)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master) -Develop Status: [![Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop) +Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop) ChaiScript From 9da9012701df40542a45c08e7b2f7b89d2694112 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 13 May 2015 06:20:25 -0600 Subject: [PATCH 004/116] Fix version number mismatch --- include/chaiscript/chaiscript_defines.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 6bfa3e7..8e45977 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -61,7 +61,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 7; - static const int version_patch = 0; + static const int version_patch = 1; template inline std::shared_ptr make_shared(Arg && ... arg) From dec88db26cd3e6d9fc31eaa6ca6ef523f39c2a0c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 19 May 2015 10:55:38 -0600 Subject: [PATCH 005/116] Minor efficiency improvement by pre sizing match stack --- include/chaiscript/language/chaiscript_common.hpp | 4 ++-- include/chaiscript/language/chaiscript_parser.hpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index d2a5e6f..8498f88 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -470,8 +470,8 @@ namespace chaiscript oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n'; - for (size_t j = 0; j < this->children.size(); ++j) { - oss << this->children[j]->to_string(t_prepend + " "); + for (auto & elem : this->children) { + oss << elem->to_string(t_prepend + " "); } return oss.str(); } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 5936713..1fdc4f5 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -67,6 +67,7 @@ namespace chaiscript m_multiline_comment_end("*/"), m_singleline_comment("//") { + m_match_stack.reserve(2); setup_operators(); } From 5fa44d5eef388206d08c18c4ce1732eb5dcc56dd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 19 May 2015 13:47:34 -0600 Subject: [PATCH 006/116] Automatically deduce types of lambda for fun() --- include/chaiscript/dispatchkit/bootstrap.hpp | 10 ++--- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 37 +++++++++---------- .../dispatchkit/register_function.hpp | 20 ++++++++++ .../chaiscript/language/chaiscript_engine.hpp | 6 +-- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 291a75f..9a87c8b 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -57,7 +57,7 @@ namespace chaiscript typedef typename std::remove_extent::type ReturnType; const auto extent = std::extent::value; m->add(user_type(), type); - m->add(fun( + 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)); @@ -68,7 +68,7 @@ namespace chaiscript ), "[]" ); - m->add(fun( + 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)); @@ -79,7 +79,7 @@ namespace chaiscript ), "[]" ); - m->add(fun( + m->add(fun( [extent](const T &) { return extent; }), "size"); @@ -465,7 +465,7 @@ namespace chaiscript operators::assign(m); operators::equal(m); - m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string"); + m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string"); m->add(fun(&Bootstrap::bool_to_string), "to_string"); m->add(fun(&unknown_assign), "="); m->add(fun(&throw_exception), "throw"); @@ -503,7 +503,7 @@ namespace chaiscript m->add(fun(&ptr_assign::type>), "="); m->add(fun(&ptr_assign::type>), "="); m->add(chaiscript::base_class()); - m->add(fun &)>( + m->add(fun( [](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr &t_rhs) { t_lhs.assign(t_rhs); } diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 260dc99..ad31f6b 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -252,7 +252,7 @@ namespace chaiscript fun(std::function (std::mem_fn(static_cast(&ContainerType::at)))), "[]"); m->add( - fun( + fun( [](const ContainerType *c, int index) -> typename ContainerType::const_reference { return c->at(index); }), "[]"); @@ -277,9 +277,9 @@ namespace chaiscript template ModulePtr container_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) { - m->add(fun([](const ContainerType *a) { return a->size(); } ), "size"); - m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); - m->add(fun([](ContainerType *a) { a->clear(); } ), "clear"); + m->add(fun([](const ContainerType *a) { return a->size(); } ), "size"); + m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); + m->add(fun([](ContainerType *a) { a->clear(); } ), "clear"); return m; } @@ -547,23 +547,20 @@ namespace chaiscript }()); - typedef std::function find_func; + m->add(fun([](const String *s, const String &f, size_t pos) { return s->find(f, pos); } ), "find"); + m->add(fun([](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ), "rfind"); + m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ), "find_first_of"); + m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of"); + m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of"); + m->add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of"); + m->add(fun([](String *s) { s->clear(); } ), "clear"); + m->add(fun([](const String *s) { return s->empty(); } ), "empty"); + m->add(fun([](const String *s) { return s->size(); } ), "size"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find(f, pos); } )), "find"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->rfind(f, pos); } ) ), "rfind"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_of(f, pos); } ) ), "find_first_of"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ) ), "find_last_of"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ) ), "find_last_not_of"); - m->add(fun(find_func( [](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ) ), "find_first_not_of"); - - m->add(fun( std::function( [](String *s) { return s->clear(); } ) ), "clear"); - m->add(fun( std::function( [](const String *s) { return s->empty(); } ) ), "empty"); - m->add(fun( std::function( [](const String *s) { return s->size(); } ) ), "size"); - - m->add(fun( std::function( [](const String *s) { return s->c_str(); } ) ), "c_str"); - m->add(fun( std::function( [](const String *s) { return s->data(); } ) ), "data"); - m->add(fun( std::function( [](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ) ), "substr"); + m->add(fun([](const String *s) { return s->c_str(); } ), "c_str"); + m->add(fun([](const String *s) { return s->data(); } ), "data"); + m->add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr"); return m; } @@ -577,7 +574,7 @@ namespace chaiscript { m->add(user_type(), type); - m->add(fun([](const FutureType &t) { return t.valid(); }), "valid"); + m->add(fun([](const FutureType &t) { return t.valid(); }), "valid"); m->add(fun(&FutureType::get), "get"); m->add(fun(&FutureType::wait), "wait"); diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index ccfdb49..4998ede 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -36,6 +36,7 @@ namespace chaiscript return std::function(func); } + template std::function to_function(Ret (Class::*func)(Args...)) { @@ -62,6 +63,25 @@ namespace chaiscript #endif } + template + std::function to_function_callable(Ret (Class::*)(Args...), T t) + { + return std::function(t); + } + + template + std::function to_function_callable(Ret (Class::*)(Args...) const, T t) + { + return std::function(t); + } + + + template + auto to_function(T t) -> decltype(to_function_callable(&T::operator(), t)) + { + return to_function_callable(&T::operator(), t); + } + } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 0592ec9..5b3602b 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -370,7 +370,7 @@ namespace chaiscript // m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); // - m_engine.add(fun &)>( + m_engine.add(fun( [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector &t_params) { return t_fun(t_params, this->m_engine.conversions()); }), "call"); @@ -378,9 +378,9 @@ namespace chaiscript m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type"); - m_engine.add(fun([this](const std::string &t_type_name){ return this->m_engine.get_type(t_type_name, true); }), "type"); + m_engine.add(fun([this](const std::string &t_type_name){ return this->m_engine.get_type(t_type_name, true); }), "type"); - m_engine.add(fun &)>( + m_engine.add(fun( [=](const Type_Info &t_from, const Type_Info &t_to, const std::function &t_func) { m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func)); } From da39b8403b371aa048f39e291dcf5372a15fafee Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 19 May 2015 14:15:21 -0600 Subject: [PATCH 007/116] Remove more usage of `new` --- .../chaiscript/dispatchkit/handle_return.hpp | 49 +++++-------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index ed165e0..d028e85 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -54,9 +54,7 @@ namespace chaiscript { static Boxed_Value handle(const std::function &f) { return Boxed_Value( - std::shared_ptr( - new dispatch::Proxy_Function_Impl(f) - ) + chaiscript::make_shared>(f) ); } }; @@ -66,10 +64,8 @@ namespace chaiscript { static Boxed_Value handle(const std::function &f) { return Boxed_Value( - std::shared_ptr( - new Proxy_Function_Impl(f) - ) - ); + chaiscript::make_shared>(f) + ); } }; @@ -78,12 +74,7 @@ namespace chaiscript { static Boxed_Value handle(const std::shared_ptr> &f) { return Boxed_Value( - std::shared_ptr( - new Assignable_Proxy_Function_Impl( - std::ref(*f), - f - ) - ) + chaiscript::make_shared>(std::ref(*f),f) ); } }; @@ -93,13 +84,8 @@ namespace chaiscript { static Boxed_Value handle(const std::shared_ptr> &f) { return Boxed_Value( - std::shared_ptr( - new Assignable_Proxy_Function_Impl( - std::ref(*f), - f - ) - ) - ); + chaiscript::make_shared>(std::ref(*f),f) + ); } }; @@ -108,13 +94,8 @@ namespace chaiscript { static Boxed_Value handle(const std::shared_ptr> &f) { return Boxed_Value( - std::shared_ptr( - new Assignable_Proxy_Function_Impl( - std::ref(*f), - f - ) - ) - ); + chaiscript::make_shared>(std::ref(*f),f) + ); } }; @@ -123,20 +104,14 @@ namespace chaiscript { static Boxed_Value handle(std::function &f) { return Boxed_Value( - std::shared_ptr( - new Assignable_Proxy_Function_Impl( - std::ref(f), - std::shared_ptr>() - ) - ) - ); + chaiscript::make_shared>(std::ref(f), + std::shared_ptr>()) + ); } static Boxed_Value handle(const std::function &f) { return Boxed_Value( - std::shared_ptr( - new dispatch::Proxy_Function_Impl(f) - ) + chaiscript::make_shared>(f) ); } }; From 051f483d20522d71b96c5c54e9ce7fd34a6914f1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 09:48:46 -0600 Subject: [PATCH 008/116] Add failing non-polymorphic Derived->Base test --- unittests/compiled_tests.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index dbed26f..b49f90e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -723,3 +723,24 @@ TEST_CASE("Object lifetime test 2") CHECK(_script.eval("to_string(test2.x)") == "10"); } + + + + +///// Non-polymorphic base class conversions +class Non_Poly_Base {}; +class Non_Poly_Derived : public Non_Poly_Base {}; +int myfunction(Non_Poly_Base *) +{ + return 2; +} + +TEST_CASE("Test Derived->Base with non-polymorphic classes") +{ + chaiscript::ChaiScript chai; + chai.add(chaiscript::base_class()); + Non_Poly_Derived d; + chai.add(chaiscript::var(&d), "d"); + chai.add(chaiscript::fun(&myfunction), "myfunction"); + CHECK(chai.eval("myfunction(d)") == 2); +} From bc8a4c42faaebb439b24716dc8ada7ec6a85e5e0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 11:08:07 -0600 Subject: [PATCH 009/116] Get non-polymorphic Derived->Base conversions working --- .../dispatchkit/type_conversions.hpp | 105 +++++++++++++++++- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 72d2315..8b9d8c8 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -107,6 +107,71 @@ namespace chaiscript }; + template + class Static_Caster + { + public: + static Boxed_Value cast(const Boxed_Value &t_from) + { + if (t_from.get_type_info().bare_equal(chaiscript::user_type())) + { + if (t_from.is_pointer()) + { + // Dynamic cast out the contained boxed value, which we know is the type we want + if (t_from.is_const()) + { + return Boxed_Value( + [&]()->std::shared_ptr{ + if (auto data = std::static_pointer_cast(detail::Cast_Helper >::cast(t_from, nullptr))) + { + return data; + } else { + throw std::bad_cast(); + } + }() + ); + } else { + return Boxed_Value( + [&]()->std::shared_ptr{ + if (auto data = std::static_pointer_cast(detail::Cast_Helper >::cast(t_from, nullptr))) + { + return data; + } else { +#ifdef CHAISCRIPT_LIBCPP + /// \todo fix this someday after libc++ is fixed. + if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) { + auto from = detail::Cast_Helper >::cast(t_from, nullptr); + if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) { + return std::static_pointer_cast(from); + } + } +#endif + throw std::bad_cast(); + } + }() + ); + } + } else { + // Pull the reference out of the contained boxed value, which we know is the type we want + if (t_from.is_const()) + { + const From &d = detail::Cast_Helper::cast(t_from, nullptr); + const To &data = static_cast(d); + return Boxed_Value(std::cref(data)); + } else { + From &d = detail::Cast_Helper::cast(t_from, nullptr); + To &data = static_cast(d); + return Boxed_Value(std::ref(data)); + } + } + } else { + throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion"); + } + } + + }; + + template class Dynamic_Caster { @@ -168,8 +233,10 @@ namespace chaiscript throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion"); } } + }; + template class Dynamic_Conversion_Impl : public Type_Conversion_Base { @@ -186,10 +253,31 @@ namespace chaiscript virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE { - return Dynamic_Caster::cast(t_derived); + return Static_Caster::cast(t_derived); } }; + template + class Static_Conversion_Impl : public Type_Conversion_Base + { + public: + Static_Conversion_Impl() + : Type_Conversion_Base(chaiscript::user_type(), chaiscript::user_type()) + { + } + + virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE + { + throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types"); + } + + virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE + { + return Static_Caster::cast(t_derived); + } + }; + + template class Type_Conversion_Impl : public Type_Conversion_Base @@ -417,17 +505,26 @@ namespace chaiscript /// \endcode /// template - Type_Conversion base_class() + Type_Conversion base_class(typename std::enable_if::value && std::is_polymorphic::value>::type* = nullptr) { //Can only be used with related polymorphic types //may be expanded some day to support conversions other than child -> parent static_assert(std::is_base_of::value, "Classes are not related by inheritance"); - static_assert(std::is_polymorphic::value, "Base class must be polymorphic"); - static_assert(std::is_polymorphic::value, "Derived class must be polymorphic"); return chaiscript::make_shared>(); } + template + Type_Conversion base_class(typename std::enable_if::value || !std::is_polymorphic::value>::type* = nullptr) + { + //Can only be used with related polymorphic types + //may be expanded some day to support conversions other than child -> parent + static_assert(std::is_base_of::value, "Classes are not related by inheritance"); + + return chaiscript::make_shared>(); + } + + template Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to, const Callable &t_func) From 515ee711ce7d210bdee5aec608bf0d9d657e3b46 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 12:00:41 -0600 Subject: [PATCH 010/116] Remove unnecessary code --- include/chaiscript/dispatchkit/type_conversions.hpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 8b9d8c8..a5abed4 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -137,15 +137,6 @@ namespace chaiscript { return data; } else { -#ifdef CHAISCRIPT_LIBCPP - /// \todo fix this someday after libc++ is fixed. - if (std::string(typeid(To).name()).find("Assignable_Proxy_Function") != std::string::npos) { - auto from = detail::Cast_Helper >::cast(t_from, nullptr); - if (std::string(typeid(*from).name()).find("Assignable_Proxy_Function_Impl") != std::string::npos) { - return std::static_pointer_cast(from); - } - } -#endif throw std::bad_cast(); } }() From 13381ffa43429c85835f0eeaca5517e0d20117da Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 15:04:04 -0600 Subject: [PATCH 011/116] Add test, tweak coverage reporting --- .travis.yml | 5 +---- CMakeLists.txt | 13 +++++++++++++ src/main.cpp | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index dc3b2ad..823eef1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,10 +14,7 @@ script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test - - mkdir gcov - - find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; - - $GCOV -d -o gcov gcov/*.gcda - - coveralls -n -E ".*\.cpp" + - coveralls -n -E ".*\.cpp" -E "catch\.hpp" --gcov $GCOV after_script: - contrib/codeanalysis/runcppcheck.sh notifications: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9cb63dd..fb0af87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,6 +314,19 @@ if(BUILD_TESTING) "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" ) + add_test(version_check_2 chai --version ) + set_property(TEST version_check_2 + PROPERTY ENVIRONMENT + "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" + PROPERTY PASS_REGULAR_EXPRESSION "${CHAI_VERSION}" + ) + + add_test(help chai --help ) + set_property(TEST help + PROPERTY ENVIRONMENT + "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" + ) + foreach(filename ${UNIT_TESTS}) message(STATUS "Adding test ${filename}") diff --git a/src/main.cpp b/src/main.cpp index 3a72df1..67725f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -324,7 +324,7 @@ int main(int argc, char *argv[]) arg += line + '\n' ; } } else if ( arg == "-v" || arg == "--version" ) { - arg = "version()" ; + arg = "print(version())" ; } else if ( arg == "-h" || arg == "--help" ) { arg = "help(-1)"; } else if ( arg == "-i" || arg == "--interactive" ) { From c32af523c39c62b74300f0a10335cbcedc64d08f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 16:02:29 -0600 Subject: [PATCH 012/116] Remove -n from coveralls call --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 823eef1..abe959c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test - - coveralls -n -E ".*\.cpp" -E "catch\.hpp" --gcov $GCOV + - coveralls -E ".*\.cpp" -E "catch\.hpp" --gcov $GCOV after_script: - contrib/codeanalysis/runcppcheck.sh notifications: From e43b1b8d0dce1277c1d519e2bd9b5f93613a395b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 16:46:07 -0600 Subject: [PATCH 013/116] Make sure we are not also doing coverage testing on catch.hpp --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index abe959c..243e529 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test - - coveralls -E ".*\.cpp" -E "catch\.hpp" --gcov $GCOV + - coveralls -E ".*\.cpp|catch\.hpp" --gcov $GCOV after_script: - contrib/codeanalysis/runcppcheck.sh notifications: From e608d14a4f3f127fb7ff8c707fdf9f91117d9c05 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 18:43:28 -0600 Subject: [PATCH 014/116] Attempt again to clean up coverage reporting --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 243e529..cffd309 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test - - coveralls -E ".*\.cpp|catch\.hpp" --gcov $GCOV + - coveralls -E ".*\.cpp" -e catch.hpp --gcov $GCOV after_script: - contrib/codeanalysis/runcppcheck.sh notifications: From 33a929ef93d7583e55eb09c78b881217d3388502 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 20 May 2015 20:06:06 -0600 Subject: [PATCH 015/116] one more attempt to ignore catch.hpp from coverage --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cffd309..210e29e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test - - coveralls -E ".*\.cpp" -e catch.hpp --gcov $GCOV + - coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV after_script: - contrib/codeanalysis/runcppcheck.sh notifications: From 03143a9f83111f9cfe822ed79aedf03663182ee8 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 09:30:42 -0600 Subject: [PATCH 016/116] Phase one of getting rid of std::function usage --- .../dispatchkit/callable_traits.hpp | 39 +++++++++++++++++++ .../dispatchkit/proxy_functions.hpp | 39 +++++++++++++++++++ .../dispatchkit/proxy_functions_detail.hpp | 25 ++++++------ .../dispatchkit/register_function.hpp | 12 +++++- 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 include/chaiscript/dispatchkit/callable_traits.hpp diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp new file mode 100644 index 0000000..447d39c --- /dev/null +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -0,0 +1,39 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ +#define CHAISCRIPT_CALLABLE_TRAITS_HPP_ + +namespace chaiscript { + namespace dispatch { + namespace detail { + + template + struct Function_Signature + { + typedef T Signature; + }; + + template + struct Callable_Traits + { + + template + static Ret deduce_ret_type(Ret (T::*)(Param...) const); + + template + static Function_Signature deduce_sig_type(Ret (T::*)(Param...) const); + + typedef decltype(deduce_ret_type(&T::operator())) Return_Type; + typedef typename decltype(deduce_sig_type(&T::operator()))::Signature Signature; + typedef decltype(deduce_sig_type(&T::operator())) Signature_Object; + }; + } + } +} + +#endif + diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 39011ca..0bd8b7c 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -549,6 +549,45 @@ namespace chaiscript virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; }; + + + /// For any callable object + template + class Proxy_Function_Callable_Impl : public Proxy_Function_Impl_Base + { + public: + Proxy_Function_Callable_Impl(Callable f) + : Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast(nullptr))), + m_f(std::move(f)), m_dummy_func(nullptr) + { + } + + virtual ~Proxy_Function_Callable_Impl() {} + + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + return detail::compare_types_cast(m_dummy_func, vals, t_conversions); + } + + virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + { + return dynamic_cast *>(&t_func) != nullptr; + } + + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + typedef typename detail::Callable_Traits::Return_Type Return_Type; + return detail::Do_Call::go(m_f, params, t_conversions); + } + + + private: + Callable m_f; + Func *m_dummy_func; + }; + /// The standard typesafe function call implementation of Proxy_Function /// It takes a std::function<> object and performs runtime /// type checking of Boxed_Value parameters, in a type safe manner diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index b90c8d6..66e7713 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -16,6 +16,7 @@ #include "boxed_value.hpp" #include "handle_return.hpp" #include "type_info.hpp" +#include "callable_traits.hpp" namespace chaiscript { class Type_Conversions; @@ -111,8 +112,8 @@ namespace chaiscript struct Call_Func { - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); @@ -126,8 +127,8 @@ namespace chaiscript #pragma warning(push) #pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this #endif - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return f(boxed_cast(std::forward(innerparams), &t_conversions)...); @@ -143,8 +144,8 @@ namespace chaiscript * if any unboxing fails the execution of the function fails and * the bad_boxed_cast is passed up to the caller. */ - template - Ret call_func(const std::function &f, + template + Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions) { if (params.size() == sizeof...(Params)) @@ -170,20 +171,20 @@ namespace chaiscript template struct Do_Call { - template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + template + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - return Handle_Return::handle(call_func(fun, params, t_conversions)); + return Handle_Return::handle(call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions)); } }; template<> struct Do_Call { - template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + template + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - call_func(fun, params, t_conversions); + call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions); return Handle_Return::handle(); } }; diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 4998ede..e526de5 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -19,6 +19,7 @@ namespace chaiscript { namespace detail { + template struct FunctionSignature { @@ -108,8 +109,17 @@ namespace chaiscript template Proxy_Function fun(const T &t) { + typedef typename dispatch::detail::Callable_Traits::Signature Signature; + return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(t))); + chaiscript::make_shared>(t)); + } + + template + Proxy_Function fun(Ret (*func)(Param...)) + { + return Proxy_Function( + chaiscript::make_shared::Signature>>(dispatch::detail::to_function(func))); } template From 630c618ae7d87bd7bee7979997f31bad7fecd803 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 09:39:21 -0600 Subject: [PATCH 017/116] Remove automagic wrapping to std::function<> --- include/chaiscript/chaiscript_stdlib.hpp | 2 +- .../chaiscript/dispatchkit/register_function.hpp | 16 ---------------- unittests/compiled_tests.cpp | 3 +-- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index 92483fd..dc6ff46 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -47,7 +47,7 @@ namespace chaiscript #ifndef CHAISCRIPT_NO_THREADS lib->add(standard_library::future_type>("future")); - lib->add(chaiscript::fun (const std::function &)>([](const std::function &t_func){ return std::async(std::launch::async, t_func);}), "async"); + lib->add(chaiscript::fun([](const std::function &t_func){ return std::async(std::launch::async, t_func);}), "async"); #endif return lib; diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index e526de5..829a7d5 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -144,22 +144,6 @@ namespace chaiscript } - /// \brief Creates a new Proxy_Function object from a std::function object - /// \param[in] f std::function to expose to ChaiScript - /// - /// \b Example: - /// \code - /// std::function f = get_some_function(); - /// chaiscript::ChaiScript chai; - /// chai.add(fun(f), "some_function"); - /// \endcode - /// - /// \sa \ref adding_functions - template - Proxy_Function fun(const std::function &f) - { - return Proxy_Function(chaiscript::make_shared>(f)); - } /// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index b49f90e..c856e9a 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -37,8 +37,7 @@ TEST_CASE("C++11 Lambdas Can Be Registered") // in an std::function or provide the signature chaiscript::ChaiScript chai; - // provide the signature - chai.add(chaiscript::fun([] { return "hello"; } ), "f1"); + chai.add(chaiscript::fun([]()->std::string { return "hello"; } ), "f1"); // wrap chai.add(chaiscript::fun(std::function([] { return "world"; } )), "f2"); From 48933bc32caa999b9876822b361488784f702417 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 10:28:28 -0600 Subject: [PATCH 018/116] Use std::ref to make free functions callable --- include/chaiscript/dispatchkit/callable_traits.hpp | 12 ++++++++---- include/chaiscript/dispatchkit/proxy_functions.hpp | 8 ++++---- .../dispatchkit/proxy_functions_detail.hpp | 8 ++++---- include/chaiscript/dispatchkit/register_function.hpp | 5 ++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index 447d39c..8a95d7e 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -14,22 +14,26 @@ namespace chaiscript { template struct Function_Signature { + + template + static Ret deduce_ret_type(Function_Signature *); + typedef T Signature; + typedef Function_Signature *ptr_type; + typedef decltype(deduce_ret_type(ptr_type(nullptr))) Return_Type; + }; template struct Callable_Traits { - template - static Ret deduce_ret_type(Ret (T::*)(Param...) const); - template static Function_Signature deduce_sig_type(Ret (T::*)(Param...) const); - typedef decltype(deduce_ret_type(&T::operator())) Return_Type; typedef typename decltype(deduce_sig_type(&T::operator()))::Signature Signature; typedef decltype(deduce_sig_type(&T::operator())) Signature_Object; + typedef typename Signature_Object::Return_Type Return_Type; }; } } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 0bd8b7c..5856f45 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -578,8 +578,8 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - typedef typename detail::Callable_Traits::Return_Type Return_Type; - return detail::Do_Call::go(m_f, params, t_conversions); + typedef typename detail::Function_Signature::Return_Type Return_Type; + return detail::Do_Call::template go(m_f, params, t_conversions); } @@ -621,7 +621,7 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return detail::Do_Call::result_type>::go(m_f, params, t_conversions); + return detail::Do_Call::result_type>::template go(m_f, params, t_conversions); } @@ -682,7 +682,7 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return detail::Do_Call::result_type>::go(m_f.get(), params, t_conversions); + return detail::Do_Call::result_type>::template go(m_f.get(), params, t_conversions); } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 66e7713..fbd1843 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -171,20 +171,20 @@ namespace chaiscript template struct Do_Call { - template + template static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - return Handle_Return::handle(call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions)); + return Handle_Return::handle(call_func(Function_Signature(), fun, params, t_conversions)); } }; template<> struct Do_Call { - template + template static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions); + call_func(Function_Signature(), fun, params, t_conversions); return Handle_Return::handle(); } }; diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 829a7d5..093bd41 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -118,8 +118,11 @@ namespace chaiscript template Proxy_Function fun(Ret (*func)(Param...)) { + auto f_ref = std::ref(*func); + return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(func))); + chaiscript::make_shared>(f_ref)); + } template From 0b812942d422046660409d021aef61a998edcf5b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 11:35:58 -0600 Subject: [PATCH 019/116] Finish removing std::function<> --- .../dispatchkit/callable_traits.hpp | 25 +++++++++++++++++++ .../dispatchkit/register_function.hpp | 17 ++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index 8a95d7e..49978d2 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -10,6 +10,31 @@ namespace chaiscript { namespace dispatch { namespace detail { + template + struct Const_Caller + { + Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {} + + template + Ret operator()(const Class &o, Inner&& ... inner) const { + return (o.*m_func)(std::forward(inner)...); + } + + Ret (Class::*m_func)(Param...) const; + }; + + template + struct Caller + { + Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {} + + template + Ret operator()(Class &o, Inner&& ... inner) const { + return (o.*m_func)(std::forward(inner)...); + } + + Ret (Class::*m_func)(Param...); + }; template struct Function_Signature diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 093bd41..438c723 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -126,17 +126,26 @@ namespace chaiscript } template - Proxy_Function fun(Ret (Class::*func)(Param...) const) + Proxy_Function fun(Ret (Class::*t_func)(Param...) const) { + auto call = dispatch::detail::Const_Caller(t_func); + return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(func))); + chaiscript::make_shared>(call)); } template - Proxy_Function fun(Ret (Class::*func)(Param...)) + Proxy_Function fun(Ret (Class::*t_func)(Param...)) { + auto call = dispatch::detail::Caller(t_func); + return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(func))); + chaiscript::make_shared>(call)); + +/* + return Proxy_Function( + chaiscript::make_shared::Signature>>(dispatch::detail::to_function(t_func))); +*/ } From df724b5c33561ca1bb975c09d9d7f794c3389442 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 12:13:49 -0600 Subject: [PATCH 020/116] Completely remove Proxy_Function_Impl --- .../dispatchkit/callable_traits.hpp | 11 +++ .../dispatchkit/function_call_detail.hpp | 2 + .../chaiscript/dispatchkit/handle_return.hpp | 8 +- .../dispatchkit/proxy_constructors.hpp | 15 +--- .../dispatchkit/proxy_functions.hpp | 41 ---------- .../dispatchkit/register_function.hpp | 74 ------------------- 6 files changed, 21 insertions(+), 130 deletions(-) diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index 49978d2..e1fe612 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -7,9 +7,20 @@ #ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ #define CHAISCRIPT_CALLABLE_TRAITS_HPP_ +#include + namespace chaiscript { namespace dispatch { namespace detail { + template + struct Constructor + { + template + std::shared_ptr operator()(Inner&& ... inner) const { + return std::make_shared(std::forward(inner)...); + } + }; + template struct Const_Caller { diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 9410d15..fb6b5fc 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -95,6 +95,7 @@ namespace chaiscript template std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions *t_conversions) { + /* if (funcs.size() == 1) { std::shared_ptr> pfi = @@ -108,6 +109,7 @@ namespace chaiscript // looks like this either wasn't a Proxy_Function_Impl or the types didn't match // we cannot make any other guesses or assumptions really, so continuing } +*/ return std::function(Build_Function_Caller_Helper(funcs, t_conversions?*t_conversions:Type_Conversions())); } diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index d028e85..d5bdb9d 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -23,7 +23,7 @@ namespace chaiscript { namespace dispatch { - template class Proxy_Function_Impl; + template class Proxy_Function_Callable_Impl; template class Assignable_Proxy_Function_Impl; namespace detail @@ -54,7 +54,7 @@ namespace chaiscript { static Boxed_Value handle(const std::function &f) { return Boxed_Value( - chaiscript::make_shared>(f) + chaiscript::make_shared>>(f) ); } }; @@ -64,7 +64,7 @@ namespace chaiscript { static Boxed_Value handle(const std::function &f) { return Boxed_Value( - chaiscript::make_shared>(f) + chaiscript::make_shared>>(f) ); } }; @@ -111,7 +111,7 @@ namespace chaiscript static Boxed_Value handle(const std::function &f) { return Boxed_Value( - chaiscript::make_shared>(f) + chaiscript::make_shared>>(f) ); } }; diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index 2866d97..063c557 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -16,21 +16,14 @@ namespace chaiscript { namespace detail { - /** - * A constructor function, used for creating a new object - * of a given type with a given set of params - */ - template - std::shared_ptr constructor_(Params ... params) - { - return std::make_shared(params...); - } template Proxy_Function build_constructor_(Class (*)(Params...)) { - typedef std::shared_ptr (sig)(Params...); - return Proxy_Function(static_cast(new Proxy_Function_Impl(std::function(&(constructor_))))); + auto call = dispatch::detail::Constructor(); + + return Proxy_Function( + chaiscript::make_shared (Params...), decltype(call)>>(call)); } } } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 5856f45..35dc100 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -588,47 +588,6 @@ namespace chaiscript Func *m_dummy_func; }; - /// The standard typesafe function call implementation of Proxy_Function - /// It takes a std::function<> object and performs runtime - /// type checking of Boxed_Value parameters, in a type safe manner - template - class Proxy_Function_Impl : public Proxy_Function_Impl_Base - { - public: - Proxy_Function_Impl(std::function f) - : Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast(nullptr))), - m_f(std::move(f)), m_dummy_func(nullptr) - { - } - - virtual ~Proxy_Function_Impl() {} - - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE - { - return detail::compare_types_cast(m_dummy_func, vals, t_conversions); - } - - virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE - { - return dynamic_cast *>(&t_func) != nullptr; - } - - std::function internal_function() const - { - return m_f; - } - - protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE - { - return detail::Do_Call::result_type>::template go(m_f, params, t_conversions); - } - - - private: - std::function m_f; - Func *m_dummy_func; - }; class Assignable_Proxy_Function : public Proxy_Function_Impl_Base { diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 438c723..ecec5ea 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -15,76 +15,6 @@ namespace chaiscript { - namespace dispatch - { - namespace detail - { - - template - struct FunctionSignature - { - }; - - template - struct FunctionSignature > - { - typedef Sig Signature; - }; - - template - std::function to_function(Ret (*func)(Args...)) - { - return std::function(func); - } - - - template - std::function to_function(Ret (Class::*func)(Args...)) - { -#ifdef CHAISCRIPT_MSVC - /// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for - /// std::function for member function pointers seems to be broken in MSVC - return std::function(std::mem_fn(func)); -#else - return std::function(func); -#endif - } - - template - std::function to_function(Ret (Class::*func)(Args...) const) - { -#if defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_LIBCPP) - /// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for - /// std::function for member function pointers seems to be broken in MSVC - return std::function([func](const Class &o, Args... args)->Ret { - return (o.*func)(std::forward(args)...); - }); -#else - return std::function(func); -#endif - } - - template - std::function to_function_callable(Ret (Class::*)(Args...), T t) - { - return std::function(t); - } - - template - std::function to_function_callable(Ret (Class::*)(Args...) const, T t) - { - return std::function(t); - } - - - template - auto to_function(T t) -> decltype(to_function_callable(&T::operator(), t)) - { - return to_function_callable(&T::operator(), t); - } - - } - } /// \brief Creates a new Proxy_Function object from a free function, member function or data member /// \param[in] t Function / member to expose @@ -142,10 +72,6 @@ namespace chaiscript return Proxy_Function( chaiscript::make_shared>(call)); -/* - return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(t_func))); -*/ } From e0234d942e8ed00a600ee8e48e08b0f86444570f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 22 May 2015 19:40:56 -0600 Subject: [PATCH 021/116] Various cleanups and fixes for older compilers --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 14 ++++---- .../chaiscript/dispatchkit/boxed_number.hpp | 22 ++++++------- .../dispatchkit/callable_traits.hpp | 33 ++++++++++--------- .../dispatchkit/proxy_functions.hpp | 12 +++---- .../dispatchkit/proxy_functions_detail.hpp | 2 +- 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index ad31f6b..650124c 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -243,18 +243,18 @@ namespace chaiscript template ModulePtr random_access_container_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) { - // cppcheck-suppress syntaxError - typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); - //In the interest of runtime safety for the m, we prefer the at() method for [] access, //to throw an exception in an out of bounds condition. m->add( - fun(std::function - (std::mem_fn(static_cast(&ContainerType::at)))), "[]"); + fun( + [](ContainerType &c, int index) -> typename ContainerType::reference { + return c.at(index); + }), "[]"); + m->add( fun( - [](const ContainerType *c, int index) -> typename ContainerType::const_reference { - return c->at(index); + [](const ContainerType &c, int index) -> typename ContainerType::const_reference { + return c.at(index); }), "[]"); return m; diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index a57ed7a..fa3ba6c 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -60,7 +60,7 @@ namespace chaiscript { private: template - static void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) + inline static void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) { #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO if (t == 0) { @@ -70,7 +70,7 @@ namespace chaiscript } template - static void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) + inline static void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) { } @@ -78,7 +78,7 @@ namespace chaiscript { template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + inline static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) { switch (t_oper) { @@ -103,7 +103,7 @@ namespace chaiscript struct binary { template - static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) + inline static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { @@ -140,7 +140,7 @@ namespace chaiscript struct binary_int { template - static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) + inline static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { switch (t_oper) { @@ -173,7 +173,7 @@ namespace chaiscript struct const_binary_int { template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + inline static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) { switch (t_oper) { @@ -201,7 +201,7 @@ namespace chaiscript struct const_binary { template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + inline static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) { switch (t_oper) { @@ -227,7 +227,7 @@ namespace chaiscript template struct Go { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + inline static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { @@ -249,7 +249,7 @@ namespace chaiscript template struct Go { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + inline static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { @@ -269,7 +269,7 @@ namespace chaiscript }; template - static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { const auto &inp_ = t_rhs.get_type_info(); @@ -310,7 +310,7 @@ namespace chaiscript } } - static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { const Type_Info &inp_ = t_lhs.get_type_info(); diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index e1fe612..5ffa093 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -47,29 +47,32 @@ namespace chaiscript { Ret (Class::*m_func)(Param...); }; + template struct Function_Signature { - - template - static Ret deduce_ret_type(Function_Signature *); - - typedef T Signature; - typedef Function_Signature *ptr_type; - typedef decltype(deduce_ret_type(ptr_type(nullptr))) Return_Type; - }; + template + struct Function_Signature + { + typedef Ret Return_Type; + typedef Ret (Signature)(Params...); + }; + + template + struct Function_Signature + { + typedef Ret Return_Type; + typedef Ret (Signature)(Params...); + }; + + template struct Callable_Traits { - - template - static Function_Signature deduce_sig_type(Ret (T::*)(Param...) const); - - typedef typename decltype(deduce_sig_type(&T::operator()))::Signature Signature; - typedef decltype(deduce_sig_type(&T::operator())) Signature_Object; - typedef typename Signature_Object::Return_Type Return_Type; + typedef typename Function_Signature::Signature Signature; + typedef typename Function_Signature::Return_Type Return_Type; }; } } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 35dc100..e0a413a 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -558,7 +558,7 @@ namespace chaiscript public: Proxy_Function_Callable_Impl(Callable f) : Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast(nullptr))), - m_f(std::move(f)), m_dummy_func(nullptr) + m_f(std::move(f)) { } @@ -566,7 +566,7 @@ namespace chaiscript virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return detail::compare_types_cast(m_dummy_func, vals, t_conversions); + return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE @@ -582,10 +582,8 @@ namespace chaiscript return detail::Do_Call::template go(m_f, params, t_conversions); } - private: Callable m_f; - Func *m_dummy_func; }; @@ -611,17 +609,16 @@ namespace chaiscript public: Assignable_Proxy_Function_Impl(std::reference_wrapper> t_f, std::shared_ptr> t_ptr) : Assignable_Proxy_Function(detail::build_param_type_list(static_cast(nullptr))), - m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr)), m_dummy_func(nullptr) + m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr)) { assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); - } virtual ~Assignable_Proxy_Function_Impl() {} virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return detail::compare_types_cast(m_dummy_func, vals, t_conversions); + return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE @@ -648,7 +645,6 @@ namespace chaiscript private: std::reference_wrapper> m_f; std::shared_ptr> m_shared_ptr_holder; - Func *m_dummy_func; }; /// Attribute getter Proxy_Function implementation template diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index fbd1843..fb1418e 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -98,7 +98,7 @@ namespace chaiscript template bool compare_types_cast(Ret (*)(Params...), const std::vector ¶ms, const Type_Conversions &t_conversions) - { + { try { Try_Cast::do_try(params, 0, t_conversions); } catch (const exception::bad_boxed_cast &) { From 919c3f2b4a77c9a83026fa30290caf89ec3d3d96 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 May 2015 13:10:29 -0600 Subject: [PATCH 022/116] Finish removing std::function and std::bind internally --- .../chaiscript/language/chaiscript_engine.hpp | 39 ++++++++--------- .../chaiscript/language/chaiscript_eval.hpp | 43 ++++++++++--------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 5b3602b..233f906 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -356,13 +356,14 @@ namespace chaiscript add(t_lib); } - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_system, std::ref(m_engine)), "dump_system"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::dump_object, std::ref(m_engine)), "dump_object"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects"); + m_engine.add(fun([this](){ m_engine.dump_system(); }), "dump_system"); + m_engine.add(fun([this](const Boxed_Value &t_bv){ m_engine.dump_object(t_bv); }), "dump_object"); + m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_type){ return m_engine.is_type(t_bv, t_type); }), "is_type"); + m_engine.add(fun([this](const Boxed_Value &t_bv){ return m_engine.type_name(t_bv); }), "type_name"); + m_engine.add(fun([this](const std::string &t_f){ return m_engine.function_exists(t_f); }), "function_exists"); + m_engine.add(fun([this](){ return m_engine.get_function_objects(); }), "get_functions"); + m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects"); + m_engine.add(chaiscript::make_shared( [this](const std::vector &t_params) { return m_engine.call_exists(t_params); @@ -375,10 +376,10 @@ namespace chaiscript return t_fun(t_params, this->m_engine.conversions()); }), "call"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name"); + m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name"); - m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type"); - m_engine.add(fun([this](const std::string &t_type_name){ return this->m_engine.get_type(t_type_name, true); }), "type"); + m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type"); + m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type"); m_engine.add(fun( [=](const Type_Info &t_from, const Type_Info &t_to, const std::function &t_func) { @@ -387,24 +388,22 @@ namespace chaiscript ), "add_type_conversion"); - typedef std::string (ChaiScript::*load_mod_1)(const std::string&); - typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&); - m_engine.add(fun(static_cast(&ChaiScript::load_module), this), "load_module"); - m_engine.add(fun(static_cast(&ChaiScript::load_module), this), "load_module"); + m_engine.add(fun([this](const std::string &t_module, const std::string &t_file){ return load_module(t_module, t_file); }), "load_module"); + m_engine.add(fun([this](const std::string &t_module){ return load_module(t_module); }), "load_module"); - m_engine.add(fun(&ChaiScript::use, this), "use"); - m_engine.add(fun(&ChaiScript::internal_eval_file, this), "eval_file"); - m_engine.add(fun(&ChaiScript::internal_eval, this), "eval"); - m_engine.add(fun(&ChaiScript::internal_eval_ast, this), "eval"); + m_engine.add(fun([this](const std::string &t_file){ return use(t_file); }), "use"); + m_engine.add(fun([this](const std::string &t_file){ return internal_eval_file(t_file); }), "eval_file"); + m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval"); + m_engine.add(fun([this](const AST_NodePtr &t_ast){ return internal_eval_ast(t_ast); }), "eval"); m_engine.add(fun(&ChaiScript::version_major), "version_major"); m_engine.add(fun(&ChaiScript::version_minor), "version_minor"); m_engine.add(fun(&ChaiScript::version_patch), "version_patch"); m_engine.add(fun(&ChaiScript::version), "version"); - m_engine.add(fun(&ChaiScript::add_global_const, this), "add_global_const"); - m_engine.add(fun(&ChaiScript::add_global, this), "add_global"); + m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const"); + m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global"); do_eval(ChaiScript_Prelude::chaiscript_prelude(), "standard prelude"); } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 2e8a922..895dcad 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1418,36 +1418,40 @@ namespace chaiscript std::shared_ptr guard; if (guardnode) { guard = std::make_shared - (std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), guardnode, - t_param_names, std::placeholders::_1, std::map()), static_cast(numparams), guardnode); + ([&t_ss, t_param_names, guardnode](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(t_ss, guardnode, t_param_names, t_params, std::map()); + }, static_cast(numparams), guardnode); } try { const std::string & l_annotation = annotation?annotation->text:""; - const std::string & function_name = children[static_cast(1 + class_offset)]->text; + auto node = children.back(); if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); - t_ss.add(std::make_shared(class_name, std::make_shared(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), children.back(), t_param_names, std::placeholders::_1, std::map()), - static_cast(numparams), children.back(), param_types, l_annotation, guard)), + + t_ss.add(std::make_shared(class_name, + std::make_shared( + [&t_ss, t_param_names, node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); + }, + static_cast(numparams), node, param_types, l_annotation, guard)), function_name); } else { - // if the type is unknown, then this generates a function that looks up the type // at runtime. Defining the type first before this is called is better auto type = t_ss.get_type(class_name, false); param_types.push_front(class_name, type); - t_ss.add( - std::make_shared(class_name, - std::make_shared(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), children.back(), - t_param_names, std::placeholders::_1, std::map()), static_cast(numparams), children.back(), - param_types, l_annotation, guard), type), function_name); + t_ss.add(std::make_shared(class_name, + std::make_shared( + [&t_ss, t_param_names, node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); + }, + static_cast(numparams), node, param_types, l_annotation, guard), type), + function_name); } } catch (const exception::reserved_word_error &e) { @@ -1473,15 +1477,14 @@ namespace chaiscript std::string class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; try { + std::string attr_name = this->children[static_cast(1 + class_offset)]->text; + t_ss.add( std::make_shared( std::move(class_name), - fun(std::function( - std::bind(static_cast(&dispatch::Dynamic_Object::get_attr), - std::placeholders::_1, - this->children[static_cast(1 + class_offset)]->text - )) - ), + fun([attr_name](dispatch::Dynamic_Object &t_obj) { + return t_obj.get_attr(attr_name); + }), true ), this->children[static_cast(1 + class_offset)]->text); From bb2938307cbbdf481377ece40d4aa0ac30015804 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 23 May 2015 16:16:39 -0600 Subject: [PATCH 023/116] Move prelude into stdlib so it's not included everywhere --- include/chaiscript/chaiscript_stdlib.hpp | 3 +++ include/chaiscript/language/chaiscript_engine.hpp | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index dc6ff46..c07e64c 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -18,6 +18,7 @@ #include "dispatchkit/bootstrap.hpp" #include "dispatchkit/bootstrap_stl.hpp" #include "dispatchkit/boxed_value.hpp" +#include "language/chaiscript_prelude.chai" #ifndef CHAISCRIPT_NO_THREADS #include @@ -50,6 +51,8 @@ namespace chaiscript lib->add(chaiscript::fun([](const std::function &t_func){ return std::async(std::launch::async, t_func);}), "async"); #endif + lib->eval(ChaiScript_Prelude::chaiscript_prelude() /*, "standard prelude"*/ ); + return lib; } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 233f906..a7d3bad 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -44,7 +44,6 @@ #include "../dispatchkit/exception_specification.hpp" #include "chaiscript_parser.hpp" -#include "chaiscript_prelude.chai" namespace chaiscript { @@ -405,7 +404,6 @@ namespace chaiscript m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global"); - do_eval(ChaiScript_Prelude::chaiscript_prelude(), "standard prelude"); } From c9312c0b7a751065c451a2cfcda729e0003f6003 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 19:59:25 -0600 Subject: [PATCH 024/116] Enable coverity scan? hopefully --- .travis.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 210e29e..eb3d0ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,20 @@ notifications: on_start: false # default: false env: global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= + - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + # via the "travis encrypt" command using the project repo's public key + - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" + + +addons: + coverity_scan: + project: + name: "ChaiScript/ChaiScript" + description: "Build submitted via Travis CI" + notification_email: jason@emptycrate.com + build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; make clean" + build_command: "make -j2" + branch_pattern: coverity_scan From 8ed4e6fad8c84c413ea50b9a3d7aba239241ed8f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 20:17:13 -0600 Subject: [PATCH 025/116] Fix coverity settings? --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index eb3d0ab..1f30e3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,9 +42,9 @@ addons: project: name: "ChaiScript/ChaiScript" description: "Build submitted via Travis CI" - notification_email: jason@emptycrate.com - build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; make clean" - build_command: "make -j2" - branch_pattern: coverity_scan + notification_email: jason@emptycrate.com + build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; make clean" + build_command: "make -j2" + branch_pattern: coverity_scan From f54bd484e6a1619ada0cbd6870bc7272c24f4710 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 20:31:07 -0600 Subject: [PATCH 026/116] Attempt to fix build matrix and coverity --- .travis.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1f30e3f..867351c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,20 @@ compiler: env: - GCC_VER=4.6 - GCC_VER=4.8 + + + global: + - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + # via the "travis encrypt" command using the project repo's public key + - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" + before_install: - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -qq g++-4.8 - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi + - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi script: - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 @@ -29,13 +37,6 @@ notifications: on_success: change # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: false # default: false -env: - global: - - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= - # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key - - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" - addons: coverity_scan: From a04fe9d5a51310bba9e19556a3241c85eb26112b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 22:19:59 -0600 Subject: [PATCH 027/116] Fix env variables layout? --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 867351c..6725e11 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,9 @@ language: cpp compiler: - gcc env: - - GCC_VER=4.6 - - GCC_VER=4.8 + matrix: + - GCC_VER=4.6 + - GCC_VER=4.8 global: From f274d6beb38dcb60a632014f0015103e9b4e3370 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 22:31:27 -0600 Subject: [PATCH 028/116] Another attempt at coverity --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6725e11..0da8ba3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ addons: name: "ChaiScript/ChaiScript" description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com - build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; make clean" + build_command_prepend: "cmake . ; make clean" build_command: "make -j2" branch_pattern: coverity_scan From 1a02903b99e906b5c2c0825bebd207c46b46690b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 22:47:53 -0600 Subject: [PATCH 029/116] Another attempt with coverity support, add debugging --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0da8ba3..bec8b8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,9 @@ before_install: - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -qq g++-4.8 - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi + - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export GCOV="gcov"; fi script: + - cat cov-int/build-log.txt - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - make -j2 - make test @@ -46,7 +47,7 @@ addons: description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com build_command_prepend: "cmake . ; make clean" - build_command: "make -j2" + build_command: "make -j2 VERBOSE=1" branch_pattern: coverity_scan From cfc67f619a80633e0753caa365780c4d26a4c5b5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 29 May 2015 23:08:27 -0600 Subject: [PATCH 030/116] Travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bec8b8b..8df43b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,8 +46,8 @@ addons: name: "ChaiScript/ChaiScript" description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com - build_command_prepend: "cmake . ; make clean" - build_command: "make -j2 VERBOSE=1" + build_command_prepend: "cmake ." + build_command: "cmake --build ." branch_pattern: coverity_scan From 70326a5dfffeb1f1cb2457a14ed1545d4eff33ff Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 06:32:14 -0600 Subject: [PATCH 031/116] Try to distill travis / coverity settings --- .travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8df43b5..91866bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,15 +18,15 @@ before_install: - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -qq g++-4.8 - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export GCOV="gcov"; fi + - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" COVERALLS="1" CPPCHECK="1"; else export GCOV="gcov"; fi script: - - cat cov-int/build-log.txt - - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - - make -j2 - - make test - - coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV + - if [ ${COVERITY_SCAN_BRANCH} = 1 ]; then cat cov-int/build-log.txt; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make test ; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 && ${COVERALLS} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi after_script: - - contrib/codeanalysis/runcppcheck.sh + - if [ ${COVERITY_SCAN_BRANCH} != 1 && ${COVERALLS} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi notifications: email: recipients: @@ -47,7 +47,7 @@ addons: description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com build_command_prepend: "cmake ." - build_command: "cmake --build ." + build_command: "cmake --build . --target chai" branch_pattern: coverity_scan From bb0d1005138e53cb2d414401f0338f22fbbc636b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 07:33:34 -0600 Subject: [PATCH 032/116] Work around coverity crash I'm not 100% convinced on these changes, but they might be for the better. --- .../chaiscript/dispatchkit/dispatchkit.hpp | 9 ++- .../dispatchkit/type_conversions.hpp | 13 +-- include/chaiscript/dispatchkit/type_info.hpp | 79 ++++++++++--------- 3 files changed, 50 insertions(+), 51 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 5e7d18d..be4d8a7 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1175,8 +1175,13 @@ namespace chaiscript const auto lhssize = lhsparamtypes.size(); const auto rhssize = rhsparamtypes.size(); - CHAISCRIPT_CONSTEXPR auto boxed_type = user_type(); - CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type(); +#ifdef CHAISCRIPT_HAS_MAGIC_STATICS + auto boxed_type = user_type(); + auto boxed_pod_type = user_type(); +#else + static auto boxed_type = user_type(); + static auto boxed_pod_type = user_type(); +#endif for (size_t i = 1; i < lhssize && i < rhssize; ++i) { diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index a5abed4..a08addd 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -300,13 +300,6 @@ namespace chaiscript class Type_Conversions { public: - struct Less_Than - { - bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const - { - return *t_lhs != *t_rhs && t_lhs->before(*t_rhs); - } - }; Type_Conversions() : m_mutex(), @@ -329,7 +322,7 @@ namespace chaiscript { } - const std::set &thread_cache() const + const std::set &thread_cache() const { auto &cache = *m_thread_cache; if (cache.size() != m_num_types) @@ -466,9 +459,9 @@ namespace chaiscript mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; - std::set m_convertableTypes; + std::set m_convertableTypes; std::atomic_size_t m_num_types; - mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; + mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; mutable chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index de61ab6..0bee9c6 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace chaiscript @@ -28,9 +29,12 @@ namespace chaiscript /// \brief Compile time deduced information about a type class Type_Info { + private: + class Undef {}; + public: - CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, - bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) + Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + bool t_is_arithmetic, const std::type_index &t_ti, const std::type_index &t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic), @@ -38,8 +42,8 @@ namespace chaiscript { } - CHAISCRIPT_CONSTEXPR Type_Info() - : m_type_info(nullptr), m_bare_type_info(nullptr), + Type_Info() + : m_type_info(typeid(Type_Info::Undef)), m_bare_type_info(typeid(Type_Info::Undef)), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), m_is_undef(true) @@ -55,46 +59,43 @@ namespace chaiscript Type_Info& operator=(const Type_Info&) = default; - CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { - return ti.m_type_info == m_type_info - || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); + return ti.m_type_info == m_type_info; } - CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return m_type_info != nullptr && (*m_type_info) == ti; + return m_type_info == ti; } - CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { - return ti.m_bare_type_info == m_bare_type_info - || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); + return ti.m_bare_type_info == m_bare_type_info; } - CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return m_bare_type_info != nullptr - && (*m_bare_type_info) == ti; + return m_bare_type_info == ti; } - CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } - CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } - CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } - CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } - CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } + bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; } + bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { - if (m_type_info) + if (m_is_undef) { - return m_type_info->name(); + return m_type_info.name(); } else { return ""; } @@ -102,22 +103,22 @@ namespace chaiscript std::string bare_name() const { - if (m_bare_type_info) + if (m_is_undef) { - return m_bare_type_info->name(); + return m_bare_type_info.name(); } else { return ""; } } - CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + const std::type_index &bare_type_info() const { return m_bare_type_info; } private: - const std::type_info *m_type_info; - const std::type_info *m_bare_type_info; + std::type_index m_type_info; + std::type_index m_bare_type_info; bool m_is_const; bool m_is_reference; bool m_is_pointer; @@ -139,8 +140,8 @@ namespace chaiscript return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - &typeid(T), - &typeid(typename Bare_Type::type)); + typeid(T), + typeid(typename Bare_Type::type)); } }; @@ -154,8 +155,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - &typeid(std::shared_ptr ), - &typeid(typename Bare_Type::type)); + typeid(std::shared_ptr ), + typeid(typename Bare_Type::type)); } }; @@ -169,8 +170,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - &typeid(const std::shared_ptr &), - &typeid(typename Bare_Type::type)); + typeid(const std::shared_ptr &), + typeid(typename Bare_Type::type)); } }; @@ -184,8 +185,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - &typeid(std::reference_wrapper ), - &typeid(typename Bare_Type::type)); + typeid(std::reference_wrapper ), + typeid(typename Bare_Type::type)); } }; @@ -199,8 +200,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - &typeid(const std::reference_wrapper &), - &typeid(typename Bare_Type::type)); + typeid(const std::reference_wrapper &), + typeid(typename Bare_Type::type)); } }; From aa60cffe852b02823f128b87368920aa8e8c8490 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 13:34:34 -0600 Subject: [PATCH 033/116] Add g++5.1 cleanup coverity use --- .travis.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 91866bf..b3ba313 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ compiler: - gcc env: matrix: - - GCC_VER=4.6 - - GCC_VER=4.8 - + - CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6" + - CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" + - CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1 global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= @@ -17,16 +17,18 @@ before_install: - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - sudo apt-get install -qq g++-4.8 - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" COVERALLS="1" CPPCHECK="1"; else export GCOV="gcov"; fi + - if [ "$CXX" = "g++-4.8" ]; then sudo apt-get install -qq g++-4.8; fi + - if [ "$CXX" = "g++-5.1" ]; then sudo apt-get install -qq g++-5.1; fi + script: - - if [ ${COVERITY_SCAN_BRANCH} = 1 ]; then cat cov-int/build-log.txt; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make test ; fi - - if [ ${COVERITY_SCAN_BRANCH} != 1 && ${COVERALLS} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + - make test + - if [ ${COVERALLS} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + after_script: - - if [ ${COVERITY_SCAN_BRANCH} != 1 && ${COVERALLS} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi + - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi + notifications: email: recipients: @@ -46,7 +48,7 @@ addons: name: "ChaiScript/ChaiScript" description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com - build_command_prepend: "cmake ." + build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . " build_command: "cmake --build . --target chai" branch_pattern: coverity_scan From ee672f5132c2404731a7045103375242ed00ec1b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 13:43:49 -0600 Subject: [PATCH 034/116] Further travis / coverity cleanups --- .travis.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3ba313..1fdaf71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ compiler: - gcc env: matrix: - - CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6" - - CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" - - CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1 + - GCC_VER="4.8" + - GCC_VER="4.6" + - GCC_VER="5.1" global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= @@ -14,11 +14,14 @@ env: - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" before_install: + - if [ "$GCC_VER" = "4.6" ]; export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi + - if [ "$GCC_VER" = "4.8" ]; export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi + - if [ "$GCC_VER" = "5.1" ]; export CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - if [ "$CXX" = "g++-4.8" ]; then sudo apt-get install -qq g++-4.8; fi - - if [ "$CXX" = "g++-5.1" ]; then sudo apt-get install -qq g++-5.1; fi + - if [ "$GCC_VER" = "4.8" ]; then sudo apt-get install -qq g++-4.8; fi + - if [ "$GCC_VER" = "5.1" ]; then sudo apt-get install -qq g++-5.1; fi script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi @@ -49,7 +52,7 @@ addons: description: "Build submitted via Travis CI" notification_email: jason@emptycrate.com build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . " - build_command: "cmake --build . --target chai" + build_command: "cmake --build . -- -j2" branch_pattern: coverity_scan From 114e3939f69bbff1b77d5f8992a204d843489775 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 13:55:34 -0600 Subject: [PATCH 035/116] Fix shell if command in travis --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1fdaf71..cdd8245 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ env: - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" before_install: - - if [ "$GCC_VER" = "4.6" ]; export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi - - if [ "$GCC_VER" = "4.8" ]; export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi - - if [ "$GCC_VER" = "5.1" ]; export CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1; fi + - if [ "$GCC_VER" = "4.6" ]; then export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi + - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi + - if [ "$GCC_VER" = "5.1" ]; then export CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update From d2f855e3f9ac119b94206f11063f23a5254a3a79 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 14:07:29 -0600 Subject: [PATCH 036/116] Cleanup g++-5 support for travis --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index cdd8245..2f8a07d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,9 @@ compiler: - gcc env: matrix: - - GCC_VER="4.8" - GCC_VER="4.6" - - GCC_VER="5.1" + - GCC_VER="4.8" + - GCC_VER="5" global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= @@ -15,13 +15,13 @@ env: before_install: - if [ "$GCC_VER" = "4.6" ]; then export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; fi - - if [ "$GCC_VER" = "5.1" ]; then export CXX="g++-5.1" CC="gcc-5.1" GCOV="gcov-5.1" COVERALLS=1 CPPCHECK=1; fi + - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" COVERALLS=1 CPPCHECK=1; fi + - if [ "$GCC_VER" = "5" ]; then export CXX="g++-5" CC="gcc-5" GCOV="gcov-5"; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - if [ "$GCC_VER" = "4.8" ]; then sudo apt-get install -qq g++-4.8; fi - - if [ "$GCC_VER" = "5.1" ]; then sudo apt-get install -qq g++-5.1; fi + - if [ "$GCC_VER" = "5" ]; then sudo apt-get install -qq g++-5; fi script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi From ac280a69712c83bbc0583997f19a16e8ba062d9b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 14:14:48 -0600 Subject: [PATCH 037/116] Fix name() lookups --- include/chaiscript/dispatchkit/type_info.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 0bee9c6..e92fe23 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -93,7 +93,7 @@ namespace chaiscript std::string name() const { - if (m_is_undef) + if (!m_is_undef) { return m_type_info.name(); } else { @@ -103,7 +103,7 @@ namespace chaiscript std::string bare_name() const { - if (m_is_undef) + if (!m_is_undef) { return m_bare_type_info.name(); } else { From 4b577f1f2ac0fa89b6d71031ade1f1484bf1e46f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 15:15:08 -0600 Subject: [PATCH 038/116] Undefined types are never equal --- include/chaiscript/dispatchkit/type_info.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index e92fe23..a15c245 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -71,7 +71,8 @@ namespace chaiscript bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return m_type_info == ti; + return !m_is_undef + && m_type_info == ti; } bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT @@ -81,7 +82,8 @@ namespace chaiscript bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return m_bare_type_info == ti; + return !m_is_undef + && m_bare_type_info == ti; } bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } From 023a3edf40ff5405ac47df55415d2a5b01b0f801 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 15:36:25 -0600 Subject: [PATCH 039/116] Fix static usage of Type_Info objects --- include/chaiscript/dispatchkit/dispatchkit.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index be4d8a7..02822b1 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1176,11 +1176,11 @@ namespace chaiscript const auto rhssize = rhsparamtypes.size(); #ifdef CHAISCRIPT_HAS_MAGIC_STATICS - auto boxed_type = user_type(); - auto boxed_pod_type = user_type(); -#else static auto boxed_type = user_type(); static auto boxed_pod_type = user_type(); +#else + auto boxed_type = user_type(); + auto boxed_pod_type = user_type(); #endif for (size_t i = 1; i < lhssize && i < rhssize; ++i) From 61d5e2ad85c2d81a74bc2dc94d0a52e917eb5477 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 15:47:22 -0600 Subject: [PATCH 040/116] Revert "Work around coverity crash" This reverts commit bb0d1005138e53cb2d414401f0338f22fbbc636b. Conflicts: include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_info.hpp --- .../dispatchkit/type_conversions.hpp | 13 ++- include/chaiscript/dispatchkit/type_info.hpp | 81 +++++++++---------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index a08addd..a5abed4 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -300,6 +300,13 @@ namespace chaiscript class Type_Conversions { public: + struct Less_Than + { + bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const + { + return *t_lhs != *t_rhs && t_lhs->before(*t_rhs); + } + }; Type_Conversions() : m_mutex(), @@ -322,7 +329,7 @@ namespace chaiscript { } - const std::set &thread_cache() const + const std::set &thread_cache() const { auto &cache = *m_thread_cache; if (cache.size() != m_num_types) @@ -459,9 +466,9 @@ namespace chaiscript mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; - std::set m_convertableTypes; + std::set m_convertableTypes; std::atomic_size_t m_num_types; - mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; + mutable chaiscript::detail::threading::Thread_Storage> m_thread_cache; mutable chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index a15c245..de61ab6 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include namespace chaiscript @@ -29,12 +28,9 @@ namespace chaiscript /// \brief Compile time deduced information about a type class Type_Info { - private: - class Undef {}; - public: - Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, - bool t_is_arithmetic, const std::type_index &t_ti, const std::type_index &t_bare_ti) + CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic), @@ -42,8 +38,8 @@ namespace chaiscript { } - Type_Info() - : m_type_info(typeid(Type_Info::Undef)), m_bare_type_info(typeid(Type_Info::Undef)), + CHAISCRIPT_CONSTEXPR Type_Info() + : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), m_is_undef(true) @@ -59,45 +55,46 @@ namespace chaiscript Type_Info& operator=(const Type_Info&) = default; - bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { - return ti.m_type_info == m_type_info; + return ti.m_type_info == m_type_info + || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } - bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return !m_is_undef - && m_type_info == ti; + return m_type_info != nullptr && (*m_type_info) == ti; } - bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { - return ti.m_bare_type_info == m_bare_type_info; + return ti.m_bare_type_info == m_bare_type_info + || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); } - bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { - return !m_is_undef - && m_bare_type_info == ti; + return m_bare_type_info != nullptr + && (*m_bare_type_info) == ti; } - bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } - bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } - bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } - bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; } - bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } + CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { - if (!m_is_undef) + if (m_type_info) { - return m_type_info.name(); + return m_type_info->name(); } else { return ""; } @@ -105,22 +102,22 @@ namespace chaiscript std::string bare_name() const { - if (!m_is_undef) + if (m_bare_type_info) { - return m_bare_type_info.name(); + return m_bare_type_info->name(); } else { return ""; } } - const std::type_index &bare_type_info() const + CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const { return m_bare_type_info; } private: - std::type_index m_type_info; - std::type_index m_bare_type_info; + const std::type_info *m_type_info; + const std::type_info *m_bare_type_info; bool m_is_const; bool m_is_reference; bool m_is_pointer; @@ -142,8 +139,8 @@ namespace chaiscript return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - typeid(T), - typeid(typename Bare_Type::type)); + &typeid(T), + &typeid(typename Bare_Type::type)); } }; @@ -157,8 +154,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - typeid(std::shared_ptr ), - typeid(typename Bare_Type::type)); + &typeid(std::shared_ptr ), + &typeid(typename Bare_Type::type)); } }; @@ -172,8 +169,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - typeid(const std::shared_ptr &), - typeid(typename Bare_Type::type)); + &typeid(const std::shared_ptr &), + &typeid(typename Bare_Type::type)); } }; @@ -187,8 +184,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - typeid(std::reference_wrapper ), - typeid(typename Bare_Type::type)); + &typeid(std::reference_wrapper ), + &typeid(typename Bare_Type::type)); } }; @@ -202,8 +199,8 @@ namespace chaiscript return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, - typeid(const std::reference_wrapper &), - typeid(typename Bare_Type::type)); + &typeid(const std::reference_wrapper &), + &typeid(typename Bare_Type::type)); } }; From d13d080dee7ae7ae8ba3c85e294ec0cd9687fc14 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 15:50:21 -0600 Subject: [PATCH 041/116] Remove constexpr from type_info --- include/chaiscript/dispatchkit/type_info.hpp | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index de61ab6..1db31be 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -29,7 +29,7 @@ namespace chaiscript class Type_Info { public: - CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), @@ -38,7 +38,7 @@ namespace chaiscript { } - CHAISCRIPT_CONSTEXPR Type_Info() + Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), @@ -55,40 +55,40 @@ namespace chaiscript Type_Info& operator=(const Type_Info&) = default; - CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_type_info == m_type_info || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } - CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info != nullptr && (*m_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_bare_type_info == m_bare_type_info || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); } - CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_bare_type_info != nullptr && (*m_bare_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } - CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } - CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } - CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } - CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } + bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { @@ -110,7 +110,7 @@ namespace chaiscript } } - CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + const std::type_info *bare_type_info() const { return m_bare_type_info; } @@ -134,7 +134,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -149,7 +149,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -164,7 +164,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -179,7 +179,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -194,7 +194,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -216,7 +216,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(i); /// \endcode template - CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/) + Type_Info user_type(const T &/*t*/) { return detail::Get_Type_Info::get(); } @@ -231,7 +231,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(); /// \endcode template - CHAISCRIPT_CONSTEXPR Type_Info user_type() + Type_Info user_type() { return detail::Get_Type_Info::get(); } From 3701477f7f78ad77aa6d93fa358cf6df161bdc5b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 16:03:23 -0600 Subject: [PATCH 042/116] More cleanups to travis configuration --- .travis.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f8a07d..e701d49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,23 +5,19 @@ env: matrix: - GCC_VER="4.6" - GCC_VER="4.8" - - GCC_VER="5" global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created - # via the "travis encrypt" command using the project repo's public key - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" before_install: - - if [ "$GCC_VER" = "4.6" ]; then export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8" COVERALLS=1 CPPCHECK=1; fi - - if [ "$GCC_VER" = "5" ]; then export CXX="g++-5" CC="gcc-5" GCOV="gcov-5"; fi + - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" + - if [ "$GCC_VER" = "4.8" ]; then export COVERALLS=1 CPPCHECK=1; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - if [ "$GCC_VER" = "4.8" ]; then sudo apt-get install -qq g++-4.8; fi - - if [ "$GCC_VER" = "5" ]; then sudo apt-get install -qq g++-5; fi + - apt-get install -qq g++-$GCC_VER script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi From f6600c90e4cad2a62799a6780c902f908fc848f1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 16:07:12 -0600 Subject: [PATCH 043/116] Correct missing 'sudo' for travis setup --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e701d49..ab4e905 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ before_install: - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - apt-get install -qq g++-$GCC_VER + - sudo apt-get install -qq g++-$GCC_VER script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi From cff635fb6578a16a5e8e649d63dfd9936fb35d4a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 17:02:06 -0600 Subject: [PATCH 044/116] Enable 'codecov' --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ab4e905..6b89a0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ env: before_install: - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" - - if [ "$GCC_VER" = "4.8" ]; then export COVERALLS=1 CPPCHECK=1; fi + - if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update @@ -23,11 +23,14 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - if [ ${COVERALLS} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi after_script: - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi +after_success: + - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi + notifications: email: recipients: From 916708ce295500da9abbee4b5faa0ac09683ba58 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 17:22:00 -0600 Subject: [PATCH 045/116] Disable coveralls, use codecov --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6b89a0f..db11991 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,13 +23,12 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + # - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi after_script: - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi -after_success: - - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi notifications: email: From 2848e16ea150782757dd387a777c7645bbe192c7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 17:59:36 -0600 Subject: [PATCH 046/116] Another attempt at getting codecov working --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index db11991..386d495 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test # - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + - if [ ${COVERAGE} = 1 ]; then find . -name "*.cpp" | xargs $GCOV; fi - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi after_script: From 7f871374fa6d7246e9beb8a02a0c10c9237b1e6e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 18:07:06 -0600 Subject: [PATCH 047/116] Codecov and coveralls enabled --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 386d495..cd5886f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,8 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - # - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi - - if [ ${COVERAGE} = 1 ]; then find . -name "*.cpp" | xargs $GCOV; fi + - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + # - if [ ${COVERAGE} = 1 ]; then find . -name "*.cpp" | xargs $GCOV; fi - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi after_script: From d56e32e2c4122427d492f4ffd65bb30df62daf6b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 18:35:46 -0600 Subject: [PATCH 048/116] Tweak coveralls settings --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cd5886f..08ae996 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV ; fi + - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" -i "include/chaiscript" --gcov $GCOV --gcov-options '\-lp' ; fi # - if [ ${COVERAGE} = 1 ]; then find . -name "*.cpp" | xargs $GCOV; fi - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi From 9fe8150861a817c26d33588010de41a8237d0538 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 18:48:27 -0600 Subject: [PATCH 049/116] Wrap up the coveralls / codecov choices --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 08ae996..458ccd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,9 +23,7 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" -i "include/chaiscript" --gcov $GCOV --gcov-options '\-lp' ; fi - # - if [ ${COVERAGE} = 1 ]; then find . -name "*.cpp" | xargs $GCOV; fi - - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://codecov.io/bash); fi + - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV --gcov-options '\-lp' ; fi after_script: - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi From da8fa77558f2772427d89ce13ec7a19e3e51b2df Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 30 May 2015 18:48:55 -0600 Subject: [PATCH 050/116] Update readme.md --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index cc3af26..32cb703 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,10 @@ Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScrip Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop) + + Coverity Scan Build Status + ChaiScript From 70262292733ac29e38e1041d141c72b882123f1a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 1 Jun 2015 09:43:29 -0600 Subject: [PATCH 051/116] Apply Index expansion technique to simplify code Thanks @sean-parent I saw the technique in your future implementation --- .../dispatchkit/proxy_functions_detail.hpp | 94 ++++++++----------- 1 file changed, 37 insertions(+), 57 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index b90c8d6..a77376f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -53,6 +53,23 @@ namespace chaiscript { namespace detail { + template + struct Indexes + { + }; + + template + struct Make_Indexes + { + typedef typename Make_Indexes::indexes indexes; + }; + + template + struct Make_Indexes<0, I...> + { + typedef Indexes indexes; + }; + /** * Used by Proxy_Function_Impl to return a list of all param types * it contains. @@ -65,77 +82,39 @@ namespace chaiscript } - // Forward declaration - template - struct Try_Cast; - - template - struct Try_Cast - { - static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions &t_conversions) - { - boxed_cast(params[generation], &t_conversions); - Try_Cast::do_try(params, generation+1, t_conversions); - } - }; - - // 0th case - template<> - struct Try_Cast<> - { - static void do_try(const std::vector &, size_t, const Type_Conversions &) - { - } - }; - - /** * Used by Proxy_Function_Impl to determine if it is equivalent to another * Proxy_Function_Impl object. This function is primarily used to prevent * registration of two functions with the exact same signatures */ - template - bool compare_types_cast(Ret (*)(Params...), + template + bool compare_types_cast(Indexes, Ret (*)(Params...), const std::vector ¶ms, const Type_Conversions &t_conversions) - { + { try { - Try_Cast::do_try(params, 0, t_conversions); + std::initializer_list{(boxed_cast(params[I], &t_conversions), nullptr)...}; + return true; } catch (const exception::bad_boxed_cast &) { return false; } - return true; } - template - struct Call_Func - { - - template - static Ret do_call(const std::function &f, - const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) - { - return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); - } - }; - template - struct Call_Func + bool compare_types_cast(Ret (*f)(Params...), + const std::vector ¶ms, const Type_Conversions &t_conversions) { -#ifdef CHAISCRIPT_MSVC -#pragma warning(push) -#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this -#endif - template - static Ret do_call(const std::function &f, - const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) - { - return f(boxed_cast(std::forward(innerparams), &t_conversions)...); - } -#ifdef CHAISCRIPT_MSVC -#pragma warning(pop) -#endif - }; + typedef typename Make_Indexes::indexes indexes; + return compare_types_cast(indexes(), f, params, t_conversions); + } + + template + Ret call_func(Indexes, const std::function &f, + const std::vector ¶ms, const Type_Conversions &t_conversions) + { + return f(boxed_cast(params[I], &t_conversions)...); + } + /** * Used by Proxy_Function_Impl to perform typesafe execution of a function. @@ -149,7 +128,8 @@ namespace chaiscript { if (params.size() == sizeof...(Params)) { - return Call_Func::do_call(f, params, t_conversions); + typedef typename Make_Indexes::indexes indexes; + return call_func(indexes(), f, params, t_conversions); } throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); From 520f9bc0d2c69a8735297a64fe68ebf8f73e67ad Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 1 Jun 2015 15:49:50 -0600 Subject: [PATCH 052/116] Work around bug in g++4.6 I'm going to have to start dropping support for older compilers soon. The 4.6 line is 4 years old now, and 4.7 has these issues fixed --- include/chaiscript/chaiscript_defines.hpp | 4 + .../dispatchkit/proxy_functions_detail.hpp | 119 ++++++++++++++++-- 2 files changed, 113 insertions(+), 10 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 8e45977..6d0fd99 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -35,6 +35,10 @@ #define CHAISCRIPT_HAS_THREAD_LOCAL #endif +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#define CHAISCRIPT_GCC_4_6 +#endif + #if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__) #define CHAISCRIPT_OVERRIDE override #else diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index a77376f..a98124b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -53,6 +53,113 @@ namespace chaiscript { namespace detail { + /** + * Used by Proxy_Function_Impl to return a list of all param types + * it contains. + */ + template + std::vector build_param_type_list(Ret (*)(Params...)) + { + /// \note somehow this is responsible for a large part of the code generation + return { user_type(), user_type()... }; + } + + +#ifdef CHAISCRIPT_GCC_4_6 + /// \todo REMOVE THIS WHEN WE DROP G++4.6 + + // Forward declaration + template + struct Try_Cast; + + template + struct Try_Cast + { + static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions &t_conversions) + { + boxed_cast(params[generation], &t_conversions); + Try_Cast::do_try(params, generation+1, t_conversions); + } + }; + + // 0th case + template<> + struct Try_Cast<> + { + static void do_try(const std::vector &, size_t, const Type_Conversions &) + { + } + }; + + + /** + * Used by Proxy_Function_Impl to determine if it is equivalent to another + * Proxy_Function_Impl object. This function is primarily used to prevent + * registration of two functions with the exact same signatures + */ + template + bool compare_types_cast(Ret (*)(Params...), + const std::vector ¶ms, const Type_Conversions &t_conversions) + { + try { + Try_Cast::do_try(params, 0, t_conversions); + } catch (const exception::bad_boxed_cast &) { + return false; + } + + return true; + } + + template + struct Call_Func + { + + template + static Ret do_call(const std::function &f, + const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) + { + return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); + } + }; + + template + struct Call_Func + { +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this +#endif + template + static Ret do_call(const std::function &f, + const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) + { + return f(boxed_cast(std::forward(innerparams), &t_conversions)...); + } +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif + }; + + /** + * Used by Proxy_Function_Impl to perform typesafe execution of a function. + * The function attempts to unbox each parameter to the expected type. + * if any unboxing fails the execution of the function fails and + * the bad_boxed_cast is passed up to the caller. + */ + template + Ret call_func(const std::function &f, + const std::vector ¶ms, const Type_Conversions &t_conversions) + { + if (params.size() == sizeof...(Params)) + { + return Call_Func::do_call(f, params, t_conversions); + } + + throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); + } + +#else + template struct Indexes { @@ -70,16 +177,6 @@ namespace chaiscript typedef Indexes indexes; }; - /** - * Used by Proxy_Function_Impl to return a list of all param types - * it contains. - */ - template - std::vector build_param_type_list(Ret (*)(Params...)) - { - /// \note somehow this is responsible for a large part of the code generation - return { user_type(), user_type()... }; - } /** @@ -135,6 +232,8 @@ namespace chaiscript throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); } +#endif + } } From 26a00341761dfefdf624c9ec3ca8878160d0de5f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 1 Jun 2015 16:07:10 -0600 Subject: [PATCH 053/116] Fixes for g++4.6 --- include/chaiscript/chaiscript_defines.hpp | 2 +- .../dispatchkit/proxy_functions_detail.hpp | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 6d0fd99..5b3bea5 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -35,7 +35,7 @@ #define CHAISCRIPT_HAS_THREAD_LOCAL #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6) #define CHAISCRIPT_GCC_4_6 #endif diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index d8a10cc..8257f9b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -68,7 +68,10 @@ namespace chaiscript #ifdef CHAISCRIPT_GCC_4_6 /// \todo REMOVE THIS WHEN WE DROP G++4.6 - + // + // + + // Forward declaration template struct Try_Cast; @@ -101,7 +104,7 @@ namespace chaiscript template bool compare_types_cast(Ret (*)(Params...), const std::vector ¶ms, const Type_Conversions &t_conversions) - { + { try { Try_Cast::do_try(params, 0, t_conversions); } catch (const exception::bad_boxed_cast &) { @@ -115,8 +118,8 @@ namespace chaiscript struct Call_Func { - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); @@ -130,8 +133,8 @@ namespace chaiscript #pragma warning(push) #pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this #endif - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return f(boxed_cast(std::forward(innerparams), &t_conversions)...); @@ -147,8 +150,8 @@ namespace chaiscript * if any unboxing fails the execution of the function fails and * the bad_boxed_cast is passed up to the caller. */ - template - Ret call_func(const std::function &f, + template + Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions) { if (params.size() == sizeof...(Params)) @@ -159,6 +162,8 @@ namespace chaiscript throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); } + + #else template From 7522a19af5fd4f4e6bba53a25ef777ba18b6a206 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 1 Jun 2015 16:08:04 -0600 Subject: [PATCH 054/116] g++4.6 correction --- include/chaiscript/chaiscript_defines.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 6d0fd99..5b3bea5 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -35,7 +35,7 @@ #define CHAISCRIPT_HAS_THREAD_LOCAL #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6) #define CHAISCRIPT_GCC_4_6 #endif From 85a6d85c1f9143d38b63d2afdd6d122479757af4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 2 Jun 2015 13:53:07 -0600 Subject: [PATCH 055/116] Fix warnings - use `(void)` to avoid "unused parameter" warnings - Move to clang-3.6 for thread sanitizer - found bug in 3.5's reporting --- .decent_ci-Linux.yaml | 2 +- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 6f7125f..25cb343 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -15,7 +15,7 @@ compilers: cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON - name: "clang" build_tag: ThreadSanitizer - version: "3.5" + version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON - name: "gcc" diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index a98124b..ccfe83f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -67,7 +67,7 @@ namespace chaiscript #ifdef CHAISCRIPT_GCC_4_6 /// \todo REMOVE THIS WHEN WE DROP G++4.6 - + // Forward declaration template struct Try_Cast; @@ -189,7 +189,8 @@ namespace chaiscript const std::vector ¶ms, const Type_Conversions &t_conversions) { try { - std::initializer_list{(boxed_cast(params[I], &t_conversions), nullptr)...}; + (void)params; (void)t_conversions; + (void)std::initializer_list{(boxed_cast(params[I], &t_conversions), 0)...}; return true; } catch (const exception::bad_boxed_cast &) { return false; @@ -209,6 +210,7 @@ namespace chaiscript Ret call_func(Indexes, const std::function &f, const std::vector ¶ms, const Type_Conversions &t_conversions) { + (void)params; (void)t_conversions; return f(boxed_cast(params[I], &t_conversions)...); } From 38a83e3e56dbdcfb53b7686423d8e62b2f100e0d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 2 Jun 2015 17:35:31 -0600 Subject: [PATCH 056/116] Fix MSVC2013 builds --- include/chaiscript/dispatchkit/callable_traits.hpp | 14 ++++++++++++++ include/chaiscript/dispatchkit/handle_return.hpp | 1 - .../chaiscript/dispatchkit/register_function.hpp | 5 ++--- include/chaiscript/language/chaiscript_parser.hpp | 2 -- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index 5ffa093..9954eea 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -12,6 +12,7 @@ namespace chaiscript { namespace dispatch { namespace detail { + template struct Constructor { @@ -34,6 +35,19 @@ namespace chaiscript { Ret (Class::*m_func)(Param...) const; }; + template + struct Fun_Caller + { + Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {} + + template + Ret operator()(Inner&& ... inner) const { + return (m_func)(std::forward(inner)...); + } + + Ret(*m_func)(Param...); + }; + template struct Caller { diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index d5bdb9d..e3a8254 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -9,7 +9,6 @@ #include #include -#include #include #include "boxed_number.hpp" diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index ecec5ea..598dd8b 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -7,7 +7,6 @@ #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #define CHAISCRIPT_REGISTER_FUNCTION_HPP_ -#include #include #include "bind_first.hpp" @@ -48,10 +47,10 @@ namespace chaiscript template Proxy_Function fun(Ret (*func)(Param...)) { - auto f_ref = std::ref(*func); + auto fun_call = dispatch::detail::Fun_Caller(func); return Proxy_Function( - chaiscript::make_shared>(f_ref)); + chaiscript::make_shared>(fun_call)); } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 1fdc4f5..e35165b 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -7,8 +7,6 @@ #ifndef CHAISCRIPT_PARSER_HPP_ #define CHAISCRIPT_PARSER_HPP_ -#include -#include #include #include #include From ecafb4aad02356badd6eb3f92bf6af03329ab4e1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 2 Jun 2015 18:20:13 -0600 Subject: [PATCH 057/116] Add missing cstring --- include/chaiscript/language/chaiscript_parser.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e35165b..7588d40 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -14,6 +14,8 @@ #include #include #include +#include + #include "../dispatchkit/boxed_value.hpp" #include "chaiscript_common.hpp" From b163065b3c02f64489d6b54c40d3662b3944f7c6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 06:25:41 -0600 Subject: [PATCH 058/116] Begin simplifying boxed_number implementation --- .../chaiscript/dispatchkit/boxed_number.hpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index a57ed7a..69073ac 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -476,37 +476,37 @@ namespace chaiscript const Type_Info &inp_ = bv.get_type_info(); if (inp_ == typeid(int)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(double)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(float)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(long double)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(char)) { - return to_string_aux(Boxed_Value(get_as_aux())); + return std::to_string(get_as()); } else if (inp_ == typeid(unsigned int)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(long)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(unsigned long)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::int8_t)) { - return to_string_aux(Boxed_Value(get_as_aux())); + return std::to_string(get_as()); } else if (inp_ == typeid(std::int16_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::int32_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::int64_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::uint8_t)) { - return to_string_aux(Boxed_Value(get_as_aux())); + return std::to_string(get_as()); } else if (inp_ == typeid(std::uint16_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::uint32_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else if (inp_ == typeid(std::uint64_t)) { - return to_string_aux(bv); + return std::to_string(get_as()); } else { throw chaiscript::detail::exception::bad_any_cast(); } From e759a0c544b9961b0fca69eb03a9666955191860 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 07:00:28 -0600 Subject: [PATCH 059/116] Reduce template instantiations --- include/chaiscript/dispatchkit/boxed_number.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 69073ac..f67f1f7 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -459,13 +459,13 @@ namespace chaiscript } else if (inp_ == typeid(std::int64_t)) { return get_as_aux(); } else if (inp_ == typeid(std::uint8_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint16_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint32_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint64_t)) { - return get_as_aux(); + return get_as_aux(); } else { throw chaiscript::detail::exception::bad_any_cast(); } From c6c2bcc02318e8319af862175f7efa71b9e9be27 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 08:59:01 -0600 Subject: [PATCH 060/116] More template reduction in Boxed_Number --- .../chaiscript/dispatchkit/boxed_number.hpp | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index f67f1f7..fd6de05 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -229,17 +229,18 @@ namespace chaiscript { static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { + typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return boolean::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary_int::go(t_oper, *static_cast(t_lhs.get_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return binary_int::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - return const_binary_int::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return const_binary_int::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return const_binary::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -251,17 +252,18 @@ namespace chaiscript { static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { + typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return boolean::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, *static_cast(t_lhs.get_const_ptr()), *static_cast(t_rhs.get_const_ptr()), t_lhs); + return const_binary::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -352,10 +354,16 @@ namespace chaiscript } template - Target get_as_aux() const - { - return static_cast(*static_cast(bv.get_const_ptr())); - } + inline Target get_as_aux() const + { + return get_as_aux_impl(bv); + } + + template + static inline Target get_as_aux_impl(const Boxed_Value &t_bv) + { + return static_cast(*static_cast(t_bv.get_const_ptr())); + } template static std::string to_string_aux(const Boxed_Value &v) From 78819fd3a8c2c8a22f3b97202a1e9b792ca2c098 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 18:39:49 -0600 Subject: [PATCH 061/116] fixed boxed_number to_string impl --- include/chaiscript/dispatchkit/boxed_number.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index fd6de05..9b8f774 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -467,13 +467,13 @@ namespace chaiscript } else if (inp_ == typeid(std::int64_t)) { return get_as_aux(); } else if (inp_ == typeid(std::uint8_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint16_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint32_t)) { - return get_as_aux(); + return get_as_aux(); } else if (inp_ == typeid(std::uint64_t)) { - return get_as_aux(); + return get_as_aux(); } else { throw chaiscript::detail::exception::bad_any_cast(); } From 1e41e73af288134a4cac406da1b4f2b7985b04f5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 19:17:58 -0600 Subject: [PATCH 062/116] Simplify boxed_number templates --- .../chaiscript/dispatchkit/boxed_number.hpp | 422 +++++++++--------- 1 file changed, 201 insertions(+), 221 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 9b8f774..1171517 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -60,7 +60,7 @@ namespace chaiscript { private: template - static void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) + static inline void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) { #ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO if (t == 0) { @@ -70,243 +70,223 @@ namespace chaiscript } template - static void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) + static inline void check_divide_by_zero(T, typename std::enable_if::value>::type* = nullptr) { } - struct boolean + template + static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) { - - template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + switch (t_oper) { - switch (t_oper) - { - case Operators::equals: - return const_var(t == u); - case Operators::less_than: - return const_var(t < u); - case Operators::greater_than: - return const_var(t > u); - case Operators::less_than_equal: - return const_var(t <= u); - case Operators::greater_than_equal: - return const_var(t >= u); - case Operators::not_equal: - return const_var(t != u); - default: - throw chaiscript::detail::exception::bad_any_cast(); - } - } - }; - - struct binary - { - template - static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) - { - switch (t_oper) - { - case Operators::assign: - t = u; - break; - case Operators::pre_increment: - ++t; - break; - case Operators::pre_decrement: - --t; - break; - case Operators::assign_product: - t *= u; - break; - case Operators::assign_sum: - t += u; - break; - case Operators::assign_quotient: - check_divide_by_zero(u); - t /= u; - break; - case Operators::assign_difference: - t -= u; - break; - default: - throw chaiscript::detail::exception::bad_any_cast(); - } - - return t_lhs; - } - }; - - struct binary_int - { - template - static Boxed_Value go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) - { - switch (t_oper) - { - case Operators::assign_bitwise_and: - t &= u; - break; - case Operators::assign_bitwise_or: - t |= u; - break; - case Operators::assign_shift_left: - t <<= u; - break; - case Operators::assign_shift_right: - t >>= u; - break; - case Operators::assign_remainder: - check_divide_by_zero(u); - t %= u; - break; - case Operators::assign_bitwise_xor: - t ^= u; - break; - default: - throw chaiscript::detail::exception::bad_any_cast(); - } - return t_lhs; - } - }; - - struct const_binary_int - { - template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) - { - switch (t_oper) - { - case Operators::shift_left: - return const_var(t << u); - case Operators::shift_right: - return const_var(t >> u); - case Operators::remainder: - check_divide_by_zero(u); - return const_var(t % u); - case Operators::bitwise_and: - return const_var(t & u); - case Operators::bitwise_or: - return const_var(t | u); - case Operators::bitwise_xor: - return const_var(t ^ u); - case Operators::bitwise_complement: - return const_var(~t); - default: - throw chaiscript::detail::exception::bad_any_cast(); - } - } - }; - - struct const_binary - { - template - static Boxed_Value go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) - { - switch (t_oper) - { - case Operators::sum: - return const_var(t + u); - case Operators::quotient: - check_divide_by_zero(u); - return const_var(t / u); - case Operators::product: - return const_var(t * u); - case Operators::difference: - return const_var(t - u); - case Operators::unary_minus: - return const_var(-t); - case Operators::unary_plus: - return const_var(+t); - default: - throw chaiscript::detail::exception::bad_any_cast(); - } - } - }; - - template - struct Go - { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) - { - typedef typename std::common_type::type common_type; - if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) - { - return boolean::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary_int::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - return const_binary_int::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); - } else { + case Operators::equals: + return const_var(t == u); + case Operators::less_than: + return const_var(t < u); + case Operators::greater_than: + return const_var(t > u); + case Operators::less_than_equal: + return const_var(t <= u); + case Operators::greater_than_equal: + return const_var(t >= u); + case Operators::not_equal: + return const_var(t != u); + default: throw chaiscript::detail::exception::bad_any_cast(); - } } - }; + } + + template + static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) + { + switch (t_oper) + { + case Operators::assign: + t = u; + break; + case Operators::pre_increment: + ++t; + break; + case Operators::pre_decrement: + --t; + break; + case Operators::assign_product: + t *= u; + break; + case Operators::assign_sum: + t += u; + break; + case Operators::assign_quotient: + check_divide_by_zero(u); + t /= u; + break; + case Operators::assign_difference: + t -= u; + break; + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + + return t_lhs; + } + + template + static Boxed_Value binary_int_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) + { + switch (t_oper) + { + case Operators::assign_bitwise_and: + t &= u; + break; + case Operators::assign_bitwise_or: + t |= u; + break; + case Operators::assign_shift_left: + t <<= u; + break; + case Operators::assign_shift_right: + t >>= u; + break; + case Operators::assign_remainder: + check_divide_by_zero(u); + t %= u; + break; + case Operators::assign_bitwise_xor: + t ^= u; + break; + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + return t_lhs; + } + + template + static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + { + switch (t_oper) + { + case Operators::shift_left: + return const_var(t << u); + case Operators::shift_right: + return const_var(t >> u); + case Operators::remainder: + check_divide_by_zero(u); + return const_var(t % u); + case Operators::bitwise_and: + return const_var(t & u); + case Operators::bitwise_or: + return const_var(t | u); + case Operators::bitwise_xor: + return const_var(t ^ u); + case Operators::bitwise_complement: + return const_var(~t); + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + template + static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + { + switch (t_oper) + { + case Operators::sum: + return const_var(t + u); + case Operators::quotient: + check_divide_by_zero(u); + return const_var(t / u); + case Operators::product: + return const_var(t * u); + case Operators::difference: + return const_var(t - u); + case Operators::unary_minus: + return const_var(-t); + case Operators::unary_plus: + return const_var(+t); + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + } template - struct Go + static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + -> typename std::enable_if::value && !std::is_floating_point::value, Boxed_Value>::type { - static Boxed_Value go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + typedef typename std::common_type::type common_type; + if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - typedef typename std::common_type::type common_type; - if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) - { - return boolean::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary::go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); - } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { - throw chaiscript::detail::exception::bad_any_cast(); - } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - throw chaiscript::detail::exception::bad_any_cast(); - } else if (t_oper > Operators::const_flag) { - return const_binary::go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } + return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { + return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { + return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { + return const_binary_int_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::const_flag) { + return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + } else { + throw chaiscript::detail::exception::bad_any_cast(); } - }; + } - template + template + static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + -> typename std::enable_if::value || std::is_floating_point::value, Boxed_Value>::type + { + typedef typename std::common_type::type common_type; + if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) + { + return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { + return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { + throw chaiscript::detail::exception::bad_any_cast(); + } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { + throw chaiscript::detail::exception::bad_any_cast(); + } else if (t_oper > Operators::const_flag) { + return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + template static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { const auto &inp_ = t_rhs.get_type_info(); if (inp_ == typeid(int)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(float)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long double)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(unsigned int)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(unsigned long)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int32_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint16_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint32_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint64_t)) { - return Go::go(t_oper, t_lhs, t_rhs); + return go(t_oper, t_lhs, t_rhs); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -317,37 +297,37 @@ namespace chaiscript const Type_Info &inp_ = t_lhs.get_type_info(); if (inp_ == typeid(int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long double)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(float)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(unsigned int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(unsigned long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint16_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint64_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + return oper_rhs(t_oper, t_lhs, t_rhs); } else { throw chaiscript::detail::exception::bad_any_cast(); } From be159759ea03c102893cf45119a11e364f728feb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 3 Jun 2015 21:24:09 -0600 Subject: [PATCH 063/116] Further boxed_number simplification --- .../chaiscript/dispatchkit/boxed_number.hpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 1171517..4c0ef65 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -74,8 +74,8 @@ namespace chaiscript { } - template - static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + template + static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { @@ -160,8 +160,8 @@ namespace chaiscript return t_lhs; } - template - static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + template + static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { @@ -185,8 +185,8 @@ namespace chaiscript } } - template - static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const U &u, const Boxed_Value &) + template + static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const T &u) { switch (t_oper) { @@ -215,15 +215,15 @@ namespace chaiscript typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - return const_binary_int_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + return const_binary_int_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); } else if (t_oper > Operators::const_flag) { - return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -236,7 +236,7 @@ namespace chaiscript typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { @@ -244,7 +244,7 @@ namespace chaiscript } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_flag) { - return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs), t_lhs); + return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } From 59eecab0e80c9754e7545b152187934dce82d87d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 4 Jun 2015 08:28:38 -0600 Subject: [PATCH 064/116] Remove redundant Boxed_Number type operations --- .../chaiscript/dispatchkit/boxed_number.hpp | 60 ++++--------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 4c0ef65..c911aa5 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -255,8 +255,8 @@ namespace chaiscript { const auto &inp_ = t_rhs.get_type_info(); - if (inp_ == typeid(int)) { - return go(t_oper, t_lhs, t_rhs); + if (inp_ == typeid(std::int32_t)) { + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(float)) { @@ -265,18 +265,10 @@ namespace chaiscript return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned int)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned long)) { - return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int32_t)) { - return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { @@ -296,8 +288,8 @@ namespace chaiscript { const Type_Info &inp_ = t_lhs.get_type_info(); - if (inp_ == typeid(int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + if (inp_ == typeid(std::int32_t)) { + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long double)) { @@ -306,18 +298,10 @@ namespace chaiscript return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { @@ -380,8 +364,8 @@ namespace chaiscript Boxed_Number get_as(const Type_Info &inp_) const { - if (inp_.bare_equal_type_info(typeid(int))) { - return Boxed_Number(get_as()); + if (inp_.bare_equal_type_info(typeid(int32_t))) { + return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(float))) { @@ -390,18 +374,10 @@ namespace chaiscript return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char))) { return Boxed_Number(get_as()); - } else if (inp_.bare_equal_type_info(typeid(unsigned int))) { - return Boxed_Number(get_as()); - } else if (inp_.bare_equal_type_info(typeid(long))) { - return Boxed_Number(get_as()); - } else if (inp_.bare_equal_type_info(typeid(unsigned long))) { - return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int16_t))) { return Boxed_Number(get_as()); - } else if (inp_.bare_equal_type_info(typeid(int32_t))) { - return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int64_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint8_t))) { @@ -422,8 +398,8 @@ namespace chaiscript { const Type_Info &inp_ = bv.get_type_info(); - if (inp_ == typeid(int)) { - return get_as_aux(); + if (inp_ == typeid(std::int32_t)) { + return get_as_aux(); } else if (inp_ == typeid(double)) { return get_as_aux(); } else if (inp_ == typeid(float)) { @@ -432,18 +408,10 @@ namespace chaiscript return get_as_aux(); } else if (inp_ == typeid(char)) { return get_as_aux(); - } else if (inp_ == typeid(unsigned int)) { - return get_as_aux(); - } else if (inp_ == typeid(long)) { - return get_as_aux(); - } else if (inp_ == typeid(unsigned long)) { - return get_as_aux(); } else if (inp_ == typeid(std::int8_t)) { return get_as_aux(); } else if (inp_ == typeid(std::int16_t)) { return get_as_aux(); - } else if (inp_ == typeid(std::int32_t)) { - return get_as_aux(); } else if (inp_ == typeid(std::int64_t)) { return get_as_aux(); } else if (inp_ == typeid(std::uint8_t)) { @@ -463,8 +431,8 @@ namespace chaiscript { const Type_Info &inp_ = bv.get_type_info(); - if (inp_ == typeid(int)) { - return std::to_string(get_as()); + if (inp_ == typeid(std::int32_t)) { + return std::to_string(get_as()); } else if (inp_ == typeid(double)) { return std::to_string(get_as()); } else if (inp_ == typeid(float)) { @@ -473,18 +441,10 @@ namespace chaiscript return std::to_string(get_as()); } else if (inp_ == typeid(char)) { return std::to_string(get_as()); - } else if (inp_ == typeid(unsigned int)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(long)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(unsigned long)) { - return std::to_string(get_as()); } else if (inp_ == typeid(std::int8_t)) { return std::to_string(get_as()); } else if (inp_ == typeid(std::int16_t)) { return std::to_string(get_as()); - } else if (inp_ == typeid(std::int32_t)) { - return std::to_string(get_as()); } else if (inp_ == typeid(std::int64_t)) { return std::to_string(get_as()); } else if (inp_ == typeid(std::uint8_t)) { From e4be97eb79c435f788b112765f0cb144fac41636 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 4 Jun 2015 11:04:21 -0600 Subject: [PATCH 065/116] Revert "Remove redundant Boxed_Number type operations" This reverts commit 59eecab0e80c9754e7545b152187934dce82d87d. --- .../chaiscript/dispatchkit/boxed_number.hpp | 60 +++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index c911aa5..4c0ef65 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -255,8 +255,8 @@ namespace chaiscript { const auto &inp_ = t_rhs.get_type_info(); - if (inp_ == typeid(std::int32_t)) { - return go(t_oper, t_lhs, t_rhs); + if (inp_ == typeid(int)) { + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(float)) { @@ -265,10 +265,18 @@ namespace chaiscript return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { return go(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(unsigned int)) { + return go(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(long)) { + return go(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(unsigned long)) { + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { return go(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(std::int32_t)) { + return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { return go(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { @@ -288,8 +296,8 @@ namespace chaiscript { const Type_Info &inp_ = t_lhs.get_type_info(); - if (inp_ == typeid(std::int32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); + if (inp_ == typeid(int)) { + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(double)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(long double)) { @@ -298,10 +306,18 @@ namespace chaiscript return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(char)) { return oper_rhs(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(unsigned int)) { + return oper_rhs(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(long)) { + return oper_rhs(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(unsigned long)) { + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int8_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int16_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); + } else if (inp_ == typeid(std::int32_t)) { + return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::int64_t)) { return oper_rhs(t_oper, t_lhs, t_rhs); } else if (inp_ == typeid(std::uint8_t)) { @@ -364,8 +380,8 @@ namespace chaiscript Boxed_Number get_as(const Type_Info &inp_) const { - if (inp_.bare_equal_type_info(typeid(int32_t))) { - return Boxed_Number(get_as()); + if (inp_.bare_equal_type_info(typeid(int))) { + return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(double))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(float))) { @@ -374,10 +390,18 @@ namespace chaiscript return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char))) { return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(unsigned int))) { + return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(long))) { + return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(unsigned long))) { + return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int8_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int16_t))) { return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(int32_t))) { + return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(int64_t))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(uint8_t))) { @@ -398,8 +422,8 @@ namespace chaiscript { const Type_Info &inp_ = bv.get_type_info(); - if (inp_ == typeid(std::int32_t)) { - return get_as_aux(); + if (inp_ == typeid(int)) { + return get_as_aux(); } else if (inp_ == typeid(double)) { return get_as_aux(); } else if (inp_ == typeid(float)) { @@ -408,10 +432,18 @@ namespace chaiscript return get_as_aux(); } else if (inp_ == typeid(char)) { return get_as_aux(); + } else if (inp_ == typeid(unsigned int)) { + return get_as_aux(); + } else if (inp_ == typeid(long)) { + return get_as_aux(); + } else if (inp_ == typeid(unsigned long)) { + return get_as_aux(); } else if (inp_ == typeid(std::int8_t)) { return get_as_aux(); } else if (inp_ == typeid(std::int16_t)) { return get_as_aux(); + } else if (inp_ == typeid(std::int32_t)) { + return get_as_aux(); } else if (inp_ == typeid(std::int64_t)) { return get_as_aux(); } else if (inp_ == typeid(std::uint8_t)) { @@ -431,8 +463,8 @@ namespace chaiscript { const Type_Info &inp_ = bv.get_type_info(); - if (inp_ == typeid(std::int32_t)) { - return std::to_string(get_as()); + if (inp_ == typeid(int)) { + return std::to_string(get_as()); } else if (inp_ == typeid(double)) { return std::to_string(get_as()); } else if (inp_ == typeid(float)) { @@ -441,10 +473,18 @@ namespace chaiscript return std::to_string(get_as()); } else if (inp_ == typeid(char)) { return std::to_string(get_as()); + } else if (inp_ == typeid(unsigned int)) { + return std::to_string(get_as()); + } else if (inp_ == typeid(long)) { + return std::to_string(get_as()); + } else if (inp_ == typeid(unsigned long)) { + return std::to_string(get_as()); } else if (inp_ == typeid(std::int8_t)) { return std::to_string(get_as()); } else if (inp_ == typeid(std::int16_t)) { return std::to_string(get_as()); + } else if (inp_ == typeid(std::int32_t)) { + return std::to_string(get_as()); } else if (inp_ == typeid(std::int64_t)) { return std::to_string(get_as()); } else if (inp_ == typeid(std::uint8_t)) { From b95526951f149120497d1895e77e45a30845ede8 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 8 Jun 2015 13:18:52 -0600 Subject: [PATCH 066/116] Address warnings on VS We have to ignore many of these warnings due to the nature of Boxed_Number supporting any operation. --- include/chaiscript/dispatchkit/boxed_number.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 4c0ef65..2344e09 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -43,7 +43,7 @@ namespace chaiscript // this is OK, so we're disabling size/and sign type warnings #ifdef CHAISCRIPT_MSVC #pragma warning(push) -#pragma warning(disable : 4244 4018 4389 4146 4365) +#pragma warning(disable : 4244 4018 4389 4146 4365 4267) #endif From ba492308f4f3284f045d7bed8c5ef64ebc0f50c7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 8 Jun 2015 15:19:32 -0600 Subject: [PATCH 067/116] Move from multimap to sorted vector in dispatch --- .../chaiscript/dispatchkit/proxy_functions.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index e0a413a..49b80cb 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -852,17 +852,18 @@ namespace chaiscript const std::vector &plist, const Type_Conversions &t_conversions) { //std::cout << "starting dispatch: " << funcs.size() << '\n'; - std::multimap ordered_funcs; + std::vector> ordered_funcs; + ordered_funcs.reserve(funcs.size()); for (const auto &func : funcs) { - size_t numdiffs = 0; const auto arity = func->get_arity(); if (arity == -1) { - numdiffs = plist.size(); + ordered_funcs.emplace_back(plist.size(), func.get()); } else if (arity == static_cast(plist.size())) { + size_t numdiffs = 0; for (size_t i = 0; i < plist.size(); ++i) { if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info())) @@ -870,13 +871,19 @@ namespace chaiscript ++numdiffs; } } + ordered_funcs.emplace_back(numdiffs, func.get()); } else { continue; } - - ordered_funcs.insert(std::make_pair(numdiffs, func.get())); } + std::stable_sort(ordered_funcs.begin(), ordered_funcs.end(), + [](const decltype(ordered_funcs)::const_reference &t_lhs, const decltype(ordered_funcs)::const_reference &t_rhs) + { + return t_lhs.first < t_rhs.first; + } + ); + for (const auto &func : ordered_funcs ) { try { From f9e019335309b69fcc0ce3cfbcb579698ee01de6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 10 Jun 2015 18:41:50 -0600 Subject: [PATCH 068/116] Add map `.at` method from c++11 closes #184 --- include/chaiscript/dispatchkit/bootstrap.hpp | 6 ++++++ .../chaiscript/dispatchkit/bootstrap_stl.hpp | 4 ++++ .../chaiscript/dispatchkit/proxy_functions.hpp | 2 +- include/chaiscript/language/chaiscript_eval.hpp | 7 ++++++- unittests/map_access.chai | 17 +++++++++++++++++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 9a87c8b..5dcc4a8 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -408,6 +408,12 @@ namespace chaiscript m->add(fun(return_boxed_value_vector(&dispatch::Proxy_Function_Base::get_contained_functions)), "get_contained_functions"); + m->add(user_type(), "out_of_range"); + m->add(user_type(), "logic_error"); + m->add(chaiscript::base_class()); + m->add(chaiscript::base_class()); + m->add(chaiscript::base_class()); + m->add(user_type(), "runtime_error"); m->add(chaiscript::base_class()); diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 650124c..a763e48 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -438,9 +438,13 @@ namespace chaiscript m->add(user_type(), type); typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &); + typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const; m->add(fun(static_cast(&MapType::operator[])), "[]"); + m->add(fun(static_cast(&MapType::at)), "at"); + m->add(fun(static_cast(&MapType::at)), "at"); + container_type(type, m); default_constructible_type(type, m); assignable_type(type, m); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 49b80cb..32ebe60 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -878,7 +878,7 @@ namespace chaiscript } std::stable_sort(ordered_funcs.begin(), ordered_funcs.end(), - [](const decltype(ordered_funcs)::const_reference &t_lhs, const decltype(ordered_funcs)::const_reference &t_rhs) + [](decltype(ordered_funcs)::const_reference t_lhs, decltype(ordered_funcs)::const_reference t_rhs) { return t_lhs.first < t_rhs.first; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 895dcad..37df850 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1340,9 +1340,14 @@ namespace chaiscript } throw; } + catch (const std::runtime_error &e) { + retval = handle_exception(t_ss, Boxed_Value(std::ref(e))); + } + catch (const std::out_of_range &e) { + retval = handle_exception(t_ss, Boxed_Value(std::ref(e))); + } catch (const std::exception &e) { retval = handle_exception(t_ss, Boxed_Value(std::ref(e))); - } catch (Boxed_Value &e) { retval = handle_exception(t_ss, e); diff --git a/unittests/map_access.chai b/unittests/map_access.chai index d544036..1b2d73f 100644 --- a/unittests/map_access.chai +++ b/unittests/map_access.chai @@ -1,2 +1,19 @@ auto x = ["bob":2, "fred":3] assert_equal(3, x["fred"]) + + +try { + auto m = ["bob":2, "fred":3]; + m.at("tom"); + assert_true(false); +} catch (out_of_range e) { + print("out_of_range") + assert_true(true); +} catch (e) { + print("other") + dump_object(e); + assert_true(false); +} + + +assert_equal(["bob":2, "fred":3].at("fred"), 3); From 86482b0103484cc6a15a287f00a6569f30b5c7ff Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 10 Jun 2015 18:44:30 -0600 Subject: [PATCH 069/116] Correct docs for 'filter' Closes #183 --- include/chaiscript/language/chaiscript_prelude_docs.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_prelude_docs.hpp b/include/chaiscript/language/chaiscript_prelude_docs.hpp index 7480858..25d32d1 100644 --- a/include/chaiscript/language/chaiscript_prelude_docs.hpp +++ b/include/chaiscript/language/chaiscript_prelude_docs.hpp @@ -718,14 +718,14 @@ Object drop_while(Range c, Function f); Object reduce(Range c, Function f); -/// \brief Takes elements from Range c that match function f, return them. +/// \brief Takes elements from Container c that match function f, return them. /// /// Example: /// \code /// eval> filter([1, 2, 3, 4], odd) /// [1, 3] /// \endcode -Object filter(Range c, Function f); +Object filter(Container c, Function f); /// \brief Joins the elements of the Range c into a string, delimiting each with the delim string. From 88ab00679f8ccba5b38ee7a3af4c32ea89765f19 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 10 Jun 2015 18:49:54 -0600 Subject: [PATCH 070/116] Fix spelling of Windows.h for cross compiling Closes #176 --- include/chaiscript/language/chaiscript_engine.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index a7d3bad..8d97aaa 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -37,7 +37,7 @@ #ifdef CHAISCRIPT_WINDOWS #define VC_EXTRA_LEAN #define WIN32_LEAN_AND_MEAN -#include +#include #endif #endif From 68fa049d6c7ec60efcd3de5022ccd11f081d9615 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 10 Jun 2015 19:26:21 -0600 Subject: [PATCH 071/116] Fix g++4.6 build --- include/chaiscript/dispatchkit/proxy_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 32ebe60..3056317 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -878,7 +878,7 @@ namespace chaiscript } std::stable_sort(ordered_funcs.begin(), ordered_funcs.end(), - [](decltype(ordered_funcs)::const_reference t_lhs, decltype(ordered_funcs)::const_reference t_rhs) + [](const std::pair &t_lhs, const std::pair &t_rhs) { return t_lhs.first < t_rhs.first; } From 62ca26c36c4c4405b4f65f76295c18e1e3bd2a35 Mon Sep 17 00:00:00 2001 From: kamilzubair Date: Thu, 11 Jun 2015 09:11:43 +0700 Subject: [PATCH 072/116] Add two new examples - Add example how to expose base member from derived type - Add example how to use STL --- cheatsheet.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cheatsheet.md b/cheatsheet.md index 16bed0a..5319e59 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -30,6 +30,19 @@ chai.add(chaiscript::fun(&function_with_ove ``` chai.add(chaiscript::fun(std::static_cast(&function_with_overloads)), "function_name"); ``` +This overload technique is also used when exposing base member using derived type + +``` +struct Base +{ + int data; +}; + +struct Derived : public Base +{}; + +chai.add(chaiscript::fun(static_cast(&Derived::data)), "data"); +``` ### Lambda @@ -68,6 +81,22 @@ chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const ``` +#Using STL +ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. + +``` +typedef std::vector> data_list; + data_list my_list{ make_pair(0, "Hello"), make_pair(1, "World") }; + chai.add(chaiscript::bootstrap::standard_library::vector_type("DataList")); + chai.add(chaiscript::bootstrap::standard_library::pair_type("DataElement")); + chai.add(chaiscript::var(&my_list), "data_list"); + chai.eval(R"_( + for(var i=0; i Date: Sat, 13 Jun 2015 16:56:22 -0600 Subject: [PATCH 073/116] Minor cleanups and versioning info added --- cheatsheet.md | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/cheatsheet.md b/cheatsheet.md index 5319e59..594b2f7 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -1,3 +1,13 @@ +# ChaiScript Versioning + +ChaiScript tries to follow the [Semantic Versioning](http://semver.org/) scheme. This basically means: + + * Major Version Number: API changes / breaking changes + * Minor Version Number: New Features + * Patch Version Number: Minor changes / enhancements + + + # Initializing ChaiScript ``` @@ -81,21 +91,21 @@ chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const ``` -#Using STL +# Using STL ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. ``` typedef std::vector> data_list; - data_list my_list{ make_pair(0, "Hello"), make_pair(1, "World") }; - chai.add(chaiscript::bootstrap::standard_library::vector_type("DataList")); - chai.add(chaiscript::bootstrap::standard_library::pair_type("DataElement")); - chai.add(chaiscript::var(&my_list), "data_list"); - chai.eval(R"_( - for(var i=0; i("DataList")); +chai.add(chaiscript::bootstrap::standard_library::pair_type("DataElement")); +chai.add(chaiscript::var(&my_list), "data_list"); +chai.eval(R"_( + for(var i=0; i Date: Tue, 16 Jun 2015 17:01:01 -0600 Subject: [PATCH 074/116] Add back CONSTEXPR for Type_Info --- include/chaiscript/dispatchkit/type_info.hpp | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 1db31be..81ec083 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -29,7 +29,7 @@ namespace chaiscript class Type_Info { public: - Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), @@ -38,7 +38,7 @@ namespace chaiscript { } - Type_Info() + CHAISCRIPT_CONSTEXPR Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), @@ -55,40 +55,40 @@ namespace chaiscript Type_Info& operator=(const Type_Info&) = default; - bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_type_info == m_type_info || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } - bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info != nullptr && (*m_type_info) == ti; } - bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_bare_type_info == m_bare_type_info || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); } - bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_bare_type_info != nullptr && (*m_bare_type_info) == ti; } - bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } - bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } - bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } - bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } - bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } + CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { @@ -110,7 +110,7 @@ namespace chaiscript } } - const std::type_info *bare_type_info() const + CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const { return m_bare_type_info; } From 60a497b0a69240d5852bb8f46bfbcab514d34dc9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 16 Jun 2015 17:09:07 -0600 Subject: [PATCH 075/116] Move to codecov --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 458ccd8..8fb7cca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV --gcov-options '\-lp' ; fi + - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi after_script: - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi From 0dcac05f2f80066208641360e5441451e8c2d4d2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Jun 2015 11:57:58 -0600 Subject: [PATCH 076/116] Add numeric support for wide characters --- .../chaiscript/dispatchkit/boxed_number.hpp | 351 ++++++++++-------- 1 file changed, 192 insertions(+), 159 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 15b4f8c..e1503da 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -59,6 +59,20 @@ namespace chaiscript class Boxed_Number { private: + enum class Common_Types { + t_int32, + t_double, + t_uint8, + t_int8, + t_uint16, + t_int16, + t_uint32, + t_uint64, + t_int64, + t_float, + t_long_double + }; + template static inline void check_divide_by_zero(T t, typename std::enable_if::value>::type* = nullptr) { @@ -74,6 +88,67 @@ namespace chaiscript { } + static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed) + { + return (t_size == 1 && t_signed)?(Common_Types::t_int8) + :(t_size == 1)?(Common_Types::t_uint8) + :(t_size == 2 && t_signed)?(Common_Types::t_int16) + :(t_size == 2)?(Common_Types::t_uint16) + :(t_size == 4 && t_signed)?(Common_Types::t_int32) + :(t_size == 4)?(Common_Types::t_uint32) + :(t_size == 8 && t_signed)?(Common_Types::t_int64) + :(Common_Types::t_uint64); + } + + static Common_Types get_common_type(const Boxed_Value &t_bv) + { + const Type_Info &inp_ = t_bv.get_type_info(); + + if (inp_ == typeid(int)) { + return get_common_type(sizeof(int), true); + } else if (inp_ == typeid(double)) { + return Common_Types::t_double; + } else if (inp_ == typeid(long double)) { + return Common_Types::t_long_double; + } else if (inp_ == typeid(float)) { + return Common_Types::t_float; + } else if (inp_ == typeid(char)) { + return get_common_type(sizeof(char), std::is_signed::value); + } else if (inp_ == typeid(unsigned char)) { + return get_common_type(sizeof(unsigned char), false); + } else if (inp_ == typeid(unsigned int)) { + return get_common_type(sizeof(unsigned int), false); + } else if (inp_ == typeid(long)) { + return get_common_type(sizeof(long), true); + } else if (inp_ == typeid(unsigned long)) { + return get_common_type(sizeof(unsigned long), false); + } else if (inp_ == typeid(std::int8_t)) { + return Common_Types::t_int8; + } else if (inp_ == typeid(std::int16_t)) { + return Common_Types::t_int16; + } else if (inp_ == typeid(std::int32_t)) { + return Common_Types::t_int32; + } else if (inp_ == typeid(std::int64_t)) { + return Common_Types::t_int64; + } else if (inp_ == typeid(std::uint8_t)) { + return Common_Types::t_uint8; + } else if (inp_ == typeid(std::uint16_t)) { + return Common_Types::t_uint16; + } else if (inp_ == typeid(std::uint32_t)) { + return Common_Types::t_uint32; + } else if (inp_ == typeid(std::uint64_t)) { + return Common_Types::t_uint64; + } else if (inp_ == typeid(wchar_t)) { + return get_common_type(sizeof(wchar_t), std::is_signed::value); + } else if (inp_ == typeid(char16_t)) { + return get_common_type(sizeof(char16_t), std::is_signed::value); + } else if (inp_ == typeid(char32_t)) { + return get_common_type(sizeof(char32_t), std::is_signed::value); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + template static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u) { @@ -215,15 +290,15 @@ namespace chaiscript typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); + return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + return binary_int_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - return const_binary_int_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); + return const_binary_int_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::const_flag) { - return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); + return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -236,15 +311,15 @@ namespace chaiscript typedef typename std::common_type::type common_type; if (t_oper > Operators::boolean_flag && t_oper < Operators::non_const_flag) { - return boolean_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); + return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { - return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux_impl(t_rhs), t_lhs); + return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_flag) { - return const_binary_go(t_oper, get_as_aux_impl(t_lhs), get_as_aux_impl(t_rhs)); + return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -253,94 +328,66 @@ namespace chaiscript template inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { - const auto &inp_ = t_rhs.get_type_info(); - - if (inp_ == typeid(int)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(double)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(float)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long double)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(char)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned int)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned long)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int8_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int16_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int32_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int64_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint8_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint16_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint32_t)) { - return go(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint64_t)) { - return go(t_oper, t_lhs, t_rhs); - } else { - throw chaiscript::detail::exception::bad_any_cast(); + switch (get_common_type(t_rhs)) { + case Common_Types::t_int32: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint8: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_int8: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint16: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_int16: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint32: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint64: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_int64: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_double: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_float: + return go(t_oper, t_lhs, t_rhs); + case Common_Types::t_long_double: + return go(t_oper, t_lhs, t_rhs); } + + throw chaiscript::detail::exception::bad_any_cast(); } inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { - const Type_Info &inp_ = t_lhs.get_type_info(); - - if (inp_ == typeid(int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(double)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long double)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(float)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(char)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned int)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(unsigned long)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int8_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int16_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::int64_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint8_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint16_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint32_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else if (inp_ == typeid(std::uint64_t)) { - return oper_rhs(t_oper, t_lhs, t_rhs); - } else { - throw chaiscript::detail::exception::bad_any_cast(); + switch (get_common_type(t_lhs)) { + case Common_Types::t_int32: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint8: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_int8: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint16: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_int16: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint32: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_uint64: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_int64: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_double: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_float: + return oper_rhs(t_oper, t_lhs, t_rhs); + case Common_Types::t_long_double: + return oper_rhs(t_oper, t_lhs, t_rhs); } + + throw chaiscript::detail::exception::bad_any_cast(); } template - inline Target get_as_aux() const - { - return get_as_aux_impl(bv); - } - - template - static inline Target get_as_aux_impl(const Boxed_Value &t_bv) + static inline Target get_as_aux(const Boxed_Value &t_bv) { return static_cast(*static_cast(t_bv.get_const_ptr())); } @@ -390,6 +437,14 @@ namespace chaiscript return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(char))) { return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(unsigned char))) { + return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(wchar_t))) { + return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(char16_t))) { + return Boxed_Number(get_as()); + } else if (inp_.bare_equal_type_info(typeid(char32_t))) { + return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(unsigned int))) { return Boxed_Number(get_as()); } else if (inp_.bare_equal_type_info(typeid(long))) { @@ -420,84 +475,62 @@ namespace chaiscript template Target get_as() const { - const Type_Info &inp_ = bv.get_type_info(); - - if (inp_ == typeid(int)) { - return get_as_aux(); - } else if (inp_ == typeid(double)) { - return get_as_aux(); - } else if (inp_ == typeid(float)) { - return get_as_aux(); - } else if (inp_ == typeid(long double)) { - return get_as_aux(); - } else if (inp_ == typeid(char)) { - return get_as_aux(); - } else if (inp_ == typeid(unsigned int)) { - return get_as_aux(); - } else if (inp_ == typeid(long)) { - return get_as_aux(); - } else if (inp_ == typeid(unsigned long)) { - return get_as_aux(); - } else if (inp_ == typeid(std::int8_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::int16_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::int32_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::int64_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::uint8_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::uint16_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::uint32_t)) { - return get_as_aux(); - } else if (inp_ == typeid(std::uint64_t)) { - return get_as_aux(); - } else { - throw chaiscript::detail::exception::bad_any_cast(); + switch (get_common_type(bv)) { + case Common_Types::t_int32: + return get_as_aux(bv); + case Common_Types::t_uint8: + return get_as_aux(bv); + case Common_Types::t_int8: + return get_as_aux(bv); + case Common_Types::t_uint16: + return get_as_aux(bv); + case Common_Types::t_int16: + return get_as_aux(bv); + case Common_Types::t_uint32: + return get_as_aux(bv); + case Common_Types::t_uint64: + return get_as_aux(bv); + case Common_Types::t_int64: + return get_as_aux(bv); + case Common_Types::t_double: + return get_as_aux(bv); + case Common_Types::t_float: + return get_as_aux(bv); + case Common_Types::t_long_double: + return get_as_aux(bv); } + + throw chaiscript::detail::exception::bad_any_cast(); } std::string to_string() const { - const Type_Info &inp_ = bv.get_type_info(); - - if (inp_ == typeid(int)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(double)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(float)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(long double)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(char)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(unsigned int)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(long)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(unsigned long)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::int8_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::int16_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::int32_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::int64_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::uint8_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::uint16_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::uint32_t)) { - return std::to_string(get_as()); - } else if (inp_ == typeid(std::uint64_t)) { - return std::to_string(get_as()); - } else { - throw chaiscript::detail::exception::bad_any_cast(); + switch (get_common_type(bv)) { + case Common_Types::t_int32: + return std::to_string(get_as()); + case Common_Types::t_uint8: + return std::to_string(get_as()); + case Common_Types::t_int8: + return std::to_string(get_as()); + case Common_Types::t_uint16: + return std::to_string(get_as()); + case Common_Types::t_int16: + return std::to_string(get_as()); + case Common_Types::t_uint32: + return std::to_string(get_as()); + case Common_Types::t_uint64: + return std::to_string(get_as()); + case Common_Types::t_int64: + return std::to_string(get_as()); + case Common_Types::t_double: + return std::to_string(get_as()); + case Common_Types::t_float: + return std::to_string(get_as()); + case Common_Types::t_long_double: + return std::to_string(get_as()); } + + throw chaiscript::detail::exception::bad_any_cast(); } bool operator==(const Boxed_Number &t_rhs) const From 2442e9ae20c22b7943873483a4a5426ca5d070fd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Jun 2015 13:01:54 -0600 Subject: [PATCH 077/116] Register all character types --- include/chaiscript/dispatchkit/bootstrap.hpp | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 5dcc4a8..d6600f4 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -157,7 +157,12 @@ namespace chaiscript /// Internal function for converting from a string to a value /// uses ostream operator >> to perform the conversion template - Input parse_string(const std::string &i) + auto parse_string(const std::string &i) + -> typename std::enable_if< + !std::is_same::value + && !std::is_same::value + && !std::is_same::value, + Input>::type { std::stringstream ss(i); Input t; @@ -165,6 +170,17 @@ namespace chaiscript return t; } + template + auto parse_string(const std::string &) + -> typename std::enable_if< + std::is_same::value + || std::is_same::value + || std::is_same::value, + Input>::type + { + throw std::runtime_error("Parsing of wide characters is not yet supported"); + } + /// Add all common functions for a POD type. All operators, and /// common conversions @@ -486,6 +502,9 @@ namespace chaiscript bootstrap_pod_type("unsigned_long", m); bootstrap_pod_type("size_t", m); bootstrap_pod_type("char", m); + bootstrap_pod_type("wchar_t", m); + bootstrap_pod_type("char16_t", m); + bootstrap_pod_type("char32_t", m); bootstrap_pod_type("int8_t", m); bootstrap_pod_type("int16_t", m); bootstrap_pod_type("int32_t", m); From 9e743e314722dd586995231c7aaace80df654fcf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Jun 2015 15:45:03 -0600 Subject: [PATCH 078/116] Set up links to codecov.io for coverage status --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 32cb703..75e470a 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ -Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=master)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=master) +Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=master)](http://codecov.io/github/ChaiScript/ChaiScript?branch=master) -Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![Coverage Status](https://coveralls.io/repos/ChaiScript/ChaiScript/badge.png?branch=develop)](https://coveralls.io/r/ChaiScript/ChaiScript?branch=develop) +Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=develop)](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop) Coverity Scan Build Status Date: Thu, 18 Jun 2015 21:47:05 -0600 Subject: [PATCH 079/116] Reduce to_string overloads down to what is necessary --- include/chaiscript/dispatchkit/bootstrap.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index d6600f4..8f2b3c7 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -191,11 +191,6 @@ namespace chaiscript m->add(constructor(), name); construct_pod(name, m); - auto to_s = fun(&to_string); - - if (!m->has_function(to_s, "to_string")) { - m->add(to_s, "to_string"); - } m->add(fun(&parse_string), "to_" + name); return m; } @@ -493,6 +488,9 @@ namespace chaiscript m->add(fun(&throw_exception), "throw"); m->add(fun(&what), "what"); + m->add(fun(&to_string), "to_string"); + m->add(fun(&Boxed_Number::to_string), "to_string"); + bootstrap_pod_type("double", m); bootstrap_pod_type("long_double", m); bootstrap_pod_type("float", m); From 6d632f6aa4f56c0f5dcbdb2edf986500fc3f3e77 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 06:18:49 -0600 Subject: [PATCH 080/116] Normalize methods for numeric->string conversions --- include/chaiscript/dispatchkit/boxed_number.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index e1503da..b65d5e3 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -523,11 +523,11 @@ namespace chaiscript case Common_Types::t_int64: return std::to_string(get_as()); case Common_Types::t_double: - return std::to_string(get_as()); + return to_string_aux(bv); case Common_Types::t_float: - return std::to_string(get_as()); + return to_string_aux(bv); case Common_Types::t_long_double: - return std::to_string(get_as()); + return to_string_aux(bv); } throw chaiscript::detail::exception::bad_any_cast(); From 1bf4170d8f15bff1f35593ff0120281a2767ce20 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 11:47:16 -0600 Subject: [PATCH 081/116] Simplify dispatch --- .../dispatchkit/proxy_functions.hpp | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 3056317..4806ed4 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -851,7 +851,6 @@ namespace chaiscript Boxed_Value dispatch(const Funcs &funcs, const std::vector &plist, const Type_Conversions &t_conversions) { - //std::cout << "starting dispatch: " << funcs.size() << '\n'; std::vector> ordered_funcs; ordered_funcs.reserve(funcs.size()); @@ -872,32 +871,27 @@ namespace chaiscript } } ordered_funcs.emplace_back(numdiffs, func.get()); - } else { - continue; } } - std::stable_sort(ordered_funcs.begin(), ordered_funcs.end(), - [](const std::pair &t_lhs, const std::pair &t_rhs) - { - return t_lhs.first < t_rhs.first; - } - ); - for (const auto &func : ordered_funcs ) + for (size_t i = 0; i <= plist.size(); ++i) { - try { - if (func.first == 0 || func.second->filter(plist, t_conversions)) - { - return (*(func.second))(plist, t_conversions); + for (const auto &func : ordered_funcs ) + { + try { + if (func.first == i && func.second->filter(plist, t_conversions)) + { + return (*(func.second))(plist, t_conversions); + } + } catch (const exception::bad_boxed_cast &) { + //parameter failed to cast, try again + } catch (const exception::arity_error &) { + //invalid num params, try again + } catch (const exception::guard_error &) { + //guard failed to allow the function to execute, + //try again } - } catch (const exception::bad_boxed_cast &) { - //parameter failed to cast, try again - } catch (const exception::arity_error &) { - //invalid num params, try again - } catch (const exception::guard_error &) { - //guard failed to allow the function to execute, - //try again } } From bcf573cf26903ad793820fef3675816fd5178c8c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 14:23:08 -0600 Subject: [PATCH 082/116] Don't loop over already filtered functions --- .../dispatchkit/proxy_functions.hpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 4806ed4..0e1835c 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -773,9 +773,9 @@ namespace chaiscript return true; } - template + template Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector &plist, - const Type_Conversions &t_conversions) + const Type_Conversions &t_conversions, const Funcs &t_funcs) { InItr orig(begin); @@ -783,15 +783,15 @@ namespace chaiscript while (begin != end) { - if (types_match_except_for_arithmetic(*begin, plist, t_conversions)) + if (types_match_except_for_arithmetic(begin->second, plist, t_conversions)) { if (matching_func == end) { matching_func = begin; } else { // handle const members vs non-const member, which is not really ambiguous - const auto &mat_fun_param_types = (*matching_func)->get_param_types(); - const auto &next_fun_param_types = (*begin)->get_param_types(); + const auto &mat_fun_param_types = matching_func->second->get_param_types(); + const auto &next_fun_param_types = begin->second->get_param_types(); if (plist[0].is_const() && !mat_fun_param_types[1].is_const() && next_fun_param_types[1].is_const()) { matching_func = begin; // keep the new one, the const/non-const matchup is correct @@ -799,7 +799,7 @@ namespace chaiscript // keep the old one, it has a better const/non-const matchup } else { // ambiguous function call - throw exception::dispatch_error(plist, std::vector(orig, end)); + throw exception::dispatch_error(plist, std::vector(t_funcs.begin(), t_funcs.end())); } } } @@ -810,12 +810,12 @@ namespace chaiscript if (matching_func == end) { // no appropriate function to attempt arithmetic type conversion on - throw exception::dispatch_error(plist, std::vector(orig, end)); + throw exception::dispatch_error(plist, std::vector(t_funcs.begin(), t_funcs.end())); } std::vector newplist; - const std::vector &tis = (*matching_func)->get_param_types(); + const std::vector &tis = matching_func->second->get_param_types(); for (size_t i = 0; i < plist.size(); ++i) { @@ -828,7 +828,7 @@ namespace chaiscript } try { - return (*(*matching_func))(newplist, t_conversions); + return (*(matching_func->second))(newplist, t_conversions); } catch (const exception::bad_boxed_cast &) { //parameter failed to cast } catch (const exception::arity_error &) { @@ -837,7 +837,7 @@ namespace chaiscript //guard failed to allow the function to execute } - throw exception::dispatch_error(plist, std::vector(orig, end)); + throw exception::dispatch_error(plist, std::vector(t_funcs.begin(), t_funcs.end())); } } @@ -895,7 +895,7 @@ namespace chaiscript } } - return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions); + return detail::dispatch_with_conversions(ordered_funcs.cbegin(), ordered_funcs.cend(), plist, t_conversions, funcs); } } } From b7eb469ac1a76e7e30850b9acf77ce182666d093 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 14:57:54 -0600 Subject: [PATCH 083/116] Move to some standard algorithms --- .../dispatchkit/proxy_functions.hpp | 53 ++++++++----------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 0e1835c..f8fc9a4 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -749,28 +749,16 @@ namespace chaiscript bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector &plist, const Type_Conversions &t_conversions) { - if (t_func->get_arity() != static_cast(plist.size())) - { - return false; - } - + assert(plist.size() == types.size() - 1); const std::vector &types = t_func->get_param_types(); - assert(plist.size() == types.size() - 1); - - for (size_t i = 0; i < plist.size(); ++i) - { - if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i], t_conversions) - || (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic())) - { - // types continue to match - } else { - return false; - } - } - - // all types match - return true; + return std::mismatch(plist.begin(), plist.end(), + types.begin()+1, + [&](const Boxed_Value &bv, const Type_Info &ti) { + return Proxy_Function_Base::compare_type_to_param(ti, bv, t_conversions) + || (bv.get_type_info().is_arithmetic() && ti.is_arithmetic()); + } + ) == std::make_pair(plist.end(), types.end()); } template @@ -815,17 +803,22 @@ namespace chaiscript std::vector newplist; - const std::vector &tis = matching_func->second->get_param_types(); + newplist.reserve(plist.size()); + + const std::vector &tis = matching_func->second->get_param_types(); + std::transform(tis.begin() + 1, tis.end(), + plist.begin(), + std::back_inserter(newplist), + [](const Type_Info &ti, const Boxed_Value ¶m) { + if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) { + return Boxed_Number(param).get_as(ti).bv; + } else { + return param; + } + } + ); + - for (size_t i = 0; i < plist.size(); ++i) - { - if (tis[i+1].is_arithmetic() - && plist[i].get_type_info().is_arithmetic()) { - newplist.push_back(Boxed_Number(plist[i]).get_as(tis[i+1]).bv); - } else { - newplist.push_back(plist[i]); - } - } try { return (*(matching_func->second))(newplist, t_conversions); From f9860216c9668897c8155a1deac19759c5c045f9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 16:49:16 -0600 Subject: [PATCH 084/116] Move to std::vector for local stack objects --- .../chaiscript/dispatchkit/dispatchkit.hpp | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 02822b1..6496ba6 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -390,7 +390,7 @@ namespace chaiscript { public: typedef std::map Type_Name_Map; - typedef std::map Scope; + typedef std::vector> Scope; typedef std::vector StackData; struct State @@ -445,7 +445,11 @@ namespace chaiscript for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - auto itr = stack_elem->find(name); + auto itr = std::find_if(stack_elem->begin(), stack_elem->end(), + [&](const std::pair &o) { + return o.first == name; + }); + if (itr != stack_elem->end()) { itr->second = std::move(obj); @@ -460,12 +464,20 @@ namespace chaiscript /// Adds a named object to the current scope /// \warning This version does not check the validity of the name /// it is meant for internal use only - void add_object(const std::string &name, const Boxed_Value &obj) + void add_object(const std::string &name, Boxed_Value obj) { - if (!get_stack_data().back().insert(std::make_pair(name, obj)).second) + auto &stack_elem = get_stack_data().back(); + + if (std::any_of(stack_elem.begin(), stack_elem.end(), + [&](const std::pair &o) { + return o.first == name; + })) { throw chaiscript::exception::name_conflict_error(name); } + + get_stack_data().back().emplace_back(name, std::move(obj)); + } /// Adds a new global shared object, between all the threads @@ -570,10 +582,11 @@ namespace chaiscript // Is it in the stack? for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - const auto stackitr = stack_elem->find(name); - if (stackitr != stack_elem->end()) + for (auto &s : (*stack_elem) ) { - return stackitr->second; + if (s.first == name) { + return s.second; + } } } @@ -699,9 +712,9 @@ namespace chaiscript auto &stack = get_stack_data(); if (stack.size() > 1) { - return stack[1]; + return std::map(stack[1].begin(), stack[1].end()); } else { - return stack[0]; + return std::map(stack[0].begin(), stack[0].end()); } } @@ -710,7 +723,7 @@ namespace chaiscript { auto &stack = get_stack_data(); auto &scope = stack.front(); - return scope; + return std::map(scope.begin(), scope.end()); } /// \brief Sets all of the locals for the current thread state. @@ -722,7 +735,7 @@ namespace chaiscript { auto &stack = get_stack_data(); auto &scope = stack.front(); - scope = t_locals; + scope = std::vector>(t_locals.begin(), t_locals.end()); } From 646563eb3f1270e54a4612983f37c7187612835d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 20:10:45 -0600 Subject: [PATCH 085/116] A couple of cleanups and fixes --- include/chaiscript/dispatchkit/dispatchkit.hpp | 2 +- include/chaiscript/language/chaiscript_eval.hpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 6496ba6..38ff09c 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -438,7 +438,7 @@ namespace chaiscript /// Set the value of an object, by name. If the object /// is not available in the current scope it is created - void add(const Boxed_Value &obj, const std::string &name) + void add(Boxed_Value obj, const std::string &name) { validate_object_name(name); auto &stack = get_stack_data(); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 37df850..6f8442c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -316,9 +316,10 @@ namespace chaiscript virtual ~Inplace_Fun_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - std::vector params; chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); + std::vector params; + params.reserve(this->children[1]->children.size()); for (const auto &child : this->children[1]->children) { params.push_back(child->eval(t_ss)); } From a2577b983cf0a28f0b73090a50875e6fdb0c79b0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 20:31:39 -0600 Subject: [PATCH 086/116] Don't constantly re-create the function objects --- .../chaiscript/dispatchkit/dispatchkit.hpp | 68 ++++++++++++------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 38ff09c..d752856 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -397,6 +397,7 @@ namespace chaiscript { std::map > m_functions; std::map m_function_objects; + std::map m_boxed_functions; std::map m_global_objects; Type_Name_Map m_types; std::set m_reserved_words; @@ -684,13 +685,13 @@ namespace chaiscript // std::cout << "Getting function object: " << t_name << '\n'; chaiscript::detail::threading::shared_lock l(m_mutex); - const auto &funs = get_function_objects_int(); + const auto &funs = get_boxed_functions_int(); auto itr = funs.find(t_name); if (itr != funs.end()) { - return const_var(itr->second); + return itr->second; } else { throw std::range_error("Object not found: " + t_name); } @@ -1136,6 +1137,16 @@ namespace chaiscript return m_stack_holder->stacks.back(); } + const std::map &get_boxed_functions_int() const + { + return m_state.m_boxed_functions; + } + + std::map &get_boxed_functions_int() + { + return m_state.m_boxed_functions; + } + const std::map &get_function_objects_int() const { return m_state.m_function_objects; @@ -1276,34 +1287,39 @@ namespace chaiscript auto itr = funcs.find(t_name); auto &func_objs = get_function_objects_int(); + auto &boxed_funcs = get_boxed_functions_int(); - if (itr != funcs.end()) - { - auto &vec = itr->second; - for (const auto &func : vec) - { - if ((*t_f) == *(func)) + Proxy_Function new_func = + [&]() -> Proxy_Function { + if (itr != funcs.end()) { - throw chaiscript::exception::name_conflict_error(t_name); + auto &vec = itr->second; + for (const auto &func : vec) + { + if ((*t_f) == *(func)) + { + throw chaiscript::exception::name_conflict_error(t_name); + } + } + + vec.push_back(t_f); + std::stable_sort(vec.begin(), vec.end(), &function_less_than); + return std::make_shared(vec); + } else if (t_f->has_arithmetic_param()) { + // if the function is the only function but it also contains + // arithmetic operators, we must wrap it in a dispatch function + // to allow for automatic arithmetic type conversions + std::vector vec({t_f}); + funcs.insert(std::make_pair(t_name, vec)); + return std::make_shared(std::move(vec)); + } else { + funcs.insert(std::make_pair(t_name, std::vector{t_f})); + return t_f; } - } - - vec.push_back(t_f); - std::stable_sort(vec.begin(), vec.end(), &function_less_than); - func_objs[t_name] = std::make_shared(vec); - } else if (t_f->has_arithmetic_param()) { - // if the function is the only function but it also contains - // arithmetic operators, we must wrap it in a dispatch function - // to allow for automatic arithmetic type conversions - std::vector vec({t_f}); - funcs.insert(std::make_pair(t_name, vec)); - func_objs[t_name] = std::make_shared(std::move(vec)); - } else { - funcs.insert(std::make_pair(t_name, std::vector{t_f})); - func_objs[t_name] = t_f; - } - + }(); + boxed_funcs[t_name] = const_var(new_func); + func_objs[t_name] = std::move(new_func); } mutable chaiscript::detail::threading::shared_mutex m_mutex; From a147278a7ebca8d5cb736a4dd01000d0db755e72 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Jun 2015 20:59:40 -0600 Subject: [PATCH 087/116] Fix debug builds --- include/chaiscript/dispatchkit/proxy_functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index f8fc9a4..731aa7d 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -749,8 +749,8 @@ namespace chaiscript bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector &plist, const Type_Conversions &t_conversions) { - assert(plist.size() == types.size() - 1); const std::vector &types = t_func->get_param_types(); + assert(plist.size() == types.size() - 1); return std::mismatch(plist.begin(), plist.end(), types.begin()+1, From 2870874d915ac75fef665cef1992b172b76db861 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 06:53:23 -0600 Subject: [PATCH 088/116] Fix clang build errors --- .../dispatchkit/proxy_functions.hpp | 2 +- .../chaiscript/language/chaiscript_eval.hpp | 23 ----------------- .../chaiscript/language/chaiscript_parser.hpp | 25 +------------------ 3 files changed, 2 insertions(+), 48 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 731aa7d..bb420d3 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -809,7 +809,7 @@ namespace chaiscript std::transform(tis.begin() + 1, tis.end(), plist.begin(), std::back_inserter(newplist), - [](const Type_Info &ti, const Boxed_Value ¶m) { + [](const Type_Info &ti, const Boxed_Value ¶m) -> Boxed_Value { if (ti.is_arithmetic() && param.get_type_info().is_arithmetic()) { return Boxed_Number(param).get_as(ti).bv; } else { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 6f8442c..8d1f6e1 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -282,29 +282,6 @@ namespace chaiscript }; - struct Fun_Lookup_AST_Node : public AST_Node { - public: - Fun_Lookup_AST_Node(const std::string &t_fun_name) - : AST_Node(t_fun_name, 0, Parse_Location("")) - { - } - - virtual ~Fun_Lookup_AST_Node() {} - - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { - try { - Boxed_Value bv = t_ss.get_object(text); - t_ss.add_object(text, bv); - std::cout << " Saved fun lookup: " << text << '\n'; - return bv; - } catch (...) { - return Boxed_Value(); - } - } - }; - - - /// Used in the context of in-string ${} evals, so that no new scope is created diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 7588d40..e39b632 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -216,28 +216,6 @@ namespace chaiscript } - static void optimize_fun_lookups(AST_NodePtr &p) - { - for (auto &c : p->children) - { - - if (c->identifier == AST_Node_Type::Def - || c->identifier == AST_Node_Type::Method - || c->identifier == AST_Node_Type::Lambda) { - std::vector children_to_add; - auto counts = count_fun_calls(c, false); - for (const auto &count : counts) { - // std::cout << " Fun Call Count: " << count.first << " " << count.second << '\n'; - if (count.second > 1) { - children_to_add.push_back(chaiscript::make_shared(count.first)); - } - } - c->children.back()->children.insert(c->children.back()->children.begin(), children_to_add.begin(), children_to_add.end()); - } - optimize_fun_lookups(c); - } - } - static void optimize_blocks(AST_NodePtr &p) { @@ -282,12 +260,11 @@ namespace chaiscript return count; } - AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true, bool t_optimize_fun_lookups = false) { + AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true) { AST_NodePtr p = m_match_stack.front(); //Note, optimize_blocks is currently broken; it breaks stack management if (t_optimize_blocks) { optimize_blocks(p); } if (t_optimize_returns) { optimize_returns(p); } - if (t_optimize_fun_lookups) { optimize_fun_lookups(p); } return p; } From c4633436ba37324bdbf4d9e1ce7d2863b453703a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 07:13:54 -0600 Subject: [PATCH 089/116] Avoid placeholder lookup cost --- include/chaiscript/dispatchkit/dispatchkit.hpp | 11 +---------- include/chaiscript/language/chaiscript_eval.hpp | 11 +++++------ 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index d752856..676b5f1 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -408,8 +408,7 @@ namespace chaiscript }; Dispatch_Engine() - : m_stack_holder(this), - m_place_holder(std::make_shared()) + : m_stack_holder(this) { } @@ -572,12 +571,6 @@ namespace chaiscript /// ensure that it is always in scope. Boxed_Value get_object(const std::string &name) const { - // Is it a placeholder object? - if (name == "_") - { - return m_place_holder; - } - auto &stack = get_stack_data(); // Is it in the stack? @@ -1345,8 +1338,6 @@ namespace chaiscript State m_state; - - Boxed_Value m_place_holder; }; } } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 8d1f6e1..2b8b601 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -170,15 +170,14 @@ namespace chaiscript { if (t_text == "true") { return const_var(true); - } - else if (t_text == "false") { + } else if (t_text == "false") { return const_var(false); - } - else if (t_text == "Infinity") { + } else if (t_text == "Infinity") { return const_var(std::numeric_limits::infinity()); - } - else if (t_text == "NaN") { + } else if (t_text == "NaN") { return const_var(std::numeric_limits::quiet_NaN()); + } else if (t_text == "_") { + return Boxed_Value(std::make_shared()); } else { return Boxed_Value(); } From 3eb770091286594a052bde4f05ba193976cba426 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 07:45:00 -0600 Subject: [PATCH 090/116] Add missing --- include/chaiscript/dispatchkit/proxy_functions.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index bb420d3..ee3029f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "../chaiscript_defines.hpp" #include "boxed_cast.hpp" @@ -765,8 +766,6 @@ namespace chaiscript Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector &plist, const Type_Conversions &t_conversions, const Funcs &t_funcs) { - InItr orig(begin); - InItr matching_func(end); while (begin != end) From c7689f18ec8043caef89f93374145a8e2c9c2ad5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 10:28:27 -0600 Subject: [PATCH 091/116] Save local variable location after first pass --- .../chaiscript/dispatchkit/dispatchkit.hpp | 36 +++++++++++++++---- .../chaiscript/language/chaiscript_eval.hpp | 6 ++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 676b5f1..c451515 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -569,19 +569,41 @@ namespace chaiscript /// Searches the current stack for an object of the given name /// includes a special overload for the _ place holder object to /// ensure that it is always in scope. - Boxed_Value get_object(const std::string &name) const + Boxed_Value get_object(const std::string &name, uint32_t &t_loc) const { - auto &stack = get_stack_data(); + enum class Loc : uint32_t { + located = 0x80000000, + is_local = 0x40000000, + stack_mask = 0x0FFF0000, + loc_mask = 0x0000FFFF + }; - // Is it in the stack? - for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) + unsigned int loc = t_loc; + + if (loc == 0) { - for (auto &s : (*stack_elem) ) + auto &stack = get_stack_data(); + + // Is it in the stack? + for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - if (s.first == name) { - return s.second; + for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s ) + { + if (s->first == name) { + t_loc = static_cast(std::distance(stack.rbegin(), stack_elem) << 16) + | static_cast(std::distance(stack_elem->begin(), s)) + | static_cast(Loc::located) + | static_cast(Loc::is_local); + return s->second; + } } } + + t_loc = static_cast(Loc::located); + } else if (loc & static_cast(Loc::is_local)) { + auto &stack = get_stack_data(); + + return stack[stack.size() - 1 - ((loc & static_cast(Loc::stack_mask)) >> 16)][loc & static_cast(Loc::loc_mask)].second; } // Is the value we are looking for a global? diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 2b8b601..53deb6a 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -147,7 +147,7 @@ namespace chaiscript public: Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), - m_value(get_value(t_ast_node_text)) + m_value(get_value(t_ast_node_text)), m_loc(0) { } virtual ~Id_AST_Node() {} @@ -157,7 +157,7 @@ namespace chaiscript return m_value; } else { try { - return t_ss.get_object(this->text); + return t_ss.get_object(this->text, m_loc); } catch (std::exception &) { throw exception::eval_error("Can not find object: " + this->text); @@ -184,6 +184,8 @@ namespace chaiscript } Boxed_Value m_value; + + mutable uint32_t m_loc; }; struct Char_AST_Node : public AST_Node { From ec33cf270973fc33375715bfcde3ad285da0176d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 10:52:05 -0600 Subject: [PATCH 092/116] Make local location saving atomic --- include/chaiscript/dispatchkit/dispatchkit.hpp | 15 ++++++++------- include/chaiscript/language/chaiscript_eval.hpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c451515..30d9107 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -569,7 +569,7 @@ namespace chaiscript /// Searches the current stack for an object of the given name /// includes a special overload for the _ place holder object to /// ensure that it is always in scope. - Boxed_Value get_object(const std::string &name, uint32_t &t_loc) const + Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const { enum class Loc : uint32_t { located = 0x80000000, @@ -578,7 +578,7 @@ namespace chaiscript loc_mask = 0x0000FFFF }; - unsigned int loc = t_loc; + uint32_t loc = t_loc.load(std::memory_order_relaxed); if (loc == 0) { @@ -590,16 +590,17 @@ namespace chaiscript for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s ) { if (s->first == name) { - t_loc = static_cast(std::distance(stack.rbegin(), stack_elem) << 16) - | static_cast(std::distance(stack_elem->begin(), s)) - | static_cast(Loc::located) - | static_cast(Loc::is_local); + t_loc.store( static_cast(std::distance(stack.rbegin(), stack_elem) << 16) + | static_cast(std::distance(stack_elem->begin(), s)) + | static_cast(Loc::located) + | static_cast(Loc::is_local), + std::memory_order_relaxed); return s->second; } } } - t_loc = static_cast(Loc::located); + t_loc.store( static_cast(Loc::located), std::memory_order_relaxed); } else if (loc & static_cast(Loc::is_local)) { auto &stack = get_stack_data(); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 53deb6a..9efbcbc 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -185,7 +185,7 @@ namespace chaiscript Boxed_Value m_value; - mutable uint32_t m_loc; + mutable std::atomic_uint_fast32_t m_loc; }; struct Char_AST_Node : public AST_Node { From cd2fb1ec666d76f585194ad838b24e2deda9783e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 11:45:34 -0600 Subject: [PATCH 093/116] Normalize integer types in the loc saving --- include/chaiscript/dispatchkit/dispatchkit.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 30d9107..0bbe083 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -571,14 +571,14 @@ namespace chaiscript /// ensure that it is always in scope. Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const { - enum class Loc : uint32_t { + enum class Loc : uint_fast32_t { located = 0x80000000, is_local = 0x40000000, stack_mask = 0x0FFF0000, loc_mask = 0x0000FFFF }; - uint32_t loc = t_loc.load(std::memory_order_relaxed); + uint_fast32_t loc = t_loc.load(std::memory_order_relaxed); if (loc == 0) { @@ -590,21 +590,21 @@ namespace chaiscript for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s ) { if (s->first == name) { - t_loc.store( static_cast(std::distance(stack.rbegin(), stack_elem) << 16) - | static_cast(std::distance(stack_elem->begin(), s)) - | static_cast(Loc::located) - | static_cast(Loc::is_local), + t_loc.store( static_cast(std::distance(stack.rbegin(), stack_elem) << 16) + | static_cast(std::distance(stack_elem->begin(), s)) + | static_cast(Loc::located) + | static_cast(Loc::is_local), std::memory_order_relaxed); return s->second; } } } - t_loc.store( static_cast(Loc::located), std::memory_order_relaxed); - } else if (loc & static_cast(Loc::is_local)) { + t_loc.store( static_cast(Loc::located), std::memory_order_relaxed); + } else if (loc & static_cast(Loc::is_local)) { auto &stack = get_stack_data(); - return stack[stack.size() - 1 - ((loc & static_cast(Loc::stack_mask)) >> 16)][loc & static_cast(Loc::loc_mask)].second; + return stack[stack.size() - 1 - ((loc & static_cast(Loc::stack_mask)) >> 16)][loc & static_cast(Loc::loc_mask)].second; } // Is the value we are looking for a global? From 05bec3b4a80becb827d140c77672ce4edccbebf9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 21 Jun 2015 21:09:26 -0600 Subject: [PATCH 094/116] Avoid attempting convert_down when not possible @arBmind this should be significant for you --- .../dispatchkit/type_conversions.hpp | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index a5abed4..91a496e 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -92,6 +92,11 @@ namespace chaiscript return m_from; } + virtual bool bidir() const + { + return true; + } + virtual ~Type_Conversion_Base() {} protected: @@ -262,6 +267,11 @@ namespace chaiscript throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types"); } + virtual bool bidir() const + { + return false; + } + virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE { return Static_Caster::cast(t_derived); @@ -291,6 +301,12 @@ namespace chaiscript return m_func(t_from); } + virtual bool bidir() const + { + return false; + } + + private: Callable m_func; }; @@ -367,7 +383,7 @@ namespace chaiscript const auto &types = thread_cache(); if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0) { - return has_conversion(to, from) || has_conversion(from, to); + return has_conversion(to, from); } else { return false; } @@ -417,7 +433,7 @@ namespace chaiscript bool has_conversion(const Type_Info &to, const Type_Info &from) const { chaiscript::detail::threading::shared_lock l(m_mutex); - return find(to, from) != m_conversions.end(); + return find_bidir(to, from) != m_conversions.end(); } std::shared_ptr get_conversion(const Type_Info &to, const Type_Info &from) const @@ -435,6 +451,19 @@ namespace chaiscript } private: + std::set >::const_iterator find_bidir( + const Type_Info &to, const Type_Info &from) const + { + return std::find_if(m_conversions.begin(), m_conversions.end(), + [&to, &from](const std::shared_ptr &conversion) + { + return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from)) + || (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from)); +; + } + ); + } + std::set >::const_iterator find( const Type_Info &to, const Type_Info &from) const { From 83281bff52a4ceb7a2a479a42efd5795c54924ac Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 11:11:56 -0600 Subject: [PATCH 095/116] Use placement new to avoid unique_ptr allocations --- include/chaiscript/dispatchkit/any.hpp | 102 ++++++++++++++++++------- 1 file changed, 73 insertions(+), 29 deletions(-) diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 8a624b1..9735016 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -8,6 +8,7 @@ #define CHAISCRIPT_ANY_HPP_ #include +#include namespace chaiscript { namespace detail { @@ -44,6 +45,15 @@ namespace chaiscript { class Any { private: + + + template + struct destruct { + void operator()(T *t) const { + t->~T(); + } + }; + struct Data { Data(const std::type_info &t_type) @@ -61,7 +71,7 @@ namespace chaiscript { return m_type; } - virtual std::unique_ptr clone() const = 0; + virtual void clone(void *t_ptr) const = 0; const std::type_info &m_type; }; @@ -81,9 +91,9 @@ namespace chaiscript { return &m_data; } - std::unique_ptr clone() const CHAISCRIPT_OVERRIDE + void clone(void *t_ptr) const CHAISCRIPT_OVERRIDE { - return std::unique_ptr(new Data_Impl(m_data)); + new (t_ptr) Data_Impl(m_data); } Data_Impl &operator=(const Data_Impl&) = delete; @@ -91,32 +101,70 @@ namespace chaiscript { T m_data; }; - std::unique_ptr m_data; + static const size_t buffersize = sizeof(Data_Impl>)>sizeof(Data_Impl>)?sizeof(Data_Impl>):sizeof(Data_Impl>); + bool m_constructed; + mutable std::array m_data_holder; - public: - // construct/copy/destruct - Any() = default; + inline Data *data() const + { + return reinterpret_cast(m_data_holder.data()); + } - Any(const Any &t_any) - { - if (!t_any.empty()) + + void call_destructor() + { + if (m_constructed) { - m_data = t_any.m_data->clone(); - } else { - m_data.reset(); + m_constructed = false; + data()->~Data(); } } -#if !defined(_MSC_VER) || _MSC_VER != 1800 - Any(Any &&) = default; - Any &operator=(Any &&t_any) = default; -#endif + public: + Any() + : m_constructed(false) + { + } + + // construct/copy/destruct + Any(const Any &t_any) + : m_constructed(false) + { + if (t_any.m_constructed) { + t_any.data()->clone(m_data_holder.data()); + m_constructed = true; + } + } + + Any(Any &&t_any) + : m_constructed(false) + { + if (t_any.m_constructed) { + t_any.m_constructed = false; + m_constructed = true; + m_data_holder = std::move(t_any.m_data_holder); + } + } + + Any &operator=(Any &&t_any) + { + call_destructor(); + if (t_any.m_constructed) { + t_any.m_constructed = false; + m_constructed = true; + m_data_holder = std::move(t_any.m_data_holder); + } + return *this; + } + template::type>::value>::type> explicit Any(ValueType &&t_value) - : m_data(std::unique_ptr(new Data_Impl::type>(std::forward(t_value)))) + : m_constructed(true) { + static_assert(sizeof(Data_Impl::type>) <= buffersize, "Buffer too small"); + (void)(new (m_data_holder.data()) Data_Impl::type>(std::forward(t_value))); } @@ -130,9 +178,9 @@ namespace chaiscript { template ToType &cast() const { - if (m_data && typeid(ToType) == m_data->type()) + if (m_constructed && typeid(ToType) == data()->type()) { - return *static_cast(m_data->data()); + return *static_cast(data()->data()); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -141,26 +189,22 @@ namespace chaiscript { ~Any() { + call_destructor(); } // modifiers Any & swap(Any &t_other) { - std::swap(t_other.m_data, m_data); + std::swap(t_other.m_data_holder, m_data_holder); + std::swap(t_other.m_constructed, m_constructed); return *this; } - // queries - bool empty() const - { - return !bool(m_data); - } const std::type_info & type() const { - if (m_data) - { - return m_data->type(); + if (m_constructed) { + return data()->type(); } else { return typeid(void); } From a112d97141deca9c5bf4089c9283b2f6978a5d67 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 11:48:01 -0600 Subject: [PATCH 096/116] Simplify a couple of random things --- include/chaiscript/dispatchkit/boxed_cast_helper.hpp | 9 ++++----- include/chaiscript/dispatchkit/type_info.hpp | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 3c96931..8f478bf 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -58,6 +58,7 @@ namespace chaiscript { }; + /// Cast_Helper_Inner for casting to a const * type template struct Cast_Helper_Inner @@ -81,11 +82,11 @@ namespace chaiscript typedef Result * Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { - if (ob.is_ref()) + if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result)) { - return &(ob.get().cast >()).get(); + return static_cast(throw_if_null(ob.get_ptr())); } else { - return (ob.get().cast >()).get(); + throw chaiscript::detail::exception::bad_any_cast(); } } }; @@ -149,7 +150,6 @@ namespace chaiscript { }; - /// Cast_Helper_Inner for casting to a const std::shared_ptr & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > @@ -162,7 +162,6 @@ namespace chaiscript }; - /// Cast_Helper_Inner for casting to a Boxed_Value type template<> struct Cast_Helper_Inner diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 81ec083..e15e508 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -62,7 +62,7 @@ namespace chaiscript CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { - return ti.m_type_info == m_type_info + return ti.m_type_info == m_type_info || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } @@ -87,7 +87,7 @@ namespace chaiscript CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; } CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const @@ -100,7 +100,7 @@ namespace chaiscript } } - std::string bare_name() const + std::string bare_name() const { if (m_bare_type_info) { From b53432cf28d7c47179b5bc8b2dbf80e6cce7282e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 13:02:43 -0600 Subject: [PATCH 097/116] Remove remaining uses of std::function --- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- .../dispatchkit/proxy_functions.hpp | 120 ++++++++++++------ .../chaiscript/language/chaiscript_engine.hpp | 6 +- .../chaiscript/language/chaiscript_eval.hpp | 72 ++++++----- 4 files changed, 124 insertions(+), 76 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 8f2b3c7..d832db1 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -520,7 +520,7 @@ namespace chaiscript m->add(fun(&print), "print_string"); m->add(fun(&println), "println_string"); - m->add(chaiscript::make_shared(&bind_function), "bind"); + m->add(dispatch::make_dynamic_proxy_function(&bind_function), "bind"); m->add(fun(&shared_ptr_unconst_clone), "clone"); m->add(fun(&ptr_assign::type>), "="); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index ee3029f..1e761fe 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -302,7 +302,6 @@ namespace chaiscript { public: Dynamic_Proxy_Function( - std::function &)> t_f, int t_arity=-1, AST_NodePtr t_parsenode = AST_NodePtr(), Param_Types t_param_types = Param_Types(), @@ -310,8 +309,7 @@ namespace chaiscript Proxy_Function t_guard = Proxy_Function()) : Proxy_Function_Base(build_param_type_list(t_param_types), t_arity), m_param_types(std::move(t_param_types)), - m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description)), - m_f(std::move(t_f)) + m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)), m_description(std::move(t_description)) { } @@ -350,6 +348,75 @@ namespace chaiscript return m_description; } + + protected: + bool test_guard(const std::vector ¶ms, const Type_Conversions &t_conversions) const + { + if (m_guard) + { + try { + return boxed_cast((*m_guard)(params, t_conversions)); + } catch (const exception::arity_error &) { + return false; + } catch (const exception::bad_boxed_cast &) { + return false; + } + } else { + return true; + } + } + + private: + static std::vector build_param_type_list(const Param_Types &t_types) + { + // For the return type + std::vector types{chaiscript::detail::Get_Type_Info::get()}; + + for (const auto &t : t_types.types()) + { + if (t.second.is_undef()) { + types.push_back(chaiscript::detail::Get_Type_Info::get()); + } else { + types.push_back(t.second); + } + } + + return types; + } + + Param_Types m_param_types; + Proxy_Function m_guard; + AST_NodePtr m_parsenode; + std::string m_description; + }; + + + + template + class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function + { + public: + Dynamic_Proxy_Function_Impl( + Callable t_f, + int t_arity=-1, + AST_NodePtr t_parsenode = AST_NodePtr(), + Param_Types t_param_types = Param_Types(), + std::string t_description = "", + Proxy_Function t_guard = Proxy_Function()) + : Dynamic_Proxy_Function( + t_arity, + std::move(t_parsenode), + std::move(t_param_types), + std::move(t_description), + std::move(t_guard) + ), + m_f(std::move(t_f)) + { + } + + virtual ~Dynamic_Proxy_Function_Impl() {} + + protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { @@ -368,48 +435,17 @@ namespace chaiscript } private: - bool test_guard(const std::vector ¶ms, const Type_Conversions &t_conversions) const - { - if (m_guard) - { - try { - return boxed_cast((*m_guard)(params, t_conversions)); - } catch (const exception::arity_error &) { - return false; - } catch (const exception::bad_boxed_cast &) { - return false; - } - } else { - return true; - } - } - static std::vector build_param_type_list(const Param_Types &t_types) - { - std::vector types; - - // For the return type - types.push_back(chaiscript::detail::Get_Type_Info::get()); - - for (const auto &t : t_types.types()) - { - if (t.second.is_undef()) { - types.push_back(chaiscript::detail::Get_Type_Info::get()); - } else { - types.push_back(t.second); - } - } - - return types; - } - - Param_Types m_param_types; - Proxy_Function m_guard; - AST_NodePtr m_parsenode; - std::string m_description; - std::function &)> m_f; + Callable m_f; }; + template + Proxy_Function make_dynamic_proxy_function(Callable &&c, Arg&& ... a) + { + return chaiscript::make_shared>( + std::forward(c), std::forward(a)...); + } + /// An object used by Bound_Function to represent "_" parameters /// of a binding. This allows for unbound parameters during bind. struct Placeholder_Object diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 8d97aaa..a6a604a 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -363,10 +363,12 @@ namespace chaiscript m_engine.add(fun([this](){ return m_engine.get_function_objects(); }), "get_functions"); m_engine.add(fun([this](){ return m_engine.get_scripting_objects(); }), "get_objects"); - m_engine.add(chaiscript::make_shared( + m_engine.add( + dispatch::make_dynamic_proxy_function( [this](const std::vector &t_params) { return m_engine.call_exists(t_params); - }), "call_exists"); + }) + , "call_exists"); // m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); // diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 9efbcbc..e56e0f2 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -739,12 +739,15 @@ namespace chaiscript const auto &lambda_node = this->children.back(); - return Boxed_Value(chaiscript::make_shared( - [&t_ss, lambda_node, param_names, captures](const std::vector &t_params) - { - return detail::eval_function(t_ss, lambda_node, param_names, t_params, captures); - }, - static_cast(numparams), lambda_node, param_types)); + return Boxed_Value( + dispatch::make_dynamic_proxy_function( + [&t_ss, lambda_node, param_names, captures](const std::vector &t_params) + { + return detail::eval_function(t_ss, lambda_node, param_names, t_params, captures); + }, + static_cast(numparams), lambda_node, param_types + ) + ); } private: @@ -801,25 +804,28 @@ namespace chaiscript } } - std::shared_ptr guard; + std::shared_ptr guard; if (guardnode) { - guard = std::make_shared - ([&t_ss, guardnode, t_param_names](const std::vector &t_params) - { - return detail::eval_function(t_ss, guardnode, t_param_names, t_params); - }, static_cast(numparams), guardnode); + guard = dispatch::make_dynamic_proxy_function( + [&t_ss, guardnode, t_param_names](const std::vector &t_params) + { + return detail::eval_function(t_ss, guardnode, t_param_names, t_params); + }, + static_cast(numparams), guardnode); } try { const std::string & l_function_name = this->children[0]->text; const std::string & l_annotation = this->annotation?this->annotation->text:""; const auto & func_node = this->children.back(); - t_ss.add(chaiscript::make_shared - ([&t_ss, guardnode, func_node, t_param_names](const std::vector &t_params) - { - return detail::eval_function(t_ss, func_node, t_param_names, t_params); - }, static_cast(numparams), this->children.back(), - param_types, l_annotation, guard), l_function_name); + t_ss.add( + dispatch::make_dynamic_proxy_function( + [&t_ss, guardnode, func_node, t_param_names](const std::vector &t_params) + { + return detail::eval_function(t_ss, func_node, t_param_names, t_params); + }, + static_cast(numparams), this->children.back(), + param_types, l_annotation, guard), l_function_name); } catch (const exception::reserved_word_error &e) { throw exception::eval_error("Reserved word used as function name '" + e.word() + "'"); @@ -1399,12 +1405,13 @@ namespace chaiscript const size_t numparams = t_param_names.size(); - std::shared_ptr guard; + std::shared_ptr guard; if (guardnode) { - guard = std::make_shared - ([&t_ss, t_param_names, guardnode](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(t_ss, guardnode, t_param_names, t_params, std::map()); - }, static_cast(numparams), guardnode); + guard = dispatch::make_dynamic_proxy_function( + [&t_ss, t_param_names, guardnode](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(t_ss, guardnode, t_param_names, t_params, std::map()); + }, + static_cast(numparams), guardnode); } try { @@ -1415,12 +1422,15 @@ namespace chaiscript if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); - t_ss.add(std::make_shared(class_name, - std::make_shared( - [&t_ss, t_param_names, node](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); - }, - static_cast(numparams), node, param_types, l_annotation, guard)), + t_ss.add( + std::make_shared(class_name, + dispatch::make_dynamic_proxy_function( + [&t_ss, t_param_names, node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); + }, + static_cast(numparams), node, param_types, l_annotation, guard + ) + ), function_name); } else { @@ -1429,8 +1439,8 @@ namespace chaiscript auto type = t_ss.get_type(class_name, false); param_types.push_front(class_name, type); - t_ss.add(std::make_shared(class_name, - std::make_shared( + t_ss.add(std::make_shared(class_name, + dispatch::make_dynamic_proxy_function( [&t_ss, t_param_names, node](const std::vector &t_params) { return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); }, From 4890b47460c1514a7d75bd2168aaec83fff808de Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 14:25:34 -0600 Subject: [PATCH 098/116] Reduce unary operator overhead --- .../chaiscript/dispatchkit/boxed_number.hpp | 142 ++++++++++++++---- .../chaiscript/language/chaiscript_eval.hpp | 2 +- 2 files changed, 116 insertions(+), 28 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index b65d5e3..c953886 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -171,6 +171,24 @@ namespace chaiscript } } + template + static Boxed_Value unary_go(Operators::Opers t_oper, T &t, const Boxed_Value &t_lhs) + { + switch (t_oper) + { + case Operators::pre_increment: + ++t; + break; + case Operators::pre_decrement: + --t; + break; + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + + return t_lhs; + } + template static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs) { @@ -179,12 +197,6 @@ namespace chaiscript case Operators::assign: t = u; break; - case Operators::pre_increment: - ++t; - break; - case Operators::pre_decrement: - --t; - break; case Operators::assign_product: t *= u; break; @@ -235,6 +247,18 @@ namespace chaiscript return t_lhs; } + template + static Boxed_Value const_unary_int_go(Operators::Opers t_oper, const T &t) + { + switch (t_oper) + { + case Operators::bitwise_complement: + return const_var(~t); + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + } + template static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u) { @@ -253,8 +277,20 @@ namespace chaiscript return const_var(t | u); case Operators::bitwise_xor: return const_var(t ^ u); - case Operators::bitwise_complement: - return const_var(~t); + default: + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + template + static Boxed_Value const_unary_go(Operators::Opers t_oper, const T &t) + { + switch (t_oper) + { + case Operators::unary_minus: + return const_var(-t); + case Operators::unary_plus: + return const_var(+t); default: throw chaiscript::detail::exception::bad_any_cast(); } @@ -274,10 +310,6 @@ namespace chaiscript return const_var(t * u); case Operators::difference: return const_var(t - u); - case Operators::unary_minus: - return const_var(-t); - case Operators::unary_plus: - return const_var(+t); default: throw chaiscript::detail::exception::bad_any_cast(); } @@ -314,10 +346,6 @@ namespace chaiscript return boolean_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { return binary_go(t_oper, *static_cast(t_lhs.get_ptr()), get_as_aux(t_rhs), t_lhs); - } else if (t_oper > Operators::non_const_int_flag && t_oper < Operators::const_int_flag) { - throw chaiscript::detail::exception::bad_any_cast(); - } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { - throw chaiscript::detail::exception::bad_any_cast(); } else if (t_oper > Operators::const_flag) { return const_binary_go(t_oper, get_as_aux(t_lhs), get_as_aux(t_rhs)); } else { @@ -325,6 +353,35 @@ namespace chaiscript } } + // Unary + template + static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) + -> typename std::enable_if::value, Boxed_Value>::type + { + if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { + return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); + } else if (t_oper > Operators::const_int_flag && t_oper < Operators::const_flag) { + return const_unary_int_go(t_oper, *static_cast(t_lhs.get_const_ptr())); + } else if (t_oper > Operators::const_flag) { + return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + template + static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs) + -> typename std::enable_if::value, Boxed_Value>::type + { + if (t_oper > Operators::non_const_flag && t_oper < Operators::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) { + return unary_go(t_oper, *static_cast(t_lhs.get_ptr()), t_lhs); + } else if (t_oper > Operators::const_flag) { + return const_unary_go(t_oper, *static_cast(t_lhs.get_const_ptr())); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + template inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { @@ -354,7 +411,38 @@ namespace chaiscript } throw chaiscript::detail::exception::bad_any_cast(); - } + } + + inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) + { + switch (get_common_type(t_lhs)) { + case Common_Types::t_int32: + return go(t_oper, t_lhs); + case Common_Types::t_uint8: + return go(t_oper, t_lhs); + case Common_Types::t_int8: + return go(t_oper, t_lhs); + case Common_Types::t_uint16: + return go(t_oper, t_lhs); + case Common_Types::t_int16: + return go(t_oper, t_lhs); + case Common_Types::t_uint32: + return go(t_oper, t_lhs); + case Common_Types::t_uint64: + return go(t_oper, t_lhs); + case Common_Types::t_int64: + return go(t_oper, t_lhs); + case Common_Types::t_double: + return go(t_oper, t_lhs); + case Common_Types::t_float: + return go(t_oper, t_lhs); + case Common_Types::t_long_double: + return go(t_oper, t_lhs); + } + + throw chaiscript::detail::exception::bad_any_cast(); + } + inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { @@ -565,12 +653,12 @@ namespace chaiscript Boxed_Number operator--() { - return oper(Operators::pre_decrement, this->bv, var(0)); + return oper(Operators::pre_decrement, this->bv); } Boxed_Number operator++() { - return oper(Operators::pre_increment, this->bv, var(0)); + return oper(Operators::pre_increment, this->bv); } Boxed_Number operator+(const Boxed_Number &t_rhs) const @@ -580,12 +668,12 @@ namespace chaiscript Boxed_Number operator+() const { - return oper(Operators::unary_plus, this->bv, Boxed_Value(0)); + return oper(Operators::unary_plus, this->bv); } Boxed_Number operator-() const { - return oper(Operators::unary_minus, this->bv, Boxed_Value(0)); + return oper(Operators::unary_minus, this->bv); } Boxed_Number operator-(const Boxed_Number &t_rhs) const @@ -658,7 +746,7 @@ namespace chaiscript Boxed_Number operator~() const { - return oper(Operators::bitwise_complement, this->bv, Boxed_Value(0)); + return oper(Operators::bitwise_complement, this->bv); } Boxed_Number operator^(const Boxed_Number &t_rhs) const @@ -747,12 +835,12 @@ namespace chaiscript static Boxed_Number pre_decrement(Boxed_Number t_lhs) { - return oper(Operators::pre_decrement, t_lhs.bv, var(0)); + return oper(Operators::pre_decrement, t_lhs.bv); } static Boxed_Number pre_increment(Boxed_Number t_lhs) { - return oper(Operators::pre_increment, t_lhs.bv, var(0)); + return oper(Operators::pre_increment, t_lhs.bv); } static const Boxed_Number sum(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) @@ -762,12 +850,12 @@ namespace chaiscript static const Boxed_Number unary_plus(const Boxed_Number &t_lhs) { - return oper(Operators::unary_plus, t_lhs.bv, Boxed_Value(0)); + return oper(Operators::unary_plus, t_lhs.bv); } static const Boxed_Number unary_minus(const Boxed_Number &t_lhs) { - return oper(Operators::unary_minus, t_lhs.bv, Boxed_Value(0)); + return oper(Operators::unary_minus, t_lhs.bv); } static const Boxed_Number difference(const Boxed_Number &t_lhs, const Boxed_Number &t_rhs) @@ -883,7 +971,7 @@ namespace chaiscript static Boxed_Value do_oper(Operators::Opers t_oper, const Boxed_Value &t_lhs) { - return oper(t_oper, t_lhs, const_var(0)); + return oper(t_oper, t_lhs); } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index e56e0f2..3c84eaa 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1151,7 +1151,7 @@ namespace chaiscript // short circuit arithmetic operations if (m_oper != Operators::invalid && bv.get_type_info().is_arithmetic()) { - return Boxed_Number::do_oper(m_oper, std::move(bv)); + return Boxed_Number::do_oper(m_oper, bv); } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); From e339055e0be42221a4eedd5edd8a058693de4ab8 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 16:07:57 -0600 Subject: [PATCH 099/116] Address some warnings for clang/gcc --- include/chaiscript/dispatchkit/type_conversions.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 91a496e..9071df3 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -267,7 +267,7 @@ namespace chaiscript throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types"); } - virtual bool bidir() const + virtual bool bidir() const CHAISCRIPT_OVERRIDE { return false; } @@ -301,7 +301,7 @@ namespace chaiscript return m_func(t_from); } - virtual bool bidir() const + virtual bool bidir() const CHAISCRIPT_OVERRIDE { return false; } @@ -455,7 +455,7 @@ namespace chaiscript const Type_Info &to, const Type_Info &from) const { return std::find_if(m_conversions.begin(), m_conversions.end(), - [&to, &from](const std::shared_ptr &conversion) + [&to, &from](const std::shared_ptr &conversion) -> bool { return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from)) || (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from)); From 1526ac96c16d313a712d942d53b2955689e029f5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 23 Jun 2015 16:49:58 -0600 Subject: [PATCH 100/116] Move to clang 3.6 address sanitizer --- .decent_ci-Linux.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 25cb343..24990bd 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -10,7 +10,7 @@ compilers: cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON - name: "clang" build_tag: AddressSanitizer - version: "3.5" + version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON - name: "clang" From 902f48cd4cd4cc7756898a2b07b62d251cc4e84f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 24 Jun 2015 11:25:56 -0600 Subject: [PATCH 101/116] Revert "Use placement new to avoid unique_ptr allocations" This reverts commit 83281bff52a4ceb7a2a479a42efd5795c54924ac. --- include/chaiscript/dispatchkit/any.hpp | 102 +++++++------------------ 1 file changed, 29 insertions(+), 73 deletions(-) diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 9735016..8a624b1 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -8,7 +8,6 @@ #define CHAISCRIPT_ANY_HPP_ #include -#include namespace chaiscript { namespace detail { @@ -45,15 +44,6 @@ namespace chaiscript { class Any { private: - - - template - struct destruct { - void operator()(T *t) const { - t->~T(); - } - }; - struct Data { Data(const std::type_info &t_type) @@ -71,7 +61,7 @@ namespace chaiscript { return m_type; } - virtual void clone(void *t_ptr) const = 0; + virtual std::unique_ptr clone() const = 0; const std::type_info &m_type; }; @@ -91,9 +81,9 @@ namespace chaiscript { return &m_data; } - void clone(void *t_ptr) const CHAISCRIPT_OVERRIDE + std::unique_ptr clone() const CHAISCRIPT_OVERRIDE { - new (t_ptr) Data_Impl(m_data); + return std::unique_ptr(new Data_Impl(m_data)); } Data_Impl &operator=(const Data_Impl&) = delete; @@ -101,70 +91,32 @@ namespace chaiscript { T m_data; }; - static const size_t buffersize = sizeof(Data_Impl>)>sizeof(Data_Impl>)?sizeof(Data_Impl>):sizeof(Data_Impl>); - bool m_constructed; - mutable std::array m_data_holder; - - inline Data *data() const - { - return reinterpret_cast(m_data_holder.data()); - } - - - void call_destructor() - { - if (m_constructed) - { - m_constructed = false; - data()->~Data(); - } - } + std::unique_ptr m_data; public: - Any() - : m_constructed(false) - { - } - // construct/copy/destruct - Any(const Any &t_any) - : m_constructed(false) - { - if (t_any.m_constructed) { - t_any.data()->clone(m_data_holder.data()); - m_constructed = true; + Any() = default; + + Any(const Any &t_any) + { + if (!t_any.empty()) + { + m_data = t_any.m_data->clone(); + } else { + m_data.reset(); } } - Any(Any &&t_any) - : m_constructed(false) - { - if (t_any.m_constructed) { - t_any.m_constructed = false; - m_constructed = true; - m_data_holder = std::move(t_any.m_data_holder); - } - } - - Any &operator=(Any &&t_any) - { - call_destructor(); - if (t_any.m_constructed) { - t_any.m_constructed = false; - m_constructed = true; - m_data_holder = std::move(t_any.m_data_holder); - } - return *this; - } - +#if !defined(_MSC_VER) || _MSC_VER != 1800 + Any(Any &&) = default; + Any &operator=(Any &&t_any) = default; +#endif template::type>::value>::type> explicit Any(ValueType &&t_value) - : m_constructed(true) + : m_data(std::unique_ptr(new Data_Impl::type>(std::forward(t_value)))) { - static_assert(sizeof(Data_Impl::type>) <= buffersize, "Buffer too small"); - (void)(new (m_data_holder.data()) Data_Impl::type>(std::forward(t_value))); } @@ -178,9 +130,9 @@ namespace chaiscript { template ToType &cast() const { - if (m_constructed && typeid(ToType) == data()->type()) + if (m_data && typeid(ToType) == m_data->type()) { - return *static_cast(data()->data()); + return *static_cast(m_data->data()); } else { throw chaiscript::detail::exception::bad_any_cast(); } @@ -189,22 +141,26 @@ namespace chaiscript { ~Any() { - call_destructor(); } // modifiers Any & swap(Any &t_other) { - std::swap(t_other.m_data_holder, m_data_holder); - std::swap(t_other.m_constructed, m_constructed); + std::swap(t_other.m_data, m_data); return *this; } + // queries + bool empty() const + { + return !bool(m_data); + } const std::type_info & type() const { - if (m_constructed) { - return data()->type(); + if (m_data) + { + return m_data->type(); } else { return typeid(void); } From b9875e2844f67c3c8858f395c221075ec68fd037 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 28 Jun 2015 13:20:20 -0600 Subject: [PATCH 102/116] Miscellaneous performance tweaks --- include/chaiscript/dispatchkit/dispatchkit.hpp | 6 ++++-- include/chaiscript/dispatchkit/proxy_functions.hpp | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 0bbe083..6f704b6 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1346,13 +1346,15 @@ namespace chaiscript Stack_Holder() : call_depth(0) { + stacks.reserve(2); stacks.emplace_back(1); call_params.emplace_back(); + call_params.back().reserve(2); } - std::deque stacks; + std::vector stacks; - std::deque> call_params; + std::vector> call_params; int call_depth; }; diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 1e761fe..c2d4045 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -184,10 +184,10 @@ namespace chaiscript if (m_arity == 0) { return true; - } else if (m_arity > 1 && m_types.size() > 1) { - return compare_first_type(vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions); + } else if (m_arity > 1) { + return compare_type_to_param(m_types[1], vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions); } else { - return compare_first_type(vals[0], t_conversions); + return compare_type_to_param(m_types[1], vals[0], t_conversions); } } else { return false; From 748c18f46554725204a9d2fc728ec06fadc56a72 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 28 Jun 2015 15:17:58 -0600 Subject: [PATCH 103/116] Save stack & and prevent lookups --- .../chaiscript/dispatchkit/dispatchkit.hpp | 160 +++++++++---- .../chaiscript/language/chaiscript_common.hpp | 41 ++-- .../chaiscript/language/chaiscript_eval.hpp | 212 +++++++++--------- 3 files changed, 243 insertions(+), 170 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 6f704b6..3a287da 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -384,10 +384,31 @@ namespace chaiscript namespace detail { + struct Stack_Holder + { + typedef std::vector> Scope; + typedef std::vector StackData; + + Stack_Holder() + : call_depth(0) + { + stacks.reserve(2); + stacks.emplace_back(1); + call_params.emplace_back(); + call_params.back().reserve(2); + } + + std::vector stacks; + + std::vector> call_params; + int call_depth; + }; + /// Main class for the dispatchkit. Handles management /// of the object stack, functions and registered types. class Dispatch_Engine { + public: typedef std::map Type_Name_Map; typedef std::vector> Scope; @@ -536,15 +557,27 @@ namespace chaiscript /// Adds a new scope to the stack void new_scope() { - get_stack_data().emplace_back(); - m_stack_holder->call_params.emplace_back(); + new_scope(*m_stack_holder); } /// Pops the current scope from the stack void pop_scope() { - m_stack_holder->call_params.pop_back(); - StackData &stack = get_stack_data(); + pop_scope(*m_stack_holder); + } + + /// Adds a new scope to the stack + void new_scope(Stack_Holder &t_holder) + { + get_stack_data(t_holder).emplace_back(); + t_holder.call_params.emplace_back(); + } + + /// Pops the current scope from the stack + void pop_scope(Stack_Holder &t_holder) + { + t_holder.call_params.pop_back(); + StackData &stack = get_stack_data(t_holder); if (stack.size() > 1) { stack.pop_back(); @@ -555,15 +588,15 @@ namespace chaiscript /// Pushes a new stack on to the list of stacks - void new_stack() + void new_stack(Stack_Holder &t_holder) { // add a new Stack with 1 element - m_stack_holder->stacks.emplace_back(1); + t_holder.stacks.emplace_back(1); } - void pop_stack() + void pop_stack(Stack_Holder &t_holder) { - m_stack_holder->stacks.pop_back(); + t_holder.stacks.pop_back(); } /// Searches the current stack for an object of the given name @@ -1091,55 +1124,79 @@ namespace chaiscript m_state = t_state; } + void save_function_params(Stack_Holder &t_s, std::initializer_list t_params) + { + t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(t_params)); + } + + void save_function_params(Stack_Holder &t_s, std::vector &&t_params) + { + for (auto &¶m : t_params) + { + t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(param)); + } + } + + void save_function_params(Stack_Holder &t_s, const std::vector &t_params) + { + t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end()); + } + void save_function_params(std::initializer_list t_params) { - Stack_Holder &s = *m_stack_holder; - s.call_params.back().insert(s.call_params.back().begin(), std::move(t_params)); + save_function_params(*m_stack_holder, std::move(t_params)); } void save_function_params(std::vector &&t_params) { - Stack_Holder &s = *m_stack_holder; - - for (auto &¶m : t_params) - { - s.call_params.back().insert(s.call_params.back().begin(), std::move(param)); - } + save_function_params(*m_stack_holder, std::move(t_params)); } void save_function_params(const std::vector &t_params) { - Stack_Holder &s = *m_stack_holder; - s.call_params.back().insert(s.call_params.back().begin(), t_params.begin(), t_params.end()); + save_function_params(*m_stack_holder, t_params); } - void new_function_call() + void new_function_call(Stack_Holder &t_s) { - Stack_Holder &s = *m_stack_holder; - if (s.call_depth == 0) + if (t_s.call_depth == 0) { m_conversions.enable_conversion_saves(true); } - ++s.call_depth; + ++t_s.call_depth; save_function_params(m_conversions.take_saves()); } - void pop_function_call() + void pop_function_call(Stack_Holder &t_s) { - Stack_Holder &s = *m_stack_holder; - --s.call_depth; + --t_s.call_depth; - assert(s.call_depth >= 0); + assert(t_s.call_depth >= 0); - if (s.call_depth == 0) + if (t_s.call_depth == 0) { - s.call_params.back().clear(); + t_s.call_params.back().clear(); m_conversions.enable_conversion_saves(false); } } + void new_function_call() + { + new_function_call(*m_stack_holder); + } + + void pop_function_call() + { + pop_function_call(*m_stack_holder); + } + + Stack_Holder &get_stack_holder() + { + return *m_stack_holder; + } + private: /// Returns the current stack /// make const/non const versions @@ -1148,6 +1205,11 @@ namespace chaiscript return m_stack_holder->stacks.back(); } + StackData &get_stack_data(Stack_Holder &t_holder) + { + return t_holder.stacks.back(); + } + StackData &get_stack_data() { return m_stack_holder->stacks.back(); @@ -1341,22 +1403,6 @@ namespace chaiscript mutable chaiscript::detail::threading::shared_mutex m_mutex; mutable chaiscript::detail::threading::shared_mutex m_global_object_mutex; - struct Stack_Holder - { - Stack_Holder() - : call_depth(0) - { - stacks.reserve(2); - stacks.emplace_back(1); - call_params.emplace_back(); - call_params.back().reserve(2); - } - - std::vector stacks; - - std::vector> call_params; - int call_depth; - }; Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; @@ -1364,6 +1410,32 @@ namespace chaiscript State m_state; }; + + class Dispatch_State + { + public: + Dispatch_State(Dispatch_Engine &t_engine) + : m_engine(t_engine), + m_stack_holder(t_engine.get_stack_holder()) + { + } + + Dispatch_Engine *operator->() const { + return &m_engine.get(); + } + + Dispatch_Engine &operator*() const { + return m_engine.get(); + } + + Stack_Holder &stack_holder() const { + return m_stack_holder.get(); + } + + private: + std::reference_wrapper m_engine; + std::reference_wrapper m_stack_holder; + }; } } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 8498f88..af59771 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -476,7 +476,7 @@ namespace chaiscript return oss.str(); } - Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const + Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const { try { return eval_internal(t_e); @@ -512,7 +512,7 @@ namespace chaiscript { } - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const { throw std::runtime_error("Undispatched ast_node (internal error)"); } @@ -554,21 +554,20 @@ namespace chaiscript Scope_Push_Pop(const Scope_Push_Pop &) = delete; Scope_Push_Pop& operator=(const Scope_Push_Pop &) = delete; - Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) - : m_de(t_de) + Scope_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds) + : m_ds(t_ds) { - m_de.new_scope(); + m_ds.get()->new_scope(m_ds.get().stack_holder()); } ~Scope_Push_Pop() { - m_de.pop_scope(); + m_ds.get()->pop_scope(m_ds.get().stack_holder()); } private: - - chaiscript::detail::Dispatch_Engine &m_de; + std::reference_wrapper m_ds; }; /// Creates a new function call and pops it on destruction @@ -577,31 +576,30 @@ namespace chaiscript Function_Push_Pop(const Function_Push_Pop &) = delete; Function_Push_Pop& operator=(const Function_Push_Pop &) = delete; - Function_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) - : m_de(t_de) + Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds) + : m_ds(t_ds) { - m_de.new_function_call(); + m_ds.get()->new_function_call(m_ds.get().stack_holder()); } ~Function_Push_Pop() { - m_de.pop_function_call(); + m_ds.get()->pop_function_call(m_ds.get().stack_holder()); } void save_params(const std::vector &t_params) { - m_de.save_function_params(t_params); + m_ds.get()->save_function_params(t_params); } void save_params(std::initializer_list t_params) { - m_de.save_function_params(std::move(t_params)); + m_ds.get()->save_function_params(std::move(t_params)); } private: - - chaiscript::detail::Dispatch_Engine &m_de; + std::reference_wrapper m_ds; }; /// Creates a new scope then pops it on destruction @@ -610,21 +608,20 @@ namespace chaiscript Stack_Push_Pop(const Stack_Push_Pop &) = delete; Stack_Push_Pop& operator=(const Stack_Push_Pop &) = delete; - Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de) - : m_de(t_de) + Stack_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds) + : m_ds(t_ds) { - m_de.new_stack(); + m_ds.get()->new_stack(m_ds.get().stack_holder()); } ~Stack_Push_Pop() { - m_de.pop_stack(); + m_ds.get()->pop_stack(m_ds.get().stack_holder()); } private: - - chaiscript::detail::Dispatch_Engine &m_de; + std::reference_wrapper m_ds; }; } } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 3c84eaa..4295a32 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -45,7 +45,8 @@ namespace chaiscript { /// Helper function that will set up the scope around a function call, including handling the named function parameters static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map &t_locals=std::map()) { - chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); + chaiscript::detail::Dispatch_State state(t_ss); + chaiscript::eval::detail::Scope_Push_Pop spp(state); for (const auto &local : t_locals) { t_ss.add_object(local.first, local.second); @@ -56,7 +57,7 @@ namespace chaiscript } try { - return t_node->eval(t_ss); + return t_node->eval(state); } catch (detail::Return_Value &rv) { return std::move(rv.retval); } @@ -71,7 +72,7 @@ namespace chaiscript { } virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, m_oper, text, this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -83,7 +84,7 @@ namespace chaiscript } protected: - Boxed_Value do_oper(chaiscript::detail::Dispatch_Engine &t_ss, + Boxed_Value do_oper(const chaiscript::detail::Dispatch_State &t_ss, Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) const { try { @@ -101,11 +102,11 @@ namespace chaiscript chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); fpp.save_params({t_lhs, t_rhs}); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - return t_ss.call_function(t_oper_string, t_lhs, t_rhs); + return t_ss->call_function(t_oper_string, t_lhs, t_rhs); } } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, *t_ss); } } @@ -119,7 +120,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)), m_value(std::move(t_bv)) { } virtual ~Int_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -134,7 +135,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, std::move(t_loc)), m_value(std::move(t_bv)) { } virtual ~Float_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -151,13 +152,13 @@ namespace chaiscript { } virtual ~Id_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { if (!m_value.is_undef()) { return m_value; } else { try { - return t_ss.get_object(this->text, m_loc); + return t_ss->get_object(this->text, m_loc); } catch (std::exception &) { throw exception::eval_error("Can not find object: " + this->text); @@ -220,7 +221,7 @@ namespace chaiscript Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } virtual ~Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params; @@ -236,16 +237,16 @@ namespace chaiscript try { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - return (*t_ss.boxed_cast(fn))(params, t_ss.conversions()); + return (*t_ss->boxed_cast(fn))(params, t_ss->conversions()); } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); } catch(const exception::bad_boxed_cast &){ try { - Const_Proxy_Function f = t_ss.boxed_cast(fn); + Const_Proxy_Function f = t_ss->boxed_cast(fn); // handle the case where there is only 1 function to try to call and dispatch fails on it - throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, t_ss); + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss); } catch (const exception::bad_boxed_cast &) { throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function."); } @@ -293,7 +294,7 @@ namespace chaiscript { assert(children.size() == 2); } virtual ~Inplace_Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params; @@ -307,18 +308,18 @@ namespace chaiscript try { Boxed_Value bv = this->children[0]->eval(t_ss); try { - fn = t_ss.boxed_cast(bv); + fn = t_ss->boxed_cast(bv); } catch (const exception::bad_boxed_cast &) { throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function."); } - return (*fn)(params, t_ss.conversions()); + return (*fn)(params, t_ss->conversions()); } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); } catch(const exception::bad_boxed_cast &){ // handle the case where there is only 1 function to try to call and dispatch fails on it - throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, t_ss); + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, *t_ss); } catch(const exception::arity_error &e){ throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); @@ -417,17 +418,17 @@ namespace chaiscript return retval; } - static std::pair get_arg_type(const AST_NodePtr &t_node, chaiscript::detail::Dispatch_Engine &t_ss) + static std::pair get_arg_type(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { if (t_node->children.size() < 2) { return std::pair(); } else { - return std::pair(t_node->children[0]->text, t_ss.get_type(t_node->children[0]->text, false)); + return std::pair(t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)); } } - static dispatch::Param_Types get_arg_types(const AST_NodePtr &t_node, chaiscript::detail::Dispatch_Engine &t_ss) { + static dispatch::Param_Types get_arg_types(const AST_NodePtr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { std::vector> retval; for (const auto &child : t_node->children) @@ -449,7 +450,7 @@ namespace chaiscript Operators::Opers m_oper; virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value rhs = this->children[2]->eval(t_ss); Boxed_Value lhs = this->children[0]->eval(t_ss); @@ -482,21 +483,21 @@ namespace chaiscript } else { if (!rhs.is_return_value()) { - rhs = t_ss.call_function("clone", rhs); + rhs = t_ss->call_function("clone", rhs); } rhs.reset_return_value(); } } try { - return t_ss.call_function(this->children[1]->text, std::move(lhs), rhs); + return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); } } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, e.functions, false, *t_ss); } } else if (this->children[1]->text == ":=") { @@ -508,9 +509,9 @@ namespace chaiscript } else { try { - return t_ss.call_function(this->children[1]->text, std::move(lhs), rhs); + return t_ss->call_function(this->children[1]->text, std::move(lhs), rhs); } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); } } @@ -523,7 +524,7 @@ namespace chaiscript Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Global_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { const std::string &idname = [&]()->const std::string &{ @@ -535,7 +536,7 @@ namespace chaiscript }(); try { - return t_ss.add_global_no_throw(Boxed_Value(), idname); + return t_ss->add_global_no_throw(Boxed_Value(), idname); } catch (const exception::reserved_word_error &) { throw exception::eval_error("Reserved word used as global '" + idname + "'"); @@ -550,7 +551,7 @@ namespace chaiscript Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Var_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { if (this->children[0]->identifier == AST_Node_Type::Reference) { return this->children[0]->eval(t_ss); @@ -559,7 +560,7 @@ namespace chaiscript try { Boxed_Value bv; - t_ss.add_object(idname, bv); + t_ss->add_object(idname, bv); return bv; } catch (const exception::reserved_word_error &) { @@ -584,7 +585,7 @@ namespace chaiscript Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } virtual ~Array_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; @@ -592,10 +593,10 @@ namespace chaiscript try { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); fpp.save_params(params); - return t_ss.call_function("[]", params); + return t_ss->call_function("[]", params); } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, t_ss ); + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); } } @@ -625,7 +626,7 @@ namespace chaiscript children[2]->children[0]->text:children[2]->text) { } virtual ~Dot_Access_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value retval = children[0]->eval(t_ss); @@ -643,15 +644,15 @@ namespace chaiscript try { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - t_ss.add_object("this", retval); - retval = t_ss.call_member(m_fun_name, std::move(params), has_function_params); + t_ss->add_object("this", retval); + retval = t_ss->call_member(m_fun_name, std::move(params), has_function_params); } catch(const exception::dispatch_error &e){ if (e.functions.empty()) { throw exception::eval_error("'" + m_fun_name + "' is not a function."); } else { - throw exception::eval_error(std::string(e.what()) + " for function '" + m_fun_name + "'", e.parameters, e.functions, true, t_ss); + throw exception::eval_error(std::string(e.what()) + " for function '" + m_fun_name + "'", e.parameters, e.functions, true, *t_ss); } } catch(detail::Return_Value &rv) { @@ -660,10 +661,10 @@ namespace chaiscript if (this->children[2]->identifier == AST_Node_Type::Array_Call) { try { - retval = t_ss.call_function("[]", retval, this->children[2]->children[1]->eval(t_ss)); + retval = t_ss->call_function("[]", retval, this->children[2]->children[1]->eval(t_ss)); } catch(const exception::dispatch_error &e){ - throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, t_ss); + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss); } } @@ -681,7 +682,7 @@ namespace chaiscript m_value(const_var(text)) { } virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE { return m_value; } @@ -702,7 +703,7 @@ namespace chaiscript m_value(const_var(char(text.at(0)))) { } virtual ~Single_Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -723,7 +724,7 @@ namespace chaiscript virtual ~Lambda_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ const auto captures = [&]()->std::map{ std::map named_captures; @@ -738,12 +739,13 @@ namespace chaiscript const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); const auto &lambda_node = this->children.back(); + std::reference_wrapper engine(*t_ss); return Boxed_Value( dispatch::make_dynamic_proxy_function( - [&t_ss, lambda_node, param_names, captures](const std::vector &t_params) + [engine, lambda_node, param_names, captures](const std::vector &t_params) { - return detail::eval_function(t_ss, lambda_node, param_names, t_params, captures); + return detail::eval_function(engine, lambda_node, param_names, t_params, captures); }, static_cast(numparams), lambda_node, param_types ) @@ -761,7 +763,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } virtual ~Block_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); const auto num_children = children.size(); @@ -779,7 +781,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } virtual ~Def_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector t_param_names; size_t numparams = 0; AST_NodePtr guardnode; @@ -804,12 +806,13 @@ namespace chaiscript } } + std::reference_wrapper engine(*t_ss); std::shared_ptr guard; if (guardnode) { guard = dispatch::make_dynamic_proxy_function( - [&t_ss, guardnode, t_param_names](const std::vector &t_params) + [engine, guardnode, t_param_names](const std::vector &t_params) { - return detail::eval_function(t_ss, guardnode, t_param_names, t_params); + return detail::eval_function(engine, guardnode, t_param_names, t_params); }, static_cast(numparams), guardnode); } @@ -818,11 +821,11 @@ namespace chaiscript const std::string & l_function_name = this->children[0]->text; const std::string & l_annotation = this->annotation?this->annotation->text:""; const auto & func_node = this->children.back(); - t_ss.add( + t_ss->add( dispatch::make_dynamic_proxy_function( - [&t_ss, guardnode, func_node, t_param_names](const std::vector &t_params) + [engine, guardnode, func_node, t_param_names](const std::vector &t_params) { - return detail::eval_function(t_ss, func_node, t_param_names, t_params); + return detail::eval_function(engine, func_node, t_param_names, t_params); }, static_cast(numparams), this->children.back(), param_types, l_annotation, guard), l_function_name); @@ -842,7 +845,7 @@ namespace chaiscript While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } virtual ~While_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -868,12 +871,12 @@ namespace chaiscript Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } virtual ~Class_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); /// \todo do this better // put class name in current scope so it can be looked up by the attrs and methods - t_ss.add_object("_current_class_name", const_var(children[0]->text)); + t_ss->add_object("_current_class_name", const_var(children[0]->text)); children[1]->eval(t_ss); @@ -887,7 +890,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } virtual ~Ternary_Cond_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); } @@ -903,7 +906,7 @@ namespace chaiscript If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { } virtual ~If_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); @@ -936,7 +939,7 @@ namespace chaiscript { assert(children.size() == 4); } virtual ~For_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -968,7 +971,7 @@ namespace chaiscript Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } virtual ~Switch_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { bool breaking = false; size_t currentCase = 1; bool hasMatched = false; @@ -982,7 +985,7 @@ namespace chaiscript if (this->children[currentCase]->identifier == AST_Node_Type::Case) { //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here. try { - if (hasMatched || boxed_cast(t_ss.call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) { + if (hasMatched || boxed_cast(t_ss->call_function("==", match_value, this->children[currentCase]->children[0]->eval(t_ss)))) { this->children[currentCase]->eval(t_ss); hasMatched = true; } @@ -1012,7 +1015,7 @@ namespace chaiscript { assert(children.size() == 2); /* how many children does it have? */ } virtual ~Case_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[1]->eval(t_ss); @@ -1027,7 +1030,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } virtual ~Default_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[0]->eval(t_ss); @@ -1042,12 +1045,12 @@ namespace chaiscript Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { try { std::vector vec; if (!children.empty()) { for (const auto &child : children[0]->children) { - vec.push_back(t_ss.call_function("clone", child->eval(t_ss))); + vec.push_back(t_ss->call_function("clone", child->eval(t_ss))); } } return const_var(std::move(vec)); @@ -1068,19 +1071,19 @@ namespace chaiscript Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Map_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ try { std::map retval; for (const auto &child : children[0]->children) { - Boxed_Value bv = t_ss.call_function("clone", child->children[1]->eval(t_ss)); - retval[t_ss.boxed_cast(child->children[0]->eval(t_ss))] = std::move(bv); + Boxed_Value bv = t_ss->call_function("clone", child->children[1]->eval(t_ss)); + retval[t_ss->boxed_cast(child->children[0]->eval(t_ss))] = std::move(bv); } return const_var(std::move(retval)); } catch (const exception::dispatch_error &e) { - throw exception::eval_error("Can not find appropriate copy constructor or 'clone' while inserting into Map.", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Can not find appropriate copy constructor or 'clone' while inserting into Map.", e.parameters, e.functions, false, *t_ss); } } @@ -1091,7 +1094,7 @@ namespace chaiscript Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } virtual ~Return_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ if (!this->children.empty()) { throw detail::Return_Value(children[0]->eval(t_ss)); } @@ -1107,7 +1110,7 @@ namespace chaiscript File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } virtual ~File_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { const auto num_children = children.size(); for (size_t i = 0; i < num_children-1; ++i) { children[i]->eval(t_ss); @@ -1122,10 +1125,10 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ try { Boxed_Value bv; - t_ss.add_object(this->children[0]->text, bv); + t_ss->add_object(this->children[0]->text, bv); return bv; } catch (const exception::reserved_word_error &) { @@ -1144,7 +1147,7 @@ namespace chaiscript { } virtual ~Prefix_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value bv(children[1]->eval(t_ss)); try { @@ -1156,10 +1159,10 @@ namespace chaiscript chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); fpp.save_params({bv}); - return t_ss.call_function(children[0]->text, std::move(bv)); + return t_ss->call_function(children[0]->text, std::move(bv)); } } catch (const exception::dispatch_error &e) { - throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss); } } @@ -1172,7 +1175,7 @@ namespace chaiscript Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } virtual ~Break_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ throw detail::Break_Loop(); } }; @@ -1182,7 +1185,7 @@ namespace chaiscript Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } virtual ~Continue_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ throw detail::Continue_Loop(); } }; @@ -1195,7 +1198,7 @@ namespace chaiscript { } virtual ~Noop_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ // It's a no-op, that evaluates to "true" return m_value; } @@ -1223,14 +1226,14 @@ namespace chaiscript Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Range_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ try { - return t_ss.call_function("generate_range", + return t_ss->call_function("generate_range", children[0]->children[0]->children[0]->eval(t_ss), children[0]->children[0]->children[1]->eval(t_ss)); } catch (const exception::dispatch_error &e) { - throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, t_ss); + throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss); } } @@ -1249,7 +1252,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { } virtual ~Try_AST_Node() {} - Boxed_Value handle_exception(chaiscript::detail::Dispatch_Engine &t_ss, const Boxed_Value &t_except) const + Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const { Boxed_Value retval; @@ -1271,9 +1274,9 @@ namespace chaiscript if (dispatch::Param_Types( std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} - ).match(std::vector{t_except}, t_ss.conversions())) + ).match(std::vector{t_except}, t_ss->conversions())) { - t_ss.add_object(name, t_except); + t_ss->add_object(name, t_except); if (catch_block->children.size() == 2) { //Variable capture, no guards @@ -1310,7 +1313,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1373,11 +1376,11 @@ namespace chaiscript Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } virtual ~Method_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ AST_NodePtr guardnode; - const auto d = t_ss.get_parent_locals(); + const auto d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); const auto class_offset = (itr != d.end())?-1:0; const std::string & class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; @@ -1406,10 +1409,11 @@ namespace chaiscript const size_t numparams = t_param_names.size(); std::shared_ptr guard; + std::reference_wrapper engine(*t_ss); if (guardnode) { guard = dispatch::make_dynamic_proxy_function( - [&t_ss, t_param_names, guardnode](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(t_ss, guardnode, t_param_names, t_params, std::map()); + [engine, t_param_names, guardnode](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params, std::map()); }, static_cast(numparams), guardnode); } @@ -1422,11 +1426,11 @@ namespace chaiscript if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); - t_ss.add( + t_ss->add( std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [&t_ss, t_param_names, node](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); + [engine, t_param_names, node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map()); }, static_cast(numparams), node, param_types, l_annotation, guard ) @@ -1436,13 +1440,13 @@ namespace chaiscript } else { // if the type is unknown, then this generates a function that looks up the type // at runtime. Defining the type first before this is called is better - auto type = t_ss.get_type(class_name, false); + auto type = t_ss->get_type(class_name, false); param_types.push_front(class_name, type); - t_ss.add(std::make_shared(class_name, + t_ss->add(std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [&t_ss, t_param_names, node](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(t_ss, node, t_param_names, t_params, std::map()); + [engine, t_param_names, node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params, std::map()); }, static_cast(numparams), node, param_types, l_annotation, guard), type), function_name); @@ -1463,9 +1467,9 @@ namespace chaiscript Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Attr_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { - const auto &d = t_ss.get_parent_locals(); + const auto &d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); const auto class_offset = (itr != d.end())?-1:0; std::string class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; @@ -1473,7 +1477,7 @@ namespace chaiscript try { std::string attr_name = this->children[static_cast(1 + class_offset)]->text; - t_ss.add( + t_ss->add( std::make_shared( std::move(class_name), fun([attr_name](dispatch::Dynamic_Object &t_obj) { @@ -1502,7 +1506,7 @@ namespace chaiscript { assert(children.size() == 3); } virtual ~Logical_And_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ return const_var(get_bool_condition(children[0]->eval(t_ss)) && get_bool_condition(children[2]->eval(t_ss))); } @@ -1519,7 +1523,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } virtual ~Logical_Or_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ return const_var(get_bool_condition(children[0]->eval(t_ss)) || get_bool_condition(children[2]->eval(t_ss))); } From 72aedca39ce00e8da8693a3ec0c019d1c9a8ac45 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 29 Jun 2015 20:43:12 -0600 Subject: [PATCH 104/116] Fix wrapping of functions with move only params --- .../dispatchkit/function_call_detail.hpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index fb6b5fc..b558138 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -76,16 +76,36 @@ namespace chaiscript { } - Ret operator()(Param...param) + template + Ret operator()(P&& ... param) { return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { - (std::is_reference::value&&!(std::is_same::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)... + box

(std::forward

(param))... }, m_conversions ); } + template + static auto box(Q&& q) -> typename std::enable_if::value&&!std::is_same::type>::type>::value, Boxed_Value>::type + { + return Boxed_Value(std::ref(std::forward(q))); + } + + template + static auto box(Q&& q) -> typename std::enable_if::value&&!std::is_same::type>::type>::value, Boxed_Value>::type + { + return Boxed_Value(std::forward(q)); + } + + template + static Boxed_Value box(Boxed_Value bv) + { + return bv; + } + + std::vector m_funcs; Type_Conversions m_conversions; }; From 9e93d61236b7ed7c9cfd95ac1aafab6dc08f7912 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Jul 2015 21:18:36 -0600 Subject: [PATCH 105/116] Allow user to disable nothread warning --- include/chaiscript/chaiscript_threading.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 6bac83a..26ce7d8 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -14,8 +14,10 @@ #include #include #else +#ifndef CHAISCRIPT_NO_THREADS_WARNING #pragma message ("ChaiScript is compiling without thread safety.") #endif +#endif #include "chaiscript_defines.hpp" From b270a198dc0bf5b10eef9dab3cad22a420bf94b4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Jul 2015 22:10:09 -0600 Subject: [PATCH 106/116] Don't clone return values into vector/map --- include/chaiscript/language/chaiscript_eval.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 3c84eaa..9d5d8c9 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1047,7 +1047,12 @@ namespace chaiscript std::vector vec; if (!children.empty()) { for (const auto &child : children[0]->children) { - vec.push_back(t_ss.call_function("clone", child->eval(t_ss))); + auto obj = child->eval(t_ss); + if (!obj.is_return_value()) { + vec.push_back(t_ss.call_function("clone", obj)); + } else { + vec.push_back(std::move(obj)); + } } } return const_var(std::move(vec)); @@ -1073,8 +1078,12 @@ namespace chaiscript std::map retval; for (const auto &child : children[0]->children) { - Boxed_Value bv = t_ss.call_function("clone", child->children[1]->eval(t_ss)); - retval[t_ss.boxed_cast(child->children[0]->eval(t_ss))] = std::move(bv); + auto obj = child->children[1]->eval(t_ss); + if (!obj.is_return_value()) { + obj = t_ss.call_function("clone", obj); + } + + retval[t_ss.boxed_cast(child->children[0]->eval(t_ss))] = std::move(obj); } return const_var(std::move(retval)); From 496f5aff7aa743afea6e6c5ba9d88a9b8929515c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 3 Jul 2015 14:16:24 -0600 Subject: [PATCH 107/116] Add test for passing non-const ref param --- src/test_module.cpp | 7 +++++++ unittests/non_const_param.chai | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 unittests/non_const_param.chai diff --git a/src/test_module.cpp b/src/test_module.cpp index c5da4c9..ebccf73 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -34,6 +34,11 @@ class TestBaseType int mdarray[2][3][5]; std::function func_member; + void set_string_val(std::string &t_str) + { + t_str = "42"; + } + private: TestBaseType &operator=(const TestBaseType &) = delete; }; @@ -52,6 +57,7 @@ class Type2 return m_bt.val; } + const char *get_str() const { return m_str.c_str(); @@ -171,6 +177,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::val), "val"); m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); + m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val"); #ifndef CHAISCRIPT_MSVC_12 // we cannot support these in MSVC_12 because of a bug in the implementation of diff --git a/unittests/non_const_param.chai b/unittests/non_const_param.chai new file mode 100644 index 0000000..fa385db --- /dev/null +++ b/unittests/non_const_param.chai @@ -0,0 +1,8 @@ +load_module("test_module") + +var t2 = TestBaseType(); + +var s = "5"; +t2.set_string_val(s); +assert_equal(s, "42") + From 484ff7a98b8980a2c5a50404e3758ca5cc040c3a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 3 Jul 2015 14:39:21 -0600 Subject: [PATCH 108/116] Add utility for converting std::vector types --- .../dispatchkit/type_conversions.hpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 9071df3..34f652d 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -575,6 +575,25 @@ namespace chaiscript return chaiscript::make_shared>(user_type(), user_type(), func); } + template + Type_Conversion vector_conversion() + { + auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { + const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); + + + To vec; + + for (const Boxed_Value &bv : from_vec) { + vec.push_back(detail::Cast_Helper::cast(bv, nullptr)); + } + + return Boxed_Value(std::move(vec)); + }; + + return chaiscript::make_shared>(user_type>(), user_type(), func); + } + } From 37120f486fed3fe26183cd1cbd73ad9eca3f6b0a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Jul 2015 08:43:52 -0600 Subject: [PATCH 109/116] Handle user defined conversions of return types from functor --- .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/boxed_cast.hpp | 11 ----------- .../dispatchkit/function_call_detail.hpp | 19 ++++++++++--------- .../dispatchkit/type_conversions.hpp | 3 +-- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 31344d4..c2be40f 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -36,7 +36,7 @@ namespace chaiscript } bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) - : from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast") + : from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name()) { } diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 106b9d8..1ddaacc 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -79,13 +79,6 @@ namespace chaiscript } -#ifdef CHAISCRIPT_MSVC - //Thank you MSVC, yes we know that a constant value is being used in the if - // statment in THIS VERSION of the template instantiation -#pragma warning(push) -#pragma warning(disable : 4127) -#endif - if (t_conversions && t_conversions->convertable_type()) { try { @@ -108,10 +101,6 @@ namespace chaiscript throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } -#ifdef CHAISCRIPT_MSVC -#pragma warning(pop) -#endif - } } diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index b558138..4054b59 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -31,9 +31,9 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions *t_conversions) { - return boxed_cast(dispatch::dispatch(t_funcs, params, t_conversions)); + return boxed_cast(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions); } }; @@ -44,9 +44,9 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions *t_conversions) { - return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as(); + return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as(); } }; @@ -58,9 +58,9 @@ namespace chaiscript struct Function_Caller_Ret { static void call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions *t_conversions) { - dispatch::dispatch(t_funcs, params, t_conversions); + dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()); } }; @@ -70,7 +70,7 @@ namespace chaiscript template struct Build_Function_Caller_Helper { - Build_Function_Caller_Helper(std::vector t_funcs, const Type_Conversions &t_conversions) + Build_Function_Caller_Helper(std::vector t_funcs, const Type_Conversions *t_conversions) : m_funcs(std::move(t_funcs)), m_conversions(t_conversions) { @@ -107,11 +107,12 @@ namespace chaiscript std::vector m_funcs; - Type_Conversions m_conversions; + const Type_Conversions *m_conversions; }; + /// \todo what happens if t_conversions is deleted out from under us?! template std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions *t_conversions) { @@ -131,7 +132,7 @@ namespace chaiscript } */ - return std::function(Build_Function_Caller_Helper(funcs, t_conversions?*t_conversions:Type_Conversions())); + return std::function(Build_Function_Caller_Helper(funcs, t_conversions)); } } } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 34f652d..602d4d9 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -337,7 +337,7 @@ namespace chaiscript Type_Conversions(const Type_Conversions &t_other) : m_mutex(), m_conversions(t_other.get_conversions()), - m_convertableTypes(), + m_convertableTypes(t_other.m_convertableTypes), m_num_types(m_conversions.size()), m_thread_cache(this), m_conversion_saves(this) @@ -581,7 +581,6 @@ namespace chaiscript auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); - To vec; for (const Boxed_Value &bv : from_vec) { From fe33a6aacb02785eec70b8171c76e0524b016600 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 11 Jul 2015 14:51:29 -0600 Subject: [PATCH 110/116] Add failing test for issue #192 --- src/stl_extra.cpp | 5 ++++- unittests/vector_push_back.chai | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index 6f0c5e4..d991481 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -23,7 +23,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra() { - return chaiscript::bootstrap::standard_library::list_type >("List"); + + auto module = chaiscript::bootstrap::standard_library::list_type >("List"); + module->add(chaiscript::bootstrap::standard_library::vector_type >("u16vector")); + return module; } #ifdef __llvm__ diff --git a/unittests/vector_push_back.chai b/unittests/vector_push_back.chai index 82ba4b4..eea34b7 100644 --- a/unittests/vector_push_back.chai +++ b/unittests/vector_push_back.chai @@ -3,3 +3,11 @@ x.push_back(3) assert_equal(3, x.size()) assert_equal(3, x.back()) assert_equal(1, x.front()) + + +load_module("stl_extra") + +auto uint16v = u16vector(); +uint16v.push_back(1u); +assert_equal(1, uint16v.front()); + From 51355343f102b61622014f0cc93e97696144b99e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 11 Jul 2015 16:37:54 -0600 Subject: [PATCH 111/116] Add intro docs to user defined type conversions --- cheatsheet.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cheatsheet.md b/cheatsheet.md index 594b2f7..9ff4ad4 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -80,6 +80,18 @@ It's not strictly necessary to add types, but it helps with many things. Cloning chai.add(chaiscript::user_type, "MyClass"); ``` +## Adding Type Conversions + +User defined type conversions are possible, defined in either script or in C++. + +A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition: + +``` +chai.add(chaiscript::vector_conversion>()); +``` + +This allows you to pass a ChaiScript function to a function requiring `std::vector` + ## Adding Objects ``` From 1ea608babee751dfa4130d76c86d526df5da9cc3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 11 Jul 2015 18:32:47 -0600 Subject: [PATCH 112/116] Better detect arithmetic types #192 --- include/chaiscript/dispatchkit/type_info.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index e15e508..62dc081 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -136,9 +136,11 @@ namespace chaiscript static Type_Info get() { - return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, + return Type_Info(std::is_const::type>::type>::value, + std::is_reference::value, std::is_pointer::value, std::is_void::value, - std::is_arithmetic::value && !std::is_same::type, bool>::value, + (std::is_arithmetic::value || std::is_arithmetic::type>::value) + && !std::is_same::type, bool>::value, &typeid(T), &typeid(typename Bare_Type::type)); } From 563999f3b8bfec4cd74b94e7d70392d2204f506a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 11 Jul 2015 18:34:09 -0600 Subject: [PATCH 113/116] Add note about handling of thread contexts --- include/chaiscript/chaiscript_threading.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 26ce7d8..09fc617 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -155,6 +155,7 @@ namespace chaiscript private: + /// \todo this leaks thread instances. It needs to be culled from time to time std::shared_ptr get_tls() const { unique_lock lock(m_mutex); From 2fbc377119ae802f644e19b5f67d816e23a0ab2e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 11 Jul 2015 18:36:07 -0600 Subject: [PATCH 114/116] More strongly typed handling of push_back wrapper Closes #192 --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 25 +++++++++++++++---- .../language/chaiscript_prelude.chai | 12 --------- src/stl_extra.cpp | 1 + 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index a763e48..1a03888 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -319,7 +319,7 @@ namespace chaiscript /// Add back insertion sequence concept to the given ContainerType /// http://www.sgi.com/tech/stl/BackInsertionSequence.html template - ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared()) + ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared()) { typedef typename ContainerType::reference (ContainerType::*backptr)(); @@ -328,8 +328,16 @@ namespace chaiscript typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &); m->add(fun(static_cast(&ContainerType::push_back)), - []()->std::string{ - if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + [&]()->std::string{ + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + m->eval( + "# Pushes the second value onto the container while making a clone of the value\n" + "def push_back(" + type + " container, x)\n" + "{ \n" + " container.push_back_ref(clone(x)) \n" + "} \n" + ); + return "push_back_ref"; } else { return "push_back"; @@ -345,7 +353,7 @@ namespace chaiscript /// Front insertion sequence /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html template - ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = std::make_shared()) + ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared()) { typedef typename ContainerType::reference (ContainerType::*front_ptr)(); typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const; @@ -356,8 +364,15 @@ namespace chaiscript m->add(fun(static_cast(&ContainerType::front)), "front"); m->add(fun(static_cast(&ContainerType::push_front)), - []()->std::string{ + [&]()->std::string{ if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + m->eval( + "# Pushes the second value onto the front of container while making a clone of the value\n" + "def push_front(" + type + " container, x)\n" + "{ \n" + " container.push_front_ref(clone(x)) \n" + "} \n" + ); return "push_front_ref"; } else { return "push_front"; diff --git a/include/chaiscript/language/chaiscript_prelude.chai b/include/chaiscript/language/chaiscript_prelude.chai index 88835c5..0fe2a5a 100644 --- a/include/chaiscript/language/chaiscript_prelude.chai +++ b/include/chaiscript/language/chaiscript_prelude.chai @@ -127,18 +127,6 @@ def even(x) } -# Pushes the second value onto the container first value while making a clone of the value -def push_back(container, x) : call_exists(push_back_ref, container, x) -{ - container.push_back_ref(clone(x)) -} - -# Pushes the second value onto the front of the container first value while making a clone of the value -def push_front(container, x) : call_exists(push_front_ref, container, x) -{ - container.push_front_ref(clone(x)) -} - # Inserts the third value at the position of the second value into the container of the first # while making a clone. def insert_at(container, pos, x) diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index d991481..e391b18 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -26,6 +26,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extr auto module = chaiscript::bootstrap::standard_library::list_type >("List"); module->add(chaiscript::bootstrap::standard_library::vector_type >("u16vector")); + module->add(chaiscript::vector_conversion>()); return module; } From 1f72afc8f551dc3bf6420a3c8f700434b4a96c35 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 13 Jul 2015 14:44:26 -0600 Subject: [PATCH 115/116] Add crashes and fixes found during fuzzy testing * Let unhandled exceptions propogate to user * Report eval_error when break statement is not in loop * Fix handling of 0 length scripts closes #193 * Don't crash on arity mismatch - Specifically affects the case where no overloads exist for a given function * Fix error printing for `bind` calls * Handle unexpected continue statement * Check arity during bind * Don't allow arith conversion on variadic function * Correct `bind` parameter match count * Add in expected Boxed_Value exception cases * Check access to AST, don't allow `;` in func def * Don't attempt arithmetic unary & call * Don't crash on 0 param call to `bind` * Catch errors during member function dispatch * Properly handle type of const bool & --- .travis.yml | 3 +- CMakeLists.txt | 45 ++++++++++- include/chaiscript/dispatchkit/bootstrap.hpp | 10 ++- .../chaiscript/dispatchkit/dispatchkit.hpp | 10 ++- .../dispatchkit/proxy_functions.hpp | 40 +++++----- include/chaiscript/dispatchkit/type_info.hpp | 26 +++---- .../chaiscript/language/chaiscript_common.hpp | 11 ++- .../chaiscript/language/chaiscript_eval.hpp | 21 +++-- .../chaiscript/language/chaiscript_parser.hpp | 34 ++++---- src/main.cpp | 27 ++++++- unittests/fuzzy_tests-2015-07-16.tar.bz2 | Bin 0 -> 85207 bytes unittests/type_info_test.cpp | 73 ++++++++++++------ 12 files changed, 203 insertions(+), 97 deletions(-) create mode 100644 unittests/fuzzy_tests-2015-07-16.tar.bz2 diff --git a/.travis.yml b/.travis.yml index 8fb7cca..a53e346 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,14 @@ env: before_install: - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" - if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi + - if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -qq g++-$GCC_VER script: - - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index fb0af87..59c33a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE) option(BUILD_MODULES "Build Extra Modules (stl)" TRUE) option(BUILD_SAMPLES "Build Samples Folder" FALSE) +option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE) option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE) mark_as_advanced(USE_STD_MAKE_SHARED) @@ -269,9 +270,51 @@ if(BUILD_MODULES) endif() file(GLOB UNIT_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/unittests/ ${CMAKE_CURRENT_SOURCE_DIR}/unittests/*.chai ${CMAKE_CURRENT_SOURCE_DIR}/unittests/3.x/*.chai) - list(SORT UNIT_TESTS) + +if (RUN_FUZZY_TESTS) + + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests") + + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2015-07-16.tar.bz2 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests + ) + + + file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*) + list(SORT FUZZY_CRASH_TESTS) + + file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*) + list(SORT FUZZY_EXCEPTION_TESTS) + + + foreach(filename ${FUZZY_CRASH_TESTS}) + message(STATUS "Adding test ${filename}") + add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename}) + endforeach() + + set_property(TEST ${FUZZY_CRASH_TESTS} + PROPERTY ENVIRONMENT + "CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/" + "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" + ) + + foreach(filename ${FUZZY_EXCEPTION_TESTS}) + message(STATUS "Adding test ${filename}") + add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename}) + endforeach() + + set_property(TEST ${FUZZY_EXCEPTION_TESTS} + PROPERTY ENVIRONMENT + "CHAI_USE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/unittests/" + "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" + ) + +endif() + + if(BUILD_TESTING) # Add catch tests macro diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index d832db1..1624e02 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -304,13 +304,17 @@ namespace chaiscript /// the remaining parameters are the args to bind into the result static Boxed_Value bind_function(const std::vector ¶ms) { - if (params.size() < 2) - { - throw exception::arity_error(static_cast(params.size()), 2); + if (params.empty()) { + throw exception::arity_error(0, 1); } Const_Proxy_Function f = boxed_cast(params[0]); + if (f->get_arity() != -1 && size_t(f->get_arity()) != params.size() - 1) + { + throw exception::arity_error(static_cast(params.size()), f->get_arity()); + } + return Boxed_Value(Const_Proxy_Function(std::make_shared(std::move(f), std::vector(params.begin() + 1, params.end())))); } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 6f704b6..3369879 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -22,6 +22,7 @@ #include "../chaiscript_defines.hpp" #include "../chaiscript_threading.hpp" +#include "bad_boxed_cast.hpp" #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" @@ -873,7 +874,14 @@ namespace chaiscript std::vector remaining_params{l_params.begin() + l_num_params, l_params.end()}; Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions); if (!remaining_params.empty() || bv.get_type_info().bare_equal(user_type())) { - return (*boxed_cast(bv))(remaining_params, l_conversions); + auto func = boxed_cast>(bv); + try { + return (*func)(remaining_params, l_conversions); + } catch (const chaiscript::exception::bad_boxed_cast &) { + } catch (const chaiscript::exception::arity_error &) { + } catch (const chaiscript::exception::guard_error &) { + } + throw chaiscript::exception::dispatch_error(remaining_params, std::vector{func}); } else { return bv; } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index c2d4045..1eee060 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -149,7 +149,11 @@ namespace chaiscript Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions &t_conversions) const { - return do_call(params, t_conversions); + if (m_arity < 0 || size_t(m_arity) == params.size()) { + return do_call(params, t_conversions); + } else { + throw exception::arity_error(static_cast(params.size()), m_arity); + } } /// Returns a vector containing all of the types of the parameters the function returns/takes @@ -420,18 +424,12 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - if (m_arity < 0 || params.size() == size_t(m_arity)) + if (call_match(params, t_conversions) && test_guard(params, t_conversions)) { - if (call_match(params, t_conversions) && test_guard(params, t_conversions)) - { - return m_f(params); - } else { - throw exception::guard_error(); - } - + return m_f(params); } else { - throw exception::arity_error(static_cast(params.size()), m_arity); - } + throw exception::guard_error(); + } } private: @@ -728,19 +726,14 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - if (params.size() == 1) + const Boxed_Value &bv = params[0]; + if (bv.is_const()) { - const Boxed_Value &bv = params[0]; - if (bv.is_const()) - { - const Class *o = boxed_cast(bv, &t_conversions); - return detail::Handle_Return::type>::handle(o->*m_attr); - } else { - Class *o = boxed_cast(bv, &t_conversions); - return detail::Handle_Return::type>::handle(o->*m_attr); - } + const Class *o = boxed_cast(bv, &t_conversions); + return detail::Handle_Return::type>::handle(o->*m_attr); } else { - throw exception::arity_error(static_cast(params.size()), 1); + Class *o = boxed_cast(bv, &t_conversions); + return detail::Handle_Return::type>::handle(o->*m_attr); } } @@ -787,6 +780,9 @@ namespace chaiscript const Type_Conversions &t_conversions) { const std::vector &types = t_func->get_param_types(); + + if (t_func->get_arity() == -1) return false; + assert(plist.size() == types.size() - 1); return std::mismatch(plist.begin(), plist.end(), diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 62dc081..0d5c5f3 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -29,7 +29,7 @@ namespace chaiscript class Type_Info { public: - CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), @@ -38,7 +38,7 @@ namespace chaiscript { } - CHAISCRIPT_CONSTEXPR Type_Info() + CHAISCRIPT_CONSTEXPR Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), @@ -134,14 +134,14 @@ namespace chaiscript { typedef T type; - static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, (std::is_arithmetic::value || std::is_arithmetic::type>::value) - && !std::is_same::type, bool>::value, - &typeid(T), + && !std::is_same::type>::type, bool>::value, + &typeid(T), &typeid(typename Bare_Type::type)); } }; @@ -151,11 +151,11 @@ namespace chaiscript { typedef T type; - static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, - std::is_arithmetic::value && !std::is_same::type, bool>::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, &typeid(std::shared_ptr ), &typeid(typename Bare_Type::type)); } @@ -166,11 +166,11 @@ namespace chaiscript { typedef T type; - static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, - std::is_arithmetic::value && !std::is_same::type, bool>::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, &typeid(const std::shared_ptr &), &typeid(typename Bare_Type::type)); } @@ -181,11 +181,11 @@ namespace chaiscript { typedef T type; - static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, - std::is_arithmetic::value && !std::is_same::type, bool>::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, &typeid(std::reference_wrapper ), &typeid(typename Bare_Type::type)); } @@ -196,11 +196,11 @@ namespace chaiscript { typedef T type; - static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, - std::is_arithmetic::value && !std::is_same::type, bool>::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, &typeid(const std::reference_wrapper &), &typeid(typename Bare_Type::type)); } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 8498f88..daf8dd9 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -276,10 +276,13 @@ namespace chaiscript template static std::string format_location(const T &t) { - std::ostringstream oss; - oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")"; - - return oss.str(); + if (t) { + std::ostringstream oss; + oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")"; + return oss.str(); + } else { + return "(internal)"; + } } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 9d5d8c9..00ce4b1 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1117,11 +1117,22 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } virtual ~File_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { - const auto num_children = children.size(); - for (size_t i = 0; i < num_children-1; ++i) { - children[i]->eval(t_ss); + try { + const auto num_children = children.size(); + + if (num_children > 0) { + for (size_t i = 0; i < num_children-1; ++i) { + children[i]->eval(t_ss); + } + return children.back()->eval(t_ss); + } else { + return Boxed_Value(); + } + } catch (const detail::Continue_Loop &) { + throw exception::eval_error("Unexpected `continue` statement outside of a loop"); + } catch (const detail::Break_Loop &) { + throw exception::eval_error("Unexpected `break` statement outside of a loop"); } - return children.back()->eval(t_ss); } }; @@ -1158,7 +1169,7 @@ namespace chaiscript try { // short circuit arithmetic operations - if (m_oper != Operators::invalid && bv.get_type_info().is_arithmetic()) + if (m_oper != Operators::invalid && m_oper != Operators::bitwise_and && bv.get_type_info().is_arithmetic()) { return Boxed_Number::do_oper(m_oper, bv); } else { diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e39b632..ddc484f 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -194,6 +194,7 @@ namespace chaiscript /// Returns the front-most AST node AST_NodePtr ast() const { + if (m_match_stack.empty()) throw exception::eval_error("Attempted to access AST of failed parse."); return m_match_stack.front(); } @@ -261,7 +262,7 @@ namespace chaiscript } AST_NodePtr optimized_ast(bool t_optimize_blocks = false, bool t_optimize_returns = true) { - AST_NodePtr p = m_match_stack.front(); + AST_NodePtr p = ast(); //Note, optimize_blocks is currently broken; it breaks stack management if (t_optimize_blocks) { optimize_blocks(p); } if (t_optimize_returns) { optimize_returns(p); } @@ -1208,37 +1209,32 @@ namespace chaiscript } /// Reads an end-of-line group from input, without skipping initial whitespace - bool Eol_() { + bool Eol_(const bool t_eos = false) { bool retval = false; if (has_more_input() && (Symbol_("\r\n") || Char_('\n'))) { retval = true; ++m_line; m_col = 1; - } else if (has_more_input() && Char_(';')) { + } else if (has_more_input() && !t_eos && Char_(';')) { retval = true; } return retval; } - /// Reads (and potentially captures) an end-of-line group from input - bool Eol(const bool t_capture = false) { + /// Reads until the end of the current statement + bool Eos() { SkipWS(); - if (!t_capture) { - return Eol_(); - } else { - const auto start = m_input_pos; - const auto prev_col = m_col; - const auto prev_line = m_line; - if (Eol_()) { - m_match_stack.push_back(make_node(std::string(start, m_input_pos), prev_line, prev_col)); - return true; - } else { - return false; - } - } + return Eol_(true); + } + + /// Reads (and potentially captures) an end-of-line group from input + bool Eol() { + SkipWS(); + + return Eol_(); } /// Reads a comma-separated list of values from input. Id's only, no types allowed @@ -1441,7 +1437,7 @@ namespace chaiscript } } - while (Eol()) {} + while (Eos()) {} if (Char(':')) { if (!Operator()) { diff --git a/src/main.cpp b/src/main.cpp index 67725f0..372adf7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -297,6 +297,8 @@ int main(int argc, char *argv[]) chai.add(chaiscript::fun(&get_eval_error), "get_eval_error"); chai.add(chaiscript::fun(&now), "now"); + bool eval_error_ok = false; + bool boxed_exception_ok = false; for (int i = 0; i < argc; ++i) { if ( i == 0 && argc > 1 ) { @@ -327,6 +329,12 @@ int main(int argc, char *argv[]) arg = "print(version())" ; } else if ( arg == "-h" || arg == "--help" ) { arg = "help(-1)"; + } else if ( arg == "-e" || arg == "--evalerrorok" ) { + eval_error_ok = true; + continue; + } else if ( arg == "--exception" ) { + boxed_exception_ok = true; + continue; } else if ( arg == "-i" || arg == "--interactive" ) { mode = eInteractive ; } else if ( arg.find('-') == 0 ) { @@ -352,12 +360,23 @@ int main(int argc, char *argv[]) catch (const chaiscript::exception::eval_error &ee) { std::cout << ee.pretty_print(); std::cout << '\n'; - return EXIT_FAILURE; + + if (!eval_error_ok) { + return EXIT_FAILURE; + } } - catch (std::exception &e) { - std::cout << e.what() << '\n'; - return EXIT_FAILURE; + catch (const chaiscript::Boxed_Value &e) { + std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n'; + + if (!boxed_exception_ok) { + return EXIT_FAILURE; + } } + +// catch (std::exception &e) { +// std::cout << e.what() << '\n'; +// return EXIT_FAILURE; +// } } return EXIT_SUCCESS; diff --git a/unittests/fuzzy_tests-2015-07-16.tar.bz2 b/unittests/fuzzy_tests-2015-07-16.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..d150daae59ddad453dd5b1b71777d1319a293a4c GIT binary patch literal 85207 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


3O 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
r;7;=Ss>$;eNExcIVtaCmMJbi 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 #include -void test_type(const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void, - bool t_is_undef) +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4190 4640 28251 4702 6330) +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +#ifdef __llvm__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +#pragma clang diagnostic ignored "-Wold-style-cast" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wfloat-equal" +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + + + + +#define CATCH_CONFIG_MAIN + +#include "catch.hpp" + + +TEST_CASE("Type_Info objects generate expected results") { - if (ti.is_const() == t_is_const - && ti.is_pointer() == t_is_pointer - && ti.is_reference() == t_is_reference - && ti.is_void() == t_is_void - && ti.is_undef() == t_is_undef) + const auto test_type = [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void, + bool t_is_undef, bool t_is_arithmetic) { - return; - } else { - exit(EXIT_FAILURE); - } -} + CHECK(ti.is_const() == t_is_const); + CHECK(ti.is_pointer() == t_is_pointer); + CHECK(ti.is_reference() == t_is_reference); + CHECK(ti.is_void() == t_is_void); + CHECK(ti.is_undef() == t_is_undef); + CHECK(ti.is_arithmetic() == t_is_arithmetic); + }; - -int main() -{ - test_type(chaiscript::user_type(), false, false, false, true, false); - test_type(chaiscript::user_type(), true, false, false, false, false); - test_type(chaiscript::user_type(), true, false, true, false, false); - test_type(chaiscript::user_type(), false, false, false, false, false); - test_type(chaiscript::user_type(), false, true, false, false, false); - test_type(chaiscript::user_type(), true, true, false, false, false); - test_type(chaiscript::Type_Info(), false, false, false, false, true); + SECTION("void") { test_type(chaiscript::user_type(), false, false, false, true, false, false); } + SECTION("const int") { test_type(chaiscript::user_type(), true, false, false, false, false, true); } + SECTION("const int &") { test_type(chaiscript::user_type(), true, false, true, false, false, true); } + SECTION("int") { test_type(chaiscript::user_type(), false, false, false, false, false, true); } + SECTION("int *") { test_type(chaiscript::user_type(), false, true, false, false, false, false); } + SECTION("const int *") { test_type(chaiscript::user_type(), true, true, false, false, false, false); } + SECTION("const bool &") { test_type(chaiscript::user_type(), true, false, true, false, false, false); } + SECTION("default") { test_type(chaiscript::Type_Info(), false, false, false, false, true, false); } std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n'; - - return EXIT_SUCCESS; } + + + From 63ab117e7d2f70df6fb6cec734229b7fe8409e9f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 17 Jul 2015 14:58:40 -0600 Subject: [PATCH 116/116] Add release notes for 5.7.1 --- releasenotes.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index 854b74c..c78376d 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,33 @@ Notes: ======= -Current Version: 5.7.0 +Current Version: 5.7.1 + +### Changes since 5.7.0 +* Build time reduction +* Build size reduction +* Performance increases +* Fixed ~20 crash-bugs found with fuzzy testing #194 + * Let unhandled exceptions propogate to user + * Report eval_error when break statement is not in loop + * Fix handling of 0 length scripts closes #193 + * Don't crash on arity mismatch - Specifically affects the case where no overloads exist for a given function + * Fix error printing for `bind` calls + * Handle unexpected continue statement + * Check arity during bind + * Don't allow arith conversion on variadic function + * Correct `bind` parameter match count + * Add in expected Boxed_Value exception cases + * Check access to AST, don't allow `;` in func def + * Don't attempt arithmetic unary & call + * Don't crash on 0 param call to `bind` + * Catch errors during member function dispatch + * Properly handle type of const bool & +* Automatic deduction of lambda type signatures +* Work with non-polymorphic parent/child conversions +* Move to codecov for coverage reporting +* Add `.at` method for Map objects +* Various corrections for support of move-only objects + ### Changes since 5.6.0