Simplify how functions are stored and passed. This is the first step in allowing us to sort functions so that dispatches are attempted in an organized order (as opposed to just the order they were added in).
Should have resulted in a speed imrovement too - fewer string copies during dispatch.
This commit is contained in:
@@ -119,7 +119,7 @@ namespace chaiscript
|
|||||||
class Dispatch_Function : public Proxy_Function_Base
|
class Dispatch_Function : public Proxy_Function_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Dispatch_Function(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
|
Dispatch_Function(const std::vector<Proxy_Function> &t_funcs)
|
||||||
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
||||||
m_funcs(t_funcs)
|
m_funcs(t_funcs)
|
||||||
{
|
{
|
||||||
@@ -139,39 +139,26 @@ namespace chaiscript
|
|||||||
|
|
||||||
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
virtual std::vector<Const_Proxy_Function> get_contained_functions() const
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;
|
return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
|
||||||
|
|
||||||
function_vec::const_iterator begin = m_funcs.begin();
|
|
||||||
const function_vec::const_iterator end = m_funcs.end();
|
|
||||||
|
|
||||||
std::vector<Const_Proxy_Function> fs;
|
|
||||||
|
|
||||||
while (begin != end)
|
|
||||||
{
|
|
||||||
fs.push_back(begin->second);
|
|
||||||
++begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual int get_arity() const
|
virtual int get_arity() const
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;
|
typedef std::vector<Proxy_Function> function_vec;
|
||||||
|
|
||||||
function_vec::const_iterator begin = m_funcs.begin();
|
function_vec::const_iterator begin = m_funcs.begin();
|
||||||
const function_vec::const_iterator end = m_funcs.end();
|
const function_vec::const_iterator end = m_funcs.end();
|
||||||
|
|
||||||
if (begin != end)
|
if (begin != end)
|
||||||
{
|
{
|
||||||
int arity = begin->second->get_arity();
|
int arity = (*begin)->get_arity();
|
||||||
|
|
||||||
++begin;
|
++begin;
|
||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
if (arity != begin->second->get_arity())
|
if (arity != (*begin)->get_arity())
|
||||||
{
|
{
|
||||||
// The arities in the list do not match, so it's unspecified
|
// The arities in the list do not match, so it's unspecified
|
||||||
return -1;
|
return -1;
|
||||||
@@ -188,14 +175,14 @@ namespace chaiscript
|
|||||||
|
|
||||||
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<Proxy_Function> function_vec;
|
||||||
|
|
||||||
function_vec::const_iterator begin = m_funcs.begin();
|
function_vec::const_iterator begin = m_funcs.begin();
|
||||||
function_vec::const_iterator end = m_funcs.end();
|
function_vec::const_iterator end = m_funcs.end();
|
||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
if (begin->second->call_match(vals))
|
if ((*begin)->call_match(vals))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -218,18 +205,18 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<std::string, Proxy_Function > > m_funcs;
|
std::vector<Proxy_Function> m_funcs;
|
||||||
|
|
||||||
static std::vector<Type_Info> build_type_infos(const std::vector<std::pair<std::string, Proxy_Function > > &t_funcs)
|
static std::vector<Type_Info> build_type_infos(const std::vector<Proxy_Function> &t_funcs)
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<std::string, Proxy_Function > > function_vec;
|
typedef std::vector<Proxy_Function> function_vec;
|
||||||
|
|
||||||
function_vec::const_iterator begin = t_funcs.begin();
|
function_vec::const_iterator begin = t_funcs.begin();
|
||||||
const function_vec::const_iterator end = t_funcs.end();
|
const function_vec::const_iterator end = t_funcs.end();
|
||||||
|
|
||||||
if (begin != end)
|
if (begin != end)
|
||||||
{
|
{
|
||||||
std::vector<Type_Info> type_infos = begin->second->get_param_types();
|
std::vector<Type_Info> type_infos = (*begin)->get_param_types();
|
||||||
|
|
||||||
++begin;
|
++begin;
|
||||||
|
|
||||||
@@ -237,7 +224,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
std::vector<Type_Info> param_types = begin->second->get_param_types();
|
std::vector<Type_Info> param_types = (*begin)->get_param_types();
|
||||||
|
|
||||||
if (param_types.size() != type_infos.size())
|
if (param_types.size() != type_infos.size())
|
||||||
{
|
{
|
||||||
@@ -316,7 +303,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
std::multimap<std::string, Proxy_Function> m_functions;
|
std::map<std::string, std::vector<Proxy_Function> > m_functions;
|
||||||
std::map<std::string, Boxed_Value> m_global_objects;
|
std::map<std::string, Boxed_Value> m_global_objects;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
std::set<std::string> m_reserved_words;
|
std::set<std::string> m_reserved_words;
|
||||||
@@ -486,23 +473,20 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If all that failed, then check to see if it's a function
|
// If all that failed, then check to see if it's a function
|
||||||
std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> > funcs = get_function(name);
|
std::vector<Proxy_Function> funcs = get_function(name);
|
||||||
|
|
||||||
if (funcs.empty())
|
if (funcs.empty())
|
||||||
{
|
{
|
||||||
throw std::range_error("Object not known: " + name);
|
throw std::range_error("Object not known: " + name);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (funcs.size() == 1)
|
if (funcs.size() == 1)
|
||||||
{
|
{
|
||||||
// Return the first item if there is only one,
|
// Return the first item if there is only one,
|
||||||
// no reason to take the cast of the extra level of dispatch
|
// no reason to take the cast of the extra level of dispatch
|
||||||
return const_var(funcs.begin()->second);
|
return const_var(*funcs.begin());
|
||||||
|
} else {
|
||||||
|
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Boxed_Value f(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,17 +562,25 @@ namespace chaiscript
|
|||||||
/**
|
/**
|
||||||
* Return a function by name
|
* Return a function by name
|
||||||
*/
|
*/
|
||||||
std::vector<std::pair<std::string, Proxy_Function > >
|
std::vector< Proxy_Function >
|
||||||
get_function(const std::string &t_name) const
|
get_function(const std::string &t_name) const
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
const std::map<std::string, std::vector<Proxy_Function> > &funs = get_functions_int();
|
||||||
= get_functions_int().equal_range(t_name);
|
|
||||||
|
std::map<std::string, std::vector<Proxy_Function> >::const_iterator itr
|
||||||
|
= funs.find(t_name);
|
||||||
|
|
||||||
|
if (itr != funs.end())
|
||||||
|
{
|
||||||
|
return itr->second;
|
||||||
|
} else {
|
||||||
|
return std::vector<Proxy_Function>();
|
||||||
|
}
|
||||||
|
|
||||||
return std::vector<std::pair<std::string, std::multimap<std::string, Proxy_Function >::mapped_type> >(range.first, range.second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -600,7 +592,7 @@ namespace chaiscript
|
|||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::multimap<std::string, Proxy_Function> &functions = get_functions_int();
|
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||||
return functions.find(name) != functions.end();
|
return functions.find(name) != functions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,9 +604,23 @@ namespace chaiscript
|
|||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
std::vector<std::pair<std::string, Proxy_Function> > rets;
|
||||||
|
|
||||||
const std::multimap<std::string, Proxy_Function> &functions = get_functions_int();
|
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||||
return std::vector<std::pair<std::string, Proxy_Function > >(functions.begin(), functions.end());
|
|
||||||
|
for (std::map<std::string, std::vector<Proxy_Function> >::const_iterator itr = functions.begin();
|
||||||
|
itr != functions.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
for (std::vector<Proxy_Function>::const_iterator itr2 = itr->second.begin();
|
||||||
|
itr2 != itr->second.end();
|
||||||
|
++itr2)
|
||||||
|
{
|
||||||
|
rets.push_back(std::make_pair(itr->first, *itr2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_reserved_word(const std::string &name)
|
void add_reserved_word(const std::string &name)
|
||||||
@@ -628,7 +634,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, Proxy_Function> > functions = get_function(t_name);
|
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||||
|
|
||||||
return dispatch(functions.begin(), functions.end(), params);
|
return dispatch(functions.begin(), functions.end(), params);
|
||||||
}
|
}
|
||||||
@@ -787,12 +793,12 @@ namespace chaiscript
|
|||||||
return *(m_stack_holder->stack);
|
return *(m_stack_holder->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::multimap<std::string, Proxy_Function> &get_functions_int() const
|
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
||||||
{
|
{
|
||||||
return m_state.m_functions;
|
return m_state.m_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::multimap<std::string, Proxy_Function> &get_functions_int()
|
std::map<std::string, std::vector<Proxy_Function> > &get_functions_int()
|
||||||
{
|
{
|
||||||
return m_state.m_functions;
|
return m_state.m_functions;
|
||||||
}
|
}
|
||||||
@@ -818,25 +824,36 @@ namespace chaiscript
|
|||||||
* true if the function was added, false if a function with the
|
* true if the function was added, false if a function with the
|
||||||
* same signature and name already exists.
|
* same signature and name already exists.
|
||||||
*/
|
*/
|
||||||
bool add_function(const Proxy_Function &f, const std::string &t_name)
|
bool add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||||
{
|
{
|
||||||
#ifndef CHAISCRIPT_NO_THREADS
|
#ifndef CHAISCRIPT_NO_THREADS
|
||||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::pair<std::multimap<std::string, Proxy_Function >::const_iterator, std::multimap<std::string, Proxy_Function >::const_iterator> range
|
std::map<std::string, std::vector<Proxy_Function> > &funcs = get_functions_int();
|
||||||
= m_state.m_functions.equal_range(t_name);
|
|
||||||
|
|
||||||
while (range.first != range.second)
|
std::map<std::string, std::vector<Proxy_Function> >::iterator itr
|
||||||
|
= funcs.find(t_name);
|
||||||
|
|
||||||
|
if (itr != funcs.end())
|
||||||
{
|
{
|
||||||
if ((*f) == *(range.first->second))
|
std::vector<Proxy_Function> &vec = itr->second;
|
||||||
|
for (std::vector<Proxy_Function>::const_iterator itr2 = vec.begin();
|
||||||
|
itr2 != vec.end();
|
||||||
|
++itr2)
|
||||||
{
|
{
|
||||||
return false;
|
if ((*t_f) == *(*itr2))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++range.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_state.m_functions.insert(std::make_pair(t_name, f));
|
vec.push_back(t_f);
|
||||||
|
} else {
|
||||||
|
std::vector<Proxy_Function> vec;
|
||||||
|
vec.push_back(t_f);
|
||||||
|
funcs.insert(std::make_pair(t_name, vec));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(const std::vector<std::pair<std::string, Const_Proxy_Function > > &funcs)
|
functor(const std::vector<Const_Proxy_Function> &funcs)
|
||||||
{
|
{
|
||||||
FunctionType *p=0;
|
FunctionType *p=0;
|
||||||
return detail::build_function_caller_helper(p, funcs);
|
return detail::build_function_caller_helper(p, funcs);
|
||||||
@@ -53,8 +53,8 @@ namespace chaiscript
|
|||||||
boost::function<FunctionType>
|
boost::function<FunctionType>
|
||||||
functor(Const_Proxy_Function func)
|
functor(Const_Proxy_Function func)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, Const_Proxy_Function > > funcs;
|
std::vector<Const_Proxy_Function> funcs;
|
||||||
funcs.push_back(std::make_pair(std::string(), func));
|
funcs.push_back(func);
|
||||||
return functor<FunctionType>(funcs);
|
return functor<FunctionType>(funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ namespace chaiscript
|
|||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct Function_Caller_Ret
|
struct Function_Caller_Ret
|
||||||
{
|
{
|
||||||
static Ret call(const std::vector<std::pair<std::string, Const_Proxy_Function > > &t_funcs,
|
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
{
|
{
|
||||||
return boxed_cast<Ret>(dispatch(t_funcs, params));
|
return boxed_cast<Ret>(dispatch(t_funcs, params));
|
||||||
@@ -45,7 +45,7 @@ namespace chaiscript
|
|||||||
template<>
|
template<>
|
||||||
struct Function_Caller_Ret<void>
|
struct Function_Caller_Ret<void>
|
||||||
{
|
{
|
||||||
static void call(const std::vector<std::pair<std::string, Const_Proxy_Function > > &t_funcs,
|
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||||
const std::vector<Boxed_Value> ¶ms)
|
const std::vector<Boxed_Value> ¶ms)
|
||||||
{
|
{
|
||||||
dispatch(t_funcs, params);
|
dispatch(t_funcs, params);
|
||||||
@@ -70,14 +70,14 @@ namespace chaiscript
|
|||||||
* used internally for unwrapping a function call's types
|
* used internally for unwrapping a function call's types
|
||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
Ret function_caller(const std::vector<std::pair<std::string, Const_Proxy_Function > > &funcs
|
Ret function_caller(const std::vector<Const_Proxy_Function> &funcs
|
||||||
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) )
|
||||||
{
|
{
|
||||||
std::vector<Boxed_Value> params;
|
std::vector<Boxed_Value> params;
|
||||||
|
|
||||||
BOOST_PP_REPEAT(n, addparam, ~)
|
BOOST_PP_REPEAT(n, addparam, ~)
|
||||||
|
|
||||||
return Function_Caller_Ret<Ret>::call(funcs, params);
|
return Function_Caller_Ret<Ret>::call(funcs, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,13 +85,14 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param) >
|
||||||
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
boost::function<Ret (BOOST_PP_ENUM_PARAMS(n, Param)) >
|
||||||
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<std::pair<std::string, Const_Proxy_Function> > &funcs)
|
build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector<Const_Proxy_Function> &funcs)
|
||||||
{
|
{
|
||||||
if (funcs.size() == 1)
|
if (funcs.size() == 1)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
|
boost::shared_ptr<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> > pfi =
|
||||||
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
|
boost::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (BOOST_PP_ENUM_PARAMS(n, Param))> >
|
||||||
(funcs[0].second);
|
(funcs[0]);
|
||||||
|
|
||||||
if (pfi)
|
if (pfi)
|
||||||
{
|
{
|
||||||
return pfi->internal_function();
|
return pfi->internal_function();
|
||||||
|
@@ -583,9 +583,9 @@ namespace chaiscript
|
|||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (begin->second->filter(plist))
|
if ((*begin)->filter(plist))
|
||||||
{
|
{
|
||||||
return (*begin->second)(plist);
|
return (*(*begin))(plist);
|
||||||
}
|
}
|
||||||
} catch (const bad_boxed_cast &) {
|
} catch (const bad_boxed_cast &) {
|
||||||
//parameter failed to cast, try again
|
//parameter failed to cast, try again
|
||||||
|
Reference in New Issue
Block a user