Merge branch 'develop' into method_missing

This commit is contained in:
Andreas Reischuck
2015-03-27 21:36:25 +01:00
34 changed files with 954 additions and 356 deletions

View File

@@ -303,7 +303,7 @@ namespace chaiscript
ModulePtr sequence_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
{
m->add(fun(&detail::insert_at<ContainerType>),
[](){
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "insert_ref_at";
} else {
@@ -329,7 +329,7 @@ namespace chaiscript
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
[](){
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "push_back_ref";
} else {
@@ -357,7 +357,7 @@ namespace chaiscript
m->add(fun(static_cast<constfrontptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<pushptr>(&ContainerType::push_front)),
[](){
[]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
return "push_front_ref";
} else {
@@ -418,7 +418,7 @@ namespace chaiscript
m->add(fun(&detail::insert<ContainerType>), "insert");
m->add(fun(&detail::insert_ref<ContainerType>),
[](){
[]()->std::string{
if (typeid(typename ContainerType::mapped_type) == typeid(Boxed_Value)) {
return "insert_ref";
} else {
@@ -538,7 +538,7 @@ namespace chaiscript
//Special case: add push_back to string (which doesn't support other back_insertion operations
m->add(fun(&String::push_back),
[](){
[]()->std::string{
if (typeid(typename String::value_type) == typeid(Boxed_Value)) {
return "push_back_ref";
} else {

View File

@@ -74,46 +74,47 @@ namespace chaiscript
template<typename Type>
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
{
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
try {
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
}
}
#ifdef CHAISCRIPT_MSVC
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation
//Thank you MSVC, yes we know that a constant value is being used in the if
// statment in THIS VERSION of the template instantiation
#pragma warning(push)
#pragma warning(disable : 4127)
#endif
if (t_conversions && t_conversions->convertable_type<Type>())
{
if (t_conversions && t_conversions->convertable_type<Type>())
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
// either way, we are not responsible if it doesn't work
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
} catch (...) {
try {
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
// try going the other way - down the inheritance graph
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
} catch (const chaiscript::detail::exception::bad_any_cast &) {
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
} else {
// If it's not polymorphic, just throw the error, don't waste the time on the
// attempted dynamic_cast
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
}
}
}

View File

@@ -641,6 +641,7 @@ 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);
const auto &funs = get_function_objects_int();

View File

@@ -30,7 +30,7 @@ namespace chaiscript
Proxy_Function build_constructor_(Class (*)(Params...))
{
typedef std::shared_ptr<Class> (sig)(Params...);
return Proxy_Function(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>))));
return Proxy_Function(static_cast<Proxy_Function_Impl_Base *>(new Proxy_Function_Impl<sig>(std::function<sig>(&(constructor_<Class, Params...>)))));
}
}
}

View File

@@ -180,6 +180,8 @@ namespace chaiscript
if (m_arity == 0)
{
return true;
} else if (m_arity > 1 && m_types.size() > 1) {
return compare_first_type(vals[0], t_conversions) && compare_type_to_param(m_types[2], vals[1], t_conversions);
} else {
return compare_first_type(vals[0], t_conversions);
}
@@ -233,14 +235,7 @@ namespace chaiscript
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
{
const auto &types = get_param_types();
if (types.size() < 2)
{
return true;
}
return compare_type_to_param(types[1], bv, t_conversions);
return compare_type_to_param(m_types[1], bv, t_conversions);
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs)
@@ -779,7 +774,7 @@ namespace chaiscript
Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
{
//std::cout << "starting dispatch: " << funcs.size() << '\n';
std::multimap<size_t, const Proxy_Function_Base *> ordered_funcs;
for (const auto &func : funcs)
@@ -808,11 +803,17 @@ namespace chaiscript
for (const auto &func : ordered_funcs )
{
try {
if (func.second->filter(plist, t_conversions))
if (func.first == 0 || func.second->filter(plist, t_conversions))
{
return (*(func.second))(plist, t_conversions);
}
} catch (const exception::bad_boxed_cast &) {
//std::cout << "Bad Boxed Cast: " << func.second->get_arity() << '(';
//for (const auto &p : plist) {
// std::cout << p.get_type_info().name() << ',';
//}
//std::cout << ")\n";
//parameter failed to cast, try again
} catch (const exception::arity_error &) {
//invalid num params, try again

View File

@@ -40,17 +40,25 @@ namespace chaiscript
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (Class &, Args...) > to_function(Ret (Class::*func)(Args...))
{
#ifdef CHAISCRIPT_MSVC
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret(Class &, Args...)>(std::mem_fn(func));
#else
return std::function<Ret(Class &, Args...)>(func);
#endif
}
template<typename Ret, typename Class, typename ... Args>
std::function<Ret (const Class &, Args...) > to_function(Ret (Class::*func)(Args...) const)
{
#ifdef CHAISCRIPT_MSVC
/// \todo this std::mem_fn wrap shouldn't be necessary but type conversions for
/// std::function for member function pointers seems to be broken in MSVC
return std::function<Ret (const Class &, Args...)>(std::mem_fn(func));
return std::function<Ret(const Class &, Args...)>(std::mem_fn(func));
#else
return std::function<Ret(const Class &, Args...)>(func);
#endif
}
template<bool Object>
@@ -61,7 +69,7 @@ namespace chaiscript
{
/// \todo is it possible to reduce the number of templates generated here?
return Proxy_Function(
new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t)));
static_cast<dispatch::Proxy_Function_Impl_Base *>(new Proxy_Function_Impl<typename FunctionSignature<decltype(to_function(t)) >::Signature>(to_function(t))));
}
};
@@ -118,7 +126,7 @@ namespace chaiscript
template<typename T>
Proxy_Function fun(const std::function<T> &f)
{
return Proxy_Function(new dispatch::Proxy_Function_Impl<T>(f));
return Proxy_Function(static_cast<dispatch::Proxy_Function_Impl_Base *>(new dispatch::Proxy_Function_Impl<T>(f)));
}