Merge branch 'master' into ChaiScript_5_0_CPP_11

Conflicts:
	include/chaiscript/dispatchkit/bootstrap.hpp
	include/chaiscript/dispatchkit/boxed_cast.hpp
	include/chaiscript/dispatchkit/boxed_cast_helper.hpp
	include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
	include/chaiscript/dispatchkit/dynamic_object.hpp
	include/chaiscript/dispatchkit/exception_specification.hpp
	include/chaiscript/dispatchkit/function_call.hpp
	include/chaiscript/dispatchkit/function_call_detail.hpp
	include/chaiscript/dispatchkit/proxy_functions.hpp
	include/chaiscript/dispatchkit/proxy_functions_detail.hpp
	include/chaiscript/language/chaiscript_engine.hpp
	include/chaiscript/language/chaiscript_eval.hpp
This commit is contained in:
Jason Turner
2013-02-25 12:08:32 -07:00
16 changed files with 296 additions and 305 deletions

View File

@@ -269,21 +269,6 @@ namespace chaiscript
std::vector<Boxed_Value>(params.begin() + 1, params.end())))); std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
} }
/**
* Returns true if a call can be made that consists of the first parameter
* (the function) with the remaining parameters as its arguments.
*/
static Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{
if (params.size() < 1)
{
throw exception::arity_error(static_cast<int>(params.size()), 1);
}
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())));
}
static bool has_guard(const Const_Proxy_Function &t_pf) static bool has_guard(const Const_Proxy_Function &t_pf)
{ {
@@ -379,7 +364,6 @@ namespace chaiscript
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity"); m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation"); m->add(fun(&dispatch::Proxy_Function_Base::annotation), "get_annotation");
m->add(fun(&dispatch::Proxy_Function_Base::operator()), "call");
m->add(fun(&dispatch::Proxy_Function_Base::operator==), "=="); m->add(fun(&dispatch::Proxy_Function_Base::operator==), "==");
@@ -472,9 +456,6 @@ namespace chaiscript
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "="); m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "="); m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&call_exists, std::placeholders::_1))),
"call_exists");
m->add(fun(&Boxed_Value::type_match), "type_match"); m->add(fun(&Boxed_Value::type_match), "type_match");
return m; return m;

View File

