transform_terminals.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // Copyright (C) 2016-2018 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. //[ transform_terminals
  7. #include <boost/yap/yap.hpp>
  8. struct iota_terminal_transform
  9. {
  10. // Base case. Note that we're not treating placeholders specially for this
  11. // example (they're easy to special-case if necessary).
  12. template<typename T>
  13. auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::terminal>, T && t)
  14. {
  15. // Like the std::iota() algorithm, we create replacement int terminals
  16. // with the values index_, index_ + 1, index_ + 2, etc.
  17. return boost::yap::make_terminal(index_++);
  18. }
  19. // Recursive case: Match any call expression.
  20. template<typename CallableExpr, typename... Arg>
  21. auto operator()(boost::yap::expr_tag<boost::yap::expr_kind::call>,
  22. CallableExpr callable, Arg &&... arg)
  23. {
  24. // Even though the callable in a call expression is technically a
  25. // terminal, it doesn't make a lot of sense to replace it with an int,
  26. // so we'll only transform the argument subexpressions.
  27. return boost::yap::make_expression<boost::yap::expr_kind::call>(
  28. boost::yap::as_expr(callable),
  29. boost::yap::transform(boost::yap::as_expr(arg), *this)...);
  30. }
  31. int index_;
  32. };
  33. int sum(int a, int b) { return a + b; }
  34. int main()
  35. {
  36. {
  37. // This simple sum(8, 8) expression requires both overloads of
  38. // iota_terminal_transform.
  39. auto expr = boost::yap::make_terminal(sum)(8, 8);
  40. assert(evaluate(expr) == 16);
  41. auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{1});
  42. assert(evaluate(iota_expr) == 3);
  43. }
  44. {
  45. // This expression requires only the terminal case of
  46. // iota_terminal_transform.
  47. auto expr = -(boost::yap::make_terminal(8) + 8);
  48. assert(evaluate(expr) == -16);
  49. auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{0});
  50. assert(evaluate(iota_expr) == -1);
  51. }
  52. {
  53. // Like the first expression above, this expression requires both
  54. // overloads of iota_terminal_transform.
  55. auto expr = boost::yap::make_terminal(sum)(-(boost::yap::make_terminal(8) + 8), 0);
  56. assert(evaluate(expr) == -16);
  57. auto iota_expr = boost::yap::transform(expr, iota_terminal_transform{0});
  58. assert(evaluate(iota_expr) == -3);
  59. }
  60. }
  61. //]