Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2007 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2004 Daniel Wallin
|
Chris@16
|
4
|
Chris@16
|
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 ==============================================================================*/
|
Chris@16
|
8 #ifndef PHOENIX_SCOPE_DYNAMIC_HPP
|
Chris@16
|
9 #define PHOENIX_SCOPE_DYNAMIC_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/spirit/home/phoenix/core/limits.hpp>
|
Chris@16
|
12 #include <boost/fusion/include/at.hpp>
|
Chris@16
|
13 #include <boost/fusion/include/vector.hpp>
|
Chris@16
|
14 #include <boost/spirit/home/phoenix/core/actor.hpp>
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/preprocessor/cat.hpp>
|
Chris@16
|
17 #include <boost/preprocessor/punctuation/comma_if.hpp>
|
Chris@16
|
18 #include <boost/preprocessor/seq/for_each_i.hpp>
|
Chris@16
|
19 #include <boost/preprocessor/tuple/elem.hpp>
|
Chris@16
|
20 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
|
Chris@16
|
21 #include <boost/preprocessor/repetition/enum_params.hpp>
|
Chris@16
|
22 #include <boost/preprocessor/cat.hpp>
|
Chris@16
|
23 #include <boost/preprocessor/inc.hpp>
|
Chris@16
|
24
|
Chris@16
|
25 #include <boost/noncopyable.hpp>
|
Chris@16
|
26 #include <boost/assert.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #define PHOENIX_DYNAMIC_MEMBER(z, n, data) \
|
Chris@16
|
29 typedef actor<dynamic_member<n, self_type> > \
|
Chris@16
|
30 BOOST_PP_CAT(member, BOOST_PP_INC(n));
|
Chris@16
|
31
|
Chris@16
|
32 namespace boost { namespace phoenix
|
Chris@16
|
33 {
|
Chris@16
|
34 template <typename DynamicScope>
|
Chris@16
|
35 struct dynamic_frame : noncopyable
|
Chris@16
|
36 {
|
Chris@16
|
37 typedef typename DynamicScope::tuple_type tuple_type;
|
Chris@16
|
38
|
Chris@16
|
39 dynamic_frame(DynamicScope const& scope)
|
Chris@16
|
40 : tuple()
|
Chris@16
|
41 , save(scope.frame)
|
Chris@16
|
42 , scope(scope)
|
Chris@16
|
43 {
|
Chris@16
|
44 scope.frame = this;
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 template <typename Tuple>
|
Chris@16
|
48 dynamic_frame(DynamicScope const& scope, Tuple const& init)
|
Chris@16
|
49 : tuple(init)
|
Chris@16
|
50 , save(scope.frame)
|
Chris@16
|
51 , scope(scope)
|
Chris@16
|
52 {
|
Chris@16
|
53 scope.frame = this;
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 ~dynamic_frame()
|
Chris@16
|
57 {
|
Chris@16
|
58 scope.frame = save;
|
Chris@16
|
59 }
|
Chris@16
|
60
|
Chris@16
|
61 tuple_type& data() { return tuple; }
|
Chris@16
|
62 tuple_type const& data() const { return tuple; }
|
Chris@16
|
63
|
Chris@16
|
64 private:
|
Chris@16
|
65
|
Chris@16
|
66 tuple_type tuple;
|
Chris@16
|
67 dynamic_frame* save;
|
Chris@16
|
68 DynamicScope const& scope;
|
Chris@16
|
69 };
|
Chris@16
|
70
|
Chris@16
|
71 template <int N, typename DynamicScope>
|
Chris@16
|
72 struct dynamic_member
|
Chris@16
|
73 {
|
Chris@16
|
74 typedef mpl::false_ no_nullary;
|
Chris@16
|
75 typedef typename DynamicScope::tuple_type tuple_type;
|
Chris@16
|
76
|
Chris@16
|
77 dynamic_member(DynamicScope const& scope)
|
Chris@16
|
78 : scope(scope) {}
|
Chris@16
|
79
|
Chris@16
|
80 template <typename Env>
|
Chris@16
|
81 struct result
|
Chris@16
|
82 {
|
Chris@16
|
83 typedef typename
|
Chris@16
|
84 fusion::result_of::at_c<tuple_type, N>::type
|
Chris@16
|
85 type;
|
Chris@16
|
86 };
|
Chris@16
|
87
|
Chris@16
|
88 template <typename Env>
|
Chris@16
|
89 typename result<Env>::type
|
Chris@16
|
90 eval(Env const& /*env*/) const
|
Chris@16
|
91 {
|
Chris@16
|
92 BOOST_ASSERT(scope.frame != 0);
|
Chris@16
|
93 return fusion::at_c<N>(scope.frame->data());
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 private:
|
Chris@16
|
97
|
Chris@16
|
98 DynamicScope const& scope;
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101 template <BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(PHOENIX_DYNAMIC_LIMIT, typename T, void_)>
|
Chris@16
|
102 struct dynamic : noncopyable
|
Chris@16
|
103 {
|
Chris@16
|
104 typedef fusion::vector<BOOST_PP_ENUM_PARAMS(PHOENIX_DYNAMIC_LIMIT, T)> tuple_type;
|
Chris@16
|
105 typedef dynamic<BOOST_PP_ENUM_PARAMS(PHOENIX_DYNAMIC_LIMIT, T)> self_type;
|
Chris@16
|
106 typedef dynamic_frame<self_type> dynamic_frame_type;
|
Chris@16
|
107
|
Chris@16
|
108 dynamic()
|
Chris@16
|
109 : frame(0) {}
|
Chris@16
|
110
|
Chris@16
|
111 BOOST_PP_REPEAT(PHOENIX_DYNAMIC_LIMIT, PHOENIX_DYNAMIC_MEMBER, _)
|
Chris@16
|
112
|
Chris@16
|
113 private:
|
Chris@16
|
114
|
Chris@16
|
115 template <int N, typename DynamicScope>
|
Chris@16
|
116 friend struct dynamic_member;
|
Chris@16
|
117
|
Chris@16
|
118 template <typename DynamicScope>
|
Chris@16
|
119 friend struct dynamic_frame;
|
Chris@16
|
120
|
Chris@16
|
121 mutable dynamic_frame_type* frame;
|
Chris@16
|
122 };
|
Chris@16
|
123 }}
|
Chris@16
|
124
|
Chris@16
|
125 #if defined(BOOST_MSVC)
|
Chris@16
|
126 # pragma warning(push)
|
Chris@16
|
127 # pragma warning(disable:4355)
|
Chris@16
|
128 #endif
|
Chris@16
|
129
|
Chris@16
|
130 /*
|
Chris@16
|
131 PHOENIX_DYNAMIC macro(name, type-name sequence)
|
Chris@16
|
132 Example:
|
Chris@16
|
133
|
Chris@16
|
134 PHOENIX_DYNAMIC(
|
Chris@16
|
135 my_dynamic,
|
Chris@16
|
136 (int, num)
|
Chris@16
|
137 (std::string, message)
|
Chris@16
|
138 (double, real)
|
Chris@16
|
139 );
|
Chris@16
|
140
|
Chris@16
|
141 which expands to:
|
Chris@16
|
142
|
Chris@16
|
143 struct my_dynamic : ::boost::phoenix::dynamic<int, std::string, double>
|
Chris@16
|
144 {
|
Chris@16
|
145 my_dynamic() : num(*this), message(*this), real(*this) {}
|
Chris@16
|
146
|
Chris@16
|
147 member1 num;
|
Chris@16
|
148 member2 message;
|
Chris@16
|
149 member3 real;
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 PHOENIX_DYNAMIC takes the input (containing a binary sequence)
|
Chris@16
|
153 and converts that sequence to a unary sequence of
|
Chris@16
|
154 binary tuples and passes it on to PHOENIX_DYNAMIC_I.
|
Chris@16
|
155
|
Chris@16
|
156 Thanks to Paul Mensonides for the PP macro help
|
Chris@16
|
157 */
|
Chris@16
|
158
|
Chris@16
|
159 #define PHOENIX_DYNAMIC(name, bseq) \
|
Chris@16
|
160 PHOENIX_DYNAMIC_I(name, BOOST_PP_CAT(PHOENIX_DYNAMIC_X bseq, 0)) \
|
Chris@16
|
161
|
Chris@16
|
162 #define PHOENIX_DYNAMIC_X(x, y) ((x, y)) PHOENIX_DYNAMIC_Y
|
Chris@16
|
163 #define PHOENIX_DYNAMIC_Y(x, y) ((x, y)) PHOENIX_DYNAMIC_X
|
Chris@16
|
164 #define PHOENIX_DYNAMIC_X0
|
Chris@16
|
165 #define PHOENIX_DYNAMIC_Y0
|
Chris@16
|
166
|
Chris@16
|
167 // PHOENIX_DYNAMIC_I generates the overarching structure and uses
|
Chris@16
|
168 // SEQ_FOR_EACH_I to generate the "linear" substructures.
|
Chris@16
|
169
|
Chris@16
|
170 #define PHOENIX_DYNAMIC_I(name, seq) \
|
Chris@16
|
171 struct name : \
|
Chris@16
|
172 ::boost::phoenix::dynamic< \
|
Chris@16
|
173 BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_A, ~, seq)> { \
|
Chris@16
|
174 name() : BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_B, ~, seq) {} \
|
Chris@16
|
175 BOOST_PP_SEQ_FOR_EACH_I(PHOENIX_DYNAMIC_C, ~, seq) \
|
Chris@16
|
176 } \
|
Chris@16
|
177
|
Chris@16
|
178 #define PHOENIX_DYNAMIC_A(r, _, i, xy) \
|
Chris@16
|
179 BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 0, xy) \
|
Chris@16
|
180
|
Chris@16
|
181 #define PHOENIX_DYNAMIC_B(r, _, i, xy) \
|
Chris@16
|
182 BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, xy)(*this) \
|
Chris@16
|
183
|
Chris@16
|
184 #define PHOENIX_DYNAMIC_C(r, _, i, xy) \
|
Chris@16
|
185 BOOST_PP_CAT(member, BOOST_PP_INC(i)) BOOST_PP_TUPLE_ELEM(2, 1, xy); \
|
Chris@16
|
186
|
Chris@16
|
187 #undef PHOENIX_DYNAMIC_MEMBER
|
Chris@16
|
188
|
Chris@16
|
189 #if defined(BOOST_MSVC)
|
Chris@16
|
190 # pragma warning(pop)
|
Chris@16
|
191 #endif
|
Chris@16
|
192
|
Chris@16
|
193 #endif
|