Chris@16: /*============================================================================= Chris@16: Copyright (c) 2001-2007 Joel de Guzman Chris@16: Copyright (c) 2004 Daniel Wallin Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ==============================================================================*/ Chris@16: #ifndef PHOENIX_SCOPE_DYNAMIC_HPP Chris@16: #define PHOENIX_SCOPE_DYNAMIC_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #define PHOENIX_DYNAMIC_MEMBER(z, n, data) \ Chris@16: typedef actor > \ Chris@16: BOOST_PP_CAT(member, BOOST_PP_INC(n)); Chris@16: Chris@16: namespace boost { namespace phoenix Chris@16: { Chris@16: template Chris@16: struct dynamic_frame : noncopyable Chris@16: { Chris@16: typedef typename DynamicScope::tuple_type tuple_type; Chris@16: Chris@16: dynamic_frame(DynamicScope const& scope) Chris@16: : tuple() Chris@16: , save(scope.frame) Chris@16: , scope(scope) Chris@16: { Chris@16: scope.frame = this; Chris@16: } Chris@16: Chris@16: template Chris@16: dynamic_frame(DynamicScope const& scope, Tuple const& init) Chris@16: : tuple(init) Chris@16: , save(scope.frame) Chris@16: , scope(scope) Chris@16: { Chris@16: scope.frame = this; Chris@16: } Chris@16: Chris@16: ~dynamic_frame() Chris@16: { Chris@16: scope.frame = save; Chris@16: } Chris@16: Chris@16: tuple_type& data() { return tuple; } Chris@16: tuple_type const& data() const { return tuple; } Chris@16: Chris@16: private: Chris@16: Chris@16: tuple_type tuple; Chris@16: dynamic_frame* save; Chris@16: DynamicScope const& scope; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct dynamic_member Chris@16: { Chris@16: typedef mpl::false_ no_nullary; Chris@16: typedef typename DynamicScope::tuple_type tuple_type; Chris@16: Chris@16: dynamic_member(DynamicScope const& scope) Chris@16: : scope(scope) {} Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Chris@16: fusion::result_of::at_c::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: template Chris@16: typename result::type Chris@16: eval(Env const& /*env*/) const Chris@16: { Chris@16: BOOST_ASSERT(scope.frame != 0); Chris@16: return fusion::at_c(scope.frame->data()); Chris@16: } Chris@16: Chris@16: private: Chris@16: Chris@16: DynamicScope const& scope; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct dynamic : noncopyable Chris@16: { Chris@16: typedef fusion::vector tuple_type; Chris@16: typedef dynamic self_type; Chris@16: typedef dynamic_frame dynamic_frame_type; Chris@16: Chris@16: dynamic() Chris@16: : frame(0) {} Chris@16: Chris@16: BOOST_PP_REPEAT(PHOENIX_DYNAMIC_LIMIT, PHOENIX_DYNAMIC_MEMBER, _) Chris@16: Chris@16: private: Chris@16: Chris@16: template Chris@16: friend struct dynamic_member; Chris@16: Chris@16: template Chris@16: friend struct dynamic_frame; Chris@16: Chris@16: mutable dynamic_frame_type* frame; Chris@16: }; Chris@16: }} Chris@16: Chris@16: #if defined(BOOST_MSVC) Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable:4355) Chris@16: #endif Chris@16: Chris@16: /* Chris@16: PHOENIX_DYNAMIC macro(name, type-name sequence) Chris@16: Example: Chris@16: Chris@16: PHOENIX_DYNAMIC( Chris@16: my_dynamic, Chris@16: (int, num) Chris@16: (std::string, message) Chris@16: (double, real) Chris@16: ); Chris@16: Chris@16: which expands to: Chris@16: Chris@16: struct my_dynamic : ::boost::phoenix::dynamic Chris@16: { Chris@16: my_dynamic() : num(*this), message(*this), real(*this) {} Chris@16: Chris@16: member1 num; Chris@16: member2 message; Chris@16: member3 real; Chris@16: }; Chris@16: Chris@16: PHOENIX_DYNAMIC takes the input (containing a binary sequence) Chris@16: and converts that sequence to a unary sequence of Chris@16: binary tuples and passes it on to PHOENIX_DYNAMIC_I. Chris@16: Chris@16: Thanks to Paul Mensonides for the PP macro help Chris@16: */ Chris@16: Chris@16: #define PHOENIX_DYNAMIC(name, bseq) \ Chris@16: PHOENIX_DYNAMIC_I(name, BOOST_PP_CAT(PHOENIX_DYNAMIC_X bseq, 0)) \ Chris@16: Chris@16: #define PHOENIX_DYNAMIC_X(x, y) ((x, y)) PHOENIX_DYNAMIC_Y Chris@16: #define PHOENIX_DYNAMIC_Y(x, y) ((x, y)) PHOENIX_DYNAMIC_X Chris@16: #define PHOENIX_DYNAMIC_X0 Chris@16: #define PHOENIX_DYNAMIC_Y0 Chris@16: Chris@16: // PHOENIX_DYNAMIC_I generates the overarching structure and uses Chris@16: // SEQ_FOR_EACH_I to generate the "linear" substructures. Chris@16: Chris@16: #define PHOENIX_DYNAMIC_I(name, seq) \ Chris@16: struct name : \ Chris@16: ::boost::phoenix::dynamic< \ Chris@16: BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_A, ~, seq)> { \ Chris@16: name() : BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_B, ~, seq) {} \ Chris@16: BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_C, ~, seq) \ Chris@16: } \ Chris@16: Chris@16: #define PHOENIX_DYNAMIC_A(r, _, i, xy) \ Chris@16: BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 0, xy) \ Chris@16: Chris@16: #define PHOENIX_DYNAMIC_B(r, _, i, xy) \ Chris@16: BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, xy)(*this) \ Chris@16: Chris@16: #define PHOENIX_DYNAMIC_C(r, _, i, xy) \ Chris@16: BOOST_PP_CAT(member, BOOST_PP_INC(i)) BOOST_PP_TUPLE_ELEM(2, 1, xy); \ Chris@16: Chris@16: #undef PHOENIX_DYNAMIC_MEMBER Chris@16: Chris@16: #if defined(BOOST_MSVC) Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif