mirror of
https://github.com/Z3Prover/z3
synced 2025-04-13 20:38:43 +00:00
more rewrites
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
4fe0e07080
commit
40e9e4c7f8
|
@ -115,22 +115,75 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
string + string = string
|
||||
a + (b + c) = (a + b) + c
|
||||
a + "" = a
|
||||
"" + a = a
|
||||
(a + string) + string = a + string
|
||||
*/
|
||||
br_status seq_rewriter::mk_str_concat(expr* a, expr* b, expr_ref& result) {
|
||||
std::string c, d;
|
||||
if (m_util.str.is_const(a, c) && m_util.str.is_const(b, d)) {
|
||||
result = m_util.str.mk_string(c + d);
|
||||
std::string s1, s2;
|
||||
expr* c, *d;
|
||||
bool isc1 = m_util.str.is_const(a, s1);
|
||||
bool isc2 = m_util.str.is_const(b, s2);
|
||||
if (isc1 && isc2) {
|
||||
result = m_util.str.mk_string(s1 + s2);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_concat(b, c, d)) {
|
||||
result = m_util.str.mk_concat(m_util.str.mk_concat(a, c), d);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (isc1 && s1.length() == 0) {
|
||||
result = b;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (isc2 && s2.length() == 0) {
|
||||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_concat(a, c, d) &&
|
||||
m_util.str.is_const(d, s1) && isc2) {
|
||||
result = m_util.str.mk_string(s1 + s2);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_length(expr* a, expr_ref& result) {
|
||||
std::string b;
|
||||
if (m_util.str.is_const(a, b)) {
|
||||
m_es.reset();
|
||||
m_util.str.get_concat(a, m_es);
|
||||
unsigned len = 0;
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < m_es.size(); ++i) {
|
||||
if (m_util.str.is_const(m_es[i], b)) {
|
||||
len += b.length();
|
||||
}
|
||||
else {
|
||||
m_es[j] = m_es[i];
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (j == 0) {
|
||||
result = m_autil.mk_numeral(rational(b.length()), true);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (j != m_es.size()) {
|
||||
expr_ref_vector es(m());
|
||||
for (unsigned i = 0; i < j; ++i) {
|
||||
es.push_back(m_util.str.mk_length(m_es[i]));
|
||||
}
|
||||
if (len != 0) {
|
||||
es.push_back(m_autil.mk_numeral(rational(len), true));
|
||||
}
|
||||
result = m_autil.mk_add(es.size(), es.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_substr(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s;
|
||||
rational pos, len;
|
||||
|
@ -151,6 +204,7 @@ br_status seq_rewriter::mk_str_strctn(expr* a, expr* b, expr_ref& result) {
|
|||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_charat(expr* a, expr* b, expr_ref& result) {
|
||||
std::string c;
|
||||
rational r;
|
||||
|
@ -166,10 +220,14 @@ br_status seq_rewriter::mk_str_charat(expr* a, expr* b, expr_ref& result) {
|
|||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_stridof(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s1, s2;
|
||||
rational r;
|
||||
if (m_util.str.is_const(a, s1) && m_util.str.is_const(b, s2) && m_autil.is_numeral(c, r) && r.is_unsigned()) {
|
||||
bool isc1 = m_util.str.is_const(a, s1);
|
||||
bool isc2 = m_util.str.is_const(b, s2);
|
||||
|
||||
if (isc1 && isc2 && m_autil.is_numeral(c, r) && r.is_unsigned()) {
|
||||
for (unsigned i = r.get_unsigned(); i < s1.length(); ++i) {
|
||||
if (strncmp(s1.c_str() + i, s2.c_str(), s2.length()) == 0) {
|
||||
result = m_autil.mk_numeral(rational(i) - r, true);
|
||||
|
@ -179,15 +237,23 @@ br_status seq_rewriter::mk_str_stridof(expr* a, expr* b, expr* c, expr_ref& resu
|
|||
result = m_autil.mk_numeral(rational(-1), true);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_const(b, s2) && s2.length() == 0) {
|
||||
if (m_autil.is_numeral(c, r) && r.is_neg()) {
|
||||
result = m_autil.mk_numeral(rational(-1), true);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (isc2 && s2.length() == 0) {
|
||||
result = c;
|
||||
return BR_DONE;
|
||||
}
|
||||
// Enhancement: walk segments of a, determine which segments must overlap, must not overlap, may overlap.
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s1, s2, s3;
|
||||
if (m_util.str.is_const(a, s1) && m_util.str.is_const(b, s2) && m_util.str.is_const(c, s3)) {
|
||||
if (m_util.str.is_const(a, s1) && m_util.str.is_const(b, s2) &&
|
||||
m_util.str.is_const(c, s3)) {
|
||||
std::ostringstream buffer;
|
||||
for (unsigned i = 0; i < s1.length(); ) {
|
||||
if (strncmp(s1.c_str() + i, s2.c_str(), s2.length()) == 0) {
|
||||
|
@ -206,12 +272,14 @@ br_status seq_rewriter::mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& resu
|
|||
result = a;
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_prefix(expr* a, expr* b, expr_ref& result) {
|
||||
std::string s1, s2;
|
||||
if (m_util.str.is_const(a, s1) && m_util.str.is_const(b, s2)) {
|
||||
bool isc1 = m_util.str.is_const(a, s1);
|
||||
bool isc2 = m_util.str.is_const(b, s2);
|
||||
if (isc1 && isc2) {
|
||||
bool prefix = s1.length() <= s2.length();
|
||||
for (unsigned i = 0; i < s1.length() && prefix; ++i) {
|
||||
prefix = s1[i] == s2[i];
|
||||
|
@ -219,15 +287,17 @@ br_status seq_rewriter::mk_str_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
result = m().mk_bool_val(prefix);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_const(a, s1) && s1.length() == 0) {
|
||||
if (isc1 && s1.length() == 0) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_suffix(expr* a, expr* b, expr_ref& result) {
|
||||
std::string s1, s2;
|
||||
if (m_util.str.is_const(a, s1) && m_util.str.is_const(b, s2)) {
|
||||
bool isc1 = m_util.str.is_const(a, s1);
|
||||
if (isc1 && m_util.str.is_const(b, s2)) {
|
||||
bool suffix = s1.length() <= s2.length();
|
||||
for (unsigned i = 0; i < s1.length() && suffix; ++i) {
|
||||
suffix = s1[s1.length() - i - 1] == s2[s2.length() - i - 1];
|
||||
|
@ -235,12 +305,13 @@ br_status seq_rewriter::mk_str_suffix(expr* a, expr* b, expr_ref& result) {
|
|||
result = m().mk_bool_val(suffix);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_const(a, s1) && s1.length() == 0) {
|
||||
if (isc1 && s1.length() == 0) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_itos(expr* a, expr_ref& result) {
|
||||
rational r;
|
||||
if (m_autil.is_numeral(a, r)) {
|
||||
|
|
|
@ -32,6 +32,7 @@ Notes:
|
|||
class seq_rewriter {
|
||||
seq_util m_util;
|
||||
arith_util m_autil;
|
||||
ptr_vector<expr> m_es;
|
||||
|
||||
br_status mk_str_concat(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_str_length(expr* a, expr_ref& result);
|
||||
|
|
|
@ -355,3 +355,12 @@ bool seq_decl_plugin::is_value(app* e) const {
|
|||
app* seq_util::str::mk_string(symbol const& s) {
|
||||
return u.seq.mk_string(s);
|
||||
}
|
||||
|
||||
void seq_util::str::get_concat(expr* e, ptr_vector<expr>& es) const {
|
||||
expr* e1, *e2;
|
||||
while (is_concat(e, e1, e2)) {
|
||||
get_concat(e1, es);
|
||||
e = e2;
|
||||
}
|
||||
es.push_back(e);
|
||||
}
|
||||
|
|
|
@ -181,6 +181,9 @@ public:
|
|||
bool is_const(expr const* n, std::string& s) const {
|
||||
return is_const(n) && (s = to_app(n)->get_decl()->get_parameter(0).get_symbol().str(), true);
|
||||
}
|
||||
bool is_const(expr const* n, symbol& s) const {
|
||||
return is_const(n) && (s = to_app(n)->get_decl()->get_parameter(0).get_symbol(), true);
|
||||
}
|
||||
|
||||
bool is_string(sort* s) const { return is_sort_of(s, m_fid, STRING_SORT); }
|
||||
bool is_concat(expr const* n) const { return is_app_of(n, m_fid, OP_STRING_CONCAT); }
|
||||
|
@ -209,6 +212,8 @@ public:
|
|||
MATCH_UNARY(is_itos);
|
||||
MATCH_UNARY(is_stoi);
|
||||
MATCH_BINARY(is_in_regexp);
|
||||
|
||||
void get_concat(expr* e, ptr_vector<expr>& es) const;
|
||||
};
|
||||
|
||||
class re {
|
||||
|
|
Loading…
Reference in a new issue