evaluator.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_MATH_EXPRESSION_EVALUATOR_HPP
27 #define CRYPTO3_MATH_EXPRESSION_EVALUATOR_HPP
28 
29 #ifndef CRYPTO3_MATH_EXPRESSION_HPP
30 #error "evaluator.hpp must not be included directly!"
31 #endif
32 
33 #include <map>
34 #include <string>
35 
36 #include <boost/fusion/include/adapt_struct.hpp>
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace math {
42  namespace expressions {
43  namespace detail {
44  namespace ast {
45 
46  // Optimizer
47 
48  template <typename T>
50  using result_type = bool;
51 
52  template <typename U>
53  bool operator()(U const &) const {
54  return std::is_same<U, T>::value;
55  }
56  };
57 
58  template <typename T, typename... Ts>
59  bool holds_alternative(x3::variant<Ts...> const &v) {
60  return boost::apply_visitor(holds_alternative_impl<T>(), v);
61  }
62 
63  struct ConstantFolder {
65 
67  return result_type{0};
68  }
69 
70  result_type operator()(double n) const {
71  return result_type{n};
72  }
73 
74  result_type operator()(std::string const &c) const {
75  return result_type{c};
76  }
77 
78  result_type operator()(operation const &x, operand const &lhs) const {
79  auto rhs = boost::apply_visitor(*this, x.rhs);
80 
81  if (holds_alternative<double>(lhs) && holds_alternative<double>(rhs)) {
82  return result_type{
83  x.op(boost::get<double>(lhs), boost::get<double>(rhs))};
84  }
85  return result_type{binary_op{x.op, lhs, rhs}};
86  }
87 
88  result_type operator()(unary_op const &x) const {
89  auto rhs = boost::apply_visitor(*this, x.rhs);
90 
92  if (holds_alternative<double>(rhs)) {
93  return result_type{x.op(boost::get<double>(rhs))};
94  }
95  return result_type{unary_op{x.op, rhs}};
96  }
97 
98  result_type operator()(binary_op const &x) const {
99  auto lhs = boost::apply_visitor(*this, x.lhs);
100  auto rhs = boost::apply_visitor(*this, x.rhs);
101 
104  if (holds_alternative<double>(lhs) && holds_alternative<double>(rhs)) {
105  return result_type{
106  x.op(boost::get<double>(lhs), boost::get<double>(rhs))};
107  }
108  return result_type{binary_op{x.op, lhs, rhs}};
109  }
110 
112  auto state = boost::apply_visitor(*this, x.lhs);
113  for (operation const &oper : x.rhs) {
114  state = (*this)(oper, state);
115  }
116  return result_type{state};
117  }
118  };
119 
120  struct eval {
121  using result_type = double;
122 
123  explicit eval(std::map<std::string, double> sym) : st(std::move(sym)) {}
124 
125  double operator()(nil) const {
126  BOOST_ASSERT(0);
127  return 0;
128  }
129 
130  double operator()(double n) const { return n; }
131 
132  double operator()(std::string const &c) const {
133  auto it = st.find(c);
134  if (it == st.end()) {
135  throw std::invalid_argument("Unknown variable " + c); // NOLINT
136  }
137  return it->second;
138  }
139 
140  double operator()(operation const &x, double lhs) const {
141  double rhs = boost::apply_visitor(*this, x.rhs);
142  return x.op(lhs, rhs);
143  }
144 
145  double operator()(unary_op const &x) const {
146  double rhs = boost::apply_visitor(*this, x.rhs);
147  return x.op(rhs);
148  }
149 
150  double operator()(binary_op const &x) const {
151  double lhs = boost::apply_visitor(*this, x.lhs);
152  double rhs = boost::apply_visitor(*this, x.rhs);
153  return x.op(lhs, rhs);
154  }
155 
156  double operator()(expression const &x) const {
157  double state = boost::apply_visitor(*this, x.lhs);
158  for (operation const &oper : x.rhs) {
159  state = (*this)(oper, state);
160  }
161  return state;
162  }
163 
164  private:
165  std::map<std::string, double> st;
166  };
167 
168  } // namespace ast
169  } // namespace detail
170  } // namespace expressions
171  } // namespace math
172  } // namespace crypto3
173 } // namespace nil
174 
175 #endif // CRYPTO3_MATH_EXPRESSION_EVALUATOR_HPP
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
bool holds_alternative(x3::variant< Ts... > const &v)
Definition: evaluator.hpp:59
Definition: pair.hpp:31
result_type operator()(binary_op const &x) const
Definition: evaluator.hpp:98
result_type operator()(std::string const &c) const
Definition: evaluator.hpp:74
result_type operator()(expression const &x) const
Definition: evaluator.hpp:111
result_type operator()(unary_op const &x) const
Definition: evaluator.hpp:88
result_type operator()(double n) const
Definition: evaluator.hpp:70
result_type operator()(operation const &x, operand const &lhs) const
Definition: evaluator.hpp:78
result_type operator()(nil) const
Definition: evaluator.hpp:66
double(* op)(double, double)
Definition: ast.hpp:74
double operator()(operation const &x, double lhs) const
Definition: evaluator.hpp:140
double operator()(unary_op const &x) const
Definition: evaluator.hpp:145
eval(std::map< std::string, double > sym)
Definition: evaluator.hpp:123
double operator()(nil) const
Definition: evaluator.hpp:125
double operator()(expression const &x) const
Definition: evaluator.hpp:156
double operator()(double n) const
Definition: evaluator.hpp:130
double result_type
Definition: evaluator.hpp:121
double operator()(binary_op const &x) const
Definition: evaluator.hpp:150
double operator()(std::string const &c) const
Definition: evaluator.hpp:132
std::list< operation > rhs
Definition: ast.hpp:86
bool operator()(U const &) const
Definition: evaluator.hpp:53
double(* op)(double, double)
Definition: ast.hpp:80
double(* op)(double)
Definition: ast.hpp:69