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;
}
~Data()
{
}
Type_Info m_type_info;
boost::any m_obj;
bool m_is_ref;
boost::function<bool (boost::any*)> m_is_null;
std::vector<boost::shared_ptr<Data> > m_dependencies;
};
struct Object_Data
@ -245,6 +250,24 @@ namespace chaiscript
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:
boost::shared_ptr<Data> m_data;

View File

@ -132,10 +132,6 @@ namespace chaiscript
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
{
@ -167,6 +163,12 @@ namespace chaiscript
return "";
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
return dispatch(m_funcs.begin(), m_funcs.end(), params);
}
private:
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
{
@ -111,6 +102,16 @@ namespace chaiscript
}
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
{
return dynamic_object_typename_match(bv, m_type_name, m_ti);
@ -212,17 +213,6 @@ namespace chaiscript
return m_func->call_match(new_vals);
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params);
return bv;
}
virtual int get_arity() const
{
@ -235,6 +225,19 @@ namespace chaiscript
return m_func->annotation();
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
std::vector<Boxed_Value> new_params;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params);
return bv;
}
private:
std::string m_type_name;
Proxy_Function m_func;

View File

@ -65,7 +65,12 @@ namespace chaiscript
{
public:
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; }
@ -99,6 +104,8 @@ namespace chaiscript
virtual std::string annotation() const = 0;
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const = 0;
Proxy_Function_Base(const std::vector<Type_Info> &t_types)
: m_types(t_types)
{
@ -198,7 +205,19 @@ namespace chaiscript
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))
{
@ -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<Boxed_Value> &params) const
{
@ -352,6 +361,12 @@ namespace chaiscript
return "";
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const
{
return (*m_f)(build_param_list(params));
}
private:
Const_Proxy_Function m_f;
std::vector<Boxed_Value> m_args;
@ -381,10 +396,6 @@ namespace chaiscript
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
{
@ -407,6 +418,12 @@ namespace chaiscript
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:
boost::function<Func> m_f;
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
{
@ -476,6 +476,25 @@ namespace chaiscript
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:
static std::vector<Type_Info> param_types()
{

View File

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