Fixes for type_conversion handling
This commit is contained in:
parent
ed65ad72d0
commit
e024b99b36
@ -69,9 +69,9 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr)
|
||||
{
|
||||
if (!t_conversions || bv.get_type_info().bare_equal(user_type<Type>()) || (t_conversions && !t_conversions->convertable_type<Type>())) {
|
||||
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 &) {
|
||||
@ -79,18 +79,18 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), 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);
|
||||
return detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@ -35,7 +35,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename std::add_const<Result>::type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@ -58,7 +58,7 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@ -74,7 +74,7 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
||||
{
|
||||
@ -102,7 +102,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef const Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@ -122,7 +122,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@ -139,7 +139,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@ -151,7 +151,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@ -191,7 +191,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_Value Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@ -203,7 +203,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::reference_wrapper<Boxed_Value> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return std::ref(const_cast<Boxed_Value &>(ob));
|
||||
}
|
||||
@ -259,7 +259,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
|
@ -1011,7 +1011,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ namespace chaiscript
|
||||
return arity;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
|
||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||
@ -326,7 +326,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dispatch::dispatch(m_funcs, params, t_conversions);
|
||||
}
|
||||
@ -442,7 +442,8 @@ namespace chaiscript
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) const
|
||||
{
|
||||
return chaiscript::boxed_cast<Type>(bv, &m_conversions);
|
||||
Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
|
||||
return chaiscript::boxed_cast<Type>(bv, &state);
|
||||
}
|
||||
|
||||
/// Add a new conversion for upcasting to a base class
|
||||
@ -911,7 +912,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
|
||||
bool t_has_params) const
|
||||
bool t_has_params, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (!t_has_params || t_params.empty()) {
|
||||
return false;
|
||||
@ -919,7 +920,7 @@ namespace chaiscript
|
||||
|
||||
for (const auto &fun : t_funs) {
|
||||
if (fun->is_attribute_function()) {
|
||||
if (fun->compare_first_type(t_params[0], m_conversions)) {
|
||||
if (fun->compare_first_type(t_params[0], t_conversions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -934,14 +935,15 @@ namespace chaiscript
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4715)
|
||||
#endif
|
||||
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms, bool t_has_params)
|
||||
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms, bool t_has_params,
|
||||
const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
|
||||
const auto funs = get_function(t_name, loc);
|
||||
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
|
||||
|
||||
const auto do_attribute_call =
|
||||
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions &l_conversions)->Boxed_Value
|
||||
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
|
||||
{
|
||||
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
|
||||
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
|
||||
@ -974,14 +976,14 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
if (is_attribute_call(*funs.second, params, t_has_params)) {
|
||||
return do_attribute_call(1, params, *funs.second, m_conversions);
|
||||
if (is_attribute_call(*funs.second, params, t_has_params, t_conversions)) {
|
||||
return do_attribute_call(1, params, *funs.second, t_conversions);
|
||||
} else {
|
||||
std::exception_ptr except;
|
||||
|
||||
if (!funs.second->empty()) {
|
||||
try {
|
||||
return dispatch::dispatch(*funs.second, params, m_conversions);
|
||||
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||
} catch(chaiscript::exception::dispatch_error&) {
|
||||
except = std::current_exception();
|
||||
}
|
||||
@ -997,7 +999,7 @@ namespace chaiscript
|
||||
|
||||
for (const auto &f : *method_missing_funs)
|
||||
{
|
||||
if(f->compare_first_type(params[0], m_conversions)) {
|
||||
if(f->compare_first_type(params[0], t_conversions)) {
|
||||
fs.push_back(f);
|
||||
}
|
||||
}
|
||||
@ -1021,9 +1023,9 @@ namespace chaiscript
|
||||
if (is_no_param) {
|
||||
std::vector<Boxed_Value> tmp_params(params);
|
||||
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
||||
return do_attribute_call(2, tmp_params, functions, m_conversions);
|
||||
return do_attribute_call(2, tmp_params, functions, t_conversions);
|
||||
} else {
|
||||
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, m_conversions);
|
||||
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, t_conversions);
|
||||
}
|
||||
} catch (const dispatch::option_explicit_set &e) {
|
||||
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
|
||||
@ -1046,12 +1048,13 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms) const
|
||||
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms,
|
||||
const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
uint_fast32_t loc = t_loc.load(std::memory_order_relaxed);
|
||||
const auto funs = get_function(t_name, loc);
|
||||
if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed);
|
||||
return dispatch::dispatch(*funs.second, params, m_conversions);
|
||||
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
@ -1105,8 +1108,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
const Type_Conversions_State conversions(m_conversions, m_conversions.conversion_saves());
|
||||
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), conversions));
|
||||
}
|
||||
|
||||
/// Dump all system info to stdout
|
||||
@ -1208,19 +1212,19 @@ namespace chaiscript
|
||||
save_function_params(*m_stack_holder, t_params);
|
||||
}
|
||||
|
||||
void new_function_call(Stack_Holder &t_s)
|
||||
void new_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
|
||||
{
|
||||
if (t_s.call_depth == 0)
|
||||
{
|
||||
m_conversions.enable_conversion_saves(true);
|
||||
m_conversions.enable_conversion_saves(t_saves, true);
|
||||
}
|
||||
|
||||
++t_s.call_depth;
|
||||
|
||||
save_function_params(m_conversions.take_saves());
|
||||
save_function_params(m_conversions.take_saves(t_saves));
|
||||
}
|
||||
|
||||
void pop_function_call(Stack_Holder &t_s)
|
||||
void pop_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
|
||||
{
|
||||
--t_s.call_depth;
|
||||
|
||||
@ -1229,18 +1233,18 @@ namespace chaiscript
|
||||
if (t_s.call_depth == 0)
|
||||
{
|
||||
t_s.call_params.back().clear();
|
||||
m_conversions.enable_conversion_saves(false);
|
||||
m_conversions.enable_conversion_saves(t_saves, false);
|
||||
}
|
||||
}
|
||||
|
||||
void new_function_call()
|
||||
{
|
||||
new_function_call(*m_stack_holder);
|
||||
new_function_call(*m_stack_holder, m_conversions.conversion_saves());
|
||||
}
|
||||
|
||||
void pop_function_call()
|
||||
{
|
||||
pop_function_call(*m_stack_holder);
|
||||
pop_function_call(*m_stack_holder, m_conversions.conversion_saves());
|
||||
}
|
||||
|
||||
Stack_Holder &get_stack_holder()
|
||||
@ -1510,7 +1514,8 @@ namespace chaiscript
|
||||
public:
|
||||
Dispatch_State(Dispatch_Engine &t_engine)
|
||||
: m_engine(t_engine),
|
||||
m_stack_holder(t_engine.get_stack_holder())
|
||||
m_stack_holder(t_engine.get_stack_holder()),
|
||||
m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
|
||||
{
|
||||
}
|
||||
|
||||
@ -1526,6 +1531,14 @@ namespace chaiscript
|
||||
return m_stack_holder.get();
|
||||
}
|
||||
|
||||
const Type_Conversions_State &conversions() const {
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
Type_Conversions::Conversion_Saves &conversion_saves() const {
|
||||
return m_conversions.saves();
|
||||
}
|
||||
|
||||
void add_object(const std::string &t_name, Boxed_Value obj) const {
|
||||
m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
|
||||
}
|
||||
@ -1533,6 +1546,7 @@ namespace chaiscript
|
||||
private:
|
||||
std::reference_wrapper<Dispatch_Engine> m_engine;
|
||||
std::reference_wrapper<Stack_Holder> m_stack_holder;
|
||||
Type_Conversions_State m_conversions;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace chaiscript
|
||||
|
||||
virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; }
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@ -106,7 +106,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@ -116,7 +116,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@ -134,7 +134,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
@ -156,7 +156,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@ -216,7 +216,7 @@ namespace chaiscript
|
||||
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
@ -230,7 +230,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
@ -36,7 +36,7 @@ namespace chaiscript
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
||||
[](const Const_Proxy_Function &f) {
|
||||
@ -64,7 +64,7 @@ namespace chaiscript
|
||||
/// \param[in] func A function to execute.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace chaiscript
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
||||
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
@ -86,7 +86,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@ -103,7 +103,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@ -120,7 +120,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
|
@ -31,9 +31,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions);
|
||||
if (t_conversions) {
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -44,9 +50,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as<Ret>();
|
||||
if (t_conversions) {
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -58,9 +70,15 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions());
|
||||
if (t_conversions) {
|
||||
dispatch::dispatch(t_funcs, params, *t_conversions);
|
||||
} else {
|
||||
Type_Conversions conv;
|
||||
Type_Conversions_State state(conv, conv.conversion_saves());
|
||||
dispatch::dispatch(t_funcs, params, state);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -79,11 +97,18 @@ namespace chaiscript
|
||||
template<typename ... P>
|
||||
Ret operator()(P&& ... param)
|
||||
{
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, m_conversions
|
||||
|
||||
);
|
||||
if (m_conversions) {
|
||||
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, &state
|
||||
);
|
||||
} else {
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -114,7 +139,7 @@ namespace chaiscript
|
||||
|
||||
/// \todo what happens if t_conversions is deleted out from under us?!
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
|
||||
{
|
||||
/*
|
||||
if (funcs.size() == 1)
|
||||
@ -132,7 +157,7 @@ namespace chaiscript
|
||||
}
|
||||
*/
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace chaiscript
|
||||
namespace dispatch
|
||||
{
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
|
||||
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions_State *t_conversions);
|
||||
|
||||
class Param_Types
|
||||
{
|
||||
@ -72,7 +72,7 @@ namespace chaiscript
|
||||
return m_types == t_rhs.m_types;
|
||||
}
|
||||
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
bool match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (!m_has_types) return true;
|
||||
if (vals.size() != m_types.size()) return false;
|
||||
@ -147,7 +147,7 @@ namespace chaiscript
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (m_arity < 0 || size_t(m_arity) == params.size()) {
|
||||
return do_call(params, t_conversions);
|
||||
@ -163,7 +163,7 @@ namespace chaiscript
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
|
||||
virtual bool is_attribute_function() const { return false; }
|
||||
|
||||
@ -179,7 +179,7 @@ namespace chaiscript
|
||||
|
||||
//! Return true if the function is a possible match
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (m_arity < 0)
|
||||
{
|
||||
@ -206,7 +206,7 @@ namespace chaiscript
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
@ -214,7 +214,7 @@ namespace chaiscript
|
||||
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
|| t_conversions->converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -225,13 +225,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
return compare_type_to_param(m_types[1], bv, t_conversions);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const = 0;
|
||||
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
|
||||
@ -248,7 +248,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions &t_conversions)
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (tis.size() - 1 != bvs.size())
|
||||
{
|
||||
@ -327,7 +327,7 @@ namespace chaiscript
|
||||
&& this->m_param_types == prhs->m_param_types);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions)))
|
||||
&& test_guard(vals, t_conversions);
|
||||
@ -351,7 +351,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
@ -419,7 +419,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (call_match(params, t_conversions) && test_guard(params, t_conversions))
|
||||
{
|
||||
@ -469,7 +469,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
@ -548,7 +548,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
@ -573,12 +573,12 @@ namespace chaiscript
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && 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;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -596,7 +596,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Proxy_Function_Callable_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
@ -608,7 +608,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
typedef typename detail::Function_Signature<Func>::Return_Type Return_Type;
|
||||
return detail::Do_Call<Return_Type>::template go<Func>(m_f, params, t_conversions);
|
||||
@ -648,7 +648,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Assignable_Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
@ -668,7 +668,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
|
||||
}
|
||||
@ -705,7 +705,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@ -721,7 +721,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
const Boxed_Value &bv = params[0];
|
||||
if (bv.is_const())
|
||||
@ -782,7 +782,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||
|
||||
@ -801,7 +801,7 @@ namespace chaiscript
|
||||
|
||||
template<typename InItr, typename Funcs>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions, const Funcs &t_funcs)
|
||||
const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
|
||||
{
|
||||
InItr matching_func(end);
|
||||
|
||||
@ -878,7 +878,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
|
||||
ordered_funcs.reserve(funcs.size());
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Type_Conversions_State;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
@ -77,7 +77,7 @@ namespace chaiscript
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Try_Cast<Param, Rest...>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, size_t generation, const Type_Conversions &t_conversions)
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, size_t generation, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
@ -88,7 +88,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions &)
|
||||
static void do_try(const std::vector<Boxed_Value> &, size_t, const Type_Conversions_State &)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -101,7 +101,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
@ -118,7 +118,7 @@ namespace chaiscript
|
||||
|
||||
template<typename Callable, typename ... InnerParams>
|
||||
static Ret do_call(const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
@ -133,7 +133,7 @@ namespace chaiscript
|
||||
#endif
|
||||
template<typename Callable, typename ... InnerParams>
|
||||
static Ret do_call(const Callable &f,
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
@ -150,7 +150,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
@ -190,7 +190,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params, size_t ... I>
|
||||
bool compare_types_cast(Indexes<I...>, Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
try {
|
||||
(void)params; (void)t_conversions;
|
||||
@ -204,7 +204,7 @@ namespace chaiscript
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*f)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
|
||||
return compare_types_cast(indexes(), f, params, t_conversions);
|
||||
@ -213,7 +213,7 @@ namespace chaiscript
|
||||
|
||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, Indexes<I...>, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
(void)params; (void)t_conversions;
|
||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||
@ -228,7 +228,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
typedef typename Make_Indexes<sizeof...(Params)>::indexes indexes;
|
||||
return call_func(sig, indexes(), f, params, t_conversions);
|
||||
@ -252,7 +252,7 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Signature, typename Callable>
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
|
||||
}
|
||||
@ -262,7 +262,7 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Signature, typename Callable>
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
|
@ -315,6 +315,16 @@ namespace chaiscript
|
||||
class Type_Conversions
|
||||
{
|
||||
public:
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
@ -386,15 +396,14 @@ namespace chaiscript
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
||||
Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
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(), typeid(To), "No known conversion");
|
||||
@ -404,11 +413,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
||||
Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
if (t_saves.enabled) t_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");
|
||||
@ -417,15 +426,15 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
void enable_conversion_saves(bool t_val)
|
||||
static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val)
|
||||
{
|
||||
m_conversion_saves->enabled = t_val;
|
||||
t_saves.enabled = t_val;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> take_saves()
|
||||
std::vector<Boxed_Value> take_saves(Conversion_Saves &t_saves)
|
||||
{
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, m_conversion_saves->saves);
|
||||
std::swap(ret, t_saves.saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -449,6 +458,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
Conversion_Saves &conversion_saves() const {
|
||||
return *m_conversion_saves;
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find_bidir(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
@ -458,7 +471,6 @@ namespace chaiscript
|
||||
{
|
||||
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|
||||
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
|
||||
;
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -482,15 +494,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
@ -500,6 +503,33 @@ namespace chaiscript
|
||||
mutable chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
class Type_Conversions_State
|
||||
{
|
||||
public:
|
||||
Type_Conversions_State(const Type_Conversions &t_conversions,
|
||||
Type_Conversions::Conversion_Saves &t_saves)
|
||||
: m_conversions(t_conversions),
|
||||
m_saves(t_saves)
|
||||
{
|
||||
}
|
||||
|
||||
const Type_Conversions *operator->() const {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
const Type_Conversions *get() const {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
Type_Conversions::Conversion_Saves &saves() const {
|
||||
return m_saves;
|
||||
}
|
||||
|
||||
private:
|
||||
std::reference_wrapper<const Type_Conversions> m_conversions;
|
||||
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
@ -608,8 +638,6 @@ namespace chaiscript
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::map<std::string, Boxed_Value>>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -582,12 +582,12 @@ namespace chaiscript
|
||||
Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds)
|
||||
: m_ds(t_ds)
|
||||
{
|
||||
m_ds.get()->new_function_call(m_ds.get().stack_holder());
|
||||
m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
|
||||
}
|
||||
|
||||
~Function_Push_Pop()
|
||||
{
|
||||
m_ds.get()->pop_function_call(m_ds.get().stack_holder());
|
||||
m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves());
|
||||
}
|
||||
|
||||
void save_params(const std::vector<Boxed_Value> &t_params)
|
||||
|
@ -368,11 +368,15 @@ namespace chaiscript
|
||||
|
||||
// m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
//
|
||||
//
|
||||
|
||||
m_engine.add(fun(
|
||||
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) {
|
||||
return t_fun(t_params, this->m_engine.conversions());
|
||||
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
|
||||
return t_fun(t_params, s);
|
||||
}), "call");
|
||||
|
||||
|
||||
m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name");
|
||||
|
||||
m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type");
|
||||
|
@ -118,7 +118,7 @@ namespace chaiscript
|
||||
} else {
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
fpp.save_params({t_lhs, t_rhs});
|
||||
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs});
|
||||
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions());
|
||||
}
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
@ -255,7 +255,7 @@ namespace chaiscript
|
||||
Boxed_Value fn(this->children[0]->eval(t_ss));
|
||||
|
||||
try {
|
||||
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss->conversions());
|
||||
return (*t_ss->boxed_cast<const Const_Proxy_Function &>(fn))(params, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
|
||||
@ -436,14 +436,14 @@ namespace chaiscript
|
||||
} else {
|
||||
if (!rhs.is_return_value())
|
||||
{
|
||||
rhs = t_ss->call_function("clone", m_clone_loc, {rhs});
|
||||
rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions());
|
||||
}
|
||||
rhs.reset_return_value();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs});
|
||||
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
|
||||
@ -463,7 +463,7 @@ namespace chaiscript
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs});
|
||||
return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
|
||||
} catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss);
|
||||
}
|
||||
@ -546,7 +546,7 @@ namespace chaiscript
|
||||
|
||||
try {
|
||||
fpp.save_params(params);
|
||||
return t_ss->call_function("[]", m_loc, params);
|
||||
return t_ss->call_function("[]", m_loc, params, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
|
||||
@ -599,7 +599,7 @@ namespace chaiscript
|
||||
fpp.save_params(params);
|
||||
|
||||
try {
|
||||
retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params);
|
||||
retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
if (e.functions.empty())
|
||||
@ -615,7 +615,7 @@ namespace chaiscript
|
||||
|
||||
if (this->children[2]->identifier == AST_Node_Type::Array_Call) {
|
||||
try {
|
||||
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)});
|
||||
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}, t_ss.conversions());
|
||||
}
|
||||
catch(const exception::dispatch_error &e){
|
||||
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
|
||||
@ -941,7 +941,7 @@ namespace chaiscript
|
||||
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
|
||||
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
|
||||
try {
|
||||
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}))) {
|
||||
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) {
|
||||
this->children[currentCase]->eval(t_ss);
|
||||
hasMatched = true;
|
||||
}
|
||||
@ -1011,7 +1011,7 @@ namespace chaiscript
|
||||
for (const auto &child : children[0]->children) {
|
||||
auto obj = child->eval(t_ss);
|
||||
if (!obj.is_return_value()) {
|
||||
vec.push_back(t_ss->call_function("clone", m_loc, {obj}));
|
||||
vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()));
|
||||
} else {
|
||||
vec.push_back(std::move(obj));
|
||||
}
|
||||
@ -1044,7 +1044,7 @@ namespace chaiscript
|
||||
for (const auto &child : children[0]->children) {
|
||||
auto obj = child->children[1]->eval(t_ss);
|
||||
if (!obj.is_return_value()) {
|
||||
obj = t_ss->call_function("clone", m_loc, {obj});
|
||||
obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions());
|
||||
}
|
||||
|
||||
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj);
|
||||
@ -1140,7 +1140,7 @@ namespace chaiscript
|
||||
} else {
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
fpp.save_params({bv});
|
||||
return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)});
|
||||
return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}, t_ss.conversions());
|
||||
}
|
||||
} catch (const exception::dispatch_error &e) {
|
||||
throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
|
||||
@ -1212,7 +1212,7 @@ namespace chaiscript
|
||||
try {
|
||||
auto oper1 = children[0]->children[0]->children[0]->eval(t_ss);
|
||||
auto oper2 = children[0]->children[0]->children[1]->eval(t_ss);
|
||||
return t_ss->call_function("generate_range", m_loc, {oper1, oper2});
|
||||
return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions());
|
||||
}
|
||||
catch (const exception::dispatch_error &e) {
|
||||
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
|
||||
@ -1257,7 +1257,7 @@ namespace chaiscript
|
||||
|
||||
if (dispatch::Param_Types(
|
||||
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)}
|
||||
).match(std::vector<Boxed_Value>{t_except}, t_ss->conversions()))
|
||||
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()))
|
||||
{
|
||||
t_ss.add_object(name, t_except);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user