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.
*/
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
* object pointed to, instead maintains the shared_ptr concept.
* Similar to shared_ptr_clone. Used for Proxy_Function.
*/
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));
return lhs;
if (lhs.is_unknown()
|| (!lhs.get_type_info().is_const() && lhs.get_type_info().bare_equal(chaiscript::detail::Get_Type_Info<Type>::get())))
{
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);
}
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()))));
}
@@ -634,7 +651,7 @@ namespace chaiscript
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())));
}
@@ -703,7 +720,7 @@ namespace chaiscript
m->add(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&bind_function, _1))),
"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(Proxy_Function(new Dynamic_Proxy_Function(boost::bind(&call_exists, _1))),

View File

@@ -135,6 +135,8 @@ namespace chaiscript
template<typename T>
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(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
@@ -142,14 +144,14 @@ namespace chaiscript
boost::shared_ptr<Data::Shared_Ptr_Proxy>(new Data::Shared_Ptr_Proxy_Impl<T>()))
);
std::map<const void *, Data>::iterator itr
= m_ptrs.find(obj.get());
std::map<std::pair<const void *, bool>, Data>::iterator itr
= m_ptrs.find(std::make_pair(obj.get(), b_const));
if (itr != m_ptrs.end())
{
(*data) = (itr->second);
} 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;
@@ -164,14 +166,16 @@ namespace chaiscript
template<typename T>
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(
detail::Get_Type_Info<T>::get(),
boost::any(obj),
true)
);
std::map<const void *, Data >::iterator itr
= m_ptrs.find(obj.get_pointer());
std::map<std::pair<const void *, bool>, Data >::iterator itr
= 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,
// 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);
m_ptrs.insert(std::make_pair(ptr->get(), *data));
m_ptrs.insert(std::make_pair(std::make_pair(ptr->get(), false), *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())
{
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;
m_ptrs.erase(todel);
} 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;
};

View File

@@ -87,7 +87,7 @@ namespace chaiscript
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);
}
@@ -360,7 +360,7 @@ namespace chaiscript
{
throw std::range_error("Object not known: " + name);
} else {
Boxed_Value f(Proxy_Function(new Dispatch_Function(funcs)));
Boxed_Value f(Const_Proxy_Function(new Dispatch_Function(funcs)));
cache[name] = 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))
{
@@ -180,7 +180,7 @@ namespace chaiscript
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;
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));

View File

@@ -62,7 +62,7 @@ namespace chaiscript
{
public:
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; }
@@ -139,6 +139,7 @@ namespace chaiscript
};
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
@@ -184,7 +185,7 @@ namespace chaiscript
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))
{
@@ -270,7 +271,7 @@ namespace chaiscript
class Bound_Function : public Proxy_Function_Base
{
public:
Bound_Function(const Proxy_Function &t_f,
Bound_Function(const Const_Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args)
: 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()))
@@ -289,7 +290,7 @@ namespace chaiscript
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));
}
@@ -343,7 +344,7 @@ namespace chaiscript
}
private:
Proxy_Function m_f;
Const_Proxy_Function m_f;
std::vector<Boxed_Value> m_args;
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);
}

View File

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