Move to indexed function storage
This commit is contained in:
parent
9f362608b7
commit
15eb78bd8f
@ -417,9 +417,9 @@ namespace chaiscript
|
||||
|
||||
struct State
|
||||
{
|
||||
std::map<std::string, std::vector<Proxy_Function> > m_functions;
|
||||
std::map<std::string, Proxy_Function> m_function_objects;
|
||||
std::map<std::string, Boxed_Value> m_boxed_functions;
|
||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> m_functions;
|
||||
std::vector<std::pair<std::string, Proxy_Function>> m_function_objects;
|
||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
std::set<std::string> m_reserved_words;
|
||||
@ -518,7 +518,7 @@ namespace chaiscript
|
||||
throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||
{
|
||||
@ -533,7 +533,7 @@ namespace chaiscript
|
||||
{
|
||||
validate_object_name(name);
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr == m_state.m_global_objects.end())
|
||||
@ -551,7 +551,7 @@ namespace chaiscript
|
||||
{
|
||||
validate_object_name(name);
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||
{
|
||||
@ -648,19 +648,18 @@ namespace chaiscript
|
||||
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
|
||||
}
|
||||
|
||||
// Is the value we are looking for a global?
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
// Is the value we are looking for a global or function?
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
const auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// If all that failed, then check to see if it's a function
|
||||
return get_function_object(name);
|
||||
// no? is it a function object?
|
||||
return get_function_object_int(name);
|
||||
|
||||
}
|
||||
|
||||
/// Registers a new named type
|
||||
@ -719,19 +718,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Return a function by name
|
||||
std::vector< Proxy_Function > get_function(const std::string &t_name) const
|
||||
std::shared_ptr<std::vector< Proxy_Function>> get_function(const std::string &t_name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto &funs = get_functions_int();
|
||||
|
||||
auto itr = funs.find(t_name);
|
||||
auto itr = find_keyed_value(funs, t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
return itr->second;
|
||||
} else {
|
||||
return std::vector<Proxy_Function>();
|
||||
return std::make_shared<std::vector<Proxy_Function>>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -739,12 +738,19 @@ namespace chaiscript
|
||||
/// \throws std::range_error if it does not
|
||||
Boxed_Value get_function_object(const std::string &t_name) const
|
||||
{
|
||||
// std::cout << "Getting function object: " << t_name << '\n';
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return get_function_object_int(t_name);
|
||||
}
|
||||
|
||||
/// \returns a function object (Boxed_Value wrapper) if it exists
|
||||
/// \throws std::range_error if it does not
|
||||
/// \warn does not obtain a mutex lock. \sa get_function_object for public version
|
||||
Boxed_Value get_function_object_int(const std::string &t_name) const
|
||||
{
|
||||
const auto &funs = get_boxed_functions_int();
|
||||
|
||||
auto itr = funs.find(t_name);
|
||||
auto itr = find_keyed_value(funs, t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
@ -754,13 +760,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Return true if a function exists
|
||||
bool function_exists(const std::string &name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto &functions = get_functions_int();
|
||||
return functions.find(name) != functions.end();
|
||||
return find_keyed_value(functions, name) != functions.end();
|
||||
}
|
||||
|
||||
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
|
||||
@ -817,11 +824,8 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
// add the global values
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
|
||||
}
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -858,7 +862,7 @@ namespace chaiscript
|
||||
|
||||
for (const auto & function : functions)
|
||||
{
|
||||
for (const auto & internal_func : function.second)
|
||||
for (const auto & internal_func : *function.second)
|
||||
{
|
||||
rets.emplace_back(function.first, internal_func);
|
||||
}
|
||||
@ -941,14 +945,14 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
if (is_attribute_call(funs, params, t_has_params)) {
|
||||
return do_attribute_call(1, params, funs, m_conversions);
|
||||
if (is_attribute_call(*funs, params, t_has_params)) {
|
||||
return do_attribute_call(1, params, *funs, m_conversions);
|
||||
} else {
|
||||
std::exception_ptr except;
|
||||
|
||||
if (!funs.empty()) {
|
||||
if (!funs->empty()) {
|
||||
try {
|
||||
return dispatch::dispatch(funs, params, m_conversions);
|
||||
return dispatch::dispatch(*funs, params, m_conversions);
|
||||
} catch(chaiscript::exception::dispatch_error&) {
|
||||
except = std::current_exception();
|
||||
}
|
||||
@ -960,7 +964,8 @@ namespace chaiscript
|
||||
const auto functions = [&]()->std::vector<Proxy_Function> {
|
||||
std::vector<Proxy_Function> fs;
|
||||
|
||||
for (const auto &f : get_function("method_missing"))
|
||||
const auto method_missing_funs = get_function("method_missing");
|
||||
for (const auto &f : *method_missing_funs)
|
||||
{
|
||||
if(f->compare_first_type(params[0], m_conversions)) {
|
||||
fs.push_back(f);
|
||||
@ -996,7 +1001,7 @@ namespace chaiscript
|
||||
if (except) {
|
||||
std::rethrow_exception(except);
|
||||
} else {
|
||||
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.begin(), funs.end()));
|
||||
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs->begin(), funs->end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1008,7 +1013,8 @@ namespace chaiscript
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
Boxed_Value bv = dispatch::dispatch(get_function(t_name), params, m_conversions);
|
||||
const auto funs = get_function(t_name);
|
||||
Boxed_Value bv = dispatch::dispatch(*funs, params, m_conversions);
|
||||
// the result of a clone is never to be marked as a return_value
|
||||
if (t_name == "clone") {
|
||||
bv.reset_return_value();
|
||||
@ -1140,7 +1146,6 @@ namespace chaiscript
|
||||
State get_state() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l2(m_global_object_mutex);
|
||||
|
||||
return m_state;
|
||||
}
|
||||
@ -1148,7 +1153,6 @@ namespace chaiscript
|
||||
void set_state(const State &t_state)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_global_object_mutex);
|
||||
|
||||
m_state = t_state;
|
||||
}
|
||||
@ -1245,32 +1249,32 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
|
||||
const std::map<std::string, Boxed_Value> &get_boxed_functions_int() const
|
||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
|
||||
{
|
||||
return m_state.m_boxed_functions;
|
||||
}
|
||||
|
||||
std::map<std::string, Boxed_Value> &get_boxed_functions_int()
|
||||
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int()
|
||||
{
|
||||
return m_state.m_boxed_functions;
|
||||
}
|
||||
|
||||
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
|
||||
const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
std::map<std::string, Proxy_Function> &get_function_objects_int()
|
||||
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int()
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
||||
const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const
|
||||
{
|
||||
return m_state.m_functions;
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<Proxy_Function> > &get_functions_int()
|
||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int()
|
||||
{
|
||||
return m_state.m_functions;
|
||||
}
|
||||
@ -1384,6 +1388,38 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Container, typename Key, typename Value>
|
||||
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
||||
{
|
||||
auto itr = find_keyed_value(t_c, t_key);
|
||||
|
||||
if (itr == t_c.end()) {
|
||||
t_c.emplace_back(t_key, std::forward<Value>(t_value));
|
||||
} else {
|
||||
typedef typename Container::value_type value_type;
|
||||
*itr = value_type(t_key, std::forward<Value>(t_value));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Container, typename Key>
|
||||
static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key)
|
||||
{
|
||||
return std::find_if(t_c.begin(), t_c.end(),
|
||||
[&t_key](const typename Container::value_type &o) {
|
||||
return o.first == t_key;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Container, typename Key>
|
||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key)
|
||||
{
|
||||
return std::find_if(t_c.begin(), t_c.end(),
|
||||
[&t_key](const typename Container::value_type &o) {
|
||||
return o.first == t_key;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// Implementation detail for adding a function.
|
||||
/// \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||
@ -1392,16 +1428,13 @@ namespace chaiscript
|
||||
|
||||
auto &funcs = get_functions_int();
|
||||
|
||||
auto itr = funcs.find(t_name);
|
||||
|
||||
auto &func_objs = get_function_objects_int();
|
||||
auto &boxed_funcs = get_boxed_functions_int();
|
||||
auto itr = find_keyed_value(funcs, t_name);
|
||||
|
||||
Proxy_Function new_func =
|
||||
[&]() -> Proxy_Function {
|
||||
if (itr != funcs.end())
|
||||
{
|
||||
auto &vec = itr->second;
|
||||
auto vec = *itr->second;
|
||||
for (const auto &func : vec)
|
||||
{
|
||||
if ((*t_f) == *(func))
|
||||
@ -1412,26 +1445,26 @@ namespace chaiscript
|
||||
|
||||
vec.push_back(t_f);
|
||||
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
||||
return std::make_shared<Dispatch_Function>(vec);
|
||||
itr->second = std::make_shared<std::vector<Proxy_Function>>(vec);
|
||||
return std::make_shared<Dispatch_Function>(std::move(vec));
|
||||
} else if (t_f->has_arithmetic_param()) {
|
||||
// if the function is the only function but it also contains
|
||||
// arithmetic operators, we must wrap it in a dispatch function
|
||||
// to allow for automatic arithmetic type conversions
|
||||
std::vector<Proxy_Function> vec({t_f});
|
||||
funcs.insert(std::make_pair(t_name, vec));
|
||||
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(vec));
|
||||
return std::make_shared<Dispatch_Function>(std::move(vec));
|
||||
} else {
|
||||
funcs.insert(std::make_pair(t_name, std::vector<Proxy_Function>{t_f}));
|
||||
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(std::initializer_list<Proxy_Function>({t_f})));
|
||||
return t_f;
|
||||
}
|
||||
}();
|
||||
|
||||
boxed_funcs[t_name] = const_var(new_func);
|
||||
func_objs[t_name] = std::move(new_func);
|
||||
add_keyed_value(get_boxed_functions_int(), t_name, const_var(new_func));
|
||||
add_keyed_value(get_function_objects_int(), t_name, std::move(new_func));
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
mutable chaiscript::detail::threading::shared_mutex m_global_object_mutex;
|
||||
|
||||
|
||||
Type_Conversions m_conversions;
|
||||
|
Loading…
x
Reference in New Issue
Block a user