local_variable.hpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*=============================================================================
  2. Copyright (c) 2001-2007 Joel de Guzman
  3. Copyright (c) 2004 Daniel Wallin
  4. Copyright (c) 2011 Thomas Heller
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #ifndef PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
  9. #define PHOENIX_SCOPE_DETAIL_LOCAL_VARIABLE_HPP
  10. #include <boost/mpl/int.hpp>
  11. #include <boost/mpl/bool.hpp>
  12. #include <boost/mpl/eval_if.hpp>
  13. #include <boost/mpl/identity.hpp>
  14. #include <boost/fusion/include/at.hpp>
  15. #include <boost/fusion/include/value_at.hpp>
  16. #include <boost/preprocessor/enum.hpp>
  17. #include <boost/preprocessor/repeat.hpp>
  18. #include <boost/type_traits/remove_reference.hpp>
  19. #include <boost/type_traits/is_reference.hpp>
  20. #define BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM(z, n, data) \
  21. typename T##n = unused<n>
  22. #define BOOST_PHOENIX_MAP_LOCAL_DISPATCH(z, n, data) \
  23. typedef char(&result##n)[n+2]; \
  24. static result##n get(T##n*);
  25. namespace boost { namespace phoenix
  26. {
  27. template <typename Env, typename OuterEnv, typename Locals, typename Map>
  28. struct scoped_environment;
  29. namespace detail
  30. {
  31. template <typename Key>
  32. struct local
  33. {
  34. typedef Key key_type;
  35. };
  36. namespace result_of
  37. {
  38. template <typename Locals, typename Context>
  39. struct initialize_locals;
  40. template <typename Context>
  41. struct initialize_locals<vector0<>, Context>
  42. {
  43. typedef vector0<> type;
  44. };
  45. #define M1(Z, N, D) \
  46. typename boost::phoenix::result_of::eval< \
  47. BOOST_PP_CAT(A, N) \
  48. , Context \
  49. >::type \
  50. /**/
  51. #define M0(Z, N, D) \
  52. template <BOOST_PHOENIX_typename_A(N), typename Context> \
  53. struct initialize_locals< \
  54. BOOST_PP_CAT(vector, N)< \
  55. BOOST_PHOENIX_A(N) \
  56. > \
  57. , Context \
  58. > \
  59. { \
  60. typedef \
  61. BOOST_PP_CAT(vector, N)< \
  62. BOOST_PP_ENUM(N, M1, _) \
  63. > \
  64. type; \
  65. }; \
  66. /**/
  67. BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
  68. #undef M0
  69. }
  70. template <typename Context>
  71. vector0<>
  72. initialize_locals(vector0<> const &, Context const &)
  73. {
  74. vector0<> vars;
  75. return vars;
  76. }
  77. #define M2(Z, N, D) \
  78. eval(locals. BOOST_PP_CAT(a, N), ctx) \
  79. /**/
  80. #define M0(Z, N, D) \
  81. template <BOOST_PHOENIX_typename_A(N), typename Context> \
  82. BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> \
  83. initialize_locals( \
  84. BOOST_PP_CAT(vector, N)<BOOST_PHOENIX_A(N)> const & locals \
  85. , Context const & ctx \
  86. ) \
  87. { \
  88. BOOST_PP_CAT(vector, N)<BOOST_PP_ENUM(N, M1, _)> vars \
  89. = {BOOST_PP_ENUM(N, M2, _)}; \
  90. return vars; \
  91. } \
  92. /**/
  93. BOOST_PP_REPEAT_FROM_TO(1, BOOST_PHOENIX_LIMIT, M0, _)
  94. #undef M0
  95. #undef M1
  96. #undef M2
  97. template <int N>
  98. struct unused;
  99. template <
  100. BOOST_PP_ENUM(
  101. BOOST_PHOENIX_LOCAL_LIMIT
  102. , BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
  103. , _
  104. )
  105. >
  106. struct map_local_index_to_tuple
  107. {
  108. typedef char(&not_found)[1];
  109. static not_found get(...);
  110. BOOST_PP_REPEAT(BOOST_PHOENIX_LOCAL_LIMIT, BOOST_PHOENIX_MAP_LOCAL_DISPATCH, _)
  111. };
  112. template<typename T>
  113. T* generate_pointer();
  114. template <typename Map, typename Tag>
  115. struct get_index
  116. {
  117. BOOST_STATIC_CONSTANT(int,
  118. value = (
  119. static_cast<int>((sizeof(Map::get(generate_pointer<Tag>()))) / sizeof(char)) - 2
  120. ));
  121. // if value == -1, Tag is not found
  122. typedef mpl::int_<value> type;
  123. };
  124. template <typename Local, typename Env>
  125. struct apply_local;
  126. template <typename Local, typename Env>
  127. struct outer_local
  128. {
  129. typedef typename
  130. apply_local<Local, typename Env::outer_env_type>::type
  131. type;
  132. };
  133. template <typename Locals, int Index>
  134. struct get_local_or_void
  135. {
  136. typedef typename
  137. mpl::eval_if_c<
  138. Index < Locals::size_value
  139. , fusion::result_of::at_c<Locals, Index>
  140. , mpl::identity<fusion::void_>
  141. >::type
  142. type;
  143. };
  144. template <typename Local, typename Env, int Index>
  145. struct get_local_from_index
  146. {
  147. typedef typename
  148. mpl::eval_if_c<
  149. Index == -1
  150. , outer_local<Local, Env>
  151. , get_local_or_void<typename Env::locals_type, Index>
  152. >::type
  153. type;
  154. };
  155. template <typename Local, typename Env>
  156. struct get_local
  157. {
  158. static const int index_value = get_index<typename Env::map_type, Local>::value;
  159. typedef typename
  160. get_local_from_index<Local, Env, index_value>::type
  161. type;
  162. };
  163. template <typename Local, typename Env>
  164. struct apply_local
  165. {
  166. // $$$ TODO: static assert that Env is a scoped_environment $$$
  167. typedef typename get_local<Local, Env>::type type;
  168. };
  169. template <typename Key>
  170. struct eval_local
  171. {
  172. template <typename RT, int Index, typename Env>
  173. static RT
  174. get(Env const& env, mpl::false_)
  175. {
  176. return RT(fusion::at_c<Index>(env.locals));
  177. }
  178. template <typename RT, int Index, typename Env>
  179. static RT
  180. get(Env const& env, mpl::true_)
  181. {
  182. static const int index_value = get_index<typename Env::outer_env_type::map_type, detail::local<Key> >::value;
  183. return get<RT, index_value>(
  184. env.outer_env
  185. , mpl::bool_<index_value == -1>());
  186. }
  187. template <typename RT, int Index, typename Env>
  188. static RT
  189. get(Env const& env)
  190. {
  191. return get<RT, Index>(
  192. env
  193. , mpl::bool_<Index == -1>());
  194. }
  195. };
  196. }
  197. }}
  198. #undef BOOST_PHOENIX_MAP_LOCAL_TEMPLATE_PARAM
  199. #undef BOOST_PHOENIX_MAP_LOCAL_DISPATCH
  200. #endif