diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index ef9f032c..34a684f9 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -442,6 +442,7 @@ namespace chaiscript 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(&dispatch::Dynamic_Object::has_attr), "has_attr"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "get_attr"); @@ -452,13 +453,42 @@ namespace chaiscript m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); m->add(fun(static_cast(&dispatch::Dynamic_Object::get_attr)), "[]"); - m->eval(R""( + m->eval(R"chai( def Dynamic_Object::clone() { auto &new_o = Dynamic_Object(this.get_type_name()); for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } ); new_o; } - )""); + + def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } ); + } + + def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + var rhs_attrs := rhs.get_attrs(); + var lhs_attrs := lhs.get_attrs(); + + if (rhs_attrs.size() != lhs_attrs.size()) { + true; + } else { + return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } ); + } + } + + def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name() + { + var rhs_attrs := rhs.get_attrs(); + var lhs_attrs := lhs.get_attrs(); + + if (rhs_attrs.size() != lhs_attrs.size()) { + false; + } else { + return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } ); + } + } + )chai"); m->add(fun(&has_guard), "has_guard"); m->add(fun(&get_guard), "get_guard"); diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 0f6155b0..e89d3806 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -82,6 +82,10 @@ namespace chaiscript } } + bool has_attr(const std::string &t_attr_name) const { + return m_attrs.find(t_attr_name) != m_attrs.end(); + } + Boxed_Value &get_attr(const std::string &t_attr_name) { return m_attrs[t_attr_name]; @@ -105,7 +109,6 @@ namespace chaiscript return get_attr(t_method_name); } - std::map get_attrs() const { return m_attrs; diff --git a/include/chaiscript/language/chaiscript_prelude.chai b/include/chaiscript/language/chaiscript_prelude.chai index 55514bba..934f6c43 100644 --- a/include/chaiscript/language/chaiscript_prelude.chai +++ b/include/chaiscript/language/chaiscript_prelude.chai @@ -215,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) { } } +def any_of(container, func) : call_exists(range, container) { + var t_range := range(container); + while (!t_range.empty()) { + if (func(t_range.front())) { + return true; + } + t_range.pop_front(); + } + false; +} + +def all_of(container, func) : call_exists(range, container) { + var t_range := range(container); + while (!t_range.empty()) { + if (!func(t_range.front())) { + return false; + } + t_range.pop_front(); + } + + true; +} + def back_inserter(container) { bind(push_back, container, _); }