@@ -62,10 +62,10 @@ namespace chaiscript
/// assert(i == 5); /// assert(i == 5);
/// \endcode /// \endcode
template<typename Type> template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions = Dynamic_Cast_Conversions())
{ {
try { try {
return detail::Cast_Helper<Type>::cast(bv); return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) { } catch (const chaiscript::detail::exception::bad_any_cast &) {
@@ -81,7 +81,7 @@ namespace chaiscript
try { try {
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work // either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(detail::boxed_dynamic_cast<Type>(bv)); return detail::Cast_Helper<Type>::cast(t_conversions.boxed_dynamic_cast<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) { } catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
} }

View File

@@ -13,6 +13,8 @@
namespace chaiscript namespace chaiscript
{ {
class Dynamic_Cast_Conversions;
namespace detail namespace detail
{ {
// Cast_Helper_Inner helper classes // Cast_Helper_Inner helper classes
@@ -25,7 +27,7 @@ namespace chaiscript
{ {
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type; typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
if (ob.is_ref()) if (ob.is_ref())
{ {
@@ -67,7 +69,7 @@ namespace chaiscript
{ {
typedef const Result * Result_Type; typedef const Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
if (ob.is_ref()) if (ob.is_ref())
{ {
@@ -96,7 +98,7 @@ namespace chaiscript
{ {
typedef Result * Result_Type; typedef Result * Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
if (ob.is_ref()) if (ob.is_ref())
{ {
@@ -115,7 +117,7 @@ namespace chaiscript
{ {
typedef Result& Result_Type; typedef Result& Result_Type;
static Result &cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
if (ob.is_ref()) if (ob.is_ref())
{ {
@@ -135,7 +137,7 @@ namespace chaiscript
{ {
typedef typename std::shared_ptr<Result> Result_Type; typedef typename std::shared_ptr<Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
return ob.get().cast<std::shared_ptr<Result> >(); return ob.get().cast<std::shared_ptr<Result> >();
} }
@@ -149,7 +151,7 @@ namespace chaiscript
{ {
typedef typename std::shared_ptr<const Result> Result_Type; typedef typename std::shared_ptr<const Result> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
if (!ob.get_type_info().is_const()) if (!ob.get_type_info().is_const())
{ {
@@ -197,7 +199,7 @@ namespace chaiscript
{ {
typedef const Boxed_Value & Result_Type; typedef const Boxed_Value & Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
return ob; return ob;
} }
@@ -258,9 +260,9 @@ namespace chaiscript
{ {
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type; typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &t_conversions)
{ {
return Cast_Helper_Inner<T>::cast(ob); return Cast_Helper_Inner<T>::cast(ob, t_conversions);
} }
}; };
} }

View File

@@ -823,7 +823,7 @@ namespace chaiscript
{ {
typedef Boxed_Number Result_Type; typedef Boxed_Number Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &)
{ {
return Boxed_Number(ob); return Boxed_Number(ob);
} }

View File

@@ -156,7 +156,6 @@ namespace chaiscript
~Module() ~Module()
{ {
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
} }
private: private:
@@ -279,7 +278,7 @@ namespace chaiscript
return -1; // unknown arity return -1; // unknown arity
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
typedef std::vector<Proxy_Function> function_vec; typedef std::vector<Proxy_Function> function_vec;
@@ -288,7 +287,7 @@ namespace chaiscript
while (begin != end) while (begin != end)
{ {
if ((*begin)->call_match(vals)) if ((*begin)->call_match(vals, t_conversions))
{ {
return true; return true;
} else { } else {
@@ -305,9 +304,9 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params); return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
} }
private: private:
@@ -396,7 +395,13 @@ namespace chaiscript
~Dispatch_Engine() ~Dispatch_Engine()
{ {
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end()); }
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
{
return chaiscript::boxed_cast<Type>(bv, m_conversions);
} }
/** /**
@@ -404,8 +409,7 @@ namespace chaiscript
*/ */
void add(const Dynamic_Cast_Conversion &d) void add(const Dynamic_Cast_Conversion &d)
{ {
m_conversions.push_back(d); m_conversions.add_conversion(d);
return detail::Dynamic_Conversions::get().add_conversion(d);
} }
/** /**
@@ -778,11 +782,16 @@ namespace chaiscript
m_state.m_reserved_words.insert(name); m_state.m_reserved_words.insert(name);
} }
const Dynamic_Cast_Conversions &conversions() const
{
return m_conversions;
}
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> &params) const
{ {
std::vector<Proxy_Function> functions = get_function(t_name); std::vector<Proxy_Function> functions = get_function(t_name);
return dispatch::dispatch(functions.begin(), functions.end(), params); return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
} }
Boxed_Value call_function(const std::string &t_name) const Boxed_Value call_function(const std::string &t_name) const
@@ -851,6 +860,22 @@ namespace chaiscript
std::cout << ") " << std::endl; std::cout << ") " << std::endl;
} }
/**
* Returns true if a call can be made that consists of the first parameter
* (the function) with the remaining parameters as its arguments.
*/
Boxed_Value call_exists(const std::vector<Boxed_Value> &params)
{
if (params.size() < 1)
{
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
}
Const_Proxy_Function f = this->boxed_cast<Const_Proxy_Function>(params[0]);
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
}
/** /**
* Dump all system info to stdout * Dump all system info to stdout
*/ */
@@ -1153,7 +1178,7 @@ namespace chaiscript
int call_depth; int call_depth;
}; };
std::vector<Dynamic_Cast_Conversion> m_conversions; Dynamic_Cast_Conversions m_conversions;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder; chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;

View File

@@ -44,7 +44,7 @@ namespace chaiscript
class Dynamic_Conversion class Dynamic_Conversion
{ {
public: public:
virtual Boxed_Value convert(const Boxed_Value &derived) = 0; virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
const Type_Info &base() const Type_Info &base()
{ {
@@ -78,7 +78,7 @@ namespace chaiscript
{ {
} }
virtual Boxed_Value convert(const Boxed_Value &t_derived) virtual Boxed_Value convert(const Boxed_Value &t_derived) const
{ {
if (t_derived.get_type_info().bare_equal(user_type<Derived>())) if (t_derived.get_type_info().bare_equal(user_type<Derived>()))
{ {
@@ -88,7 +88,7 @@ namespace chaiscript
if (t_derived.is_const()) if (t_derived.is_const())
{ {
std::shared_ptr<const Base> data std::shared_ptr<const Base> data
= std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived)); = std::dynamic_pointer_cast<const Base>(detail::Cast_Helper<std::shared_ptr<const Derived> >::cast(t_derived, Dynamic_Cast_Conversions()));
if (!data) if (!data)
{ {
throw std::bad_cast(); throw std::bad_cast();
@@ -97,7 +97,7 @@ namespace chaiscript
return Boxed_Value(data); return Boxed_Value(data);
} else { } else {
std::shared_ptr<Base> data std::shared_ptr<Base> data
= std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived)); = std::dynamic_pointer_cast<Base>(detail::Cast_Helper<std::shared_ptr<Derived> >::cast(t_derived, Dynamic_Cast_Conversions()));
if (!data) if (!data)
{ {
@@ -110,11 +110,11 @@ namespace chaiscript
// Pull the reference out of the contained boxed value, which we know is the type we want // Pull the reference out of the contained boxed value, which we know is the type we want
if (t_derived.is_const()) if (t_derived.is_const())
{ {
const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived); const Derived &d = detail::Cast_Helper<const Derived &>::cast(t_derived, Dynamic_Cast_Conversions());
const Base &data = dynamic_cast<const Base &>(d); const Base &data = dynamic_cast<const Base &>(d);
return Boxed_Value(std::cref(data)); return Boxed_Value(std::cref(data));
} else { } else {
Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived); Derived &d = detail::Cast_Helper<Derived &>::cast(t_derived, Dynamic_Cast_Conversions());
Base &data = dynamic_cast<Base &>(d); Base &data = dynamic_cast<Base &>(d);
return Boxed_Value(std::ref(data)); return Boxed_Value(std::ref(data));
} }
@@ -124,67 +124,60 @@ namespace chaiscript
} }
} }
}; };
}
class Dynamic_Cast_Conversions
class Dynamic_Conversions
{ {
public: public:
static inline Dynamic_Conversions &get() Dynamic_Cast_Conversions()
{ {
static Dynamic_Conversions obj; }
return obj;
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
: m_conversions(t_other.get_conversions())
{
}
void add_conversion(const std::shared_ptr<detail::Dynamic_Conversion> &conversion)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
m_conversions.insert(conversion);
} }
template<typename Base, typename Derived> template<typename Base, typename Derived>
static std::shared_ptr<Dynamic_Conversion> create() bool dynamic_cast_converts() const
{ {
std::shared_ptr<Dynamic_Conversion> conversion(new Dynamic_Conversion_Impl<Base, Derived>()); return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
/// \todo this is a hack and a kludge. The idea is to make sure that
/// the conversion is registered both in the module's notion of the static conversion object
/// and in the global notion of the static conversion object
/// someday this will almost certainly have to change. Maybe it is time for ChaiScript
/// to become a library?
Dynamic_Conversions::get().add_conversion(conversion);
return conversion;
} }
template<typename InItr> bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
void cleanup(InItr begin, const InItr &end)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); return has_conversion(base, derived);
while (begin != end)
{
if (begin->unique())
{
m_conversions.erase(begin->get());
} }
++begin; template<typename Base>
} Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
}
void add_conversion(const std::shared_ptr<Dynamic_Conversion> &conversion)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); try {
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
m_conversions.insert(conversion.get()); } catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
} }
bool has_conversion(const Type_Info &base, const Type_Info &derived) const bool has_conversion(const Type_Info &base, const Type_Info &derived) const
{ {
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return find(base, derived) != m_conversions.end(); return find(base, derived) != m_conversions.end();
} }
std::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) const
{ {
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::set<Dynamic_Conversion *>::const_iterator itr = std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr =
find(base, derived); find(base, derived);
if (itr != m_conversions.end()) if (itr != m_conversions.end())
@@ -196,12 +189,10 @@ namespace chaiscript
} }
private: private:
Dynamic_Conversions() {} std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived) const const Type_Info &base, const Type_Info &derived) const
{ {
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin(); for (std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
itr != m_conversions.end(); itr != m_conversions.end();
++itr) ++itr)
{ {
@@ -214,11 +205,17 @@ namespace chaiscript
return m_conversions.end(); return m_conversions.end();
} }
mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set<std::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
std::set<Dynamic_Conversion *> m_conversions; {
}; chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
return m_conversions;
} }
mutable chaiscript::detail::threading::shared_mutex m_mutex;
std::set<std::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
};
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion; typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you /// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
@@ -253,34 +250,9 @@ namespace chaiscript
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic"); static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic"); static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
return detail::Dynamic_Conversions::create<Base, Derived>(); return std::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
} }
namespace detail
{
template<typename Base, typename Derived>
bool dynamic_cast_converts()
{
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
}
static bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived)
{
return detail::Dynamic_Conversions::get().has_conversion(base, derived);
}
template<typename Base>
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived)
{
try {
return detail::Dynamic_Conversions::get().get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
} catch (const std::out_of_range &) {
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
} catch (const std::bad_cast &) {
throw chaiscript::exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
}
}
}
} }

View File

@@ -85,11 +85,11 @@ namespace chaiscript
} }
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (dynamic_object_typename_match(vals, m_type_name, m_ti)) if (dynamic_object_typename_match(vals, m_type_name, m_ti))
{ {
return m_func->call_match(vals); return m_func->call_match(vals, t_conversions);
} else { } else {
return false; return false;
} }
@@ -113,11 +113,11 @@ namespace chaiscript
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (dynamic_object_typename_match(params, m_type_name, m_ti)) if (dynamic_object_typename_match(params, m_type_name, m_ti))
{ {
return (*m_func)(params); return (*m_func)(params, t_conversions);
} else { } else {
throw exception::guard_error(); throw exception::guard_error();
} }
@@ -226,13 +226,13 @@ namespace chaiscript
} }
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
std::vector<Boxed_Value> new_vals; std::vector<Boxed_Value> new_vals;
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name))); new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
new_vals.insert(new_vals.end(), vals.begin(), vals.end()); new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals); return m_func->call_match(new_vals, t_conversions);
} }
@@ -248,14 +248,14 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) 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));
new_params.push_back(bv); new_params.push_back(bv);
new_params.insert(new_params.end(), params.begin(), params.end()); new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params); (*m_func)(new_params, t_conversions);
return bv; return bv;
} }

