diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp new file mode 100644 index 0000000..5e54927 --- /dev/null +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -0,0 +1,98 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + +#include + +#define addparam(z,n,text) params.push_back(boost::is_reference::value?Boxed_Value(boost::ref(BOOST_PP_CAT(p, n))):Boxed_Value(BOOST_PP_CAT(p, n) )); +#define curry(z,n,text) BOOST_PP_CAT(_, BOOST_PP_INC(n)) + + +#ifndef BOOST_PP_IS_ITERATING +#ifndef __function_call_detail_hpp__ +#define __function_call_detail_hpp__ + +#include +#include +#include +#include +#include +#include "proxy_functions.hpp" + +namespace chaiscript +{ + namespace detail + { + /** + * Internal helper class for handling the return + * value of a build_function_caller + */ + template + class Function_Caller_Ret + { + static Ret call(const std::vector > &t_funcs, + const std::vector ¶ms) + { + return boxed_cast(dispatch(t_funcs, params)); + } + }; + + /** + * Specialization for void return types + */ + template<> + struct Function_Caller_Ret + { + static void call(const std::vector > &t_funcs, + const std::vector ¶ms) + { + dispatch(t_funcs, params); + } + }; + } +} + +#define BOOST_PP_ITERATION_LIMITS ( 0, 9 ) +#define BOOST_PP_FILENAME_1 +#include BOOST_PP_ITERATE() + +# endif +#else +# define n BOOST_PP_ITERATION() + +namespace chaiscript +{ + namespace detail + { + /** + * used internally for unwrapping a function call's types + */ + template + Ret function_caller(const std::vector > &funcs + BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) + { + std::vector params; + + BOOST_PP_REPEAT(n, addparam, ~) + + return Function_Caller_Ret::call(funcs, params); + } + + /** + * used internally for unwrapping a function call's types + */ + template + boost::function + build_function_caller_helper(Ret (BOOST_PP_ENUM_PARAMS(n, Param)), const std::vector > &funcs) + { + return boost::bind(&function_caller, funcs + BOOST_PP_ENUM_TRAILING(n, curry, ~)); + } + + } +} + +#endif + diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp new file mode 100644 index 0000000..2e6ab6e --- /dev/null +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -0,0 +1,100 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + +#ifndef __handle_return_hpp__ +#define __handle_return_hpp__ + +#include "boxed_value.hpp" +#include "type_info.hpp" +#include +#include + +#include +#include + +namespace chaiscript +{ + /** + * Used internally for handling a return value from a Proxy_Function call + */ + template + struct Handle_Return + { + static Boxed_Value call(const boost::function &f) + { + return Boxed_Value(f()); + } + }; + + template + struct Handle_Return &> + { + static Boxed_Value call(const boost::function & ()> &f) + { + return Boxed_Value(f()); + } + }; + + template + struct Handle_Return &> + { + static Boxed_Value call(const boost::function & ()> &f) + { + return Boxed_Value(f()); + } + }; + + /** + * Used internally for handling a return value from a Proxy_Function call + */ + template + struct Handle_Return + { + static Boxed_Value call(const boost::function &f) + { + return Boxed_Value(boost::ref(f())); + } + }; + + /** + * Used internally for handling a return value from a Proxy_Function call + */ + template<> + struct Handle_Return + { + static Boxed_Value call(const boost::function &f) + { + return f(); + } + }; + + /** + * Used internally for handling a return value from a Proxy_Function call + */ + template<> + struct Handle_Return + { + static Boxed_Value call(const boost::function &f) + { + return f(); + } + }; + + /** + * Used internally for handling a return value from a Proxy_Function call + */ + template<> + struct Handle_Return + { + static Boxed_Value call(const boost::function &f) + { + f(); + return Boxed_Value(Boxed_Value::Void_Type()); + } + }; +} + +#endif diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp new file mode 100644 index 0000000..969af22 --- /dev/null +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -0,0 +1,121 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009, Jonathan Turner (jturner@minnow-lang.org) +// and Jason Turner (lefticus@gmail.com) +// http://www.chaiscript.com + +#include + +#define gettypeinfo(z,n,text) ti.push_back(detail::Get_Type_Info::get()); +#define casthelper(z,n,text) ,chaiscript::boxed_cast< Param ## n >(params[n]) +#define comparetype(z,n,text) && ((detail::Get_Type_Info::get() == params[n].get_type_info())) +#define trycast(z,n,text) chaiscript::boxed_cast(params[n]); + + +#ifndef BOOST_PP_IS_ITERATING +#ifndef __proxy_functions_detail_hpp__ +#define __proxy_functions_detail_hpp__ + +#include "boxed_value.hpp" +#include "type_info.hpp" +#include "handle_return.hpp" +#include +#include +#include +#include + +#include +#include + +namespace chaiscript +{ + /** + * 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) + { + } + + virtual ~arity_error() throw() {} + int got; + int expected; + }; +} + +#define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) +#define BOOST_PP_FILENAME_1 +#include BOOST_PP_ITERATE() + + +# endif +#else +# define n BOOST_PP_ITERATION() + +namespace chaiscript +{ + /** + * Used by Proxy_Function_Impl to return a list of all param types + * it contains. + */ + template + std::vector build_param_type_list(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param))) + { + std::vector ti; + ti.push_back(detail::Get_Type_Info::get()); + + BOOST_PP_REPEAT(n, gettypeinfo, ~) + + return ti; + } + + /** + * Used by Proxy_Function_Impl to perform typesafe execution of a function. + * The function attempts to unbox each paramter 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 + Boxed_Value call_func(const boost::function &f, + const std::vector ¶ms) + { + if (params.size() != n) + { + throw arity_error(params.size(), n); + } else { + return Handle_Return::call(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~))); + } + } + + /** + * Used by Proxy_Function_Impl to determine if it is equivalent to another + * Proxy_Function_Impl object. This function is primarly used to prevent + * registration of two functions with the exact same signatures + */ + template + bool compare_types(Ret (*)(BOOST_PP_ENUM_PARAMS(n, Param)), + const std::vector ¶ms) + { + if (params.size() != n) + { + return false; + } else { + bool val = true BOOST_PP_REPEAT(n, comparetype, ~); + if (val) return true; + + try { + BOOST_PP_REPEAT(n, trycast, ~); + } catch (const bad_boxed_cast &) { + return false; + } + + return true; + } + } +} + +#endif