diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 2821cfc..d5cfd00 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -122,6 +122,8 @@ namespace chaiscript { public: unique_lock(T &) {} + void lock() {} + void unlock() {} }; template @@ -129,6 +131,7 @@ namespace chaiscript { public: shared_lock(T &) {} + void lock() {} void unlock() {} }; diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 636b1e5..0c090cf 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -519,6 +519,31 @@ namespace chaiscript return m; } + namespace detail { + template + struct apple_string_workarounds + { + /// The latest version of MacOS has a broken std::string implementation which will not allow + /// us to take pointers to the members. Code compiles, but does not link + /// \todo re-evaluate at some point + + static size_t find(const String *s, const String &w, int pos) { return s->find(w, pos); } + static size_t rfind(const String *s, const String &w, size_t pos) { return s->rfind(w, pos); } + static size_t find_first_of(const String *s, const String &w, size_t pos) { return s->find_first_of(w, pos); } + static size_t find_last_of(const String *s, const String &w, size_t pos) { return s->find_last_of(w, pos); } + static size_t find_first_not_of(const String *s, const String &w, size_t pos) { return s->find_first_not_of(w, pos); } + static size_t find_last_not_of(const String *s, const String &w, size_t pos) { return s->find_last_not_of(w, pos); } + + static void clear(String *s) { s->clear(); } + static bool empty(const String *s) { return s->empty(); } + static size_t size(const String *s) { return s->size(); } + + static std::string substr(const String *s, size_t pos, size_t len) { return s->substr(pos,len); } + static const char *c_str(const String *s) { return s->c_str(); } + static const char *data(const String *s) { return s->data(); } + }; + } + /** * Add a String container * http://www.sgi.com/tech/stl/basic_string.html @@ -533,7 +558,7 @@ namespace chaiscript random_access_container_type(type, m); sequence_type(type, m); default_constructible_type(type, m); - container_type(type, m); + // container_type(type, m); assignable_type(type, m); input_range_type(type, m); diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 194efbd..ce93228 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -12,7 +12,6 @@ #include #include - namespace chaiscript { diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 1bc3be5..865bc68 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -53,9 +53,31 @@ namespace chaiscript private: std::string m_word; - }; + /** + * Exception thrown in the case that an object name is invalid because it contains illegal characters + */ + class illegal_name_error : public std::runtime_error + { + public: + illegal_name_error(const std::string &t_name) throw() + : std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name) + { + } + + virtual ~illegal_name_error() throw() {} + + std::string name() const + { + return m_name; + } + + private: + std::string m_name; + }; + + /** * Exception thrown in the case that an object name is invalid because it already exists in current context */ @@ -483,6 +505,25 @@ namespace chaiscript } } + + /** + * Adds a new global (non-const) shared object, between all the threads + */ + void add_global(const Boxed_Value &obj, const std::string &name) + { + validate_object_name(name); + + chaiscript::detail::threading::unique_lock l(m_global_object_mutex); + + if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end()) + { + throw chaiscript::exception::name_conflict_error(name); + } else { + m_state.m_global_objects.insert(std::make_pair(name, obj)); + } + } + + /** * Adds a new scope to the stack */ @@ -1102,6 +1143,10 @@ namespace chaiscript */ void validate_object_name(const std::string &name) const { + if (name.find("::") != std::string::npos) { + throw chaiscript::exception::illegal_name_error(name); + } + chaiscript::detail::threading::shared_lock l(m_mutex); if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end()) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 26c1404..b73b78c 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -515,6 +515,17 @@ namespace chaiscript return *this; } + /// \brief Adds a mutable object that is available in all contexts and to all threads + /// \param[in] t_bv Boxed_Value to add as a global + /// \param[in] t_name Name of the value to add + /// \warning The user is responsible for making sure the object is thread-safe if necessary + /// ChaiScript is thread-safe but provides no threading locking mechanism to the script + ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name) + { + m_engine.add_global(t_bv, t_name); + return *this; + } + /// \brief Represents the current state of the ChaiScript system. State and be saved and restored /// \sa ChaiScript::get_state /// \sa ChaiScript::set_state diff --git a/src/test_module.cpp b/src/test_module.cpp index 5b1aa0a..db8d562 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -11,6 +11,8 @@ class TestBaseType virtual ~TestBaseType() {} virtual int func() { return 0; } + const TestBaseType &constMe() const { return *this; } + int val; const int const_val; }; @@ -84,6 +86,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::user_type(), "TestEnum"); m->add(chaiscript::fun(&to_int), "to_int"); + m->add(chaiscript::fun(&TestBaseType::constMe), "constMe"); return m; diff --git a/unittests/member_variable_access.chai b/unittests/member_variable_access.chai new file mode 100644 index 0000000..000d058 --- /dev/null +++ b/unittests/member_variable_access.chai @@ -0,0 +1,11 @@ +load_module("test_module") + +var t0 = TestBaseType() +t0.val = 13 + +assert_equal(15, t0.const_val) +assert_equal(13, t0.val) +assert_equal(15, t0.constMe().const_val) +assert_equal(13, t0.constMe().val) + +