HAL
translator.cpp
Go to the documentation of this file.
2 
5 
6 #include <boost/multiprecision/cpp_int.hpp>
7 
8 namespace hal
9 {
10  namespace SMT
11  {
12  namespace Translator
13  {
21  Result<std::string> const2str(const std::vector<BooleanFunction::Value>& number)
22  {
23  boost::multiprecision::cpp_int value = 0;
24 
25  for (auto i = 0u; i < number.size(); i++)
26  {
27  if ((number[i] == BooleanFunction::Value::X) || (number[i] == BooleanFunction::Value::Z))
28  {
29  return ERR("Cannot translate the number to a constant value as it is undefined.");
30  }
31 
32  if (number[i] == BooleanFunction::Value::ONE)
33  {
34  boost::multiprecision::bit_set(value, i);
35  }
36  }
37 
38  std::stringstream ss;
39  ss << value;
40  return OK(ss.str());
41  }
42 
53  Result<std::string> reduce_to_smt2(const BooleanFunction::Node& node, std::vector<std::string>&& p, size_t index, const BooleanFunction& function)
54  {
55  if (node.get_arity() != p.size())
56  {
57  return ERR("could not reduce into SMT-Lib v2 string: arity of node '" + node.to_string() + "' does not match number of parameters");
58  }
59 
60  switch (node.type)
61  {
63  if (auto str = const2str(node.constant); str.is_ok())
64  {
65  return OK(std::string("(_ bv") + str.get() + " " + std::to_string(node.size) + ")");
66  }
67 
68  return ERR("could not reduce into SMT-Lib v2 string: unable to translate constant '" + node.to_string() + "'");
69  }
71  return OK(std::to_string(node.index));
73  return OK(node.variable);
74 
76  return OK("(bvand " + p[0] + " " + p[1] + ")");
78  return OK("(bvor " + p[0] + " " + p[1] + ")");
80  return OK("(bvnot " + p[0] + ")");
82  return OK("(bvxor " + p[0] + " " + p[1] + ")");
83 
85  return OK("(bvadd " + p[0] + " " + p[1] + ")");
87  return OK("(bvsub " + p[0] + " " + p[1] + ")");
89  return OK("(bvmul " + p[0] + " " + p[1] + ")");
91  return OK("(bvsdiv " + p[0] + " " + p[1] + ")");
93  return OK("(bvudiv " + p[0] + " " + p[1] + ")");
95  return OK("(bvsrem " + p[0] + " " + p[1] + ")");
97  return OK("(bvurem " + p[0] + " " + p[1] + ")");
98 
100  return OK("(concat " + p[0] + " " + p[1] + ")");
102  return OK("((_ extract " + p[2] + " " + p[1] + ") " + p[0] + ")");
104  return OK("((_ zero_extend " + std::to_string(node.size - function.get_nodes().at(index - 2).index) + ") " + p[0] + ")");
106  return OK("((_ sign_extend " + std::to_string(node.size - function.get_nodes().at(index - 2).index) + ") " + p[0] + ")");
107 
109  return OK("(bvshl " + p[0] + " (_ bv" + p[1] + " " + std::to_string(node.size) + "))");
111  return OK("(bvlshr " + p[0] + " (_ bv" + p[1] + " " + std::to_string(node.size) + "))");
113  return OK("(bvashr " + p[0] + " (_ bv" + p[1] + " " + std::to_string(node.size) + "))");
115  return OK("((_ rotate_left " + p[1] + ") " + p[0] + ")");
117  return OK("((_ rotate_right " + p[1] + ") " + p[0] + ")");
118 
120  return OK("(ite (= " + p[0] + " " + p[1] + ") (_ bv1 " + std::to_string(node.size) + ") (_ bv0 " + std::to_string(node.size) + "))");
122  return OK("(ite (bvslt " + p[0] + " " + p[1] + ") (_ bv1 " + std::to_string(node.size) + ") (_ bv0 " + std::to_string(node.size) + "))");
124  return OK("(ite (bvsle " + p[0] + " " + p[1] + ") (_ bv1 " + std::to_string(node.size) + ") (_ bv0 " + std::to_string(node.size) + "))");
126  return OK("(ite (bvule " + p[0] + " " + p[1] + ") (_ bv1 " + std::to_string(node.size) + ") (_ bv0 " + std::to_string(node.size) + "))");
128  return OK("(ite (bvult " + p[0] + " " + p[1] + ") (_ bv1 " + std::to_string(node.size) + ") (_ bv0 " + std::to_string(node.size) + "))");
130  return OK("(ite (= " + p[0] + " (_ bv1 1)) " + p[1] + " " + p[2] + ")");
131 
132  default:
133  return ERR("could not reduce into SMT-Lib v2 string: not implemented for given node type");
134  }
135  }
136 
138  {
139  std::vector<std::string> stack;
140  for (auto index = 0ul; index < function.length(); index++)
141  {
142  const auto& node = function.get_nodes().at(index);
143  std::vector<std::string> operands;
144  std::move(stack.end() - static_cast<i64>(node.get_arity()), stack.end(), std::back_inserter(operands));
145  stack.erase(stack.end() - static_cast<i64>(node.get_arity()), stack.end());
146 
147  if (auto reduction = reduce_to_smt2(node, std::move(operands), index, function); reduction.is_ok())
148  {
149  stack.emplace_back(reduction.get());
150  }
151  else
152  {
153  return ERR_APPEND(reduction.get_error(), "could not translate Boolean function to SMT-Lib v2 string: reduction to SMT-Lib v2 string failed");
154  }
155  }
156 
157  switch (stack.size())
158  {
159  case 1:
160  return OK(stack.back());
161  default:
162  return ERR("could not translate Boolean function to SMT-Lib v2 string: stack is imbalanced");
163  }
164  }
165  } // namespace Translator
166  } // namespace SMT
167 } // namespace hal
int64_t i64
Definition: defines.h:37
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
Result< std::string > translate_to_smt2(const BooleanFunction &function)
Definition: translator.cpp:137
Result< std::string > reduce_to_smt2(const BooleanFunction::Node &node, std::vector< std::string > &&p, size_t index, const BooleanFunction &function)
Definition: translator.cpp:53
Result< std::string > const2str(const std::vector< BooleanFunction::Value > &number)
Definition: translator.cpp:21
std::vector< BooleanFunction::Value > constant
The (optional) constant value of the node.
u16 type
The type of the node.
u16 size
The bit-size of the node.
std::string variable
The (optional) variable name of the node.
u16 index
The (optional) index value of the node.