mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
7ed9996fc0
commit
835b57b775
9 changed files with 100 additions and 97 deletions
|
@ -47,4 +47,5 @@ z3_add_component(rewriter
|
|||
fpa_rewriter_params.pyg
|
||||
poly_rewriter_params.pyg
|
||||
rewriter_params.pyg
|
||||
seq_rewriter_params.pyg
|
||||
)
|
||||
|
|
|
@ -646,13 +646,13 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
}
|
||||
|
||||
expr* cond2 = nullptr, *t2 = nullptr, *e2 = nullptr;
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
VERIFY(BR_FAILED != try_ite_value(to_app(t), val, result));
|
||||
if (m().is_ite(t, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) &&
|
||||
BR_FAILED != try_ite_value(to_app(t), val, result)) {
|
||||
result = m().mk_ite(cond, result, mk_eq(e, val));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2)) {
|
||||
VERIFY(BR_FAILED != try_ite_value(to_app(e), val, result));
|
||||
if (m().is_ite(e, cond2, t2, e2) && m().is_value(t2) && m().is_value(e2) &&
|
||||
BR_FAILED != try_ite_value(to_app(e), val, result)) {
|
||||
result = m().mk_ite(cond, mk_eq(t, val), result);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ Notes:
|
|||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "ast/rewriter/seq_rewriter_params.hpp"
|
||||
#include "math/automata/automaton.h"
|
||||
#include "math/automata/symbolic_automata_def.h"
|
||||
|
||||
|
@ -387,6 +388,17 @@ eautomaton* re2automaton::seq2aut(expr* e) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void seq_rewriter::updt_params(params_ref const & p) {
|
||||
seq_rewriter_params sp(p);
|
||||
m_coalesce_chars = sp.coalesce_chars();
|
||||
}
|
||||
|
||||
static void get_param_descrs(param_descrs & r) {
|
||||
seq_rewriter_params::collect_param_descrs(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_family_id() == get_fid());
|
||||
br_status st = BR_FAILED;
|
||||
|
@ -531,7 +543,11 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
st = mk_str_lt(args[0], args[1], result);
|
||||
break;
|
||||
case OP_STRING_CONST:
|
||||
return BR_FAILED;
|
||||
st = BR_FAILED;
|
||||
if (!m_coalesce_chars) {
|
||||
st = mk_str_units(f, result);
|
||||
}
|
||||
break;
|
||||
case OP_STRING_ITOS:
|
||||
SASSERT(num_args == 1);
|
||||
st = mk_str_itos(args[0], result);
|
||||
|
@ -563,7 +579,7 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
br_status seq_rewriter::mk_seq_unit(expr* e, expr_ref& result) {
|
||||
unsigned ch;
|
||||
// specifically we want (_ BitVector 8)
|
||||
if (m_util.is_const_char(e, ch)) {
|
||||
if (m_util.is_const_char(e, ch) && m_coalesce_chars) {
|
||||
// convert to string constant
|
||||
zstring str(ch);
|
||||
TRACE("seq_verbose", tout << "rewrite seq.unit of 8-bit value " << ch << " to string constant \"" << str<< "\"" << std::endl;);
|
||||
|
@ -584,8 +600,8 @@ br_status seq_rewriter::mk_seq_unit(expr* e, expr_ref& result) {
|
|||
br_status seq_rewriter::mk_seq_concat(expr* a, expr* b, expr_ref& result) {
|
||||
zstring s1, s2;
|
||||
expr* c, *d;
|
||||
bool isc1 = m_util.str.is_string(a, s1);
|
||||
bool isc2 = m_util.str.is_string(b, s2);
|
||||
bool isc1 = m_util.str.is_string(a, s1) && m_coalesce_chars;
|
||||
bool isc2 = m_util.str.is_string(b, s2) && m_coalesce_chars;
|
||||
if (isc1 && isc2) {
|
||||
result = m_util.str.mk_string(s1 + s2);
|
||||
return BR_DONE;
|
||||
|
@ -1511,6 +1527,23 @@ br_status seq_rewriter::mk_seq_suffix(expr* a, expr* b, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_units(func_decl* f, expr_ref& result) {
|
||||
zstring s;
|
||||
VERIFY(m_util.str.is_string(f, s));
|
||||
expr_ref_vector es(m());
|
||||
unsigned sz = s.length();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
es.push_back(m_util.str.mk_unit(m_util.str.mk_char(s, j)));
|
||||
}
|
||||
if (es.empty()) {
|
||||
result = m_util.str.mk_empty(f->get_range());
|
||||
}
|
||||
else {
|
||||
result = m_util.str.mk_concat(es);
|
||||
}
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_le(expr* a, expr* b, expr_ref& result) {
|
||||
result = m().mk_not(m_util.str.mk_lex_lt(b, a));
|
||||
return BR_REWRITE2;
|
||||
|
|
|
@ -108,6 +108,7 @@ class seq_rewriter {
|
|||
arith_util m_autil;
|
||||
re2automaton m_re2aut;
|
||||
expr_ref_vector m_es, m_lhs, m_rhs;
|
||||
bool m_coalesce_chars;
|
||||
|
||||
br_status mk_seq_unit(expr* e, expr_ref& result);
|
||||
br_status mk_seq_concat(expr* a, expr* b, expr_ref& result);
|
||||
|
@ -122,6 +123,7 @@ class seq_rewriter {
|
|||
br_status mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_seq_prefix(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_suffix(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_str_units(func_decl* f, expr_ref& result);
|
||||
br_status mk_str_itos(expr* a, expr_ref& result);
|
||||
br_status mk_str_stoi(expr* a, expr_ref& result);
|
||||
br_status mk_str_in_regexp(expr* a, expr* b, expr_ref& result);
|
||||
|
@ -164,15 +166,16 @@ class seq_rewriter {
|
|||
bool get_lengths(expr* e, expr_ref_vector& lens, rational& pos);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
seq_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m), m_autil(m), m_re2aut(m), m_es(m), m_lhs(m), m_rhs(m) {
|
||||
m_util(m), m_autil(m), m_re2aut(m), m_es(m), m_lhs(m), m_rhs(m), m_coalesce_chars(true) {
|
||||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
||||
void updt_params(params_ref const & p) {}
|
||||
static void get_param_descrs(param_descrs & r) {}
|
||||
void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
|
||||
void set_solver(expr_solver* solver) { m_re2aut.set_solver(solver); }
|
||||
bool has_solver() { return m_re2aut.has_solver(); }
|
||||
|
|
|
@ -1052,9 +1052,9 @@ app* seq_util::mk_lt(expr* ch1, expr* ch2) const {
|
|||
return m.mk_not(bv().mk_ule(ch2, ch1));
|
||||
}
|
||||
|
||||
bool seq_util::str::is_string(expr const* n, zstring& s) const {
|
||||
if (is_string(n)) {
|
||||
s = zstring(to_app(n)->get_decl()->get_parameter(0).get_symbol().bare_str());
|
||||
bool seq_util::str::is_string(func_decl const* f, zstring& s) const {
|
||||
if (is_string(f)) {
|
||||
s = zstring(f->get_parameter(0).get_symbol().bare_str());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -1062,6 +1062,10 @@ bool seq_util::str::is_string(expr const* n, zstring& s) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool seq_util::str::is_string(expr const* n, zstring& s) const {
|
||||
return is_app(n) && is_string(to_app(n)->get_decl(), s);
|
||||
}
|
||||
|
||||
bool seq_util::str::is_nth_i(expr const* n, expr*& s, unsigned& idx) const {
|
||||
expr* i = nullptr;
|
||||
if (!is_nth_i(n, s, i)) return false;
|
||||
|
|
|
@ -295,7 +295,9 @@ public:
|
|||
bool is_string(expr const* n, symbol& s) const {
|
||||
return is_string(n) && (s = to_app(n)->get_decl()->get_parameter(0).get_symbol(), true);
|
||||
}
|
||||
bool is_string(func_decl const* f) const { return is_decl_of(f, m_fid, OP_STRING_CONST); }
|
||||
bool is_string(expr const* n, zstring& s) const;
|
||||
bool is_string(func_decl const* f, zstring& s) const;
|
||||
bool is_empty(expr const* n) const { symbol s;
|
||||
return is_app_of(n, m_fid, OP_SEQ_EMPTY) || (is_string(n, s) && !s.is_numerical() && *s.bare_str() == 0);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue