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