22
33#include " smt2_incremental_decision_procedure.h"
44
5+ #include < solvers/smt2_incremental/convert_expr_to_smt.h>
56#include < solvers/smt2_incremental/smt_commands.h>
7+ #include < solvers/smt2_incremental/smt_core_theory.h>
8+ #include < solvers/smt2_incremental/smt_terms.h>
69#include < solvers/smt2_incremental/smt_to_smt2_string.h>
710#include < util/expr.h>
811#include < util/namespace.h>
12+ #include < util/range.h>
13+ #include < util/std_expr.h>
914#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+ }
1092
1193smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret (
1294 const namespacet &_ns,
@@ -23,8 +105,27 @@ smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret(
23105 smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}});
24106}
25107
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+
26125exprt smt2_incremental_decision_proceduret::handle (const exprt &expr)
27126{
127+ log.debug () << " `handle` -\n " << expr.pretty (2 , 0 ) << messaget::eom;
128+ ensure_handle_for_expr_defined (expr);
28129 return expr;
29130}
30131
@@ -53,9 +154,22 @@ smt2_incremental_decision_proceduret::get_number_of_solver_calls() const
53154
54155void smt2_incremental_decision_proceduret::set_to (const exprt &expr, bool value)
55156{
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});
59173}
60174
61175void smt2_incremental_decision_proceduret::push (
0 commit comments