View File

@@ -15,65 +15,65 @@ namespace chaiscript
{ {
struct Exception_Handler_Base struct Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) = 0; virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
protected: protected:
template<typename T> template<typename T>
void throw_type(const Boxed_Value &bv) void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
try { T t = boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {} try { T t = t_engine.boxed_cast<T>(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {}
} }
}; };
template<typename T1> template<typename T1>
struct Exception_Handler_Impl1 : Exception_Handler_Base struct Exception_Handler_Impl1 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
} }
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
struct Exception_Handler_Impl2 : Exception_Handler_Base struct Exception_Handler_Impl2 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
struct Exception_Handler_Impl3 : Exception_Handler_Base struct Exception_Handler_Impl3 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3, typename T4> template<typename T1, typename T2, typename T3, typename T4>
struct Exception_Handler_Impl4 : Exception_Handler_Base struct Exception_Handler_Impl4 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
throw_type<T4>(bv); throw_type<T4>(bv, t_engine);
} }
}; };
template<typename T1, typename T2, typename T3, typename T4, typename T5> template<typename T1, typename T2, typename T3, typename T4, typename T5>
struct Exception_Handler_Impl5 : Exception_Handler_Base struct Exception_Handler_Impl5 : Exception_Handler_Base
{ {
virtual void handle(const Boxed_Value &bv) virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine)
{ {
throw_type<T1>(bv); throw_type<T1>(bv, t_engine);
throw_type<T2>(bv); throw_type<T2>(bv, t_engine);
throw_type<T3>(bv); throw_type<T3>(bv, t_engine);
throw_type<T4>(bv); throw_type<T4>(bv, t_engine);
throw_type<T5>(bv); throw_type<T5>(bv, t_engine);
} }
}; };
} }

