Merge branch 'develop' into method_missing
This commit is contained in:
@@ -136,10 +136,14 @@ namespace chaiscript
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(user_type<T>(), name);
|
||||
m->add(constructor<T ()>(), name);
|
||||
m->add(constructor<T()>(), name);
|
||||
construct_pod<T>(name, m);
|
||||
|
||||
m->add(fun(&to_string<T>), "to_string");
|
||||
auto to_s = fun(&to_string<T>);
|
||||
|
||||
if (!m->has_function(to_s, "to_string")) {
|
||||
m->add(to_s, "to_string");
|
||||
}
|
||||
m->add(fun(&parse_string<T>), "to_" + name);
|
||||
return m;
|
||||
}
|
||||
@@ -471,7 +475,6 @@ namespace chaiscript
|
||||
m->add(chaiscript::fun(&has_parse_tree), "has_parse_tree");
|
||||
m->add(chaiscript::fun(&get_parse_tree), "get_parse_tree");
|
||||
|
||||
m->add(chaiscript::user_type<chaiscript::exception::eval_error>(), "eval_error");
|
||||
m->add(chaiscript::base_class<std::runtime_error, chaiscript::exception::eval_error>());
|
||||
|
||||
m->add(chaiscript::user_type<chaiscript::exception::arithmetic_error>(), "arithmetic_error");
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr assignable_type(const std::string &type, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
basic_constructors<ContainerType>(type, m);
|
||||
copy_constructor<ContainerType>(type, m);
|
||||
operators::assign<ContainerType>(m);
|
||||
return m;
|
||||
}
|
||||
@@ -443,6 +443,7 @@ namespace chaiscript
|
||||
m->add(fun(static_cast<elemaccess>(&MapType::operator[])), "[]");
|
||||
|
||||
container_type<MapType>(type, m);
|
||||
default_constructible_type<MapType>(type, m);
|
||||
assignable_type<MapType>(type, m);
|
||||
unique_associative_container_type<MapType>(type, m);
|
||||
pair_associative_container_type<MapType>(type, m);
|
||||
|
||||
@@ -65,21 +65,11 @@ namespace chaiscript
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return &(ob.get().cast<std::reference_wrapper<Result> >()).get();
|
||||
} else {
|
||||
return &(ob.get().cast<std::reference_wrapper<const Result> >()).get();
|
||||
}
|
||||
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return (ob.get().cast<std::shared_ptr<Result> >()).get();
|
||||
} else {
|
||||
return (ob.get().cast<std::shared_ptr<const Result> >()).get();
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -101,6 +91,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
|
||||
@@ -199,6 +199,14 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool has_function(const Proxy_Function &new_f, const std::string &name)
|
||||
{
|
||||
return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair<Proxy_Function, std::string> &existing_f) {
|
||||
return existing_f.second == name && *(existing_f.first) == *(new_f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
@@ -580,7 +588,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Returns the type info for a named type
|
||||
Type_Info get_type(const std::string &name) const
|
||||
Type_Info get_type(const std::string &name, bool t_throw = true) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@@ -591,7 +599,11 @@ namespace chaiscript
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
throw std::range_error("Type Not Known");
|
||||
if (t_throw) {
|
||||
throw std::range_error("Type Not Known");
|
||||
} else {
|
||||
return Type_Info();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the registered name of a known type_info object
|
||||
@@ -1018,14 +1030,6 @@ namespace chaiscript
|
||||
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
|
||||
{
|
||||
const auto &lhsparamtypes = lhs->get_param_types();
|
||||
const auto &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_type = user_type<Boxed_Value>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
@@ -1055,6 +1059,14 @@ namespace chaiscript
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto &lhsparamtypes = lhs->get_param_types();
|
||||
const auto &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_type = user_type<Boxed_Value>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace chaiscript
|
||||
const Proxy_Function &t_func,
|
||||
const Type_Info &t_ti)
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(t_ti.is_undef()?nullptr:new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
&& "Programming error, Dynamic_Object_Function must have at least one parameter (this)");
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
@@ -33,15 +34,19 @@ namespace chaiscript
|
||||
template<typename Ret>
|
||||
struct Handle_Return
|
||||
{
|
||||
static Boxed_Value handle(const Ret &r)
|
||||
{
|
||||
return const_var(r);
|
||||
}
|
||||
|
||||
static Boxed_Value handle(Ret &&r)
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<std::is_pod<typename std::decay<T>::type>::value>::type>
|
||||
static Boxed_Value handle(T r)
|
||||
{
|
||||
return Boxed_Value(std::move(r));
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<!std::is_pod<typename std::decay<T>::type>::value>::type>
|
||||
static Boxed_Value handle(T &&r)
|
||||
{
|
||||
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
|
||||
@@ -529,12 +529,7 @@ namespace chaiscript
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (static_cast<int>(vals.size()) != get_arity())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions);
|
||||
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions));
|
||||
}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
@@ -722,8 +717,18 @@ namespace chaiscript
|
||||
{
|
||||
matching_func = begin;
|
||||
} else {
|
||||
// More than one function matches, not attempting
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
// handle const members vs non-const member, which is not really ambiguous
|
||||
const auto &mat_fun_param_types = (*matching_func)->get_param_types();
|
||||
const auto &next_fun_param_types = (*begin)->get_param_types();
|
||||
|
||||
if (plist[0].is_const() && !mat_fun_param_types[1].is_const() && next_fun_param_types[1].is_const()) {
|
||||
matching_func = begin; // keep the new one, the const/non-const matchup is correct
|
||||
} else if (!plist[0].is_const() && !mat_fun_param_types[1].is_const() && next_fun_param_types[1].is_const()) {
|
||||
// keep the old one, it has a better const/non-const matchup
|
||||
} else {
|
||||
// ambiguous function call
|
||||
throw exception::dispatch_error(plist, std::vector<Const_Proxy_Function>(orig, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,12 +813,6 @@ namespace chaiscript
|
||||
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
|
||||
|
||||
@@ -119,24 +119,27 @@ namespace chaiscript
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
std::shared_ptr<const To> data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<const To>{
|
||||
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
} else {
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
return Boxed_Value(
|
||||
[&]()->std::shared_ptr<To>{
|
||||
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
|
||||
{
|
||||
return data;
|
||||
} else {
|
||||
throw std::bad_cast();
|
||||
}
|
||||
}()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
@@ -439,9 +442,7 @@ namespace chaiscript
|
||||
static_assert(std::is_convertible<From, To>::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 &&from = detail::Cast_Helper<From>::cast(t_bv, nullptr);
|
||||
To to(from);
|
||||
return chaiscript::Boxed_Value(to);
|
||||
return chaiscript::Boxed_Value(To(detail::Cast_Helper<From>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
|
||||
Reference in New Issue
Block a user