Compare commits

...

1 Commits

Author SHA1 Message Date
Jason Turner
5f10d9980b Attempt at simplifying function registration 2016-04-03 21:50:13 -06:00
11 changed files with 478 additions and 325 deletions

View File

@ -213,7 +213,7 @@ endif()
include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)

View File

@ -28,7 +28,6 @@
#include "operators.hpp"
#include "proxy_constructors.hpp"
#include "proxy_functions.hpp"
#include "proxy_functions_detail.hpp"
#include "register_function.hpp"
#include "type_info.hpp"
#include "../utility/utility.hpp"

View File

@ -13,53 +13,6 @@ namespace chaiscript {
namespace dispatch {
namespace detail {
template<typename Class, typename ... Param>
struct Constructor
{
template<typename ... Inner>
std::shared_ptr<Class> operator()(Inner&& ... inner) const {
return std::make_shared<Class>(std::forward<Inner>(inner)...);
}
};
template<typename Ret, typename Class, typename ... Param>
struct Const_Caller
{
Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(const Class &o, Inner&& ... inner) const {
return (o.*m_func)(std::forward<Inner>(inner)...);
}
Ret (Class::*m_func)(Param...) const;
};
template<typename Ret, typename ... Param>
struct Fun_Caller
{
Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Inner&& ... inner) const {
return (m_func)(std::forward<Inner>(inner)...);
}
Ret(*m_func)(Param...);
};
template<typename Ret, typename Class, typename ... Param>
struct Caller
{
Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {}
template<typename ... Inner>
Ret operator()(Class &o, Inner&& ... inner) const {
return (o.*m_func)(std::forward<Inner>(inner)...);
}
Ret (Class::*m_func)(Param...);
};
template<typename T>
struct Arity

View File

@ -141,22 +141,6 @@ namespace chaiscript
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_State *t_conversions)
{
/*
if (funcs.size() == 1)
{
std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
(funcs[0]);
if (pfi)
{
return pfi->internal_function();
}
// looks like this either wasn't a Proxy_Function_Impl or the types didn't match
// we cannot make any other guesses or assumptions really, so continuing
}
*/
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
}
}

View File

