diff --git a/src/ast/rewriter/seq_rewriter.cpp b/src/ast/rewriter/seq_rewriter.cpp index 49957a01f..30d43105c 100644 --- a/src/ast/rewriter/seq_rewriter.cpp +++ b/src/ast/rewriter/seq_rewriter.cpp @@ -1673,6 +1673,37 @@ br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) { result = a; return BR_DONE; } + expr* a1 = nullptr, *b1 = nullptr; + if (m_util.re.is_star(a, a1) && m_util.re.is_star(b, b1) && a1 == b1) { + result = a; + return BR_DONE; + } + if (m_util.re.is_star(a, a1) && a1 == b) { + result = m_util.re.mk_concat(b, a); + return BR_DONE; + } + { + unsigned lo1, hi1, lo2, hi2; + if (m_util.re.is_loop(a, a1, lo1, hi1) && m_util.re.is_loop(b, b1, lo2, hi2) && a1 == b1) { + result = m_util.re.mk_loop(a1, lo1 + lo2, hi1 + hi2); + return BR_DONE; + } + if (m_util.re.is_loop(a, a1, lo1) && m_util.re.is_loop(b, b1, lo2) && a1 == b1) { + result = m_util.re.mk_loop(a1, lo1 + lo2); + return BR_DONE; + } + } + { + expr* lo1, *hi1, *lo2, *hi2; + if (m_util.re.is_loop(a, a1, lo1, hi1) && m_util.re.is_loop(b, b1, lo2, hi2) && a1 == b1) { + result = m_util.re.mk_loop(a1, m_autil.mk_add(lo1, lo2), m_autil.mk_add(hi1, hi2)); + return BR_DONE; + } + if (m_util.re.is_loop(a, a1, lo1) && m_util.re.is_loop(b, b1, lo2) && a1 == b1) { + result = m_util.re.mk_loop(a1, m_autil.mk_add(lo1, lo2)); + return BR_DONE; + } + } return BR_FAILED; } /* diff --git a/src/ast/seq_decl_plugin.cpp b/src/ast/seq_decl_plugin.cpp index 6a0cb3ff8..105a498f9 100644 --- a/src/ast/seq_decl_plugin.cpp +++ b/src/ast/seq_decl_plugin.cpp @@ -1093,6 +1093,16 @@ app* seq_util::re::mk_loop(expr* r, unsigned lo, unsigned hi) { return m.mk_app(m_fid, OP_RE_LOOP, 2, params, 1, &r); } +app* seq_util::re::mk_loop(expr* r, expr* lo) { + expr* rs[2] = { r, lo }; + return m.mk_app(m_fid, OP_RE_LOOP, 0, nullptr, 2, rs); +} + +app* seq_util::re::mk_loop(expr* r, expr* lo, expr* hi) { + expr* rs[3] = { r, lo, hi }; + return m.mk_app(m_fid, OP_RE_LOOP, 0, nullptr, 3, rs); +} + app* seq_util::re::mk_full_char(sort* s) { return m.mk_app(m_fid, OP_RE_FULL_CHAR_SET, 0, nullptr, 0, nullptr, s); } @@ -1129,3 +1139,28 @@ bool seq_util::re::is_loop(expr const* n, expr*& body, unsigned& lo) { } return false; } + +bool seq_util::re::is_loop(expr const* n, expr*& body, expr*& lo, expr*& hi) { + if (is_loop(n)) { + app const* a = to_app(n); + if (a->get_num_args() == 3) { + body = a->get_arg(0); + lo = a->get_arg(1); + hi = a->get_arg(2); + return true; + } + } + return false; +} + +bool seq_util::re::is_loop(expr const* n, expr*& body, expr*& lo) { + if (is_loop(n)) { + app const* a = to_app(n); + if (a->get_num_args() == 2) { + body = a->get_arg(0); + lo = a->get_arg(1); + return true; + } + } + return false; +} diff --git a/src/ast/seq_decl_plugin.h b/src/ast/seq_decl_plugin.h index 471ed0229..c72252641 100644 --- a/src/ast/seq_decl_plugin.h +++ b/src/ast/seq_decl_plugin.h @@ -366,6 +366,8 @@ public: app* mk_opt(expr* r) { return m.mk_app(m_fid, OP_RE_OPTION, r); } app* mk_loop(expr* r, unsigned lo); app* mk_loop(expr* r, unsigned lo, unsigned hi); + app* mk_loop(expr* r, expr* lo); + app* mk_loop(expr* r, expr* lo, expr* hi); app* mk_full_char(sort* s); app* mk_full_seq(sort* s); app* mk_empty(sort* s); @@ -394,6 +396,8 @@ public: MATCH_UNARY(is_opt); bool is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi); bool is_loop(expr const* n, expr*& body, unsigned& lo); + bool is_loop(expr const* n, expr*& body, expr*& lo, expr*& hi); + bool is_loop(expr const* n, expr*& body, expr*& lo); bool is_unroll(expr const* n) const { return is_app_of(n, m_fid, _OP_RE_UNROLL); } }; str str;