View File

@@ -29,10 +29,10 @@ namespace chaiscript
*/ */
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType>
functor(const std::vector<Const_Proxy_Function> &funcs) functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions &t_conversions)
{ {
FunctionType *p=0; FunctionType *p=0;
return detail::build_function_caller_helper(p, funcs); return detail::build_function_caller_helper(p, funcs, t_conversions);
} }
/** /**
@@ -50,11 +50,11 @@ namespace chaiscript
*/ */
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType>
functor(Const_Proxy_Function func) functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions &t_conversions)
{ {
std::vector<Const_Proxy_Function> funcs; std::vector<Const_Proxy_Function> funcs;
funcs.push_back(func); funcs.push_back(func);
return functor<FunctionType>(funcs); return functor<FunctionType>(funcs, t_conversions);
} }
/** /**
@@ -63,9 +63,9 @@ namespace chaiscript
*/ */
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType>
functor(const Boxed_Value &bv) functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
{ {
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv)); return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
} }
} }
@@ -78,13 +78,13 @@ namespace chaiscript
{ {
typedef std::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob); return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
} }
} }
}; };
@@ -97,13 +97,13 @@ namespace chaiscript
{ {
typedef std::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<std::function<Signature> >::cast(ob); return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
} }
} }
}; };
@@ -116,13 +116,13 @@ namespace chaiscript
{ {
typedef std::function<Signature> Result_Type; typedef std::function<Signature> Result_Type;
static Result_Type cast(const Boxed_Value &ob) static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>())) if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
{ {
return dispatch::functor<Signature>(ob); return dispatch::functor<Signature>(ob, t_conversions);
} else { } else {
return Cast_Helper_Inner<const std::function<Signature> >::cast(ob); return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
} }
} }
}; };

View File

