Merge branch 'develop' into Fix_Crash_From_CppCon

This commit is contained in:
Jason Turner
2015-11-20 05:53:44 -07:00
48 changed files with 1738 additions and 368 deletions

View File

@@ -440,6 +440,8 @@ namespace chaiscript
m->add(constructor<dispatch::Dynamic_Object ()>(), "Dynamic_Object");
m->add(fun(&dispatch::Dynamic_Object::get_type_name), "get_type_name");
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
@@ -467,9 +469,11 @@ namespace chaiscript
m->add(fun(&Boxed_Value::is_ref), "is_var_reference");
m->add(fun(&Boxed_Value::is_pointer), "is_var_pointer");
m->add(fun(&Boxed_Value::is_return_value), "is_var_return_value");
m->add(fun(&Boxed_Value::reset_return_value), "reset_var_return_value");
m->add(fun(&Boxed_Value::is_type), "is_type");
m->add(fun(&Boxed_Value::get_attr), "get_var_attr");
m->add(fun(&Boxed_Value::copy_attrs), "copy_var_attrs");
m->add(fun(&Boxed_Value::clone_attrs), "clone_var_attrs");
m->add(fun(&Boxed_Value::get_type_info), "get_type_info");
m->add(user_type<Type_Info>(), "Type_Info");
@@ -492,6 +496,7 @@ namespace chaiscript
basic_constructors<bool>("bool", m);
operators::assign<bool>(m);
operators::equal<bool>(m);
operators::not_equal<bool>(m);
m->add(fun([](const std::string &s) -> std::string { return s; }), "to_string");
m->add(fun(&Bootstrap::bool_to_string), "to_string");
@@ -509,6 +514,8 @@ namespace chaiscript
bootstrap_pod_type<long>("long", m);
bootstrap_pod_type<unsigned int>("unsigned_int", m);
bootstrap_pod_type<unsigned long>("unsigned_long", m);
bootstrap_pod_type<long long>("long_long", m);
bootstrap_pod_type<unsigned long long>("unsigned_long_long", m);
bootstrap_pod_type<size_t>("size_t", m);
bootstrap_pod_type<char>("char", m);
bootstrap_pod_type<wchar_t>("wchar_t", m);

View File

