// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #include #include #include #include #include #include "boxed_cast.hpp" #include "boxed_number.hpp" #include "boxed_value.hpp" #include "type_conversions.hpp" #include "proxy_functions.hpp" namespace chaiscript { namespace dispatch { namespace detail { /// Internal helper class for handling the return /// value of a build_function_caller template struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, const std::vector ¶ms, const Type_Conversions *t_conversions) { return boxed_cast(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions); } }; /** * Specialization for arithmetic return types */ template struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, const std::vector ¶ms, const Type_Conversions *t_conversions) { return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as(); } }; /** * Specialization for void return types */ template<> struct Function_Caller_Ret { static void call(const std::vector &t_funcs, const std::vector ¶ms, const Type_Conversions *t_conversions) { dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()); } }; /** * used internally for unwrapping a function call's types */ template struct Build_Function_Caller_Helper { Build_Function_Caller_Helper(std::vector t_funcs, const Type_Conversions *t_conversions) : m_funcs(std::move(t_funcs)), m_conversions(t_conversions) { } template Ret operator()(P&& ... param) { return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { box

(std::forward

(param))... }, m_conversions ); } template static auto box(Q&& q) -> typename std::enable_if::value&&!std::is_same::type>::type>::value, Boxed_Value>::type { return Boxed_Value(std::ref(std::forward(q))); } template static auto box(Q&& q) -> typename std::enable_if::value&&!std::is_same::type>::type>::value, Boxed_Value>::type { return Boxed_Value(std::forward(q)); } template static Boxed_Value box(Boxed_Value bv) { return bv; } std::vector m_funcs; const Type_Conversions *m_conversions; }; /// \todo what happens if t_conversions is deleted out from under us?! template std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions *t_conversions) { /* if (funcs.size() == 1) { std::shared_ptr> pfi = std::dynamic_pointer_cast > (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(Build_Function_Caller_Helper(funcs, t_conversions)); } } } } #endif