Add const correctness for proxy functions. Add unit tests for function variable assignment scenarios

This commit is contained in:
Jason Turner
2009-09-19 21:13:12 +00:00
parent c5f837fd19
commit 7cdd772f2b
12 changed files with 63 additions and 32 deletions

View File

@@ -533,22 +533,39 @@ namespace chaiscript
* function variables. * function variables.
*/ */
template<typename Type> template<typename Type>
boost::shared_ptr<Type> shared_ptr_clone(boost::shared_ptr<Type> f) boost::shared_ptr<Type> shared_ptr_clone(const boost::shared_ptr<Type> &p)
{ {
return f; return p;
} }
/**
* Specific version of shared_ptr_clone just for Proxy_Functions
* probably not necessary, probably could just use the version above,
* but here we are.
*/
Proxy_Function proxy_function_clone(const Const_Proxy_Function &f)
{
return boost::const_pointer_cast<Proxy_Function_Base>(f);
}
/** /**
* Assignment function for shared_ptr objects, does not perform a copy of the * Assignment function for shared_ptr objects, does not perform a copy of the
* object pointed to, instead maintains the shared_ptr concept. * object pointed to, instead maintains the shared_ptr concept.
* Similar to shared_ptr_clone. Used for Proxy_Function. * Similar to shared_ptr_clone. Used for Proxy_Function.
*/ */
template<typename Type> template<typename Type>
Boxed_Value ptr_assign(Boxed_Value lhs, boost::shared_ptr<Type> rhs) Boxed_Value ptr_assign(Boxed_Value lhs, const boost::shared_ptr<typename boost::add_const<Type>::type> &rhs)
{ {
lhs.assign(Boxed_Value(rhs)); if (lhs.is_unknown()
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
return lhs; {
lhs.assign(Boxed_Value(rhs));
return lhs;
} else {
throw bad_boxed_cast("type mismatch in pointer assignment");
}
} }
/** /**
@@ -617,9 +634,9 @@ namespace chaiscript
throw arity_error(params.size(), 2); throw arity_error(params.size(), 2);
} }
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]); Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(Proxy_Function(new Bound_Function(f, return Boxed_Value(Const_Proxy_Function(new Bound_Function(f,
std::vector<Boxed_Value>(params.begin() + 1, params.end())))); std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
} }
@@ -634,7 +651,7 @@ namespace chaiscript
throw arity_error(params.size(), 1); throw arity_error(params.size(), 1);
} }
Proxy_Function f = boxed_cast<Proxy_Function >(params[0]); Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()))); return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end())));
} }
@@ -703,7 +720,7 @@ namespace chaiscript
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))), m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
"bind"); "bind");
m->add(fun(&shared_ptr_clone<Proxy_Function_Base>), "clone"); m->add(fun(&proxy_function_clone), "clone");
m->add(fun(&ptr_assign<Proxy_Function_Base>), "="); m->add(fun(&ptr_assign<Proxy_Function_Base>), "=");
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))), m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),

View File

@@ -135,6 +135,8 @@ namespace chaiscript
template<typename T> template<typename T>
boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj) boost::shared_ptr<Data> get(const boost::shared_ptr<T> &obj)
{ {
bool b_const = boost::is_const<T>::value;
boost::shared_ptr<Data> data(new Data( boost::shared_ptr<Data> data(new Data(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(obj), boost::any(obj),
@@ -142,14 +144,14 @@ namespace chaiscript
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>())) boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
); );
std::map<const void *, Data>::iterator itr std::map<std::pair<const void *, bool>, Data>::iterator itr
= m_ptrs.find(obj.get()); = m_ptrs.find(std::make_pair(obj.get(), b_const));
if (itr != m_ptrs.end()) if (itr != m_ptrs.end())
{ {
(*data) = (itr->second); (*data) = (itr->second);
} else { } else {
m_ptrs.insert(std::make_pair(obj.get(), *data)); m_ptrs.insert(std::make_pair(std::make_pair(obj.get(), b_const), *data));
} }
return data; return data;
@@ -164,14 +166,16 @@ namespace chaiscript
template<typename T> template<typename T>
boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj) boost::shared_ptr<Data> get(boost::reference_wrapper<T> obj)
{ {
bool b_const = boost::is_const<T>::value;
boost::shared_ptr<Data> data(new Data( boost::shared_ptr<Data> data(new Data(
detail::Get_Type_Info<T>::get(), detail::Get_Type_Info<T>::get(),
boost::any(obj), boost::any(obj),
true) true)
); );
std::map<const void *, Data >::iterator itr std::map<std::pair<const void *, bool>, Data >::iterator itr
= m_ptrs.find(obj.get_pointer()); = m_ptrs.find(std::make_pair(obj.get_pointer(), b_const) );
// If the ptr is found in the cache and it is the correct type, // If the ptr is found in the cache and it is the correct type,
// return it. It may be the incorrect type when two variables share the // return it. It may be the incorrect type when two variables share the
@@ -201,7 +205,7 @@ namespace chaiscript
boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj); boost::shared_ptr<T> *ptr = boost::any_cast<boost::shared_ptr<T> >(&data->m_obj);
m_ptrs.insert(std::make_pair(ptr->get(), *data)); m_ptrs.insert(std::make_pair(std::make_pair(ptr->get(), false), *data));
return data; return data;
} }
@@ -228,13 +232,13 @@ namespace chaiscript
} }
std::map<const void *, Data >::iterator itr = m_ptrs.begin(); std::map<std::pair<const void *, bool>, Data>::iterator itr = m_ptrs.begin();
while (itr != m_ptrs.end()) while (itr != m_ptrs.end())
{ {
if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1) if (itr->second.m_ptr_proxy->unique(&itr->second.m_obj) == 1)
{ {
std::map<const void *, Data >::iterator todel = itr; std::map<std::pair<const void *, bool>, Data >::iterator todel = itr;
++itr; ++itr;
m_ptrs.erase(todel); m_ptrs.erase(todel);
} else { } else {
@@ -243,7 +247,7 @@ namespace chaiscript
} }
} }
std::map<const void *, Data > m_ptrs; std::map<std::pair<const void *, bool>, Data > m_ptrs;
int m_cullcount; int m_cullcount;
}; };

View File

@@ -87,7 +87,7 @@ namespace chaiscript
virtual ~Dispatch_Function() {} virtual ~Dispatch_Function() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{ {
return dispatch(m_funcs.begin(), m_funcs.end(), params); return dispatch(m_funcs.begin(), m_funcs.end(), params);
} }
@@ -360,7 +360,7 @@ namespace chaiscript
{ {
throw std::range_error("Object not known: " + name); throw std::range_error("Object not known: " + name);
} else { } else {
Boxed_Value f(Proxy_Function(new Dispatch_Function(funcs))); Boxed_Value f(Const_Proxy_Function(new Dispatch_Function(funcs)));
cache[name] = f; cache[name] = f;
return f; return f;
} }

View File

@@ -99,7 +99,7 @@ namespace chaiscript
} }
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{ {
if (dynamic_object_typename_match(params, m_type_name)) if (dynamic_object_typename_match(params, m_type_name))
{ {
@@ -180,7 +180,7 @@ 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) virtual Boxed_Value operator()(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));

View File

@@ -62,7 +62,7 @@ namespace chaiscript
{ {
public: public:
virtual ~Proxy_Function_Base() {} virtual ~Proxy_Function_Base() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) = 0; virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const = 0;
std::vector<Type_Info> get_param_types() const { return m_types; } std::vector<Type_Info> get_param_types() const { return m_types; }
@@ -139,6 +139,7 @@ namespace chaiscript
}; };
typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function; typedef boost::shared_ptr<Proxy_Function_Base> Proxy_Function;
typedef boost::shared_ptr<const Proxy_Function_Base> Const_Proxy_Function;
/** /**
* Exception thrown if a function's guard fails to execute * Exception thrown if a function's guard fails to execute
@@ -184,7 +185,7 @@ namespace chaiscript
virtual ~Dynamic_Proxy_Function() {} virtual ~Dynamic_Proxy_Function() {}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(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))
{ {
@@ -270,7 +271,7 @@ namespace chaiscript
class Bound_Function : public Proxy_Function_Base class Bound_Function : public Proxy_Function_Base
{ {
public: public:
Bound_Function(const Proxy_Function &t_f, Bound_Function(const Const_Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args) const std::vector<Boxed_Value> &t_args)
: Proxy_Function_Base(std::vector<Type_Info>()), : Proxy_Function_Base(std::vector<Type_Info>()),
m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size())) m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
@@ -289,7 +290,7 @@ namespace chaiscript
return m_f->call_match(build_param_list(vals)); return m_f->call_match(build_param_list(vals));
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{ {
return (*m_f)(build_param_list(params)); return (*m_f)(build_param_list(params));
} }
@@ -343,7 +344,7 @@ namespace chaiscript
} }
private: private:
Proxy_Function m_f; Const_Proxy_Function m_f;
std::vector<Boxed_Value> m_args; std::vector<Boxed_Value> m_args;
int m_arity; int m_arity;
}; };
@@ -375,7 +376,7 @@ namespace chaiscript
} }
} }
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{ {
return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params); return Do_Call<typename boost::function<Func>::result_type>::go(m_f, params);
} }

View File

@@ -470,7 +470,7 @@ namespace chaiscript
try { try {
ss.set_stack(new_stack); ss.set_stack(new_stack);
Boxed_Value retval = (*boxed_cast<Proxy_Function >(fn))(plb); Boxed_Value retval = (*boxed_cast<Const_Proxy_Function>(fn))(plb);
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
return retval; return retval;
} }
@@ -512,7 +512,7 @@ namespace chaiscript
Boxed_Value fn = eval_token(ss, node->children[0]); Boxed_Value fn = eval_token(ss, node->children[0]);
try { try {
Boxed_Value retval = (*boxed_cast<Proxy_Function >(fn))(plb); Boxed_Value retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
return retval; return retval;
} }
catch(const dispatch_error &e){ catch(const dispatch_error &e){
@@ -575,7 +575,7 @@ namespace chaiscript
//fn = ss.get_function(fun_name); //fn = ss.get_function(fun_name);
ss.set_stack(new_stack); ss.set_stack(new_stack);
//retval = dispatch(fn, plb); //retval = dispatch(fn, plb);
retval = (*boxed_cast<Proxy_Function >(fn))(plb); retval = (*boxed_cast<Const_Proxy_Function >(fn))(plb);
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
} }
catch(const dispatch_error &e){ catch(const dispatch_error &e){

View File

@@ -0,0 +1,3 @@
var x = `+`
x = `-`
print(x(5,4))

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1 @@
clone = `-`

View File

@@ -0,0 +1 @@
Error: "Mismatched types in equation" in 'unittests/invalid_function_assignment.chai' at (1, 7)

View File

@@ -0,0 +1,2 @@
var x = 5
x = `-`

View File

@@ -0,0 +1 @@
Error: "Mismatched types in equation" in 'unittests/invalid_function_reassignment.chai' at (2, 3)