@ -20,11 +20,19 @@ class Boxed_Number;
namespace chaiscript
{
template<typename T> std::shared_ptr<dispatch::Proxy_Function_Base> fun(const T &t);
template<typename Ret, typename ... Param>
std::shared_ptr<dispatch::Proxy_Function_Base> assignable_fun(
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
std::shared_ptr<std::function<Ret (Param...)>> t_ptr
);
namespace dispatch
{
template<class T, class U> class Proxy_Function_Callable_Impl;
template<class T> class Assignable_Proxy_Function_Impl;
namespace detail
{
/**
@ -53,7 +61,7 @@ namespace chaiscript
{
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
chaiscript::fun(f)
);
}
};
@ -68,7 +76,7 @@ namespace chaiscript
{
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
assignable_fun(std::ref(*f), f)
);
}
};
@ -88,14 +96,13 @@ namespace chaiscript
{
static Boxed_Value handle(std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(f),
std::shared_ptr<std::function<Ret>>())
assignable_fun(std::ref(f), std::shared_ptr<std::function<Ret>>())
);
}
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
chaiscript::fun(f)
);
}
};

View File

@ -17,13 +17,32 @@ namespace chaiscript
namespace detail
{
template<typename Class, typename ... Params >
Proxy_Function build_constructor_(Class (*)(Params...))
template<typename Class, typename ... Params, size_t ... I >
Proxy_Function build_constructor_(Class (*)(Params...), std::index_sequence<I...>)
{
auto call = dispatch::detail::Constructor<Class, Params...>();
return [](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func()
: dispatch::Proxy_Function_Impl_Base({user_type<std::shared_ptr<Class>>(), user_type<Params>()...})
{
}
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Params...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return Handle_Return<std::shared_ptr<Class>>::handle(std::make_shared<Class>(boxed_cast<Params>(params[I], &t_conversions)...));
}
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>();
}();
}
}
}
@ -44,7 +63,7 @@ namespace chaiscript
Proxy_Function constructor()
{
T *f = nullptr;
return (dispatch::detail::build_constructor_(f));
return dispatch::detail::build_constructor_(f, std::make_index_sequence<dispatch::detail::Arity<T>::arity>());
}
}

View File

@ -21,15 +21,34 @@
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_value.hpp"
#include "proxy_functions_detail.hpp"
#include "type_info.hpp"
#include "dynamic_object.hpp"
#include "callable_traits.hpp"
#include "handle_return.hpp"
namespace chaiscript {
class Type_Conversions;
namespace exception {
class bad_boxed_cast;
struct arity_error;
/**
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
{
arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
got(t_got), expected(t_expected)
{
}
arity_error(const arity_error &) = default;
virtual ~arity_error() noexcept {}
int got;
int expected;
};
} // namespace exception
} // namespace chaiscript
@ -559,6 +578,48 @@ namespace chaiscript
return "";
}
bool operator==(const Proxy_Function_Base &t_func) const override
{
const auto *t_other = dynamic_cast<const Proxy_Function_Impl_Base *>(&t_func);
return
t_other != nullptr &&
t_other->m_types.size() == m_types.size() &&
[this, &t_other](){
auto begin1 = std::begin(m_types);
const auto end1 = std::end(m_types);
auto begin2 = std::begin(t_other->m_types);
while (begin1 != end1) {
if (*begin1 != *begin2) {
return false;
}
if (begin1->is_const() != begin2->is_const()) {
return false;
}
++begin1;
++begin2;
}
return true;
}();
}
template<typename ... Param>
static bool compare_types_with_cast_impl(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
std::vector<Boxed_Value>::size_type i = 0;
(void)i; (void)params; (void)t_conversions;
// this is ok because the order of evaluation of initializer lists is well defined
(void)std::initializer_list<int>{(boxed_cast<Param>(params[i++], &t_conversions), 0)...};
return true;
} catch (const exception::bad_boxed_cast &) {
return false;
}
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return static_cast<int>(vals.size()) == get_arity()
@ -569,41 +630,6 @@ namespace chaiscript
};
/// For any callable object
template<typename Func, typename Callable>
class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base
{
public:
Proxy_Function_Callable_Impl(Callable f)
: Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast<Func *>(nullptr))),
m_f(std::move(f))
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
bool operator==(const Proxy_Function_Base &t_func) const override
{
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const 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);
}
private:
Callable m_f;
};
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
{
public:
@ -615,47 +641,6 @@ namespace chaiscript
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
};
template<typename Func>
class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function
{
public:
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
: Assignable_Proxy_Function(detail::build_param_type_list(static_cast<Func *>(nullptr))),
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr))
{
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
bool operator==(const Proxy_Function_Base &t_func) const override
{
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
}
std::function<Func> internal_function() const
{
return m_f.get();
}
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return detail::Do_Call<typename std::function<Func>::result_type>::template go<Func>(m_f.get(), params, t_conversions);
}
private:
std::reference_wrapper<std::function<Func>> m_f;
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
};
/// Attribute getter Proxy_Function implementation

View File

@ -1,151 +0,0 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
#ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_
#include <functional>
#include <stdexcept>
#include <vector>
#include <array>
#include "../chaiscript_defines.hpp"
#include "boxed_cast.hpp"
#include "boxed_value.hpp"
#include "handle_return.hpp"
#include "type_info.hpp"
#include "callable_traits.hpp"
namespace chaiscript {
class Type_Conversions_State;
namespace exception {
class bad_boxed_cast;
} // namespace exception
} // namespace chaiscript
namespace chaiscript
{
namespace exception
{
/**
* Exception thrown when there is a mismatch in number of
* parameters during Proxy_Function execution
*/
struct arity_error : std::range_error
{
arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
got(t_got), expected(t_expected)
{
}
arity_error(const arity_error &) = default;
virtual ~arity_error() noexcept {}
int got;
int expected;
};
}
namespace dispatch
{
namespace detail
{
/**
* Used by Proxy_Function_Impl to return a list of all param types
* it contains.
*/
template<typename Ret, typename ... Params>
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
{
/// \note somehow this is responsible for a large part of the code generation
return { user_type<Ret>(), user_type<Params>()... };
}
/**
* Used by Proxy_Function_Impl to determine if it is equivalent to another
* Proxy_Function_Impl object. This function is primarily used to prevent
* registration of two functions with the exact same signatures
*/
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
try {
std::vector<Boxed_Value>::size_type i = 0;
(void)i;
(void)params; (void)t_conversions;
// this is ok because the order of evaluation of initializer lists is well defined
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
return true;
} catch (const exception::bad_boxed_cast &) {
return false;
}
}
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
std::index_sequence<I...>, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
(void)params; (void)t_conversions;
return f(boxed_cast<Params>(params[I], &t_conversions)...);
}
/**
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
* The function attempts to unbox each parameter to the expected type.
* if any unboxing fails the execution of the function fails and
* the bad_boxed_cast is passed up to the caller.
*/
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> &params, const Type_Conversions_State &t_conversions)
{
return call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
}
}
}
}
namespace chaiscript
{
namespace dispatch
{
namespace detail
{
template<typename Ret>
struct Do_Call
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(Function_Signature<Signature>(), fun, params, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Signature, typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
{
call_func(Function_Signature<Signature>(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};
}
}
}
#endif

View File

@ -11,6 +11,8 @@
#include "bind_first.hpp"
#include "proxy_functions.hpp"
#include "handle_return.hpp"
#include "function_call.hpp"
namespace chaiscript
{
@ -35,45 +37,396 @@ namespace chaiscript
/// \endcode
///
/// \sa \ref adding_functions
//
//
template<typename ... Param, size_t ... I>
Proxy_Function assignable_fun(
std::reference_wrapper<std::function<void (Param...)>> t_func,
std::shared_ptr<std::function<void (Param...)>> t_ptr,
std::index_sequence<I...>)
{
return [t_func, t_ptr](){
class Func final : public dispatch::Assignable_Proxy_Function
{
public:
Func(std::reference_wrapper<std::function<void (Param...)>> t_f, std::shared_ptr<std::function<void (Param...)>> t_p)
: Assignable_Proxy_Function({user_type<void>(), user_type<Param>()...}),
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p))
{
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
m_f.get() = dispatch::functor<void (Param...)>(t_rhs, nullptr);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
m_f(boxed_cast<Param>(params.at(I), &t_conversions)...);
return dispatch::detail::Handle_Return<void>::handle();
}
private:
std::reference_wrapper<std::function<void (Param...)>> m_f;
std::shared_ptr<std::function<void (Param...)>> m_shared_ptr_holder;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func, t_ptr);
}();
}
template<typename Ret, typename ... Param, size_t ... I>
Proxy_Function assignable_fun(
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
std::shared_ptr<std::function<Ret (Param...)>> t_ptr,
std::index_sequence<I...>)
{
return [t_func, t_ptr](){
class Func final : public dispatch::Assignable_Proxy_Function
{
public:
Func(std::reference_wrapper<std::function<Ret (Param...)>> t_f, std::shared_ptr<std::function<Ret (Param...)>> t_p)
: Assignable_Proxy_Function({user_type<Ret>(), user_type<Param>()...}),
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p))
{
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) override {
m_f.get() = dispatch::functor<Ret (Param...)>(t_rhs, nullptr);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return dispatch::detail::Handle_Return<Ret>::handle(m_f(boxed_cast<Param>(params.at(I), &t_conversions)...));
}
private:
std::reference_wrapper<std::function<Ret (Param...)>> m_f;
std::shared_ptr<std::function<Ret (Param...)>> m_shared_ptr_holder;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func, t_ptr);
}();
}
template<typename Ret, typename ... Param>
Proxy_Function assignable_fun(
std::reference_wrapper<std::function<Ret (Param...)>> t_func,
std::shared_ptr<std::function<Ret (Param...)>> t_ptr
)
{
return assignable_fun(std::move(t_func), std::move(t_ptr), std::make_index_sequence<sizeof...(Param)>());
}
template<typename T, typename ... Param, size_t ... I>
Proxy_Function fun(const T &t_func, void (*)(Param...), std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(const T &func)
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
m_f(boxed_cast<Param>(params[I], &t_conversions)...);
return dispatch::detail::Handle_Return<void>::handle();
}
private:
T m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Ret, typename T, typename ... Param, size_t ... I>
Proxy_Function fun(const T &t_func, Ret (*)(Param...), std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(const T &func)
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return dispatch::detail::Handle_Return<Ret>::handle(m_f(boxed_cast<Param>(params.at(I), &t_conversions)...));
}
private:
T m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename T>
Proxy_Function fun(const T &t)
{
typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
Signature *f = nullptr;
return fun(t, f, std::make_index_sequence<dispatch::detail::Arity<Signature>::arity>());
}
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
template<typename ... Param, size_t ... I>
Proxy_Function fun(void (*t_func)(Param...), std::index_sequence<I...>)
{
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Param>()...}),
m_f(func)
{
}
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
(*m_f)(boxed_cast<Param>(params[I], &t_conversions)...);
return dispatch::detail::Handle_Return<void>::handle();
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Ret, typename ... Param, size_t ... I>
Proxy_Function fun(Ret (*t_func)(Param...), std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return dispatch::detail::Handle_Return<Ret>::handle((*m_f)(boxed_cast<Param>(params[I], &t_conversions)...));
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Class, typename ... Param, size_t ... I>
Proxy_Function fun(void (Class::*t_func)(Param...) const, std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<const Class &>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<const Class &, Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
const Class &o = static_cast<const Class &>(boxed_cast<const Class &>(params[0], &t_conversions));
(o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...);
return dispatch::detail::Handle_Return<void>::handle();
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Ret, typename Class, typename ... Param, size_t ... I>
Proxy_Function fun(Ret (Class::*t_func)(Param...) const, std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<const Class &>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<const Class &, Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
const Class &o = static_cast<const Class &>(boxed_cast<const Class &>(params[0], &t_conversions));
return dispatch::detail::Handle_Return<Ret>::handle((o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...));
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Class, typename ... Param, size_t ... I>
Proxy_Function fun(void (Class::*t_func)(Param...), std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<void>(), user_type<Class &>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Class &, Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
Class &o = static_cast<Class &>(boxed_cast<Class &>(params[0], &t_conversions));
(o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...);
return dispatch::detail::Handle_Return<void>::handle();
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Ret, typename Class, typename ... Param, size_t ... I>
Proxy_Function fun(Ret (Class::*t_func)(Param...), std::index_sequence<I...>)
{
return [t_func](){
class Func final : public dispatch::Proxy_Function_Impl_Base
{
public:
Func(decltype(t_func) func)
: dispatch::Proxy_Function_Impl_Base({user_type<Ret>(), user_type<Class &>(), user_type<Param>()...}),
m_f(func)
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
return compare_types_with_cast_impl<Class &, Param...>(params, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
{
Class &o = static_cast<Class &>(boxed_cast<Class &>(params[0], &t_conversions));
return dispatch::detail::Handle_Return<Ret>::handle((o.*m_f)(boxed_cast<Param>(params[I+1], &t_conversions)...));
}
private:
decltype(t_func) m_f;
};
return chaiscript::make_shared<dispatch::Proxy_Function_Base, Func>(t_func);
}();
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
{
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
return fun(t_func, std::make_index_sequence<sizeof...(Param)>());
}
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
{
return fun(func, std::make_index_sequence<sizeof...(Param)>());
}
template<typename Ret, typename Class, typename ... Param>
Proxy_Function fun(Ret (Class::*t_func)(Param...))
{
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
return fun(t_func, std::make_index_sequence<sizeof...(Param)>());
}
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
{

View File

@ -53,6 +53,11 @@ namespace chaiscript
|| *ti.m_type_info == *m_type_info;
}
constexpr bool operator!=(const Type_Info &ti) const noexcept
{
return !(*this == ti);
}
constexpr bool operator==(const std::type_info &ti) const noexcept
{
return !is_undef() && (*m_type_info) == ti;

View File

@ -24,7 +24,6 @@
#include "../dispatchkit/dispatchkit.hpp"
#include "../dispatchkit/dynamic_object_detail.hpp"
#include "../dispatchkit/proxy_functions.hpp"
#include "../dispatchkit/proxy_functions_detail.hpp"
#include "../dispatchkit/register_function.hpp"
#include "../dispatchkit/type_info.hpp"
#include "chaiscript_algebraic.hpp"