mirror of
https://github.com/Z3Prover/z3
synced 2025-10-07 08:21:56 +00:00
seq
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
fe1039d12f
commit
c5a9d81d93
7 changed files with 239 additions and 51 deletions
|
@ -328,6 +328,9 @@ public:
|
|||
app * mk_numeral(sexpr const * p, unsigned i) {
|
||||
return plugin().mk_numeral(p, i);
|
||||
}
|
||||
app * mk_int(int i) {
|
||||
return mk_numeral(rational(i), true);
|
||||
}
|
||||
app * mk_le(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LE, arg1, arg2); }
|
||||
app * mk_ge(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GE, arg1, arg2); }
|
||||
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
||||
|
|
|
@ -55,22 +55,28 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
return mk_seq_concat(args[0], args[1], result);
|
||||
case OP_SEQ_LENGTH:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_str_length(args[0], result);
|
||||
return mk_seq_length(args[0], result);
|
||||
case OP_SEQ_EXTRACT:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_str_substr(args[0], args[1], args[2], result);
|
||||
return mk_seq_extract(args[0], args[1], args[2], result);
|
||||
case OP_SEQ_CONTAINS:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_str_strctn(args[0], args[1], result);
|
||||
return mk_seq_contains(args[0], args[1], result);
|
||||
case OP_SEQ_AT:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_str_at(args[0], args[1], result);
|
||||
return mk_seq_at(args[0], args[1], result);
|
||||
case OP_SEQ_PREFIX:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_prefix(args[0], args[1], result);
|
||||
case OP_SEQ_SUFFIX:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_seq_suffix(args[0], args[1], result);
|
||||
case OP_SEQ_INDEX:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_seq_index(args[0], args[1], args[2], result);
|
||||
case OP_SEQ_REPLACE:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_seq_replace(args[0], args[1], args[2], result);
|
||||
case OP_SEQ_TO_RE:
|
||||
return BR_FAILED;
|
||||
case OP_SEQ_IN_RE:
|
||||
|
@ -78,12 +84,6 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
|
||||
case OP_STRING_CONST:
|
||||
return BR_FAILED;
|
||||
case OP_STRING_STRIDOF:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_str_stridof(args[0], args[1], args[2], result);
|
||||
case OP_STRING_STRREPL:
|
||||
SASSERT(num_args == 3);
|
||||
return mk_str_strrepl(args[0], args[1], args[2], result);
|
||||
case OP_STRING_ITOS:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_str_itos(args[0], result);
|
||||
|
@ -101,7 +101,8 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case _OP_STRING_IN_REGEXP:
|
||||
case _OP_STRING_TO_REGEXP:
|
||||
case _OP_STRING_SUBSTR:
|
||||
|
||||
case _OP_STRING_STRREPL:
|
||||
case _OP_STRING_STRIDOF:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return BR_FAILED;
|
||||
|
@ -143,7 +144,7 @@ br_status seq_rewriter::mk_seq_concat(expr* a, expr* b, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_length(expr* a, expr_ref& result) {
|
||||
br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
|
||||
std::string b;
|
||||
m_es.reset();
|
||||
m_util.str.get_concat(a, m_es);
|
||||
|
@ -176,7 +177,7 @@ br_status seq_rewriter::mk_str_length(expr* a, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_substr(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s;
|
||||
rational pos, len;
|
||||
if (m_util.str.is_string(a, s) && m_autil.is_numeral(b, pos) && m_autil.is_numeral(c, len) &&
|
||||
|
@ -188,7 +189,7 @@ br_status seq_rewriter::mk_str_substr(expr* a, expr* b, expr* c, expr_ref& resul
|
|||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
br_status seq_rewriter::mk_str_strctn(expr* a, expr* b, expr_ref& result) {
|
||||
br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
|
||||
std::string c, d;
|
||||
if (m_util.str.is_string(a, c) && m_util.str.is_string(b, d)) {
|
||||
result = m().mk_bool_val(0 != strstr(d.c_str(), c.c_str()));
|
||||
|
@ -212,7 +213,7 @@ br_status seq_rewriter::mk_str_strctn(expr* a, expr* b, expr_ref& result) {
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_at(expr* a, expr* b, expr_ref& result) {
|
||||
br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) {
|
||||
std::string c;
|
||||
rational r;
|
||||
if (m_util.str.is_string(a, c) && m_autil.is_numeral(b, r) && r.is_unsigned()) {
|
||||
|
@ -228,7 +229,7 @@ br_status seq_rewriter::mk_str_at(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) {
|
||||
br_status seq_rewriter::mk_seq_index(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s1, s2;
|
||||
rational r;
|
||||
bool isc1 = m_util.str.is_string(a, s1);
|
||||
|
@ -257,15 +258,17 @@ br_status seq_rewriter::mk_str_stridof(expr* a, expr* b, expr* c, expr_ref& resu
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status seq_rewriter::mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
br_status seq_rewriter::mk_seq_replace(expr* a, expr* b, expr* c, expr_ref& result) {
|
||||
std::string s1, s2, s3;
|
||||
if (m_util.str.is_string(a, s1) && m_util.str.is_string(b, s2) &&
|
||||
m_util.str.is_string(c, s3)) {
|
||||
std::ostringstream buffer;
|
||||
bool can_replace = true;
|
||||
for (size_t i = 0; i < s1.length(); ) {
|
||||
if (strncmp(s1.c_str() + i, s2.c_str(), s2.length()) == 0) {
|
||||
if (can_replace && strncmp(s1.c_str() + i, s2.c_str(), s2.length()) == 0) {
|
||||
buffer << s3;
|
||||
i += s2.length();
|
||||
can_replace = false;
|
||||
}
|
||||
else {
|
||||
buffer << s1[i];
|
||||
|
|
|
@ -35,12 +35,12 @@ class seq_rewriter {
|
|||
ptr_vector<expr> m_es, m_lhs, m_rhs;
|
||||
|
||||
br_status mk_seq_concat(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_str_length(expr* a, expr_ref& result);
|
||||
br_status mk_str_substr(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_str_strctn(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_str_at(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_str_stridof(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_str_strrepl(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_seq_length(expr* a, expr_ref& result);
|
||||
br_status mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
br_status mk_seq_contains(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_at(expr* a, expr* b, expr_ref& result);
|
||||
br_status mk_seq_index(expr* a, expr* b, expr* c, expr_ref& result);
|
||||
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_itos(expr* a, expr_ref& result);
|
||||
|
|
|
@ -177,6 +177,7 @@ void seq_decl_plugin::init() {
|
|||
sort* reAreA[2] = { reA, reA };
|
||||
sort* AA[2] = { A, A };
|
||||
sort* seqAint2T[3] = { seqA, intT, intT };
|
||||
sort* seq2AintT[3] = { seqA, seqA, intT };
|
||||
sort* str2T[2] = { strT, strT };
|
||||
sort* str3T[3] = { strT, strT, strT };
|
||||
sort* strTint2T[3] = { strT, intT, intT };
|
||||
|
@ -184,6 +185,7 @@ void seq_decl_plugin::init() {
|
|||
sort* strTreT[2] = { strT, reT };
|
||||
sort* str2TintT[3] = { strT, strT, intT };
|
||||
sort* seqAintT[2] = { seqA, intT };
|
||||
sort* seq3A[3] = { seqA, seqA, seqA };
|
||||
m_sigs.resize(LAST_SEQ_OP);
|
||||
// TBD: have (par ..) construct and load parameterized signature from premable.
|
||||
m_sigs[OP_SEQ_UNIT] = alloc(psig, m, "seq.unit", 1, 1, &A, seqA);
|
||||
|
@ -193,6 +195,8 @@ void seq_decl_plugin::init() {
|
|||
m_sigs[OP_SEQ_SUFFIX] = alloc(psig, m, "seq.suffixof", 1, 2, seqAseqA, boolT);
|
||||
m_sigs[OP_SEQ_CONTAINS] = alloc(psig, m, "seq.contains", 1, 2, seqAseqA, boolT);
|
||||
m_sigs[OP_SEQ_EXTRACT] = alloc(psig, m, "seq.extract", 1, 3, seqAint2T, seqA);
|
||||
m_sigs[OP_SEQ_REPLACE] = alloc(psig, m, "seq.replace", 1, 3, seq3A, strT);
|
||||
m_sigs[OP_SEQ_INDEX] = alloc(psig, m, "seq.indexof", 1, 3, seq2AintT, intT);
|
||||
m_sigs[OP_SEQ_AT] = alloc(psig, m, "seq.at", 1, 2, seqAintT, seqA);
|
||||
m_sigs[OP_SEQ_LENGTH] = alloc(psig, m, "seq.len", 1, 1, &seqA, intT);
|
||||
m_sigs[OP_RE_PLUS] = alloc(psig, m, "re.+", 1, 1, &reA, reA);
|
||||
|
@ -209,8 +213,8 @@ void seq_decl_plugin::init() {
|
|||
m_sigs[OP_SEQ_TO_RE] = alloc(psig, m, "seq.to.re", 1, 1, &seqA, reA);
|
||||
m_sigs[OP_SEQ_IN_RE] = alloc(psig, m, "seq.in.re", 1, 2, seqAreA, boolT);
|
||||
m_sigs[OP_STRING_CONST] = 0;
|
||||
m_sigs[OP_STRING_STRIDOF] = alloc(psig, m, "str.indexof", 0, 3, str2TintT, intT);
|
||||
m_sigs[OP_STRING_STRREPL] = alloc(psig, m, "str.replace", 0, 3, str3T, strT);
|
||||
m_sigs[_OP_STRING_STRIDOF] = alloc(psig, m, "str.indexof", 0, 3, str2TintT, intT);
|
||||
m_sigs[_OP_STRING_STRREPL] = alloc(psig, m, "str.replace", 0, 3, str3T, strT);
|
||||
m_sigs[OP_STRING_ITOS] = alloc(psig, m, "int.to.str", 0, 1, &intT, strT);
|
||||
m_sigs[OP_STRING_STOI] = alloc(psig, m, "str.to.int", 0, 1, &strT, intT);
|
||||
m_sigs[OP_REGEXP_LOOP] = alloc(psig, m, "re.loop", 0, 2, strTint2T, reT); // maybe 3 arguments.
|
||||
|
@ -347,6 +351,17 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
info.set_left_associative();
|
||||
return m.mk_func_decl(m_sigs[k]->m_name, rng, rng, rng, info);
|
||||
}
|
||||
|
||||
case OP_SEQ_REPLACE:
|
||||
return mk_seq_fun(k, arity, domain, range, _OP_STRING_STRREPL);
|
||||
case _OP_STRING_STRREPL:
|
||||
return mk_str_fun(k, arity, domain, range, OP_SEQ_REPLACE);
|
||||
|
||||
case OP_SEQ_INDEX:
|
||||
return mk_seq_fun(k, arity, domain, range, _OP_STRING_STRIDOF);
|
||||
case _OP_STRING_STRIDOF:
|
||||
return mk_str_fun(k, arity, domain, range, OP_SEQ_INDEX);
|
||||
|
||||
case OP_SEQ_PREFIX:
|
||||
return mk_seq_fun(k, arity, domain, range, _OP_STRING_PREFIX);
|
||||
case _OP_STRING_PREFIX:
|
||||
|
@ -387,8 +402,6 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
case _OP_STRING_SUBSTR:
|
||||
return mk_str_fun(k, arity, domain, range, OP_SEQ_EXTRACT);
|
||||
|
||||
case OP_STRING_STRIDOF:
|
||||
case OP_STRING_STRREPL:
|
||||
case OP_STRING_ITOS:
|
||||
case OP_STRING_STOI:
|
||||
case OP_REGEXP_LOOP:
|
||||
|
|
|
@ -39,8 +39,10 @@ enum seq_op_kind {
|
|||
OP_SEQ_SUFFIX,
|
||||
OP_SEQ_CONTAINS,
|
||||
OP_SEQ_EXTRACT,
|
||||
OP_SEQ_REPLACE,
|
||||
OP_SEQ_AT,
|
||||
OP_SEQ_LENGTH,
|
||||
OP_SEQ_LENGTH,
|
||||
OP_SEQ_INDEX,
|
||||
OP_SEQ_TO_RE,
|
||||
OP_SEQ_IN_RE,
|
||||
|
||||
|
@ -59,12 +61,11 @@ enum seq_op_kind {
|
|||
|
||||
// string specific operators.
|
||||
OP_STRING_CONST,
|
||||
OP_STRING_STRIDOF, // TBD generalize
|
||||
OP_STRING_STRREPL, // TBD generalize
|
||||
OP_STRING_ITOS,
|
||||
OP_STRING_STOI,
|
||||
OP_REGEXP_LOOP, // TBD re-loop: integers as parameters or arguments?
|
||||
// internal only operators. Converted to SEQ variants.
|
||||
_OP_STRING_STRREPL,
|
||||
_OP_STRING_CONCAT,
|
||||
_OP_STRING_LENGTH,
|
||||
_OP_STRING_STRCTN,
|
||||
|
@ -74,6 +75,7 @@ enum seq_op_kind {
|
|||
_OP_STRING_TO_REGEXP,
|
||||
_OP_STRING_CHARAT,
|
||||
_OP_STRING_SUBSTR,
|
||||
_OP_STRING_STRIDOF,
|
||||
_OP_SEQ_SKOLEM,
|
||||
LAST_SEQ_OP
|
||||
};
|
||||
|
@ -175,6 +177,9 @@ public:
|
|||
app* mk_string(char const* s) { return mk_string(symbol(s)); }
|
||||
app* mk_string(std::string const& s) { return mk_string(symbol(s.c_str())); }
|
||||
app* mk_concat(expr* a, expr* b) { expr* es[2] = { a, b }; return m.mk_app(m_fid, OP_SEQ_CONCAT, 2, es); }
|
||||
app* mk_concat(expr* a, expr* b, expr* c) {
|
||||
return mk_concat(mk_concat(a, b), c);
|
||||
}
|
||||
expr* mk_concat(unsigned n, expr* const* es) { if (n == 1) return es[0]; SASSERT(n > 1); return m.mk_app(m_fid, OP_SEQ_CONCAT, n, es); }
|
||||
app* mk_length(expr* a) { return m.mk_app(m_fid, OP_SEQ_LENGTH, 1, &a); }
|
||||
app* mk_substr(expr* a, expr* b, expr* c) { expr* es[3] = { a, b, c }; return m.mk_app(m_fid, OP_SEQ_EXTRACT, 3, es); }
|
||||
|
@ -200,8 +205,8 @@ public:
|
|||
bool is_extract(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_EXTRACT); }
|
||||
bool is_contains(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_CONTAINS); }
|
||||
bool is_at(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_AT); }
|
||||
bool is_stridof(expr const* n) const { return is_app_of(n, m_fid, OP_STRING_STRIDOF); }
|
||||
bool is_repl(expr const* n) const { return is_app_of(n, m_fid, OP_STRING_STRREPL); }
|
||||
bool is_index(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_INDEX); }
|
||||
bool is_replace(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_REPLACE); }
|
||||
bool is_prefix(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_PREFIX); }
|
||||
bool is_suffix(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_SUFFIX); }
|
||||
bool is_itos(expr const* n) const { return is_app_of(n, m_fid, OP_STRING_ITOS); }
|
||||
|
@ -215,8 +220,8 @@ public:
|
|||
MATCH_TERNARY(is_extract);
|
||||
MATCH_BINARY(is_contains);
|
||||
MATCH_BINARY(is_at);
|
||||
MATCH_BINARY(is_stridof);
|
||||
MATCH_BINARY(is_repl);
|
||||
MATCH_BINARY(is_index);
|
||||
MATCH_TERNARY(is_replace);
|
||||
MATCH_BINARY(is_prefix);
|
||||
MATCH_BINARY(is_suffix);
|
||||
MATCH_UNARY(is_itos);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue