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.
This commit is contained in:
Jason Turner 2010-10-02 13:26:06 +00:00
parent 43dbd8ac78
commit 74e719c053
5 changed files with 106 additions and 58 deletions

View File

@ -70,10 +70,15 @@ namespace chaiscript
return *this; return *this;
} }
~Data()
{
}
Type_Info m_type_info; Type_Info m_type_info;
boost::any m_obj; boost::any m_obj;
bool m_is_ref; bool m_is_ref;
boost::function<bool (boost::any*)> m_is_null; boost::function<bool (boost::any*)> m_is_null;
std::vector<boost::shared_ptr<Data> > m_dependencies;
}; };
struct Object_Data struct Object_Data
@ -245,6 +250,24 @@ namespace chaiscript
return !is_ref(); return !is_ref();
} }
void clear_dependencies()
{
m_data->m_dependencies.clear();
}
template<typename InItr>
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: private:
boost::shared_ptr<Data> m_data; boost::shared_ptr<Data> m_data;

View File

@ -132,10 +132,6 @@ namespace chaiscript
virtual ~Dispatch_Function() {} virtual ~Dispatch_Function() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
return dispatch(m_funcs.begin(), m_funcs.end(), params);
}
virtual int get_arity() const virtual int get_arity() const
{ {
@ -167,6 +163,12 @@ namespace chaiscript
return ""; return "";
} }
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
return dispatch(m_funcs.begin(), m_funcs.end(), params);
}
private: private:
std::vector<std::pair<std::string, Proxy_Function > > m_funcs; std::vector<std::pair<std::string, Proxy_Function > > m_funcs;
}; };

View File

@ -90,15 +90,6 @@ namespace chaiscript
} }
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) 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 virtual int get_arity() const
{ {
@ -111,6 +102,16 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) 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 virtual bool compare_first_type(const Boxed_Value &bv) const
{ {
return dynamic_object_typename_match(bv, m_type_name, m_ti); return dynamic_object_typename_match(bv, m_type_name, m_ti);
@ -212,7 +213,20 @@ namespace chaiscript
return m_func->call_match(new_vals); return m_func->call_match(new_vals);
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) 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<Boxed_Value> &params) const
{ {
std::vector<Boxed_Value> new_params; std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name)); chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
@ -224,17 +238,6 @@ namespace chaiscript
return bv; 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: private:
std::string m_type_name; std::string m_type_name;
Proxy_Function m_func; Proxy_Function m_func;

View File

@ -65,7 +65,12 @@ namespace chaiscript
{ {
public: public:
virtual ~Proxy_Function_Base() {} virtual ~Proxy_Function_Base() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const = 0; Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
Boxed_Value bv = do_call(params);
bv.add_dependencies(params.begin(), params.end());
return bv;
}
std::vector<Type_Info> get_param_types() const { return m_types; } std::vector<Type_Info> get_param_types() const { return m_types; }
@ -99,6 +104,8 @@ namespace chaiscript
virtual std::string annotation() const = 0; virtual std::string annotation() const = 0;
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const = 0;
Proxy_Function_Base(const std::vector<Type_Info> &t_types) Proxy_Function_Base(const std::vector<Type_Info> &t_types)
: m_types(t_types) : m_types(t_types)
{ {
@ -198,7 +205,19 @@ namespace chaiscript
virtual ~Dynamic_Proxy_Function() {} virtual ~Dynamic_Proxy_Function() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) 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<Boxed_Value> &params) const
{ {
if (m_arity < 0 || params.size() == size_t(m_arity)) 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: private:
bool test_guard(const std::vector<Boxed_Value> &params) const bool test_guard(const std::vector<Boxed_Value> &params) const
{ {
@ -352,6 +361,12 @@ namespace chaiscript
return ""; return "";
} }
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
return (*m_f)(build_param_list(params));
}
private: private:
Const_Proxy_Function m_f; Const_Proxy_Function m_f;
std::vector<Boxed_Value> m_args; std::vector<Boxed_Value> m_args;
@ -381,10 +396,6 @@ namespace chaiscript
return pimpl != 0; return pimpl != 0;
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
}
virtual int get_arity() const virtual int get_arity() const
{ {
@ -407,6 +418,12 @@ namespace chaiscript
return ""; return "";
} }
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
}
private: private:
boost::function<Func> m_f; boost::function<Func> m_f;
Func *m_dummy_func; Func *m_dummy_func;
@ -438,23 +455,6 @@ namespace chaiscript
} }
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
if (params.size() == 1)
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
} else {
Class *o = boxed_cast<Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
}
} else {
throw arity_error(params.size(), 1);
}
}
virtual int get_arity() const virtual int get_arity() const
{ {
@ -476,6 +476,25 @@ namespace chaiscript
return ""; return "";
} }
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
if (params.size() == 1)
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
{
const Class *o = boxed_cast<const Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
} else {
Class *o = boxed_cast<Class *>(bv);
return Handle_Return<typename boost::add_reference<T>::type>::handle(o->*m_attr);
}
} else {
throw arity_error(params.size(), 1);
}
}
private: private:
static std::vector<Type_Info> param_types() static std::vector<Type_Info> param_types()
{ {

View File

@ -138,6 +138,7 @@ namespace chaiscript
try { try {
if (lhs.is_undef()) { if (lhs.is_undef()) {
retval = ss.call_function("clone", retval); retval = ss.call_function("clone", retval);
retval.clear_dependencies();
} }
try { try {