@@ -335,6 +335,7 @@ namespace chaiscript
"def push_back(" + type + " container, x)\n"
"{ \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_back_ref(x) \n"
" } else { \n"
" container.push_back_ref(clone(x)); \n"
@@ -375,6 +376,7 @@ namespace chaiscript
"def push_front(" + type + " container, x)\n"
"{ \n"
" if (x.is_var_return_value()) {\n"
" x.reset_var_return_value() \n"
" container.push_front_ref(x) \n"
" } else { \n"
" container.push_front_ref(clone(x)); \n"
@@ -468,6 +470,30 @@ namespace chaiscript
m->add(fun(static_cast<elem_access>(&MapType::at)), "at");
m->add(fun(static_cast<const_elem_access>(&MapType::at)), "at");
if (typeid(MapType) == typeid(std::map<std::string, Boxed_Value>))
{
m->eval(R"(
def Map::`==`(Map rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {
auto r1 = range(this);
auto r2 = range(rhs);
while (!r1.empty())
{
if (!eq(r1.front().first, r2.front().first) || !eq(r1.front().second, r2.front().second))
{
return false;
}
r1.pop_front();
r2.pop_front();
}
true;
}
} )"
);
}
container_type<MapType>(type, m);
default_constructible_type<MapType>(type, m);
assignable_type<MapType>(type, m);
@@ -523,7 +549,7 @@ namespace chaiscript
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
{
m->eval(R"(
def Vector::`==`(rhs) : type_match(rhs, this) {
def Vector::`==`(Vector rhs) {
if ( rhs.size() != this.size() ) {
return false;
} else {

View File

@@ -100,6 +100,7 @@ namespace chaiscript
:(Common_Types::t_uint64);
}
static Common_Types get_common_type(const Boxed_Value &t_bv)
{
const Type_Info &inp_ = t_bv.get_type_info();
@@ -120,8 +121,12 @@ namespace chaiscript
return get_common_type(sizeof(unsigned int), false);
} else if (inp_ == typeid(long)) {
return get_common_type(sizeof(long), true);
} else if (inp_ == typeid(long long)) {
return get_common_type(sizeof(long long), true);
} else if (inp_ == typeid(unsigned long)) {
return get_common_type(sizeof(unsigned long), false);
} else if (inp_ == typeid(unsigned long long)) {
return get_common_type(sizeof(unsigned long long), false);
} else if (inp_ == typeid(std::int8_t)) {
return Common_Types::t_int8;
} else if (inp_ == typeid(std::int16_t)) {
@@ -513,6 +518,21 @@ namespace chaiscript
validate_boxed_number(bv);
}
static bool is_floating_point(const Boxed_Value &t_bv)
{
const Type_Info &inp_ = t_bv.get_type_info();
if (inp_ == typeid(double)) {
return true;
} else if (inp_ == typeid(long double)) {
return true;
} else if (inp_ == typeid(float)) {
return true;
} else {
return false;
}
}
Boxed_Number get_as(const Type_Info &inp_) const
{
if (inp_.bare_equal_type_info(typeid(int))) {
@@ -537,8 +557,12 @@ namespace chaiscript
return Boxed_Number(get_as<unsigned int>());
} else if (inp_.bare_equal_type_info(typeid(long))) {
return Boxed_Number(get_as<long>());
} else if (inp_.bare_equal_type_info(typeid(long long))) {
return Boxed_Number(get_as<long long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
return Boxed_Number(get_as<unsigned long>());
} else if (inp_.bare_equal_type_info(typeid(unsigned long long))) {
return Boxed_Number(get_as<unsigned long long>());
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
return Boxed_Number(get_as<int8_t>());
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {

View File

@@ -297,6 +297,13 @@ namespace chaiscript
return *this;
}
Boxed_Value &clone_attrs(const Boxed_Value &t_obj)
{
copy_attrs(t_obj);
reset_return_value();
return *this;
}
/// \returns true if the two Boxed_Values share the same internal type
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT

View File

@@ -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,21 @@ 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?
auto obj = get_function_object_int(name, loc);
if (obj.first != loc) t_loc.store(uint_fast32_t(obj.first), std::memory_order_relaxed);
return obj.second;
}
/// Registers a new named type
@@ -718,20 +720,29 @@ namespace chaiscript
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
}
std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
{
uint_fast32_t method_missing_loc = m_method_missing_loc.load(std::memory_order_relaxed);
auto method_missing_funs = get_function("method_missing", method_missing_loc);
if (method_missing_funs.first != method_missing_loc) m_method_missing_loc.store(uint_fast32_t(method_missing_funs.first), std::memory_order_relaxed);
return std::move(method_missing_funs.second);
}
/// Return a function by name
std::vector< Proxy_Function > get_function(const std::string &t_name) const
std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string &t_name, const size_t t_hint) 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, t_hint);
if (itr != funs.end())
{
return itr->second;
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
return std::vector<Proxy_Function>();
return std::make_pair(size_t(0), std::make_shared<std::vector<Proxy_Function>>());
}
}
@@ -739,28 +750,36 @@ 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, 0).second;
}
/// \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
std::pair<size_t, Boxed_Value> get_function_object_int(const std::string &t_name, const size_t t_hint) const
{
const auto &funs = get_boxed_functions_int();
auto itr = funs.find(t_name);
auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end())
{
return itr->second;
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
throw std::range_error("Object not found: " + t_name);
}
}
/// 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 +836,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 +874,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);
}
@@ -903,9 +919,11 @@ namespace chaiscript
#pragma warning(push)
#pragma warning(disable : 4715)
#endif
Boxed_Value call_member(const std::string &t_name, const std::vector<Boxed_Value> &params, bool t_has_params)
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params)
{
const auto funs = get_function(t_name);
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
const auto do_attribute_call =
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
@@ -941,14 +959,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.second, params, t_has_params)) {
return do_attribute_call(1, params, *funs.second, m_conversions);
} else {
std::exception_ptr except;
if (!funs.empty()) {
if (!funs.second->empty()) {
try {
return dispatch::dispatch(funs, params, m_conversions);
return dispatch::dispatch(*funs.second, params, m_conversions);
} catch(chaiscript::exception::dispatch_error&) {
except = std::current_exception();
}
@@ -960,7 +978,9 @@ 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_method_missing_functions();
for (const auto &f : *method_missing_funs)
{
if(f->compare_first_type(params[0], m_conversions)) {
fs.push_back(f);
@@ -982,12 +1002,17 @@ namespace chaiscript
}();
if (!functions.empty()) {
if (is_no_param) {
std::vector<Boxed_Value> tmp_params(params);
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
return do_attribute_call(2, tmp_params, functions, m_conversions);
} else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
try {
if (is_no_param) {
std::vector<Boxed_Value> tmp_params(params);
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
return do_attribute_call(2, tmp_params, functions, m_conversions);
} else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
}
} catch (const dispatch::option_explicit_set &e) {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
e.what());
}
}
@@ -996,7 +1021,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.second->begin(), funs.second->end()));
}
}
}
@@ -1006,30 +1031,14 @@ namespace chaiscript
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, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params) const
{
Boxed_Value bv = dispatch::dispatch(get_function(t_name), 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();
}
return bv;
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
const auto funs = get_function(t_name, loc);
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
return dispatch::dispatch(*funs.second, params, m_conversions);
}
Boxed_Value call_function(const std::string &t_name) const
{
return call_function(t_name, std::vector<Boxed_Value>());
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1)}));
}
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1, Boxed_Value p2) const
{
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1), std::move(p2)}));
}
/// Dump object info to stdout
void dump_object(const Boxed_Value &o) const
@@ -1140,7 +1149,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 +1156,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 +1252,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 +1391,49 @@ 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.reserve(t_c.size() + 1); // tightly control growth of memory usage here
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;
});
}
template<typename Container, typename Key>
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
{
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
return t_c.begin() + t_hint;
} else {
return find_keyed_value(t_c, 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 +1442,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))
@@ -1410,33 +1457,35 @@ namespace chaiscript
}
}
vec.reserve(vec.size() + 1); // tightly control vec growth
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;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
mutable std::atomic_uint_fast32_t m_method_missing_loc;
State m_state;
};

