You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
232 lines
8.3 KiB
232 lines
8.3 KiB
/*============================================================================= |
|
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
|
|
|