/*============================================================================= Copyright (c) 2001-2007 Joel de Guzman Copyright (c) 2004 Daniel Wallin 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 #include #include #include #include #include #include #include #include #include #include #include #include #define PHOENIX_MAP_LOCAL_TEMPLATE_PARAM(z, n, data) \ typename T##n = unused #define PHOENIX_MAP_LOCAL_DISPATCH(z, n, data) \ typedef char(&result##n)[n+2]; \ static result##n get(T##n*); namespace boost { namespace phoenix { template struct scoped_environment; namespace detail { template struct initialize_local { template struct result; template struct result { typedef typename remove_reference::type actor_type; typedef typename actor_type::template result::type type; }; initialize_local(Env const& env) : env(env) {} template typename result::type operator()(Actor const& actor) const { return actor.eval(env); } Env const& env; private: // silence MSVC warning C4512: assignment operator could not be generated initialize_local& operator= (initialize_local const&); }; template struct is_scoped_environment : mpl::false_ {}; template struct is_scoped_environment > : mpl::true_ {}; template struct unused; template struct map_local_index_to_tuple { typedef char(¬_found)[1]; static not_found get(...); BOOST_PP_REPEAT(PHOENIX_LOCAL_LIMIT, PHOENIX_MAP_LOCAL_DISPATCH, _) }; template T* generate_pointer(); template struct get_index { BOOST_STATIC_CONSTANT(int, value = ( static_cast((sizeof(Map::get(generate_pointer()))) / sizeof(char)) - 2 )); // if value == -1, Tag is not found typedef mpl::int_ type; }; template struct apply_local; template struct outer_local { typedef typename apply_local::type type; }; template struct get_local_or_void { typedef typename mpl::eval_if< mpl::less > , fusion::result_of::at , mpl::identity >::type type; }; template struct get_local_from_index { typedef typename mpl::eval_if< mpl::equal_to > , outer_local , get_local_or_void >::type type; }; template struct get_local { typedef typename get_index< typename Env::map_type, typename Local::key_type>::type index_type; typedef typename get_local_from_index::type type; }; template struct apply_local { // $$$ TODO: static assert that Env is a scoped_environment $$$ typedef typename get_local::type type; }; template struct eval_local { template static RT get(Env const& env, Index, mpl::false_) { return RT(fusion::at(env.locals)); } template static RT get(Env const& env, Index index, mpl::true_) { typedef typename get_index::type index_type; return get( env.outer_env , index_type() , mpl::equal_to >()); } template static RT get(Env const& env, Index index) { return get( env , index , mpl::equal_to >()); } }; } }} #undef PHOENIX_MAP_LOCAL_TEMPLATE_PARAM #undef PHOENIX_MAP_LOCAL_DISPATCH #endif