2
2
3
3
#include " smt2_incremental_decision_procedure.h"
4
4
5
+ #include < solvers/smt2_incremental/convert_expr_to_smt.h>
5
6
#include < solvers/smt2_incremental/smt_commands.h>
7
+ #include < solvers/smt2_incremental/smt_core_theory.h>
8
+ #include < solvers/smt2_incremental/smt_terms.h>
6
9
#include < solvers/smt2_incremental/smt_to_smt2_string.h>
7
10
#include < util/expr.h>
8
11
#include < util/namespace.h>
12
+ #include < util/range.h>
13
+ #include < util/std_expr.h>
9
14
#include < util/string_utils.h>
15
+ #include < util/symbol.h>
16
+
17
+ #include < stack>
18
+
19
+ // / \brief Find all sub expressions of the given \p expr which need to be
20
+ // / expressed as separate smt commands.
21
+ // / \note This pass over \p expr is tightly coupled to the implementation of
22
+ // / `convert_expr_to_smt`. This is because any sub expressions which
23
+ // / `convert_expr_to_smt` translates into function applications, must also be
24
+ // / returned by this`gather_dependent_expressions` function.
25
+ static std::unordered_set<exprt, irep_hash>
26
+ gather_dependent_expressions (const exprt &expr)
27
+ {
28
+ std::unordered_set<exprt, irep_hash> dependent_expressions;
29
+ expr.visit_pre ([&](const exprt &expr_node) {
30
+ if (can_cast_expr<symbol_exprt>(expr_node))
31
+ {
32
+ dependent_expressions.insert (expr_node);
33
+ }
34
+ });
35
+ return dependent_expressions;
36
+ }
37
+
38
+ // / \brief Defines any functions which \p expr depends on, which have not yet
39
+ // / been defined, along with their dependencies in turn.
40
+ void smt2_incremental_decision_proceduret::define_dependent_functions (
41
+ const exprt &expr)
42
+ {
43
+ std::unordered_set<exprt, irep_hash> seen_expressions =
44
+ make_range (expression_identifiers)
45
+ .map ([](const std::pair<exprt, smt_identifier_termt> &expr_identifier) {
46
+ return expr_identifier.first ;
47
+ });
48
+ std::stack<exprt> to_be_defined;
49
+ const auto dependencies_needed = [&](const exprt &expr) {
50
+ bool result = false ;
51
+ for (const auto &dependency : gather_dependent_expressions (expr))
52
+ {
53
+ if (!seen_expressions.insert (dependency).second )
54
+ continue ;
55
+ result = true ;
56
+ to_be_defined.push (dependency);
57
+ }
58
+ return result;
59
+ };
60
+ dependencies_needed (expr);
61
+ while (!to_be_defined.empty ())
62
+ {
63
+ const exprt current = to_be_defined.top ();
64
+ if (dependencies_needed (current))
65
+ continue ;
66
+ if (const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(current))
67
+ {
68
+ const irep_idt &identifier = symbol_expr->get_identifier ();
69
+ const symbolt *symbol = nullptr ;
70
+ if (!ns.lookup (identifier, symbol))
71
+ {
72
+ if (dependencies_needed (symbol->value ))
73
+ continue ;
74
+ const smt_define_function_commandt function{
75
+ symbol->name , {}, convert_expr_to_smt (symbol->value )};
76
+ expression_identifiers.emplace (*symbol_expr, function.identifier ());
77
+ send_to_solver (function);
78
+ }
79
+ else
80
+ {
81
+ const smt_declare_function_commandt function{
82
+ smt_identifier_termt (
83
+ identifier, convert_type_to_smt_sort (symbol_expr->type ())),
84
+ {}};
85
+ expression_identifiers.emplace (*symbol_expr, function.identifier ());
86
+ send_to_solver (function);
87
+ }
88
+ }
89
+ to_be_defined.pop ();
90
+ }
91
+ }
10
92
11
93
smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret (
12
94
const namespacet &_ns,
@@ -23,8 +105,27 @@ smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
23
105
smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}});
24
106
}
25
107
108
+ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined (
109
+ const exprt &expr)
110
+ {
111
+ if (
112
+ expression_handle_identifiers.find (expr) !=
113
+ expression_handle_identifiers.cend ())
114
+ {
115
+ return ;
116
+ }
117
+
118
+ define_dependent_functions (expr);
119
+ smt_define_function_commandt function{
120
+ " B" + std::to_string (handle_sequence ()), {}, convert_expr_to_smt (expr)};
121
+ expression_handle_identifiers.emplace (expr, function.identifier ());
122
+ send_to_solver (function);
123
+ }
124
+
26
125
exprt smt2_incremental_decision_proceduret::handle (const exprt &expr)
27
126
{
127
+ log .debug () << " `handle` -\n " << expr.pretty (2 , 0 ) << messaget::eom;
128
+ ensure_handle_for_expr_defined (expr);
28
129
return expr;
29
130
}
30
131
@@ -53,9 +154,22 @@ smt2_incremental_decision_proceduret::get_number_of_solver_calls() const
53
154
54
155
void smt2_incremental_decision_proceduret::set_to (const exprt &expr, bool value)
55
156
{
56
- UNIMPLEMENTED_FEATURE (
57
- " `set_to` (" + std::string{value ? " true" : " false" } + " ):\n " +
58
- expr.pretty (2 , 0 ));
157
+ PRECONDITION (can_cast_type<bool_typet>(expr.type ()));
158
+ log .debug () << " `set_to` (" << std::string{value ? " true" : " false" }
159
+ << " ) -\n " << expr.pretty (2 , 0 ) << messaget::eom;
160
+
161
+ define_dependent_functions (expr);
162
+ auto converted_term = [&]() -> smt_termt {
163
+ const auto expression_handle_identifier =
164
+ expression_handle_identifiers.find (expr);
165
+ if (expression_handle_identifier != expression_handle_identifiers.cend ())
166
+ return expression_handle_identifier->second ;
167
+ else
168
+ return convert_expr_to_smt (expr);
169
+ }();
170
+ if (!value)
171
+ converted_term = smt_core_theoryt::make_not (converted_term);
172
+ send_to_solver (smt_assert_commandt{converted_term});
59
173
}
60
174
61
175
void smt2_incremental_decision_proceduret::push (
0 commit comments