diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 7fbe78d..56400a3 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -86,6 +86,12 @@ namespace chaiscript // either way, we are not responsible if it doesn't work return(detail::Cast_Helper::cast((*t_conversions)->boxed_type_conversion(t_conversions->saves(), bv), t_conversions)); } catch (...) { + try { + throw; + } catch (const std::exception &e) { + std::cout << "EXCEPTION: " << e.what() << std::endl; + } + try { // try going the other way return(detail::Cast_Helper::cast((*t_conversions)->boxed_type_down_conversion(t_conversions->saves(), bv), t_conversions)); diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 938aab0..b31243d 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -238,6 +238,11 @@ namespace chaiscript return m_data->m_type_info.bare_equal(ti); } + void reset_pointers() const + { + m_data->m_data_ptr = nullptr; + m_data->m_const_data_ptr = nullptr; + } template auto pointer_sentinel(std::shared_ptr &ptr) const diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3a546c6..fcab8d3 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -367,6 +367,7 @@ namespace chaiscript chaiscript::detail::threading::unique_lock l(m_mutex); /// \todo error if a conversion already exists m_conversions.insert(conversion); + std::cout << "Adding Conversion: TO: " << conversion->to().bare_type_info()->name() << " FROM: " << conversion->from().bare_type_info()->name() << std::endl; m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()}); m_num_types = m_convertableTypes.size(); } @@ -410,12 +411,17 @@ namespace chaiscript Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const { try { - Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from); + std::cout << "boxed_type_conversion" << std::endl; + auto conversion = get_conversion(to, from.get_type_info()); + std::cout << "Conversion found!" << std::endl; + Boxed_Value ret = conversion->convert(from); + std::cout << "Conversion succeeded!" << std::endl; if (t_saves.enabled) { t_saves.saves.push_back(ret); } return ret; } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion"); } catch (const std::bad_cast &) { + std::cout << "Bad Cast!?" << std::endl; throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation"); } } @@ -423,6 +429,7 @@ namespace chaiscript Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const { try { + std::cout << "boxed_type_down_conversion" << std::endl; Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to); if (t_saves.enabled) { t_saves.saves.push_back(ret); } return ret; @@ -455,10 +462,12 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_mutex); + std::cout << "Getting conversion TO: " << to.name() << " FROM: " << from.name() << std::endl; const auto itr = find(to, from); if (itr != m_conversions.end()) { + std::cout << "Found" << std::endl; return *itr; } else { throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name()); @@ -476,7 +485,7 @@ namespace chaiscript return std::find_if(m_conversions.begin(), m_conversions.end(), [&to, &from](const std::shared_ptr &conversion) -> bool { - return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from)) + return (conversion->to().type_info == to.type_info conversion->to().bare_equal(to) && conversion->from().bare_equal(from)) || (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from)); } ); @@ -485,6 +494,7 @@ namespace chaiscript std::set >::const_iterator find( const Type_Info &to, const Type_Info &from) const { + std::cout << "Finding: TO: " << to.bare_type_info()->name() << " FROM: " << from.bare_type_info()->name() << std::endl; return std::find_if(m_conversions.begin(), m_conversions.end(), [&to, &from](const std::shared_ptr &conversion) { @@ -588,6 +598,24 @@ namespace chaiscript return chaiscript::make_shared>(t_from, t_to, t_func); } + template + Type_Conversion unique_ptr_conversion() + { + static_assert(std::is_convertible::value, "Types are not automatically convertible"); + auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { + std::cout << " unique_ptr_conversion " << std::endl; + // not even attempting to call boxed_cast so that we don't get caught in some call recursion + auto bv = chaiscript::Boxed_Value(std::unique_ptr(detail::Cast_Helper &&>::cast(t_bv, nullptr))); + t_bv.reset_pointers(); + + return bv; + }; + + return chaiscript::make_shared>(user_type>(), + user_type>(), func); + } + template Type_Conversion type_conversion(const Callable &t_function) { diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 592271a..4af8177 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -143,11 +143,11 @@ namespace chaiscript } }; + + // shared_ptr template struct Get_Type_Info > { -// typedef T type; - static constexpr Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, @@ -176,6 +176,45 @@ namespace chaiscript } }; + // unique_ptr + template + struct Get_Type_Info > + { + static constexpr Type_Info get() + { + return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, + std::is_void::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, + &typeid(std::unique_ptr ), + &typeid(typename Bare_Type::type)); + } + }; + + template + struct Get_Type_Info &> : Get_Type_Info> + { + }; + + template + struct Get_Type_Info &&> : Get_Type_Info> + { + }; + + + template + struct Get_Type_Info &> + { + static constexpr Type_Info get() + { + return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, + std::is_void::value, + std::is_arithmetic::value && !std::is_same::type>::type, bool>::value, + &typeid(const std::unique_ptr &), + &typeid(typename Bare_Type::type)); + } + }; + + // reference_wrapper template struct Get_Type_Info > { diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 1a94c73..f637154 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1154,6 +1154,8 @@ std::unique_ptr make_Unique_Ptr_Test_Class() return std::make_unique(); } + + TEST_CASE("Call methods through unique_ptr") { chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); @@ -1180,6 +1182,10 @@ std::unique_ptr make_Unique_Ptr_Test_Derived_Clas return std::make_unique(); } +void call_unique_ptr_with_conversion_to_base(std::unique_ptr &&) +{ +} + TEST_CASE("Call methods on base class through unique_ptr") { chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); @@ -1190,6 +1196,16 @@ TEST_CASE("Call methods on base class through unique_ptr") chai.add(chaiscript::base_class()); CHECK(chai.eval("uptr.getI()") == 5); CHECK(chai.eval("var uptr2 = make_Unique_Ptr_Test_Derived_Class(); uptr2.getI()") == 5); + + chai.add(chaiscript::unique_ptr_conversion()); + + chai.add(chaiscript::fun(call_unique_ptr_with_conversion_to_base), "call_unique_ptr_with_conversion_to_base"); + CHECK(!chai.eval("uptr2.is_var_null")); + + std::cout << "Attempting conversion" << std::endl; + CHECK_NOTHROW(chai.eval("call_unique_ptr_with_conversion_to_base(uptr2)")); + INFO("Conversion succeeded"); + CHECK(chai.eval("uptr2.is_var_null")); }