@@ -26,9 +26,9 @@ namespace chaiscript
struct Function_Caller_Ret struct Function_Caller_Ret
{ {
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params)); return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
} }
}; };
@@ -39,9 +39,9 @@ namespace chaiscript
struct Function_Caller_Ret<void> struct Function_Caller_Ret<void>
{ {
static void call(const std::vector<Const_Proxy_Function> &t_funcs, static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
dispatch::dispatch(t_funcs, params); dispatch::dispatch(t_funcs, params, t_conversions);
} }
}; };
@@ -51,8 +51,9 @@ namespace chaiscript
template<typename Ret, typename ... Param> template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper struct Build_Function_Caller_Helper
{ {
Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs) Build_Function_Caller_Helper(const std::vector<Const_Proxy_Function> &t_funcs, const Dynamic_Cast_Conversions &t_conversions)
: m_funcs(t_funcs) : m_funcs(t_funcs),
m_conversions(t_conversions)
{ {
} }
@@ -60,19 +61,20 @@ namespace chaiscript
{ {
return Function_Caller_Ret<Ret>::call(m_funcs, { return Function_Caller_Ret<Ret>::call(m_funcs, {
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)... (std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
} }, m_conversions
); );
} }
std::vector<Const_Proxy_Function> m_funcs; std::vector<Const_Proxy_Function> m_funcs;
Dynamic_Cast_Conversions m_conversions;
}; };
template<typename Ret, typename ... Params> template<typename Ret, typename ... Params>
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs) std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (funcs.size() == 1) if (funcs.size() == 1)
{ {
@@ -88,7 +90,7 @@ namespace chaiscript
// we cannot make any other guesses or assumptions really, so continuing // we cannot make any other guesses or assumptions really, so continuing
} }
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs)); return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions));
} }
} }
} }

View File