View File

@@ -24,23 +24,55 @@ namespace chaiscript
{
namespace dispatch
{
struct option_explicit_set : std::runtime_error {
option_explicit_set(const std::string &t_param_name)
: std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
{
}
option_explicit_set(const option_explicit_set &) = default;
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
};
class Dynamic_Object
{
public:
Dynamic_Object(std::string t_type_name)
: m_type_name(std::move(t_type_name))
: m_type_name(std::move(t_type_name)), m_option_explicit(false)
{
}
Dynamic_Object() : m_type_name("")
Dynamic_Object() : m_type_name(""), m_option_explicit(false)
{
}
bool is_explicit() const
{
return m_option_explicit;
}
void set_explicit(const bool t_explicit)
{
m_option_explicit = t_explicit;
}
std::string get_type_name() const
{
return m_type_name;
}
const Boxed_Value &operator[](const std::string &t_attr_name) const
{
return get_attr(t_attr_name);
}
Boxed_Value &operator[](const std::string &t_attr_name)
{
return get_attr(t_attr_name);
}
const Boxed_Value &get_attr(const std::string &t_attr_name) const
{
auto a = m_attrs.find(t_attr_name);
@@ -59,11 +91,19 @@ namespace chaiscript
Boxed_Value &method_missing(const std::string &t_method_name)
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
const Boxed_Value &method_missing(const std::string &t_method_name) const
{
if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
throw option_explicit_set(t_method_name);
}
return get_attr(t_method_name);
}
@@ -75,6 +115,7 @@ namespace chaiscript
private:
std::string m_type_name;
bool m_option_explicit;
std::map<std::string, Boxed_Value> m_attrs;
};

View File

@@ -40,7 +40,7 @@ namespace chaiscript
{
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
[](const Const_Proxy_Function &f) {
return f->get_arity() == -1 || f->get_arity() == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
});
if (!has_arity_match) {

View File

@@ -211,7 +211,7 @@ namespace chaiscript
if (ti.is_undef()
|| ti.bare_equal(user_type<Boxed_Value>())
|| (!bv.get_type_info().is_undef()
&& (ti.bare_equal(user_type<Boxed_Number>())
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|| ti.bare_equal(bv.get_type_info())
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|| t_conversions.converts(ti, bv.get_type_info())
@@ -760,6 +760,14 @@ namespace chaiscript
{
}
dispatch_error(std::vector<Boxed_Value> t_parameters,
std::vector<Const_Proxy_Function> t_functions,
const std::string &t_desc)
: std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions))
{
}
dispatch_error(const dispatch_error &) = default;
virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {}

View File

@@ -32,17 +32,17 @@ namespace chaiscript
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
m_is_undef(false)
m_flags((t_is_const << is_const_flag)
+ (t_is_reference << is_reference_flag)
+ (t_is_pointer << is_pointer_flag)
+ (t_is_void << is_void_flag)
+ (t_is_arithmetic << is_arithmetic_flag))
{
}
CHAISCRIPT_CONSTEXPR Type_Info()
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_is_const(false), m_is_reference(false), m_is_pointer(false),
m_is_void(false), m_is_arithmetic(false),
m_is_undef(true)
m_flags(1 << is_undef_flag)
{
}
@@ -83,12 +83,12 @@ namespace chaiscript
&& (*m_bare_type_info) == ti;
}
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_const_flag); }
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_reference_flag); }
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_void_flag); }
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_arithmetic_flag); }
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_undef_flag); }
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_pointer_flag); }
std::string name() const
{
@@ -118,12 +118,13 @@ namespace chaiscript
private:
const std::type_info *m_type_info;
const std::type_info *m_bare_type_info;
bool m_is_const;
bool m_is_reference;
bool m_is_pointer;
bool m_is_void;
bool m_is_arithmetic;
bool m_is_undef;
unsigned int m_flags;
static const int is_const_flag = 0;
static const int is_reference_flag = 1;
static const int is_pointer_flag = 2;
static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5;
};
namespace detail