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