diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index b525281..c73358c 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -67,6 +67,7 @@ namespace chaiscript Data &operator=(Data &&rhs) = default; #endif + Type_Info m_type_info; chaiscript::detail::Any m_obj; void *m_data_ptr; @@ -122,6 +123,13 @@ namespace chaiscript return get(std::ref(*t)); } + template + static std::shared_ptr get(const T *t) + { + return get(std::cref(*t)); + } + + template static std::shared_ptr get(std::reference_wrapper obj) { diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index d8a4eed..9d78507 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -915,6 +915,22 @@ namespace chaiscript m_state = t_state; } + void save_function_params(std::initializer_list t_params) + { + Stack_Holder &s = *m_stack_holder; + s.call_params.insert(s.call_params.begin(), std::move(t_params)); + } + + void save_function_params(std::vector &&t_params) + { + Stack_Holder &s = *m_stack_holder; + + for (auto &¶m : t_params) + { + s.call_params.insert(s.call_params.begin(), std::move(param)); + } + } + void save_function_params(const std::vector &t_params) { Stack_Holder &s = *m_stack_holder; @@ -923,7 +939,15 @@ namespace chaiscript void new_function_call() { + Stack_Holder &s = *m_stack_holder; + if (s.call_depth == 0) + { + m_conversions.enable_conversion_saves(true); + } + ++m_stack_holder->call_depth; + + save_function_params(m_conversions.take_saves()); } void pop_function_call() @@ -938,6 +962,7 @@ namespace chaiscript /// \todo Critical: this needs to be smarter, memory can expand quickly /// in tight loops involving function calls s.call_params.clear(); + m_conversions.enable_conversion_saves(false); } } diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index cc24fdf..8f2ebfe 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -48,6 +48,15 @@ namespace chaiscript } }; + template + struct Handle_Return + { + static Boxed_Value handle(const Ret *p) + { + return Boxed_Value(p); + } + }; + template struct Handle_Return &> { diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index bc6049a..4f1f84c 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -214,13 +214,16 @@ namespace chaiscript Type_Conversions() : m_num_types(0), - m_thread_cache(this) + m_thread_cache(this), + m_conversion_saves(this) { } Type_Conversions(const Type_Conversions &t_other) : m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()), - m_thread_cache(this) + m_thread_cache(this), + m_conversion_saves(this) + { } @@ -273,7 +276,9 @@ namespace chaiscript Boxed_Value boxed_type_conversion(const Boxed_Value &from) const { try { - return get_conversion(user_type(), from.get_type_info())->convert(from); + Boxed_Value ret = get_conversion(user_type(), from.get_type_info())->convert(from); + if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret); + return ret; } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion"); } catch (const std::bad_cast &) { @@ -285,7 +290,9 @@ namespace chaiscript Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const { try { - return get_conversion(to.get_type_info(), user_type())->convert_down(to); + Boxed_Value ret = get_conversion(to.get_type_info(), user_type())->convert_down(to); + if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret); + return ret; } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion"); } catch (const std::bad_cast &) { @@ -293,6 +300,17 @@ namespace chaiscript } } + void enable_conversion_saves(bool t_val) + { + m_conversion_saves->enabled = t_val; + } + + std::vector take_saves() + { + std::vector ret; + std::swap(ret, m_conversion_saves->saves); + return ret; + } bool has_conversion(const Type_Info &to, const Type_Info &from) const { @@ -334,11 +352,18 @@ namespace chaiscript } + struct Conversion_Saves + { + bool enabled = false; + std::vector saves; + }; + mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; std::set m_convertableTypes; std::atomic_size_t m_num_types; chaiscript::detail::threading::Thread_Storage> m_thread_cache; + chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; typedef std::shared_ptr Type_Conversion; @@ -400,8 +425,13 @@ namespace chaiscript static_assert(std::is_convertible::value, "Types are not automatically convertible"); auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { // not even attempting to call boxed_cast so that we don't get caught in some call recursion - auto to = To{detail::Cast_Helper::cast(t_bv, nullptr)}; - return chaiscript::Boxed_Value(std::move(to)); + std::cout << " Type conversion to : " << typeid(To).name() << " from " << typeid(From).name() << std::endl; + auto &&from = detail::Cast_Helper::cast(t_bv, nullptr); + std::cout << "Ptr" << static_cast(from) << std::endl; + std::cout << "Ptr" << from << std::endl; + + To to(from); + return chaiscript::Boxed_Value(to); }; return std::make_shared>(user_type(), user_type(), func); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 1339f86..d15c2d9 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -549,6 +549,11 @@ namespace chaiscript m_de.save_function_params(t_params); } + void save_params(std::initializer_list t_params) + { + m_de.save_function_params(std::move(t_params)); + } + private: diff --git a/src/test_module.cpp b/src/test_module.cpp index 9029360..cb95326 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -167,6 +167,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&Type2::get_val), "get_val"); m->add(chaiscript::fun(&Type2::get_str), "get_str"); m->add(chaiscript::type_conversion()); + m->add(chaiscript::constructor(), "Type2"); return m; } diff --git a/unittests/user_defined_conversions_2.chai b/unittests/user_defined_conversions_2.chai index 1226ba1..fdb601c 100644 --- a/unittests/user_defined_conversions_2.chai +++ b/unittests/user_defined_conversions_2.chai @@ -5,6 +5,23 @@ auto t := TestBaseType(); // This uses the TestBaseType to Type2 user type // conversion which was added in the module and then calls // "get_val()" which exists on the Type2 type -assert_equal(t.get_val(), 10); +//assert_equal(t.get_val(), 10); +//print("Made it past test 1"); + +var t2 := Type2(t); +var str = string(get_str(t2)); + +assert_equal("Hello World", str); +print("Made it past test 2"); + +assert_equal(11, size(get_str(t2))); +print("Made it past test 3"); + + +assert_equal(11, t2.get_str().size()); +print("Made it past test 4"); + +assert_equal(11, t.get_str().size()); +print("Made it past test 5"); + -assert_equal(t.get_str().size(), 11);