From 6f01568a9ae3dd735e79922d4a4d1922d467fb91 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 15:28:33 -0700 Subject: [PATCH 01/12] Fix function_member call from last commit --- include/chaiscript/dispatchkit/dispatchkit.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 1345b137..158bf0ea 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -911,13 +911,12 @@ namespace chaiscript return false; } - for (const auto &fun : t_funs) { - if (fun->is_attribute_function() - && fun->compare_first_type(t_params[0], t_conversions)) { - } - } + return std::any_of(std::cbegin(t_funs), std::cend(t_funs), + [&](const auto &fun) { + return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions); + } + ); - return false; } #ifdef CHAISCRIPT_MSVC From 16c4a119905bb755692252039b3099373d12622a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 18:17:04 -0700 Subject: [PATCH 02/12] More C++11/C++14 updates --- .../chaiscript/dispatchkit/dispatchkit.hpp | 4 +- .../chaiscript/dispatchkit/function_call.hpp | 9 +-- .../chaiscript/dispatchkit/handle_return.hpp | 75 +++---------------- .../chaiscript/language/chaiscript_parser.hpp | 2 +- 4 files changed, 15 insertions(+), 75 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 158bf0ea..ef1682dc 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -312,7 +312,7 @@ namespace chaiscript bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { - return std::any_of(m_funcs.cbegin(), m_funcs.cend(), + return std::any_of(std::begin(m_funcs), std::end(m_funcs), [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); } @@ -911,7 +911,7 @@ namespace chaiscript return false; } - return std::any_of(std::cbegin(t_funs), std::cend(t_funs), + return std::any_of(std::begin(t_funs), std::end(t_funs), [&](const auto &fun) { return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions); } diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index ea0a61e2..990be95a 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -35,8 +35,7 @@ namespace chaiscript /// \returns A std::function object for dispatching /// \param[in] funcs the set of functions to dispatch on. template - std::function - functor(const std::vector &funcs, const Type_Conversions_State *t_conversions) + std::function functor(const std::vector &funcs, const Type_Conversions_State *t_conversions) { const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(), [](const Const_Proxy_Function &f) { @@ -63,8 +62,7 @@ namespace chaiscript /// \returns A std::function object for dispatching /// \param[in] func A function to execute. template - std::function - functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions) + std::function functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions) { return functor(std::vector({std::move(func)}), t_conversions); } @@ -72,8 +70,7 @@ namespace chaiscript /// Helper for automatically unboxing a Boxed_Value that contains a function object /// and creating a typesafe C++ function caller from it. template - std::function - functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions) + std::function functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions) { return functor(boxed_cast(bv, t_conversions), t_conversions); } diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 17c6d4e1..ca353ecf 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -59,13 +59,8 @@ namespace chaiscript }; template - struct Handle_Return> + struct Handle_Return> : Handle_Return &> { - static Boxed_Value handle(const std::function &f) { - return Boxed_Value( - chaiscript::make_shared>>(f) - ); - } }; template @@ -79,23 +74,13 @@ namespace chaiscript }; template - struct Handle_Return> &> + struct Handle_Return> &> : Handle_Return>> { - static Boxed_Value handle(const std::shared_ptr> &f) { - return Boxed_Value( - chaiscript::make_shared>(std::ref(*f),f) - ); - } }; template - struct Handle_Return>> + struct Handle_Return>> : Handle_Return>> { - static Boxed_Value handle(const std::shared_ptr> &f) { - return Boxed_Value( - chaiscript::make_shared>(std::ref(*f),f) - ); - } }; template @@ -143,21 +128,13 @@ namespace chaiscript }; template - struct Handle_Return > + struct Handle_Return> : Handle_Return &> { - static Boxed_Value handle(const std::shared_ptr &r) - { - return Boxed_Value(r, true); - } }; template - struct Handle_Return &> + struct Handle_Return &> : Handle_Return &> { - static Boxed_Value handle(const std::shared_ptr &r) - { - return Boxed_Value(r, true); - } }; template @@ -170,9 +147,6 @@ namespace chaiscript }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template struct Handle_Return { @@ -187,9 +161,6 @@ namespace chaiscript } }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template<> struct Handle_Return { @@ -199,40 +170,19 @@ namespace chaiscript } }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template<> - struct Handle_Return + struct Handle_Return : Handle_Return { - static Boxed_Value handle(const Boxed_Value &r) - { - return r; - } }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template<> - struct Handle_Return + struct Handle_Return : Handle_Return { - static Boxed_Value handle(const Boxed_Value &r) - { - return r; - } }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template<> - struct Handle_Return + struct Handle_Return : Handle_Return { - static Boxed_Value handle(const Boxed_Value &r) - { - return r; - } }; /** @@ -247,16 +197,9 @@ namespace chaiscript } }; - /** - * Used internally for handling a return value from a Proxy_Function call - */ template<> - struct Handle_Return + struct Handle_Return : Handle_Return { - static Boxed_Value handle(const Boxed_Number &r) - { - return r.bv; - } }; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index bd18a6d2..c1da4272 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -60,7 +60,7 @@ namespace chaiscript static std::array, detail::max_alphabet> build_alphabet() { - std::array, detail::max_alphabet> alphabet = {}; + std::array, detail::max_alphabet> alphabet; for (auto &alpha : alphabet) { alpha.fill(false); From 34a2001a7bca497c0cd1ccd113ef0a561d4b4d65 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 07:05:12 -0700 Subject: [PATCH 03/12] Reduce lookups into stack indexes --- include/chaiscript/dispatchkit/dispatchkit.hpp | 10 +++++++--- include/chaiscript/language/chaiscript_eval.hpp | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index ef1682dc..352b086f 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -620,7 +620,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, std::atomic_uint_fast32_t &t_loc) const + Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const { enum class Loc : uint_fast32_t { located = 0x80000000, @@ -633,7 +633,7 @@ namespace chaiscript if (loc == 0) { - auto &stack = get_stack_data(); + auto &stack = get_stack_data(t_holder); // Is it in the stack? for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) @@ -652,7 +652,7 @@ namespace chaiscript t_loc = static_cast(Loc::located); } else if (loc & static_cast(Loc::is_local)) { - auto &stack = get_stack_data(); + auto &stack = get_stack_data(t_holder); return stack[stack.size() - 1 - ((loc & static_cast(Loc::stack_mask)) >> 16)][loc & static_cast(Loc::loc_mask)].second; } @@ -1528,6 +1528,10 @@ namespace chaiscript m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get()); } + Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const { + return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get()); + } + private: std::reference_wrapper m_engine; std::reference_wrapper m_stack_holder; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index d7bc7e0b..b692538c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -168,7 +168,7 @@ namespace chaiscript 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); From c5f4a4dfd8fd954bce2220ef0df42fa440a29036 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 07:05:29 -0700 Subject: [PATCH 04/12] various c++11/c++14 cleanups --- .../chaiscript/dispatchkit/dynamic_object.hpp | 8 ++-- .../dispatchkit/dynamic_object_detail.hpp | 10 ++--- .../dispatchkit/type_conversions.hpp | 44 +++++++++---------- include/chaiscript/dispatchkit/type_info.hpp | 18 ++------ 4 files changed, 32 insertions(+), 48 deletions(-) diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index b35ded6d..0f6155b0 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -44,9 +44,7 @@ namespace chaiscript { } - Dynamic_Object() : m_type_name(""), m_option_explicit(false) - { - } + Dynamic_Object() = default; bool is_explicit() const { @@ -114,8 +112,8 @@ namespace chaiscript } private: - std::string m_type_name; - bool m_option_explicit; + const std::string m_type_name = ""; + bool m_option_explicit = false; std::map m_attrs; }; diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 14f080df..76e3cbf4 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -211,15 +211,15 @@ namespace chaiscript return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { std::vector new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; new_vals.insert(new_vals.end(), vals.begin(), vals.end()); return m_func->call_match(new_vals, t_conversions); - } + } - virtual std::string annotation() const override + std::string annotation() const override { return m_func->annotation(); } @@ -237,8 +237,8 @@ namespace chaiscript } private: - std::string m_type_name; - Proxy_Function m_func; + const std::string m_type_name; + const Proxy_Function m_func; }; } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 122f74df..6660b25a 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -46,7 +46,7 @@ namespace chaiscript bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default; - virtual ~bad_boxed_dynamic_cast() noexcept {} + virtual ~bad_boxed_dynamic_cast() noexcept = default; }; class bad_boxed_type_cast : public bad_boxed_cast @@ -70,7 +70,7 @@ namespace chaiscript bad_boxed_type_cast(const bad_boxed_type_cast &) = default; - virtual ~bad_boxed_type_cast() noexcept {} + virtual ~bad_boxed_type_cast() noexcept = default; }; } @@ -97,7 +97,7 @@ namespace chaiscript return true; } - virtual ~Type_Conversion_Base() {} + virtual ~Type_Conversion_Base() = default; protected: Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from) @@ -107,8 +107,8 @@ namespace chaiscript private: - Type_Info m_to; - Type_Info m_from; + const Type_Info m_to; + const Type_Info m_from; }; @@ -126,7 +126,7 @@ namespace chaiscript 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; @@ -137,7 +137,7 @@ namespace chaiscript ); } else { return Boxed_Value( - [&]()->std::shared_ptr{ + [&](){ if (auto data = std::static_pointer_cast(detail::Cast_Helper >::cast(t_from, nullptr))) { return data; @@ -182,7 +182,7 @@ namespace chaiscript if (t_from.is_const()) { return Boxed_Value( - [&]()->std::shared_ptr{ + [&](){ if (auto data = std::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_from, nullptr))) { return data; @@ -193,7 +193,7 @@ namespace chaiscript ); } else { return Boxed_Value( - [&]()->std::shared_ptr{ + [&](){ if (auto data = std::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_from, nullptr))) { return data; @@ -242,12 +242,12 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override + Boxed_Value convert_down(const Boxed_Value &t_base) const override { return Dynamic_Caster::cast(t_base); } - virtual Boxed_Value convert(const Boxed_Value &t_derived) const override + Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster::cast(t_derived); } @@ -262,17 +262,18 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override + Boxed_Value convert_down(const Boxed_Value &t_base) const 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"); + 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 override + bool bidir() const override { return false; } - virtual Boxed_Value convert(const Boxed_Value &t_derived) const override + Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster::cast(t_derived); } @@ -290,12 +291,12 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &) const override + Boxed_Value convert_down(const Boxed_Value &) const override { throw chaiscript::exception::bad_boxed_type_cast("No conversion exists"); } - virtual Boxed_Value convert(const Boxed_Value &t_from) const override + Boxed_Value convert(const Boxed_Value &t_from) const override { /// \todo better handling of errors from the conversion function return m_func(t_from); @@ -317,11 +318,7 @@ namespace chaiscript public: struct Conversion_Saves { - Conversion_Saves() - : enabled(false) - {} - - bool enabled; + bool enabled = false; std::vector saves; }; @@ -350,7 +347,6 @@ namespace chaiscript m_num_types(m_conversions.size()), m_thread_cache(this), m_conversion_saves(this) - { } @@ -448,7 +444,7 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_mutex); - auto itr = find(to, from); + const auto itr = find(to, from); if (itr != m_conversions.end()) { diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index f1f54cb0..74e1a92a 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -40,17 +40,7 @@ namespace chaiscript { } - constexpr Type_Info() - : m_type_info(nullptr), m_bare_type_info(nullptr), - m_flags(1 << is_undef_flag) - { - } - - Type_Info(Type_Info&&) = default; - Type_Info& operator=(Type_Info&&) = default; - Type_Info(const Type_Info&) = default; - Type_Info& operator=(const Type_Info&) = default; - + constexpr Type_Info() = default; constexpr bool operator<(const Type_Info &ti) const noexcept { @@ -113,15 +103,15 @@ namespace chaiscript } private: - const std::type_info *m_type_info; - const std::type_info *m_bare_type_info; - unsigned int m_flags; + const std::type_info *m_type_info = nullptr; + const std::type_info *m_bare_type_info = nullptr; static const int is_const_flag = 0; static const int is_reference_flag = 1; static const int is_pointer_flag = 2; static const int is_void_flag = 3; static const int is_arithmetic_flag = 4; static const int is_undef_flag = 5; + unsigned int m_flags = (1 << is_undef_flag); }; namespace detail From afa3f2249c9ac92db3eea3f7fbb7e6355e98e0e3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 08:16:25 -0700 Subject: [PATCH 05/12] Mark i as unused for the sake of MSVC 0th case --- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 96f88967..69b88a82 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -78,6 +78,7 @@ namespace chaiscript { try { std::vector::size_type i = 0; + (void)i; (void)params; (void)t_conversions; // this is ok because the order of evaluation of initializer lists is well defined (void)std::initializer_list{(boxed_cast(params[i++], &t_conversions), 0)...}; From 16ffbca6d6d5596389668edaf3b0278dece6158e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 08:36:53 -0700 Subject: [PATCH 06/12] Simplify type_info comparisons --- include/chaiscript/dispatchkit/type_info.hpp | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 74e1a92a..ad88434a 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -50,24 +50,23 @@ namespace chaiscript constexpr bool operator==(const Type_Info &ti) const noexcept { return ti.m_type_info == m_type_info - || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); + || *ti.m_type_info == *m_type_info; } constexpr bool operator==(const std::type_info &ti) const noexcept { - return m_type_info != nullptr && (*m_type_info) == ti; + return !is_undef() && (*m_type_info) == ti; } constexpr bool bare_equal(const Type_Info &ti) const 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 + || *ti.m_bare_type_info == *m_bare_type_info; } constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept { - return m_bare_type_info != nullptr - && (*m_bare_type_info) == ti; + return !is_undef() && (*m_bare_type_info) == ti; } constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; } @@ -79,7 +78,7 @@ namespace chaiscript std::string name() const { - if (m_type_info) + if (!is_undef()) { return m_type_info->name(); } else { @@ -89,7 +88,7 @@ namespace chaiscript std::string bare_name() const { - if (m_bare_type_info) + if (!is_undef()) { return m_bare_type_info->name(); } else { @@ -103,8 +102,10 @@ namespace chaiscript } private: - const std::type_info *m_type_info = nullptr; - const std::type_info *m_bare_type_info = nullptr; + struct Unknown_Type {}; + + const std::type_info *m_type_info = &typeid(Unknown_Type); + const std::type_info *m_bare_type_info = &typeid(Unknown_Type); static const int is_const_flag = 0; static const int is_reference_flag = 1; static const int is_pointer_flag = 2; From d5ae30191d7f501a5b120f9e685a6297ed300732 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 12:44:05 -0700 Subject: [PATCH 07/12] Add =, ==, and != for Dynamic_Objects closes #251 --- include/chaiscript/dispatchkit/bootstrap.hpp | 34 +++++++++++++++++-- .../chaiscript/dispatchkit/dynamic_object.hpp | 5 ++- .../language/chaiscript_prelude.chai | 23 +++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index ef9f032c..34a684f9 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -442,6 +442,7 @@ namespace chaiscript m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs"); m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit"); m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit"); + m->add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); @@ -452,13 +453,42 @@ namespace chaiscript m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); - m->eval(R""( + m->eval(R"chai( def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } ); new_o; } - )""); + + def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } ); + } + + def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + var rhs_attrs := rhs.get_attrs(); + var lhs_attrs := lhs.get_attrs(); + + if (rhs_attrs.size() != lhs_attrs.size()) { + true; + } else { + return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } ); + } + } + + def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + var rhs_attrs := rhs.get_attrs(); + var lhs_attrs := lhs.get_attrs(); + + if (rhs_attrs.size() != lhs_attrs.size()) { + false; + } else { + return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } ); + } + } + )chai"); m->add(fun(&has_guard), "has_guard"); m->add(fun(&get_guard), "get_guard"); diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 0f6155b0..e89d3806 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -82,6 +82,10 @@ namespace chaiscript } } + bool has_attr(const std::string &t_attr_name) const { + return m_attrs.find(t_attr_name) != m_attrs.end(); + } + Boxed_Value &get_attr(const std::string &t_attr_name) { return m_attrs[t_attr_name]; @@ -105,7 +109,6 @@ namespace chaiscript return get_attr(t_method_name); } - std::map get_attrs() const { return m_attrs; diff --git a/include/chaiscript/language/chaiscript_prelude.chai b/include/chaiscript/language/chaiscript_prelude.chai index 55514bba..934f6c43 100644 --- a/include/chaiscript/language/chaiscript_prelude.chai +++ b/include/chaiscript/language/chaiscript_prelude.chai @@ -215,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) { } } +def any_of(container, func) : call_exists(range, container) { + var t_range := range(container); + while (!t_range.empty()) { + if (func(t_range.front())) { + return true; + } + t_range.pop_front(); + } + false; +} + +def all_of(container, func) : call_exists(range, container) { + var t_range := range(container); + while (!t_range.empty()) { + if (!func(t_range.front())) { + return false; + } + t_range.pop_front(); + } + + true; +} + def back_inserter(container) { bind(push_back, container, _); } From d95f59fa975e6c26ff45ef6a4a7739f3ad60e8fa Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 19:50:58 -0700 Subject: [PATCH 08/12] Add test for dynamic object assignments --- unittests/dynamic_object_assignment.chai | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 unittests/dynamic_object_assignment.chai diff --git a/unittests/dynamic_object_assignment.chai b/unittests/dynamic_object_assignment.chai new file mode 100644 index 00000000..ea0b31a2 --- /dev/null +++ b/unittests/dynamic_object_assignment.chai @@ -0,0 +1,26 @@ +class MyClass +{ + def MyClass() + { + this.x = 2; + } + + var x; +} + + +var o = MyClass(); +var o2 = MyClass(); + +o2.x = 5; +o = o2; + +assert_true(o.x == 5) +assert_true(o == o2) + +o2.x = 3; + +print(o2.x); +print(o.x); + +assert_true(o != o2) From de635298874d8caa7a90646777f10cfac8007e3d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 20:06:57 -0700 Subject: [PATCH 09/12] Add failing test for pointer based member data Issue #245 --- src/test_module.cpp | 9 ++++++++- unittests/member_variable_access.chai | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test_module.cpp b/src/test_module.cpp index b0ce5aef..c854e21f 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -11,7 +11,7 @@ class TestBaseType TestBaseType() : val(10), const_val(15), mdarray{} { } TestBaseType(int) : val(10), const_val(15), mdarray{} { } TestBaseType(int *) : val(10), const_val(15), mdarray{} { } - + TestBaseType(const TestBaseType &) = default; virtual ~TestBaseType() {} virtual int func() { return 0; } @@ -22,6 +22,11 @@ class TestBaseType int val; const int const_val; + const int *const_val_ptr = &const_val; + + const int *get_const_val_ptr() { + return const_val_ptr; + } int mdarray[2][3][5]; std::function func_member; @@ -168,6 +173,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::val), "val"); m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); + m->add(chaiscript::fun(&TestBaseType::const_val_ptr), "const_val_ptr"); + m->add(chaiscript::fun(&TestBaseType::get_const_val_ptr), "get_const_val_ptr"); m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val"); diff --git a/unittests/member_variable_access.chai b/unittests/member_variable_access.chai index 000d0582..10d6f902 100644 --- a/unittests/member_variable_access.chai +++ b/unittests/member_variable_access.chai @@ -8,4 +8,6 @@ assert_equal(13, t0.val) assert_equal(15, t0.constMe().const_val) assert_equal(13, t0.constMe().val) +assert_equal(15, t0.get_const_val_ptr()) +assert_equal(15, t0.const_val_ptr) From 7dcd6b8447f775876c7d8f5d3bfc0a02f3af811d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 12 Mar 2016 22:04:01 -0700 Subject: [PATCH 10/12] Implement member pointer value support closes #245 --- .../dispatchkit/proxy_functions.hpp | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 507abb62..e7a8ad90 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -705,14 +705,40 @@ namespace chaiscript if (bv.is_const()) { const Class *o = boxed_cast(bv, &t_conversions); - return detail::Handle_Return::type>::handle(o->*m_attr); + return do_call_impl(o); } else { Class *o = boxed_cast(bv, &t_conversions); - return detail::Handle_Return::type>::handle(o->*m_attr); + return do_call_impl(o); } } private: + template + auto do_call_impl(Class *o) const -> std::enable_if_t::value, Boxed_Value> + { + return detail::Handle_Return::handle(o->*m_attr); + } + + template + auto do_call_impl(const Class *o) const -> std::enable_if_t::value, Boxed_Value> + { + return detail::Handle_Return::handle(o->*m_attr); + } + + template + auto do_call_impl(Class *o) const -> std::enable_if_t::value, Boxed_Value> + { + return detail::Handle_Return::type>::handle(o->*m_attr); + } + + template + auto do_call_impl(const Class *o) const -> std::enable_if_t::value, Boxed_Value> + { + return detail::Handle_Return::type>::handle(o->*m_attr); + } + + + static std::vector param_types() { return {user_type(), user_type()}; From b424d1f9cb0ef73eb41c585893c99dede8faef1f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 13 Mar 2016 15:33:23 -0600 Subject: [PATCH 11/12] delimit chaiscript text blocks --- include/chaiscript/chaiscript_stdlib.hpp | 2 +- include/chaiscript/dispatchkit/bootstrap.hpp | 4 ++-- .../{chaiscript_prelude.chai => chaiscript_prelude.hpp} | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename include/chaiscript/language/{chaiscript_prelude.chai => chaiscript_prelude.hpp} (98%) diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index 4b38f2cd..ca0214af 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -18,7 +18,7 @@ #include "dispatchkit/bootstrap.hpp" #include "dispatchkit/bootstrap_stl.hpp" #include "dispatchkit/boxed_value.hpp" -#include "language/chaiscript_prelude.chai" +#include "language/chaiscript_prelude.hpp" #include "utility/json_wrap.hpp" #ifndef CHAISCRIPT_NO_THREADS diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 34a684f9..1f519dc8 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -453,7 +453,7 @@ namespace chaiscript m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); - m->eval(R"chai( + m->eval(R"chaiscript( def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } ); @@ -488,7 +488,7 @@ namespace chaiscript return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } ); } } - )chai"); + )chaiscript"); m->add(fun(&has_guard), "has_guard"); m->add(fun(&get_guard), "get_guard"); diff --git a/include/chaiscript/language/chaiscript_prelude.chai b/include/chaiscript/language/chaiscript_prelude.hpp similarity index 98% rename from include/chaiscript/language/chaiscript_prelude.chai rename to include/chaiscript/language/chaiscript_prelude.hpp index 934f6c43..98e09026 100644 --- a/include/chaiscript/language/chaiscript_prelude.chai +++ b/include/chaiscript/language/chaiscript_prelude.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// and Jason Turner (jason@emptycrate.com) +// and 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PRELUDE_HPP_ @@ -9,7 +9,7 @@ namespace chaiscript { struct ChaiScript_Prelude { - static std::string chaiscript_prelude() { return R""( + static std::string chaiscript_prelude() { return R"chaiscript( def lt(l, r) { if (call_exists(`<`, l, r)) { @@ -553,7 +553,7 @@ def find(container, value) { } -)""; +)chaiscript"; } }; From c57ea79d0d02230d820f455a3418f045bdb61b8e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 13 Mar 2016 16:26:46 -0600 Subject: [PATCH 12/12] Update reference to prelude --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7427542a..f1b3108d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,7 +213,7 @@ endif() include_directories(include) -set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp) +set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)