mirror of
https://github.com/Z3Prover/z3
synced 2025-07-18 02:16:40 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3
This commit is contained in:
commit
2b190039d5
16 changed files with 645 additions and 53 deletions
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include"seq_rewriter.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_util.h"
|
||||
|
||||
|
||||
br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
|
@ -187,6 +188,21 @@ br_status seq_rewriter::mk_str_strctn(expr* a, expr* b, expr_ref& result) {
|
|||
result = m().mk_bool_val(0 != strstr(d.c_str(), c.c_str()));
|
||||
return BR_DONE;
|
||||
}
|
||||
// check if subsequence of a is in b.
|
||||
ptr_vector<expr> as, bs;
|
||||
m_util.str.get_concat(a, as);
|
||||
m_util.str.get_concat(b, bs);
|
||||
bool found = false;
|
||||
for (unsigned i = 0; !found && i < bs.size(); ++i) {
|
||||
if (as.size() > bs.size() - i) break;
|
||||
unsigned j = 0;
|
||||
for (; j < as.size() && as[j] == bs[i+j]; ++j) {};
|
||||
found = j == as.size();
|
||||
}
|
||||
if (found) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
@ -261,6 +277,7 @@ br_status seq_rewriter::mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& resu
|
|||
}
|
||||
|
||||
br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
||||
TRACE("seq", tout << mk_pp(a, m()) << " " << mk_pp(b, m()) << "\n";);
|
||||
std::string s1, s2;
|
||||
bool isc1 = m_util.str.is_string(a, s1);
|
||||
bool isc2 = m_util.str.is_string(b, s2);
|
||||
|
@ -276,24 +293,177 @@ br_status seq_rewriter::mk_seq_prefix(expr* a, expr* b, expr_ref& result) {
|
|||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
expr* a1 = m_util.str.get_leftmost_concat(a);
|
||||
expr* b1 = m_util.str.get_leftmost_concat(b);
|
||||
isc1 = m_util.str.is_string(a1, s1);
|
||||
isc2 = m_util.str.is_string(b1, s2);
|
||||
ptr_vector<expr> as, bs;
|
||||
|
||||
if (a1 != b1 && isc1 && isc2) {
|
||||
if (s1.length() <= s2.length()) {
|
||||
if (strncmp(s1.c_str(), s2.c_str(), s1.length()) == 0) {
|
||||
if (a == a1) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
m_util.str.get_concat(a, as);
|
||||
m_util.str.get_concat(b, bs);
|
||||
SASSERT(as.size() > 1);
|
||||
s2 = std::string(s2.c_str() + s1.length(), s2.length() - s1.length());
|
||||
bs[0] = m_util.str.mk_string(s2);
|
||||
result = m_util.str.mk_prefix(m_util.str.mk_concat(as.size()-1, as.c_ptr()+1),
|
||||
m_util.str.mk_concat(bs.size(), bs.c_ptr()));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
else {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (strncmp(s1.c_str(), s2.c_str(), s2.length()) == 0) {
|
||||
if (b == b1) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
m_util.str.get_concat(a, as);
|
||||
m_util.str.get_concat(b, bs);
|
||||
SASSERT(bs.size() > 1);
|
||||
s1 = std::string(s1.c_str() + s2.length(), s1.length() - s2.length());
|
||||
as[0] = m_util.str.mk_string(s1);
|
||||
result = m_util.str.mk_prefix(m_util.str.mk_concat(as.size(), as.c_ptr()),
|
||||
m_util.str.mk_concat(bs.size()-1, bs.c_ptr()+1));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
else {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a1 != b1) {
|
||||
return BR_FAILED;
|
||||
}
|
||||
m_util.str.get_concat(a, as);
|
||||
m_util.str.get_concat(b, bs);
|
||||
unsigned i = 0;
|
||||
for (; i < as.size() && i < bs.size() && as[i] == bs[i]; ++i) {};
|
||||
if (i == as.size()) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (i == bs.size()) {
|
||||
expr_ref_vector es(m());
|
||||
for (unsigned j = i; j < as.size(); ++j) {
|
||||
es.push_back(m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), as[j]));
|
||||
}
|
||||
result = mk_and(es);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
if (i > 0) {
|
||||
a = m_util.str.mk_concat(as.size() - i, as.c_ptr() + i);
|
||||
b = m_util.str.mk_concat(bs.size() - i, bs.c_ptr() + i);
|
||||
result = m_util.str.mk_prefix(a, b);
|
||||
return BR_DONE;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_seq_suffix(expr* a, expr* b, expr_ref& result) {
|
||||
std::string s1, s2;
|
||||
bool isc1 = m_util.str.is_string(a, s1);
|
||||
if (isc1 && m_util.str.is_string(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];
|
||||
}
|
||||
result = m().mk_bool_val(suffix);
|
||||
if (a == b) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
std::string s1, s2;
|
||||
if (m_util.str.is_empty(a)) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.str.is_empty(b)) {
|
||||
result = m().mk_eq(m_util.str.mk_empty(m().get_sort(a)), a);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
// concatenation is left-associative, so a2, b2 are not concatenations
|
||||
expr* a1, *a2, *b1, *b2;
|
||||
if (m_util.str.is_concat(a, a1, a2) &&
|
||||
m_util.str.is_concat(b, b1, b2) && a2 == b2) {
|
||||
result = m_util.str.mk_suffix(a1, b1);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
if (m_util.str.is_concat(b, b1, b2) && b2 == a) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
bool isc1 = false;
|
||||
bool isc2 = false;
|
||||
|
||||
if (m_util.str.is_concat(a, a1, a2) && m_util.str.is_string(a2, s1)) {
|
||||
isc1 = true;
|
||||
}
|
||||
else if (m_util.str.is_string(a, s1)) {
|
||||
isc1 = true;
|
||||
a2 = a;
|
||||
a1 = 0;
|
||||
}
|
||||
|
||||
if (m_util.str.is_concat(b, b1, b2) && m_util.str.is_string(b2, s2)) {
|
||||
isc2 = true;
|
||||
}
|
||||
else if (m_util.str.is_string(b, s2)) {
|
||||
isc2 = true;
|
||||
b2 = b;
|
||||
b1 = 0;
|
||||
}
|
||||
if (isc1 && isc2) {
|
||||
if (s1.length() == s2.length()) {
|
||||
SASSERT(s1 != s2);
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (s1.length() < s2.length()) {
|
||||
bool suffix = true;
|
||||
for (unsigned i = 0; i < s1.length(); ++i) {
|
||||
suffix = s1[s1.length()-i-1] == s2[s2.length()-i-1];
|
||||
}
|
||||
if (suffix && a1 == 0) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (suffix) {
|
||||
s2 = std::string(s2.c_str(), s2.length()-s1.length());
|
||||
b2 = m_util.str.mk_string(s2);
|
||||
result = m_util.str.mk_suffix(a1, b1?m_util.str.mk_concat(b1, b2):b2);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(s1.length() > s2.length());
|
||||
if (b1 == 0) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
bool suffix = true;
|
||||
for (unsigned i = 0; i < s2.length(); ++i) {
|
||||
suffix = s1[s1.length()-i-1] == s2[s2.length()-i-1];
|
||||
}
|
||||
if (suffix) {
|
||||
s1 = std::string(s1.c_str(), s1.length()-s2.length());
|
||||
a2 = m_util.str.mk_string(s1);
|
||||
result = m_util.str.mk_suffix(a1?m_util.str.mk_concat(a1, a2):a2, b1);
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue