From 74e719c0532f24ff5c1789e7eb2f35ac63e1497c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 2 Oct 2010 13:26:06 +0000 Subject: [PATCH] Add object dependency tracking to make sure that during nested function calls all returned values are not prematurely destructed. All tests pass on vc2008 now. --- .../chaiscript/dispatchkit/boxed_value.hpp | 23 +++++ .../chaiscript/dispatchkit/dispatchkit.hpp | 10 ++- .../chaiscript/dispatchkit/dynamic_object.hpp | 45 +++++----- .../dispatchkit/proxy_functions.hpp | 85 ++++++++++++------- .../chaiscript/language/chaiscript_eval.hpp | 1 + 5 files changed, 106 insertions(+), 58 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 5e6209d..59584fa 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -70,10 +70,15 @@ namespace chaiscript return *this; } + ~Data() + { + } + Type_Info m_type_info; boost::any m_obj; bool m_is_ref; boost::function m_is_null; + std::vector > m_dependencies; }; struct Object_Data @@ -245,6 +250,24 @@ namespace chaiscript return !is_ref(); } + void clear_dependencies() + { + m_data->m_dependencies.clear(); + } + + template + void add_dependencies(InItr begin, const InItr &end) + { + while (begin != end) + { + if (begin->m_data != m_data) + { + m_data->m_dependencies.push_back(begin->m_data); + } + ++begin; + } + } + private: boost::shared_ptr m_data; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 33677b3..786ea13 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -132,10 +132,6 @@ namespace chaiscript virtual ~Dispatch_Function() {} - virtual Boxed_Value operator()(const std::vector ¶ms) const - { - return dispatch(m_funcs.begin(), m_funcs.end(), params); - } virtual int get_arity() const { @@ -167,6 +163,12 @@ namespace chaiscript return ""; } + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const + { + return dispatch(m_funcs.begin(), m_funcs.end(), params); + } + private: std::vector > m_funcs; }; diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index c25a945..18cd649 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -90,15 +90,6 @@ namespace chaiscript } } - virtual Boxed_Value operator()(const std::vector ¶ms) const - { - if (dynamic_object_typename_match(params, m_type_name, m_ti)) - { - return (*m_func)(params); - } else { - throw guard_error(); - } - } virtual int get_arity() const { @@ -111,6 +102,16 @@ namespace chaiscript } protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const + { + if (dynamic_object_typename_match(params, m_type_name, m_ti)) + { + return (*m_func)(params); + } else { + throw guard_error(); + } + } + virtual bool compare_first_type(const Boxed_Value &bv) const { return dynamic_object_typename_match(bv, m_type_name, m_ti); @@ -212,7 +213,20 @@ namespace chaiscript return m_func->call_match(new_vals); } - virtual Boxed_Value operator()(const std::vector ¶ms) const + + virtual int get_arity() const + { + // "this" is not considered part of the arity + return m_func->get_arity() - 1; + } + + virtual std::string annotation() const + { + return m_func->annotation(); + } + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const { std::vector new_params; chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name)); @@ -224,17 +238,6 @@ namespace chaiscript return bv; } - virtual int get_arity() const - { - // "this" is not considered part of the arity - return m_func->get_arity() - 1; - } - - virtual std::string annotation() const - { - return m_func->annotation(); - } - private: std::string m_type_name; Proxy_Function m_func; diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index ac6ef43..fbc854d 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -65,7 +65,12 @@ namespace chaiscript { public: virtual ~Proxy_Function_Base() {} - virtual Boxed_Value operator()(const std::vector ¶ms) const = 0; + Boxed_Value operator()(const std::vector ¶ms) const + { + Boxed_Value bv = do_call(params); + bv.add_dependencies(params.begin(), params.end()); + return bv; + } std::vector get_param_types() const { return m_types; } @@ -99,6 +104,8 @@ namespace chaiscript virtual std::string annotation() const = 0; protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const = 0; + Proxy_Function_Base(const std::vector &t_types) : m_types(t_types) { @@ -198,7 +205,19 @@ namespace chaiscript virtual ~Dynamic_Proxy_Function() {} - virtual Boxed_Value operator()(const std::vector ¶ms) const + + virtual int get_arity() const + { + return m_arity; + } + + virtual std::string annotation() const + { + return m_description; + } + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const { if (m_arity < 0 || params.size() == size_t(m_arity)) { @@ -215,16 +234,6 @@ namespace chaiscript } } - virtual int get_arity() const - { - return m_arity; - } - - virtual std::string annotation() const - { - return m_description; - } - private: bool test_guard(const std::vector ¶ms) const { @@ -352,6 +361,12 @@ namespace chaiscript return ""; } + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const + { + return (*m_f)(build_param_list(params)); + } + private: Const_Proxy_Function m_f; std::vector m_args; @@ -381,10 +396,6 @@ namespace chaiscript return pimpl != 0; } - virtual Boxed_Value operator()(const std::vector ¶ms) const - { - return Do_Call::result_type>::go(m_f, params); - } virtual int get_arity() const { @@ -407,6 +418,12 @@ namespace chaiscript return ""; } + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const + { + return Do_Call::result_type>::go(m_f, params); + } + private: boost::function m_f; Func *m_dummy_func; @@ -438,23 +455,6 @@ namespace chaiscript } } - virtual Boxed_Value operator()(const std::vector ¶ms) const - { - if (params.size() == 1) - { - const Boxed_Value &bv = params[0]; - if (bv.is_const()) - { - const Class *o = boxed_cast(bv); - return Handle_Return::type>::handle(o->*m_attr); - } else { - Class *o = boxed_cast(bv); - return Handle_Return::type>::handle(o->*m_attr); - } - } else { - throw arity_error(params.size(), 1); - } - } virtual int get_arity() const { @@ -476,6 +476,25 @@ namespace chaiscript return ""; } + protected: + virtual Boxed_Value do_call(const std::vector ¶ms) const + { + if (params.size() == 1) + { + const Boxed_Value &bv = params[0]; + if (bv.is_const()) + { + const Class *o = boxed_cast(bv); + return Handle_Return::type>::handle(o->*m_attr); + } else { + Class *o = boxed_cast(bv); + return Handle_Return::type>::handle(o->*m_attr); + } + } else { + throw arity_error(params.size(), 1); + } + } + private: static std::vector param_types() { diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 754e86f..ec1b467 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -138,6 +138,7 @@ namespace chaiscript try { if (lhs.is_undef()) { retval = ss.call_function("clone", retval); + retval.clear_dependencies(); } try {