1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file transform.hpp
3 /// A special-purpose proto1 compiler for applying a transformation to an
4 /// expression. The transformation is a proto1 lambda. The result of the
5 /// transformation is forwarded to the specified compiler, or to the
6 /// default compiler for the resulting expression is no compiler is
7 /// specified. Also included are some basic transforms, such as one that
8 /// extracts the operand of a unary op, the left and right operands of
9 /// a binary op, and a way to compose multiple transforms into one.
10 //
11 //  Copyright 2007 Eric Niebler. Distributed under the Boost
12 //  Software License, Version 1.0. (See accompanying file
13 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14 
15 #ifndef BOOST_PROTO_V1_COMPILER_TRANSFORM_HPP_EAN_04_01_2005
16 #define BOOST_PROTO_V1_COMPILER_TRANSFORM_HPP_EAN_04_01_2005
17 
18 #include <boost/xpressive/proto/v1_/proto_fwd.hpp>
19 #include <boost/xpressive/proto/v1_/arg_traits.hpp>
20 
21 namespace boost { namespace proto1
22 {
23 
24     ///////////////////////////////////////////////////////////////////////////////
25     // transform_compiler
26     //   accepts a transformation as a lambda, applies the transformation to any
27     //   parse tree passed in, and then compiles the result using the specified
28     //   compiler
29     template<typename Lambda, typename DomainTag, typename Compiler>
30     struct transform_compiler
31     {
32         template<typename Op, typename State, typename Visitor>
33         struct apply
34         {
35             typedef typename Compiler::BOOST_NESTED_TEMPLATE apply
36             <
37                 typename Lambda::BOOST_NESTED_TEMPLATE apply<Op, State, Visitor>::type
38               , State
39               , Visitor
40             >::type type;
41         };
42 
43         template<typename Op, typename State, typename Visitor>
44         static typename apply<Op, State, Visitor>::type
callboost::proto1::transform_compiler45         call(Op const &op, State const &state, Visitor &visitor)
46         {
47             return Compiler::call(Lambda::call(op, state, visitor), state, visitor);
48         }
49     };
50 
51     ///////////////////////////////////////////////////////////////////////////////
52     // if no compiler is specified, the transform_compiler forwards to the default
53     // compiler
54     template<typename Lambda, typename DomainTag>
55     struct transform_compiler<Lambda, DomainTag, void>
56     {
57         template<typename Op, typename State, typename Visitor>
58         struct apply
59         {
60             typedef typename Lambda::BOOST_NESTED_TEMPLATE apply
61             <
62                 Op
63               , State
64               , Visitor
65             >::type trans_type;
66 
67             typedef proto1::compiler<typename tag_type<trans_type>::type, DomainTag> compiler_type;
68 
69             typedef typename compiler_type::BOOST_NESTED_TEMPLATE apply
70             <
71                 trans_type
72               , State
73               , Visitor
74             >::type type;
75         };
76 
77         template<typename Op, typename State, typename Visitor>
78         static typename apply<Op, State, Visitor>::type
callboost::proto1::transform_compiler79         call(Op const &op, State const &state, Visitor &visitor)
80         {
81             return proto1::compile(Lambda::call(op, state, visitor), state, visitor, DomainTag());
82         }
83     };
84 
85     ///////////////////////////////////////////////////////////////////////////////
86     // identity_transform
87     //   pass through without doing a transform
88     struct identity_transform
89     {
90         template<typename Op, typename, typename>
91         struct apply
92         {
93             typedef Op type;
94         };
95 
96         template<typename Op, typename State, typename Visitor>
callboost::proto1::identity_transform97         static Op const &call(Op const &op, State const &, Visitor &)
98         {
99             return op;
100         }
101     };
102 
103     ///////////////////////////////////////////////////////////////////////////////
104     // arg_transform
105     struct arg_transform
106     {
107         template<typename Op, typename, typename>
108         struct apply
109         {
110             typedef typename arg_type<Op>::type type;
111         };
112 
113         template<typename Op, typename State, typename Visitor>
114         static typename arg_type<Op>::const_reference
callboost::proto1::arg_transform115         call(Op const &op, State const &, Visitor &)
116         {
117             return proto1::arg(op);
118         }
119     };
120 
121     ///////////////////////////////////////////////////////////////////////////////
122     // left_transform
123     struct left_transform
124     {
125         template<typename Op, typename, typename>
126         struct apply
127         {
128             typedef typename left_type<Op>::type type;
129         };
130 
131         template<typename Op, typename State, typename Visitor>
132         static typename left_type<Op>::const_reference
callboost::proto1::left_transform133         call(Op const &op, State const &, Visitor &)
134         {
135             return proto1::left(op);
136         }
137     };
138 
139     ///////////////////////////////////////////////////////////////////////////////
140     // right_transform
141     struct right_transform
142     {
143         template<typename Op, typename, typename>
144         struct apply
145         {
146             typedef typename right_type<Op>::type type;
147         };
148 
149         template<typename Op, typename State, typename Visitor>
150         static typename right_type<Op>::const_reference
callboost::proto1::right_transform151         call(Op const &op, State const &, Visitor &)
152         {
153             return proto1::right(op);
154         }
155     };
156 
157     ///////////////////////////////////////////////////////////////////////////////
158     // unary_op_transform
159     //   insert a unary operation
160     template<typename Tag>
161     struct unary_op_transform
162     {
163         template<typename Op, typename, typename>
164         struct apply
165         {
166             typedef unary_op<Op, Tag> type;
167         };
168 
169         template<typename Op, typename State, typename Visitor>
170         static unary_op<Op, Tag>
callboost::proto1::unary_op_transform171         call(Op const &op, State const &, Visitor &)
172         {
173             return proto1::make_op<Tag>(op);
174         }
175     };
176 
177     ///////////////////////////////////////////////////////////////////////////////
178     // compose_transforms
179     //   execute two transforms in succession
180     template<typename First, typename Second>
181     struct compose_transforms
182     {
183         template<typename Op, typename State, typename Visitor>
184         struct apply
185         {
186             typedef typename Second::BOOST_NESTED_TEMPLATE apply
187             <
188                 typename First::BOOST_NESTED_TEMPLATE apply<Op, State, Visitor>::type
189               , State
190               , Visitor
191             >::type type;
192         };
193 
194         template<typename Op, typename State, typename Visitor>
195         static typename apply<Op, State, Visitor>::type
callboost::proto1::compose_transforms196         call(Op const &op, State const &state, Visitor &visitor)
197         {
198             return Second::call(First::call(op, state, visitor), state, visitor);
199         }
200     };
201 
202     ///////////////////////////////////////////////////////////////////////////////
203     // conditional_transform
204     //   Conditionally execute a transform
205     template<typename Predicate, typename IfTransform, typename ElseTransform>
206     struct conditional_transform
207     {
208         template<typename Op, typename State, typename Visitor>
209         struct apply
210         {
211             typedef typename boost::mpl::if_
212             <
213                 typename Predicate::BOOST_NESTED_TEMPLATE apply<Op, State, Visitor>::type
214               , IfTransform
215               , ElseTransform
216             >::type transform_type;
217 
218             typedef typename transform_type::BOOST_NESTED_TEMPLATE apply
219             <
220                 Op
221               , State
222               , Visitor
223             >::type type;
224         };
225 
226         template<typename Op, typename State, typename Visitor>
227         static typename apply<Op, State, Visitor>::type
callboost::proto1::conditional_transform228         call(Op const &op, State const &state, Visitor &visitor)
229         {
230             return apply<Op, State, Visitor>::transform_type::call(op, state, visitor);
231         }
232     };
233 
234     template<typename Always>
235     struct always_transform
236     {
237         template<typename, typename, typename>
238         struct apply
239         {
240             typedef Always type;
241         };
242 
243         template<typename Op, typename State, typename Visitor>
244         static Always
callboost::proto1::always_transform245         call(Op const &, State const &, Visitor &)
246         {
247             return Always();
248         }
249     };
250 
251 }}
252 
253 #endif
254