invert.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*==============================================================================
  2. Copyright (c) 2005-2010 Joel de Guzman
  3. Copyright (c) 2010 Thomas Heller
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #include <boost/phoenix/phoenix.hpp>
  8. #include <boost/proto/proto.hpp>
  9. #include <boost/proto/debug.hpp>
  10. namespace phoenix = boost::phoenix;
  11. namespace proto = boost::proto;
  12. using phoenix::evaluator;
  13. #ifdef _MSC_VER
  14. // redifining evaluator, this is because MSVC chokes on function types like:
  15. // F(G(...))
  16. #define evaluator(A0, A1) proto::call<phoenix::evaluator(A0, A1)>
  17. #endif
  18. struct invert_actions
  19. {
  20. template <typename Rule>
  21. struct when
  22. : proto::nary_expr<
  23. proto::_
  24. , proto::vararg<
  25. proto::when<proto::_, evaluator(proto::_, phoenix::_context)>
  26. >
  27. >
  28. {};
  29. };
  30. template <>
  31. struct invert_actions::when<phoenix::rule::plus>
  32. : proto::call<
  33. phoenix::functional::make_minus(
  34. evaluator(proto::_left, phoenix::_context)
  35. , evaluator(proto::_right, phoenix::_context)
  36. )
  37. >
  38. {};
  39. template <>
  40. struct invert_actions::when<phoenix::rule::minus>
  41. : proto::call<
  42. phoenix::functional::make_plus(
  43. evaluator(proto::_left, phoenix::_context)
  44. , evaluator(proto::_right, phoenix::_context)
  45. )
  46. >
  47. {};
  48. template <>
  49. struct invert_actions::when<phoenix::rule::multiplies>
  50. : proto::call<
  51. phoenix::functional::make_divides(
  52. evaluator(proto::_left, phoenix::_context)
  53. , evaluator(proto::_right, phoenix::_context)
  54. )
  55. >
  56. {};
  57. template <>
  58. struct invert_actions::when<phoenix::rule::divides>
  59. : proto::call<
  60. phoenix::functional::make_multiplies(
  61. evaluator(proto::_left, phoenix::_context)
  62. , evaluator(proto::_right, phoenix::_context)
  63. )
  64. >
  65. {};
  66. #ifdef _MSC_VER
  67. #undef evaluator
  68. #endif
  69. template <typename Expr>
  70. void print_expr(Expr const & expr)
  71. {
  72. std::cout << "before inversion:\n";
  73. proto::display_expr(expr);
  74. std::cout << "after inversion:\n";
  75. proto::display_expr(
  76. phoenix::eval(
  77. expr
  78. , phoenix::context(
  79. phoenix::nothing
  80. , invert_actions()
  81. )
  82. )
  83. );
  84. std::cout << "\n";
  85. }
  86. template <typename Expr>
  87. typename
  88. boost::phoenix::result_of::eval<
  89. Expr const&
  90. , phoenix::result_of::make_context<
  91. phoenix::result_of::make_env<>::type
  92. , invert_actions
  93. >::type
  94. >::type
  95. invert(Expr const & expr)
  96. {
  97. return
  98. phoenix::eval(
  99. expr
  100. , phoenix::make_context(
  101. phoenix::make_env()
  102. , invert_actions()
  103. )
  104. );
  105. }
  106. int main()
  107. {
  108. using phoenix::placeholders::_1;
  109. using phoenix::placeholders::_2;
  110. using phoenix::placeholders::_3;
  111. using phoenix::placeholders::_4;
  112. print_expr(_1);
  113. print_expr(_1 + _2);
  114. print_expr(_1 + _2 - _3);
  115. print_expr(_1 * _2);
  116. print_expr(_1 * _2 / _3);
  117. print_expr(_1 * _2 + _3);
  118. print_expr(_1 * _2 - _3);
  119. print_expr(if_(_1 * _4)[_2 - _3]);
  120. print_expr(_1 * invert(_2 - _3));
  121. }