233 lines
8.6 KiB
Plaintext
233 lines
8.6 KiB
Plaintext
/*=============================================================================
|
|
Copyright (c) 2001-2007 Joel de Guzman
|
|
Copyright (c) 2004 Daniel Wallin
|
|
Copyright (c) 2011 Thomas Heller
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
==============================================================================*/
|
|
#ifndef PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
|
|
#define PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
|
|
|
|
#include <boost/mpl/int.hpp>
|
|
#include <boost/mpl/bool.hpp>
|
|
#include <boost/mpl/eval_if.hpp>
|
|
#include <boost/mpl/identity.hpp>
|
|
#include <boost/fusion/include/at.hpp>
|
|
#include <boost/fusion/include/value_at.hpp>
|
|
#include <boost/preprocessor/enum.hpp>
|
|
#include <boost/preprocessor/repeat.hpp>
|
|
#include <boost/type_traits/remove_reference.hpp>
|
|
#include <boost/type_traits/is_reference.hpp>
|
|
|
|
#define BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM(z, n, data) \
|
|
typename T##n = unused<n>
|
|
|
|
#define BOOST_PHOENIX_MAP_LOCAL_DISPATCH(z, n, data) \
|
|
typedef char(&result##n)[n+2]; \
|
|
static result##n get(T##n*);
|
|
|
|
namespace boost { namespace phoenix
|
|
{
|
|
template <typename Env, typename OuterEnv, typename Locals, typename Map>
|
|
struct scoped_environment;
|
|
|
|
namespace detail
|
|
{
|
|
template <typename Key>
|
|
struct local
|
|
{
|
|
typedef Key key_type;
|
|
};
|
|
|
|
namespace result_of
|
|
{
|
|
template <typename Locals, typename Context>
|
|
struct initialize_locals;
|
|
|
|
template <typename Context>
|
|
struct initialize_locals<vector0<>, Context>
|
|
{
|
|
typedef vector0<> type;
|
|
};
|
|
|
|
#define M1(Z, N, D) \
|
|
typename boost::phoenix::result_of::eval< \
|
|
BOOST_PP_CAT(A, N) \
|
|
, Context \
|
|
>::type \
|
|
/**/
|
|
|
|
#define M0(Z, N, D) \
|
|
template <BOOST_PHOENIX_typename_A(N), typename Context> \
|
|
struct initialize_locals< \
|
|
BOOST_PP_CAT(vector, N)< \
|
|
BOOST_PHOENIX_A(N) \
|
|
> \
|
|
, Context \
|
|
> \
|
|
{ \
|
|
typedef \
|
|
BOOST_PP_CAT(vector, N)< \
|
|
BOOST_PP_ENUM(N, M1, _) \
|
|
> \
|
|
type; \
|
|
}; \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
|
|
#undef M0
|
|
}
|
|
|
|
template <typename Context>
|
|
vector0<>
|
|
initialize_locals(vector0<> const &, Context const &)
|
|
{
|
|
vector0<> vars;
|
|
return vars;
|
|
}
|
|
#define M2(Z, N, D) \
|
|
eval(locals. BOOST_PP_CAT(a, N), ctx) \
|
|
/**/
|
|
|
|
#define M0(Z, N, D) \
|
|
template <BOOST_PHOENIX_typename_A(N), typename Context> \
|
|
BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> \
|
|
initialize_locals( \
|
|
BOOST_PP_CAT(vector, N)<BOOST_PHOENIX_A(N)> const & locals \
|
|
, Context const & ctx \
|
|
) \
|
|
{ \
|
|
BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> vars \
|
|
= {BOOST_PP_ENUM(N, M2, _)}; \
|
|
return vars; \
|
|
} \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
|
|
#undef M0
|
|
#undef M1
|
|
#undef M2
|
|
|
|
template <int N>
|
|
struct unused;
|
|
|
|
template <
|
|
BOOST_PP_ENUM(
|
|
BOOST_PHOENIX_LOCAL_LIMIT
|
|
, BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
|
|
, _
|
|
)
|
|
>
|
|
struct map_local_index_to_tuple
|
|
{
|
|
typedef char(¬_found)[1];
|
|
static not_found get(...);
|
|
|
|
BOOST_PP_REPEAT(BOOST_PHOENIX_LOCAL_LIMIT, BOOST_PHOENIX_MAP_LOCAL_DISPATCH, _)
|
|
};
|
|
|
|
template<typename T>
|
|
T* generate_pointer();
|
|
|
|
template <typename Map, typename Tag>
|
|
struct get_index
|
|
{
|
|
BOOST_STATIC_CONSTANT(int,
|
|
value = (
|
|
static_cast<int>((sizeof(Map::get(generate_pointer<Tag>()))) / sizeof(char)) - 2
|
|
));
|
|
|
|
// if value == -1, Tag is not found
|
|
typedef mpl::int_<value> type;
|
|
};
|
|
|
|
|
|
template <typename Local, typename Env>
|
|
struct apply_local;
|
|
|
|
template <typename Local, typename Env>
|
|
struct outer_local
|
|
{
|
|
typedef typename
|
|
apply_local<Local, typename Env::outer_env_type>::type
|
|
type;
|
|
};
|
|
|
|
template <typename Locals, int Index>
|
|
struct get_local_or_void
|
|
{
|
|
typedef typename
|
|
mpl::eval_if_c<
|
|
Index < Locals::size_value
|
|
, fusion::result_of::at_c<Locals, Index>
|
|
, mpl::identity<fusion::void_>
|
|
>::type
|
|
type;
|
|
};
|
|
|
|
template <typename Local, typename Env, int Index>
|
|
struct get_local_from_index
|
|
{
|
|
typedef typename
|
|
mpl::eval_if_c<
|
|
Index == -1
|
|
, outer_local<Local, Env>
|
|
, get_local_or_void<typename Env::locals_type, Index>
|
|
>::type
|
|
type;
|
|
};
|
|
|
|
template <typename Local, typename Env>
|
|
struct get_local
|
|
{
|
|
static const int index_value = get_index<typename Env::map_type, Local>::value;
|
|
|
|
typedef typename
|
|
get_local_from_index<Local, Env, index_value>::type
|
|
type;
|
|
};
|
|
|
|
template <typename Local, typename Env>
|
|
struct apply_local
|
|
{
|
|
// $$$ TODO: static assert that Env is a scoped_environment $$$
|
|
typedef typename get_local<Local, Env>::type type;
|
|
};
|
|
|
|
template <typename Key>
|
|
struct eval_local
|
|
{
|
|
template <typename RT, int Index, typename Env>
|
|
static RT
|
|
get(Env const& env, mpl::false_)
|
|
{
|
|
return RT(fusion::at_c<Index>(env.locals));
|
|
}
|
|
|
|
template <typename RT, int Index, typename Env>
|
|
static RT
|
|
get(Env const& env, mpl::true_)
|
|
{
|
|
static const int index_value = get_index<typename Env::outer_env_type::map_type, detail::local<Key> >::value;
|
|
|
|
return get<RT, index_value>(
|
|
env.outer_env
|
|
, mpl::bool_<index_value == -1>());
|
|
}
|
|
|
|
template <typename RT, int Index, typename Env>
|
|
static RT
|
|
get(Env const& env)
|
|
{
|
|
return get<RT, Index>(
|
|
env
|
|
, mpl::bool_<Index == -1>());
|
|
}
|
|
};
|
|
}
|
|
}}
|
|
|
|
#undef BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
|
|
#undef BOOST_PHOENIX_MAP_LOCAL_DISPATCH
|
|
|
|
#endif
|