Favor filtering of functions during dispatch over exceptions to determine appropriate function to call. Results in approximately 50% reduction in runtime for long running scripts

This commit is contained in:
Jason Turner 2009-08-06 04:22:13 +00:00
parent 0ff107a818
commit a3d4b6698a
3 changed files with 96 additions and 28 deletions

View File

@ -97,11 +97,6 @@ namespace chaiscript
return *this; return *this;
} }
static bool get_false()
{
return false;
}
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;

View File

@ -94,6 +94,11 @@ namespace chaiscript
return std::vector<Type_Info>(); return std::vector<Type_Info>();
} }
virtual int get_arity() const
{
return -1;
}
virtual bool call_match(const std::vector<Boxed_Value> &vals) const virtual bool call_match(const std::vector<Boxed_Value> &vals) const
{ {
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec; typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;

View File

@ -178,6 +178,47 @@ namespace chaiscript
virtual std::vector<Type_Info> get_param_types() const = 0; virtual std::vector<Type_Info> get_param_types() const = 0;
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 = 0;
//! Return true if the function is a possible match
//! to the passed in values
bool filter(const std::vector<Boxed_Value> &vals) const
{
int arity = get_arity();
if (arity < 0)
{
return true;
} else if (size_t(arity) == vals.size()) {
if (arity == 0)
{
return true;
} else {
const std::vector<Type_Info> &types = get_param_types();
if (types.size() < 2)
{
return true;
}
const Type_Info &ti = types[1];
if (!ti.m_bare_type_info || !(vals[0].get_type_info().m_bare_type_info)
|| (*ti.m_bare_type_info) == (*user_type<Boxed_Value>().m_bare_type_info)
|| (*ti.m_bare_type_info) == (*user_type<Boxed_POD_Value>().m_bare_type_info)
|| (*vals[0].get_type_info().m_bare_type_info) == (*ti.m_bare_type_info))
{
return true;
} else {
return false;
}
}
} else {
return false;
}
}
virtual int get_arity() const = 0;
virtual std::string annotation() const = 0; virtual std::string annotation() const = 0;
}; };
@ -209,7 +250,8 @@ namespace chaiscript
int t_arity=-1, int t_arity=-1,
const std::string &t_description = "", const std::string &t_description = "",
const Proxy_Function &t_guard = Proxy_Function()) const Proxy_Function &t_guard = Proxy_Function())
: m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard) : m_f(t_f), m_arity(t_arity), m_description(t_description), m_guard(t_guard),
m_types(build_param_type_list(t_arity))
{ {
} }
@ -243,23 +285,14 @@ namespace chaiscript
} }
} }
virtual int get_arity() const
{
return m_arity;
}
virtual std::vector<Type_Info> get_param_types() const virtual std::vector<Type_Info> get_param_types() const
{ {
std::vector<Type_Info> types; return m_types;
types.push_back(Get_Type_Info<Boxed_Value>::get());
if (m_arity >= 0)
{
for (int i = 0; i < m_arity; ++i)
{
types.push_back(Get_Type_Info<Boxed_Value>::get());
}
} else {
types.push_back(Get_Type_Info<std::vector<Boxed_Value> >::get());
}
return types;
} }
virtual std::string annotation() const virtual std::string annotation() const
@ -284,10 +317,30 @@ namespace chaiscript
} }
} }
static std::vector<Type_Info> build_param_type_list(int arity)
{
std::vector<Type_Info> types;
types.push_back(Get_Type_Info<Boxed_Value>::get());
if (arity >= 0)
{
for (int i = 0; i < arity; ++i)
{
types.push_back(Get_Type_Info<Boxed_Value>::get());
}
} else {
types.push_back(Get_Type_Info<std::vector<Boxed_Value> >::get());
}
return types;
}
boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f; boost::function<Boxed_Value (const std::vector<Boxed_Value> &)> m_f;
int m_arity; int m_arity;
std::string m_description; std::string m_description;
Proxy_Function m_guard; Proxy_Function m_guard;
std::vector<Type_Info> m_types;
}; };
/** /**
@ -309,7 +362,7 @@ namespace chaiscript
public: public:
Bound_Function(const Proxy_Function &t_f, Bound_Function(const Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args) const std::vector<Boxed_Value> &t_args)
: m_f(t_f), m_args(t_args) : m_f(t_f), m_args(t_args), m_arity(m_f->get_arity()<0?-1:(m_f->get_arity() - m_args.size()))
{ {
} }
@ -373,6 +426,11 @@ namespace chaiscript
return std::vector<Type_Info>(); return std::vector<Type_Info>();
} }
virtual int get_arity() const
{
return m_arity;
}
virtual std::string annotation() const virtual std::string annotation() const
{ {
return ""; return "";
@ -381,6 +439,7 @@ namespace chaiscript
private: private:
Proxy_Function m_f; Proxy_Function m_f;
std::vector<Boxed_Value> m_args; std::vector<Boxed_Value> m_args;
int m_arity;
}; };
/** /**
@ -393,7 +452,7 @@ namespace chaiscript
{ {
public: public:
Proxy_Function_Impl(const boost::function<Func> &f) Proxy_Function_Impl(const boost::function<Func> &f)
: m_f(f) : m_f(f), m_dummy_func(0), m_types(build_param_type_list(m_dummy_func))
{ {
} }
@ -416,14 +475,18 @@ namespace chaiscript
virtual std::vector<Type_Info> get_param_types() const virtual std::vector<Type_Info> get_param_types() const
{ {
Func *f = 0; return m_types;
return build_param_type_list(f);
} }
virtual int get_arity() const
{
return 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
{ {
Func *f = 0; return compare_types(m_dummy_func, vals);
return compare_types(f, vals);
} }
virtual std::string annotation() const virtual std::string annotation() const
@ -433,6 +496,8 @@ namespace chaiscript
private: private:
boost::function<Func> m_f; boost::function<Func> m_f;
Func *m_dummy_func;
std::vector<Type_Info> m_types;
}; };
/** /**
@ -464,7 +529,10 @@ namespace chaiscript
++itr) ++itr)
{ {
try { try {
return (*itr->second)(plist); if (itr->second->filter(plist))
{
return (*itr->second)(plist);
}
} catch (const bad_boxed_cast &) { } catch (const bad_boxed_cast &) {
//parameter failed to cast, try again //parameter failed to cast, try again
} catch (const arity_error &) { } catch (const arity_error &) {