
And also apply cleanups suggested from resharper Conflicts: include/chaiscript/language/chaiscript_parser.hpp
120 lines
3.9 KiB
C++
120 lines
3.9 KiB
C++
// 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 <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#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<typename Ret, bool is_arithmetic>
|
|
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)
|
|
{
|
|
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Specialization for arithmetic return types
|
|
*/
|
|
template<typename Ret>
|
|
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)
|
|
{
|
|
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Specialization for void return types
|
|
*/
|
|
template<>
|
|
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)
|
|
{
|
|
dispatch::dispatch(t_funcs, params, t_conversions);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* used internally for unwrapping a function call's types
|
|
*/
|
|
template<typename Ret, typename ... Param>
|
|
struct Build_Function_Caller_Helper
|
|
{
|
|
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
|
: m_funcs(std::move(t_funcs)),
|
|
m_conversions(t_conversions)
|
|
{
|
|
}
|
|
|
|
Ret operator()(Param...param)
|
|
{
|
|
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
|
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
|
|
}, m_conversions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
std::vector<Const_Proxy_Function> m_funcs;
|
|
Type_Conversions m_conversions;
|
|
};
|
|
|
|
|
|
|
|
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)
|
|
{
|
|
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:Type_Conversions()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|