File indexing completed on 2025-01-18 09:50:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_PROTO_CONTEXT_DEFAULT_HPP_EAN_01_08_2007
0012 #define BOOST_PROTO_CONTEXT_DEFAULT_HPP_EAN_01_08_2007
0013
0014 #include <boost/config.hpp>
0015 #include <boost/preprocessor/arithmetic/add.hpp>
0016 #include <boost/preprocessor/arithmetic/sub.hpp>
0017 #include <boost/preprocessor/iteration/iterate.hpp>
0018 #include <boost/preprocessor/repetition/enum.hpp>
0019 #include <boost/preprocessor/repetition/enum_shifted.hpp>
0020 #include <boost/utility/result_of.hpp>
0021 #include <boost/type_traits/is_const.hpp>
0022 #include <boost/type_traits/is_function.hpp>
0023 #include <boost/type_traits/remove_reference.hpp>
0024 #include <boost/type_traits/is_member_pointer.hpp>
0025 #include <boost/type_traits/is_member_object_pointer.hpp>
0026 #include <boost/type_traits/is_member_function_pointer.hpp>
0027 #include <boost/proto/proto_fwd.hpp>
0028 #include <boost/proto/tags.hpp>
0029 #include <boost/proto/eval.hpp>
0030 #include <boost/proto/traits.hpp> // for proto::child_c()
0031 #include <boost/proto/detail/decltype.hpp>
0032
0033 namespace boost { namespace proto
0034 {
0035
0036
0037 #define UNREF(x) typename boost::remove_reference<x>::type
0038
0039 namespace context
0040 {
0041 template<
0042 typename Expr
0043 , typename Context
0044 , typename Tag
0045 , long Arity
0046 >
0047 struct default_eval
0048 {};
0049
0050 template<typename Expr, typename Context>
0051 struct default_eval<Expr, Context, tag::terminal, 0>
0052 {
0053 typedef
0054 typename proto::result_of::value<Expr &>::type
0055 result_type;
0056
0057 result_type operator ()(Expr &expr, Context &) const
0058 {
0059 return proto::value(expr);
0060 }
0061 };
0062
0063
0064
0065 #define BOOST_PROTO_UNARY_DEFAULT_EVAL(OP, TAG, MAKE) \
0066 template<typename Expr, typename Context> \
0067 struct default_eval<Expr, Context, TAG, 1> \
0068 { \
0069 private: \
0070 typedef typename proto::result_of::child_c<Expr, 0>::type e0; \
0071 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; \
0072 public: \
0073 BOOST_PROTO_DECLTYPE_(OP proto::detail::MAKE<r0>(), result_type) \
0074 result_type operator ()(Expr &expr, Context &ctx) const \
0075 { \
0076 return OP proto::eval(proto::child_c<0>(expr), ctx); \
0077 } \
0078 }; \
0079
0080
0081
0082
0083 #define BOOST_PROTO_BINARY_DEFAULT_EVAL(OP, TAG, LMAKE, RMAKE) \
0084 template<typename Expr, typename Context> \
0085 struct default_eval<Expr, Context, TAG, 2> \
0086 { \
0087 private: \
0088 typedef typename proto::result_of::child_c<Expr, 0>::type e0; \
0089 typedef typename proto::result_of::child_c<Expr, 1>::type e1; \
0090 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0; \
0091 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1; \
0092 public: \
0093 BOOST_PROTO_DECLTYPE_( \
0094 proto::detail::LMAKE<r0>() OP proto::detail::RMAKE<r1>() \
0095 , result_type \
0096 ) \
0097 result_type operator ()(Expr &expr, Context &ctx) const \
0098 { \
0099 return proto::eval( \
0100 proto::child_c<0>(expr), ctx) OP proto::eval(proto::child_c<1>(expr) \
0101 , ctx \
0102 ); \
0103 } \
0104 }; \
0105
0106
0107 BOOST_PROTO_UNARY_DEFAULT_EVAL(+, proto::tag::unary_plus, make)
0108 BOOST_PROTO_UNARY_DEFAULT_EVAL(-, proto::tag::negate, make)
0109 BOOST_PROTO_UNARY_DEFAULT_EVAL(*, proto::tag::dereference, make)
0110 BOOST_PROTO_UNARY_DEFAULT_EVAL(~, proto::tag::complement, make)
0111 BOOST_PROTO_UNARY_DEFAULT_EVAL(&, proto::tag::address_of, make)
0112 BOOST_PROTO_UNARY_DEFAULT_EVAL(!, proto::tag::logical_not, make)
0113 BOOST_PROTO_UNARY_DEFAULT_EVAL(++, proto::tag::pre_inc, make_mutable)
0114 BOOST_PROTO_UNARY_DEFAULT_EVAL(--, proto::tag::pre_dec, make_mutable)
0115
0116 BOOST_PROTO_BINARY_DEFAULT_EVAL(<<, proto::tag::shift_left, make_mutable, make)
0117 BOOST_PROTO_BINARY_DEFAULT_EVAL(>>, proto::tag::shift_right, make_mutable, make)
0118 BOOST_PROTO_BINARY_DEFAULT_EVAL(*, proto::tag::multiplies, make, make)
0119 BOOST_PROTO_BINARY_DEFAULT_EVAL(/, proto::tag::divides, make, make)
0120 BOOST_PROTO_BINARY_DEFAULT_EVAL(%, proto::tag::modulus, make, make)
0121 BOOST_PROTO_BINARY_DEFAULT_EVAL(+, proto::tag::plus, make, make)
0122 BOOST_PROTO_BINARY_DEFAULT_EVAL(-, proto::tag::minus, make, make)
0123 BOOST_PROTO_BINARY_DEFAULT_EVAL(<, proto::tag::less, make, make)
0124 BOOST_PROTO_BINARY_DEFAULT_EVAL(>, proto::tag::greater, make, make)
0125 BOOST_PROTO_BINARY_DEFAULT_EVAL(<=, proto::tag::less_equal, make, make)
0126 BOOST_PROTO_BINARY_DEFAULT_EVAL(>=, proto::tag::greater_equal, make, make)
0127 BOOST_PROTO_BINARY_DEFAULT_EVAL(==, proto::tag::equal_to, make, make)
0128 BOOST_PROTO_BINARY_DEFAULT_EVAL(!=, proto::tag::not_equal_to, make, make)
0129 BOOST_PROTO_BINARY_DEFAULT_EVAL(||, proto::tag::logical_or, make, make)
0130 BOOST_PROTO_BINARY_DEFAULT_EVAL(&&, proto::tag::logical_and, make, make)
0131 BOOST_PROTO_BINARY_DEFAULT_EVAL(&, proto::tag::bitwise_and, make, make)
0132 BOOST_PROTO_BINARY_DEFAULT_EVAL(|, proto::tag::bitwise_or, make, make)
0133 BOOST_PROTO_BINARY_DEFAULT_EVAL(^, proto::tag::bitwise_xor, make, make)
0134
0135 BOOST_PROTO_BINARY_DEFAULT_EVAL(=, proto::tag::assign, make_mutable, make)
0136 BOOST_PROTO_BINARY_DEFAULT_EVAL(<<=, proto::tag::shift_left_assign, make_mutable, make)
0137 BOOST_PROTO_BINARY_DEFAULT_EVAL(>>=, proto::tag::shift_right_assign, make_mutable, make)
0138 BOOST_PROTO_BINARY_DEFAULT_EVAL(*=, proto::tag::multiplies_assign, make_mutable, make)
0139 BOOST_PROTO_BINARY_DEFAULT_EVAL(/=, proto::tag::divides_assign, make_mutable, make)
0140 BOOST_PROTO_BINARY_DEFAULT_EVAL(%=, proto::tag::modulus_assign, make_mutable, make)
0141 BOOST_PROTO_BINARY_DEFAULT_EVAL(+=, proto::tag::plus_assign, make_mutable, make)
0142 BOOST_PROTO_BINARY_DEFAULT_EVAL(-=, proto::tag::minus_assign, make_mutable, make)
0143 BOOST_PROTO_BINARY_DEFAULT_EVAL(&=, proto::tag::bitwise_and_assign, make_mutable, make)
0144 BOOST_PROTO_BINARY_DEFAULT_EVAL(|=, proto::tag::bitwise_or_assign, make_mutable, make)
0145 BOOST_PROTO_BINARY_DEFAULT_EVAL(^=, proto::tag::bitwise_xor_assign, make_mutable, make)
0146
0147 #undef BOOST_PROTO_UNARY_DEFAULT_EVAL
0148 #undef BOOST_PROTO_BINARY_DEFAULT_EVAL
0149
0150
0151 template<typename Expr, typename Context>
0152 struct is_member_function_eval
0153 : is_member_function_pointer<
0154 typename detail::uncvref<
0155 typename proto::result_of::eval<
0156 typename remove_reference<
0157 typename proto::result_of::child_c<Expr, 1>::type
0158 >::type
0159 , Context
0160 >::type
0161 >::type
0162 >
0163 {};
0164
0165
0166 template<typename Expr, typename Context, bool IsMemFunCall>
0167 struct memfun_eval
0168 {
0169 private:
0170 typedef typename result_of::child_c<Expr, 0>::type e0;
0171 typedef typename result_of::child_c<Expr, 1>::type e1;
0172 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0173 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0174 public:
0175 typedef typename detail::mem_ptr_fun<r0, r1>::result_type result_type;
0176 result_type operator ()(Expr &expr, Context &ctx) const
0177 {
0178 return detail::mem_ptr_fun<r0, r1>()(
0179 proto::eval(proto::child_c<0>(expr), ctx)
0180 , proto::eval(proto::child_c<1>(expr), ctx)
0181 );
0182 }
0183 };
0184
0185
0186 template<typename Expr, typename Context>
0187 struct memfun_eval<Expr, Context, true>
0188 {
0189 private:
0190 typedef typename result_of::child_c<Expr, 0>::type e0;
0191 typedef typename result_of::child_c<Expr, 1>::type e1;
0192 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0193 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0194 public:
0195 typedef detail::memfun<r0, r1> result_type;
0196 result_type const operator ()(Expr &expr, Context &ctx) const
0197 {
0198 return detail::memfun<r0, r1>(
0199 proto::eval(proto::child_c<0>(expr), ctx)
0200 , proto::eval(proto::child_c<1>(expr), ctx)
0201 );
0202 }
0203 };
0204
0205 template<typename Expr, typename Context>
0206 struct default_eval<Expr, Context, tag::mem_ptr, 2>
0207 : memfun_eval<Expr, Context, is_member_function_eval<Expr, Context>::value>
0208 {};
0209
0210
0211 template<typename Expr, typename Context>
0212 struct default_eval<Expr, Context, proto::tag::post_inc, 1>
0213 {
0214 private:
0215 typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0216 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0217 public:
0218 BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() ++, result_type)
0219 result_type operator ()(Expr &expr, Context &ctx) const
0220 {
0221 return proto::eval(proto::child_c<0>(expr), ctx) ++;
0222 }
0223 };
0224
0225
0226 template<typename Expr, typename Context>
0227 struct default_eval<Expr, Context, proto::tag::post_dec, 1>
0228 {
0229 private:
0230 typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0231 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0232 public:
0233 BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() --, result_type)
0234 result_type operator ()(Expr &expr, Context &ctx) const
0235 {
0236 return proto::eval(proto::child_c<0>(expr), ctx) --;
0237 }
0238 };
0239
0240
0241 template<typename Expr, typename Context>
0242 struct default_eval<Expr, Context, proto::tag::subscript, 2>
0243 {
0244 private:
0245 typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0246 typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0247 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0248 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0249 public:
0250 BOOST_PROTO_DECLTYPE_(proto::detail::make_subscriptable<r0>()[proto::detail::make<r1>()], result_type)
0251 result_type operator ()(Expr &expr, Context &ctx) const
0252 {
0253 return proto::eval(proto::child_c<0>(expr), ctx)[proto::eval(proto::child_c<1>(expr), ctx)];
0254 }
0255 };
0256
0257
0258 template<typename Expr, typename Context>
0259 struct default_eval<Expr, Context, proto::tag::if_else_, 3>
0260 {
0261 private:
0262 typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0263 typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0264 typedef typename proto::result_of::child_c<Expr, 2>::type e2;
0265 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0266 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0267 typedef typename proto::result_of::eval<UNREF(e2), Context>::type r2;
0268 public:
0269 BOOST_PROTO_DECLTYPE_(
0270 proto::detail::make<r0>()
0271 ? proto::detail::make<r1>()
0272 : proto::detail::make<r2>()
0273 , result_type
0274 )
0275 result_type operator ()(Expr &expr, Context &ctx) const
0276 {
0277 return proto::eval(proto::child_c<0>(expr), ctx)
0278 ? proto::eval(proto::child_c<1>(expr), ctx)
0279 : proto::eval(proto::child_c<2>(expr), ctx);
0280 }
0281 };
0282
0283
0284 template<typename Expr, typename Context>
0285 struct default_eval<Expr, Context, proto::tag::comma, 2>
0286 {
0287 private:
0288 typedef typename proto::result_of::child_c<Expr, 0>::type e0;
0289 typedef typename proto::result_of::child_c<Expr, 1>::type e1;
0290 typedef typename proto::result_of::eval<UNREF(e0), Context>::type r0;
0291 typedef typename proto::result_of::eval<UNREF(e1), Context>::type r1;
0292 public:
0293 typedef typename proto::detail::comma_result<r0, r1>::type result_type;
0294 result_type operator ()(Expr &expr, Context &ctx) const
0295 {
0296 return proto::eval(proto::child_c<0>(expr), ctx), proto::eval(proto::child_c<1>(expr), ctx);
0297 }
0298 };
0299
0300
0301 #define BOOST_PROTO_DEFAULT_EVAL_TYPE(Z, N, DATA) \
0302 typename proto::result_of::eval< \
0303 typename remove_reference< \
0304 typename proto::result_of::child_c<DATA, N>::type \
0305 >::type \
0306 , Context \
0307 >::type \
0308
0309
0310 #define BOOST_PROTO_DEFAULT_EVAL(Z, N, DATA) \
0311 proto::eval(proto::child_c<N>(DATA), context) \
0312
0313
0314 template<typename Expr, typename Context>
0315 struct default_eval<Expr, Context, proto::tag::function, 1>
0316 {
0317 typedef
0318 typename proto::detail::result_of_fixup<
0319 BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr)
0320 >::type
0321 function_type;
0322
0323 typedef
0324 typename BOOST_PROTO_RESULT_OF<function_type()>::type
0325 result_type;
0326
0327 result_type operator ()(Expr &expr, Context &context) const
0328 {
0329 return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)();
0330 }
0331 };
0332
0333 template<typename Expr, typename Context>
0334 struct default_eval<Expr, Context, proto::tag::function, 2>
0335 {
0336 typedef
0337 typename proto::detail::result_of_fixup<
0338 BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 0, Expr)
0339 >::type
0340 function_type;
0341
0342 typedef
0343 typename detail::result_of_<
0344 function_type(BOOST_PROTO_DEFAULT_EVAL_TYPE(~, 1, Expr))
0345 >::type
0346 result_type;
0347
0348 result_type operator ()(Expr &expr, Context &context) const
0349 {
0350 return this->invoke(
0351 expr
0352 , context
0353 , is_member_function_pointer<function_type>()
0354 , is_member_object_pointer<function_type>()
0355 );
0356 }
0357
0358 private:
0359 result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::false_) const
0360 {
0361 return BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)(BOOST_PROTO_DEFAULT_EVAL(~, 1, expr));
0362 }
0363
0364 result_type invoke(Expr &expr, Context &context, mpl::true_, mpl::false_) const
0365 {
0366 BOOST_PROTO_USE_GET_POINTER();
0367 typedef typename detail::class_member_traits<function_type>::class_type class_type;
0368 return (
0369 BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->*
0370 BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)
0371 )();
0372 }
0373
0374 result_type invoke(Expr &expr, Context &context, mpl::false_, mpl::true_) const
0375 {
0376 BOOST_PROTO_USE_GET_POINTER();
0377 typedef typename detail::class_member_traits<function_type>::class_type class_type;
0378 return (
0379 BOOST_PROTO_GET_POINTER(class_type, (BOOST_PROTO_DEFAULT_EVAL(~, 1, expr))) ->*
0380 BOOST_PROTO_DEFAULT_EVAL(~, 0, expr)
0381 );
0382 }
0383 };
0384
0385
0386 #include <boost/proto/context/detail/default_eval.hpp>
0387
0388 #undef BOOST_PROTO_DEFAULT_EVAL_TYPE
0389 #undef BOOST_PROTO_DEFAULT_EVAL
0390
0391
0392
0393 struct default_context
0394 {
0395
0396
0397 template<typename Expr, typename ThisContext = default_context const>
0398 struct eval
0399 : default_eval<Expr, ThisContext>
0400 {};
0401 };
0402
0403 }
0404
0405 }}
0406
0407 #undef UNREF
0408
0409 #endif