@@ -39,9 +39,9 @@ namespace chaiscript
{ {
public: public:
virtual ~Proxy_Function_Base() {} virtual ~Proxy_Function_Base() {}
Boxed_Value operator()(const std::vector<Boxed_Value> &params) const Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const
{ {
Boxed_Value bv = do_call(params); Boxed_Value bv = do_call(params, t_conversions);
return bv; return bv;
} }
@@ -52,7 +52,7 @@ namespace chaiscript
const std::vector<Type_Info> &get_param_types() const { return m_types; } const std::vector<Type_Info> &get_param_types() const { return m_types; }
virtual bool operator==(const Proxy_Function_Base &) const = 0; virtual bool operator==(const Proxy_Function_Base &) const = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals) const = 0; virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
bool has_arithmetic_param() const bool has_arithmetic_param() const
{ {
@@ -66,7 +66,7 @@ namespace chaiscript
//! Return true if the function is a possible match //! Return true if the function is a possible match
//! to the passed in values //! to the passed in values
bool filter(const std::vector<Boxed_Value> &vals) const bool filter(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
int arity = get_arity(); int arity = get_arity();
@@ -78,7 +78,7 @@ namespace chaiscript
{ {
return true; return true;
} else { } else {
return compare_first_type(vals[0]); return compare_first_type(vals[0], t_conversions);
} }
} else { } else {
return false; return false;
@@ -90,15 +90,15 @@ namespace chaiscript
virtual std::string annotation() const = 0; virtual std::string annotation() const = 0;
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv) static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (ti.is_undef() if (ti.is_undef()
|| ti.bare_equal(user_type<Boxed_Value>()) || ti.bare_equal(user_type<Boxed_Value>())
|| (!bv.get_type_info().is_undef() || (!bv.get_type_info().is_undef()
&& (ti.bare_equal(user_type<Boxed_Number>()) && (ti.bare_equal(user_type<Boxed_Number>())
|| ti.bare_equal(bv.get_type_info()) || ti.bare_equal(bv.get_type_info())
|| chaiscript::detail::dynamic_cast_converts(ti, bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >()) || bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|| t_conversions.dynamic_cast_converts(ti, bv.get_type_info())
) )
) )
) )
@@ -109,7 +109,7 @@ namespace chaiscript
} }
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const = 0; virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) 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_has_arithmetic_param(false) : m_types(t_types), m_has_arithmetic_param(false)
@@ -125,7 +125,7 @@ namespace chaiscript
} }
virtual bool compare_first_type(const Boxed_Value &bv) const virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
{ {
const std::vector<Type_Info> &types = get_param_types(); const std::vector<Type_Info> &types = get_param_types();
@@ -135,11 +135,11 @@ namespace chaiscript
} }
const Type_Info &ti = types[1]; const Type_Info &ti = types[1];
return compare_type_to_param(ti, bv); return compare_type_to_param(ti, bv, t_conversions);
} }
bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs) const static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
{ {
if (tis.size() - 1 != bvs.size()) if (tis.size() - 1 != bvs.size())
{ {
@@ -215,10 +215,10 @@ namespace chaiscript
&& !this->m_guard && !prhs->m_guard); && !this->m_guard && !prhs->m_guard);
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
return (m_arity < 0 || vals.size() == size_t(m_arity)) return (m_arity < 0 || vals.size() == size_t(m_arity))
&& test_guard(vals); && test_guard(vals, t_conversions);
} }
virtual ~Dynamic_Proxy_Function() {} virtual ~Dynamic_Proxy_Function() {}
@@ -245,12 +245,12 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (m_arity < 0 || params.size() == size_t(m_arity)) if (m_arity < 0 || params.size() == size_t(m_arity))
{ {
if (test_guard(params)) if (test_guard(params, t_conversions))
{ {
return m_f(params); return m_f(params);
} else { } else {
@@ -263,12 +263,12 @@ namespace chaiscript
} }
private: private:
bool test_guard(const std::vector<Boxed_Value> &params) const bool test_guard(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (m_guard) if (m_guard)
{ {
try { try {
return boxed_cast<bool>((*m_guard)(params)); return boxed_cast<bool>((*m_guard)(params, t_conversions));
} catch (const exception::arity_error &) { } catch (const exception::arity_error &) {
return false; return false;
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
@@ -336,14 +336,9 @@ namespace chaiscript
virtual ~Bound_Function() {} virtual ~Bound_Function() {}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
return m_f->call_match(build_param_list(vals)); return m_f->call_match(build_param_list(vals), t_conversions);
}
virtual Boxed_Value operator()(const std::vector<Boxed_Value> &params) const
{
return (*m_f)(build_param_list(params));
} }
virtual std::vector<Const_Proxy_Function> get_contained_functions() const virtual std::vector<Const_Proxy_Function> get_contained_functions() const
@@ -421,9 +416,9 @@ namespace chaiscript
return retval; return retval;
} }
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
return (*m_f)(build_param_list(params)); return (*m_f)(build_param_list(params), t_conversions);
} }
private: private:
@@ -460,14 +455,14 @@ namespace chaiscript
return static_cast<int>(m_types.size()) - 1; return static_cast<int>(m_types.size()) - 1;
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (int(vals.size()) != get_arity()) if (int(vals.size()) != get_arity())
{ {
return false; return false;
} }
return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals); return compare_types(m_types, vals) || detail::compare_types_cast(m_dummy_func, vals, t_conversions);
} }
virtual std::string annotation() const virtual std::string annotation() const
@@ -481,9 +476,9 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params); return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
} }
private: private:
@@ -524,7 +519,7 @@ namespace chaiscript
return 1; return 1;
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const
{ {
if (vals.size() != 1) if (vals.size() != 1)
{ {
@@ -540,17 +535,17 @@ namespace chaiscript
} }
protected: protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params) const virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions) const
{ {
if (params.size() == 1) if (params.size() == 1)
{ {
const Boxed_Value &bv = params[0]; const Boxed_Value &bv = params[0];
if (bv.is_const()) if (bv.is_const())
{ {
const Class *o = boxed_cast<const Class *>(bv); const Class *o = boxed_cast<const Class *>(bv, t_conversions);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr); return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
} else { } else {
Class *o = boxed_cast<Class *>(bv); Class *o = boxed_cast<Class *>(bv, t_conversions);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr); return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
} }
} else { } else {
@@ -596,7 +591,8 @@ namespace chaiscript
namespace detail namespace detail
{ {
template<typename FuncType> template<typename FuncType>
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist) bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
const Dynamic_Cast_Conversions &t_conversions)
{ {
if (t_func->get_arity() != plist.size()) if (t_func->get_arity() != plist.size())
{ {
@@ -609,7 +605,7 @@ namespace chaiscript
for (int i = 0; i < plist.size(); ++i) for (int i = 0; i < plist.size(); ++i)
{ {
if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i]) if (Proxy_Function_Base::compare_type_to_param(types[i+1], plist[i], t_conversions)
|| (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic())) || (types[i+1].is_arithmetic() && plist[i].get_type_info().is_arithmetic()))
{ {
// types continue to match // types continue to match
@@ -623,7 +619,8 @@ namespace chaiscript
} }
template<typename InItr> template<typename InItr>
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist) Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
const Dynamic_Cast_Conversions &t_conversions)
{ {
InItr orig(begin); InItr orig(begin);
@@ -631,7 +628,7 @@ namespace chaiscript
while (begin != end) while (begin != end)
{ {
if (types_match_except_for_arithmetic(*begin, plist)) if (types_match_except_for_arithmetic(*begin, plist, t_conversions))
{ {
if (matching_func == end) if (matching_func == end)
{ {
@@ -666,7 +663,7 @@ namespace chaiscript
} }
try { try {
return (*(*matching_func))(newplist); return (*(*matching_func))(newplist, t_conversions);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
//parameter failed to cast //parameter failed to cast
} catch (const exception::arity_error &) { } catch (const exception::arity_error &) {
@@ -687,15 +684,15 @@ namespace chaiscript
*/ */
template<typename InItr> template<typename InItr>
Boxed_Value dispatch(InItr begin, const InItr &end, Boxed_Value dispatch(InItr begin, const InItr &end,
const std::vector<Boxed_Value> &plist) const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
{ {
InItr orig(begin); InItr orig(begin);
while (begin != end) while (begin != end)
{ {
try { try {
if ((*begin)->filter(plist)) if ((*begin)->filter(plist, t_conversions))
{ {
return (*(*begin))(plist); return (*(*begin))(plist, t_conversions);
} }
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
//parameter failed to cast, try again //parameter failed to cast, try again
@@ -708,7 +705,7 @@ namespace chaiscript
++begin; ++begin;
} }
return detail::dispatch_with_conversions(orig, end, plist); return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
} }
/** /**
@@ -718,9 +715,9 @@ namespace chaiscript
*/ */
template<typename Funcs> template<typename Funcs>
Boxed_Value dispatch(const Funcs &funcs, Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist) const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
{ {
return dispatch::dispatch(funcs.begin(), funcs.end(), plist); return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions);
} }
} }
} }

View File

@@ -63,10 +63,10 @@ namespace chaiscript
template<typename Param, typename ... Rest> template<typename Param, typename ... Rest>
struct Try_Cast<Param, Rest...> struct Try_Cast<Param, Rest...>
{ {
static void do_try(const std::vector<Boxed_Value> &params, int generation) static void do_try(const std::vector<Boxed_Value> &params, int generation, const Dynamic_Cast_Conversions &t_conversions)
{ {
boxed_cast<Param>(params[generation]); boxed_cast<Param>(params[generation], t_conversions);
Try_Cast<Rest...>::do_try(params, generation+1); Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
} }
}; };
@@ -74,7 +74,7 @@ namespace chaiscript
template<> template<>
struct Try_Cast<> struct Try_Cast<>
{ {
static void do_try(const std::vector<Boxed_Value> &, int) static void do_try(const std::vector<Boxed_Value> &, int, const Dynamic_Cast_Conversions &)
{ {
} }
}; };
@@ -88,10 +88,10 @@ namespace chaiscript
*/ */
template<typename Ret, typename ... Params> template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...), bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
try { try {
Try_Cast<Params...>::do_try(params, 0); Try_Cast<Params...>::do_try(params, 0, t_conversions);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
return false; return false;
} }
@@ -105,9 +105,9 @@ namespace chaiscript
template<typename ... InnerParams> template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f, static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params, InnerParams &&... innerparams) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
{ {
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]); return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
} }
}; };
@@ -116,9 +116,9 @@ namespace chaiscript
{ {
template<typename ... InnerParams> template<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f, static Ret do_call(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &, InnerParams &&... innerparams) const std::vector<Boxed_Value> &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
{ {
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams))...); return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), t_conversions)...);
} }
}; };
@@ -130,11 +130,11 @@ namespace chaiscript
*/ */
template<typename Ret, typename ... Params> template<typename Ret, typename ... Params>
Ret call_func(const std::function<Ret (Params...)> &f, Ret call_func(const std::function<Ret (Params...)> &f,
const std::vector<Boxed_Value> &params) const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
if (params.size() == sizeof...(Params)) if (params.size() == sizeof...(Params))
{ {
return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params); return Call_Func<Ret, sizeof...(Params), Params...>::do_call(f, params, t_conversions);
} }
throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params)); throw exception::arity_error(static_cast<int>(params.size()), sizeof...(Params));
@@ -156,9 +156,9 @@ namespace chaiscript
struct Do_Call struct Do_Call
{ {
template<typename Fun> template<typename Fun>
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params) static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
return Handle_Return<Ret>::handle(call_func(fun, params)); return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
} }
}; };
@@ -166,9 +166,9 @@ namespace chaiscript
struct Do_Call<void> struct Do_Call<void>
{ {
template<typename Fun> template<typename Fun>
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params) static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Dynamic_Cast_Conversions &t_conversions)
{ {
call_func(fun, params); call_func(fun, params, t_conversions);
return Handle_Return<void>::handle(); return Handle_Return<void>::handle();
} }
}; };

View File

@@ -338,6 +338,10 @@ namespace chaiscript
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&chaiscript::detail::Dispatch_Engine::call_exists, std::ref(m_engine), std::placeholders::_1))),
"call_exists");
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
@@ -731,7 +735,7 @@ namespace chaiscript
return do_eval(t_script); return do_eval(t_script);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw bv;
} }
@@ -754,15 +758,23 @@ namespace chaiscript
T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__") T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__")
{ {
try { try {
return boxed_cast<T>(do_eval(t_input, t_filename)); return m_engine.boxed_cast<T>(do_eval(t_input, t_filename));
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw bv;
} }
} }
/// \brief casts an object while applying any Dynamic_Conversion available
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
{
return m_engine.boxed_cast<Type>(bv);
}
/// \brief Evaluates a string. /// \brief Evaluates a string.
/// ///
/// \param[in] t_input Script to execute /// \param[in] t_input Script to execute
@@ -779,7 +791,7 @@ namespace chaiscript
return do_eval(t_input, t_filename); return do_eval(t_input, t_filename);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw bv;
} }
@@ -795,7 +807,7 @@ namespace chaiscript
return do_eval(load_file(t_filename), t_filename); return do_eval(load_file(t_filename), t_filename);
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw bv;
} }
@@ -812,10 +824,10 @@ namespace chaiscript
template<typename T> template<typename T>
T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) {
try { try {
return boxed_cast<T>(do_eval(load_file(t_filename), t_filename)); return m_engine.boxed_cast<T>(do_eval(load_file(t_filename), t_filename));
} catch (Boxed_Value &bv) { } catch (Boxed_Value &bv) {
if (t_handler) { if (t_handler) {
t_handler->handle(bv); t_handler->handle(bv, m_engine);
} }
throw bv; throw bv;
} }

View File

@@ -226,7 +226,7 @@ namespace chaiscript
Boxed_Value fn = this->children[0]->eval(t_ss); Boxed_Value fn = this->children[0]->eval(t_ss);
try { try {
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(params); const Boxed_Value &retval = (*t_ss.boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss.conversions());
return retval; return retval;
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
@@ -234,7 +234,7 @@ namespace chaiscript
} }
catch(const exception::bad_boxed_cast &){ catch(const exception::bad_boxed_cast &){
try { try {
Const_Proxy_Function f = boxed_cast<const Const_Proxy_Function &>(fn); Const_Proxy_Function f = t_ss.boxed_cast<const Const_Proxy_Function &>(fn);
// handle the case where there is only 1 function to try to call and dispatch fails on it // handle the case where there is only 1 function to try to call and dispatch fails on it
std::vector<Const_Proxy_Function> funcs; std::vector<Const_Proxy_Function> funcs;
funcs.push_back(f); funcs.push_back(f);
@@ -294,11 +294,11 @@ namespace chaiscript
try { try {
bv = this->children[0]->eval(t_ss); bv = this->children[0]->eval(t_ss);
try { try {
fn = boxed_cast<const Const_Proxy_Function &>(bv); fn = t_ss.boxed_cast<const Const_Proxy_Function &>(bv);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function."); throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
} }
return (*fn)(params); return (*fn)(params, t_ss.conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss); throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, t_ss);
@@ -1046,7 +1046,7 @@ namespace chaiscript
std::map<std::string, Boxed_Value> retval; std::map<std::string, Boxed_Value> retval;
for (size_t i = 0; i < this->children[0]->children.size(); ++i) { for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss)); Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))] retval[t_ss.boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))]
= bv; = bv;
} }
return const_var(retval); return const_var(retval);

View File

@@ -42,9 +42,9 @@ struct System
std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks; std::map<std::string, std::function<std::string (const std::string &) > > m_callbacks;
void add_callback(const std::string &t_name, void add_callback(const std::string &t_name,
const chaiscript::Proxy_Function &t_func) const std::function<std::string (const std::string &)> &t_func)
{ {
m_callbacks[t_name] = chaiscript::dispatch::functor<std::string (const std::string &)>(t_func); m_callbacks[t_name] = t_func;
} }

View File

@@ -9,7 +9,7 @@ int test_generic()
try { try {
chai.eval("throw(runtime_error(\"error\"));"); chai.eval("throw(runtime_error(\"error\"));");
} catch (const chaiscript::Boxed_Value &bv) { } catch (const chaiscript::Boxed_Value &bv) {
const std::exception &e = chaiscript::boxed_cast<const std::exception &>(bv); const std::exception &e = chai.boxed_cast<const std::exception &>(bv);
if (e.what() == std::string("error")) if (e.what() == std::string("error"))
{ {
return EXIT_SUCCESS; return EXIT_SUCCESS;