summaryrefslogtreecommitdiff
path: root/src/theory/strings/sequences_rewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/strings/sequences_rewriter.cpp')
-rw-r--r--src/theory/strings/sequences_rewriter.cpp169
1 files changed, 135 insertions, 34 deletions
diff --git a/src/theory/strings/sequences_rewriter.cpp b/src/theory/strings/sequences_rewriter.cpp
index babf260fc..fbb40f212 100644
--- a/src/theory/strings/sequences_rewriter.cpp
+++ b/src/theory/strings/sequences_rewriter.cpp
@@ -352,7 +352,7 @@ Node SequencesRewriter::rewriteStrEqualityExt(Node node)
}
else if (ne.getKind() == STRING_SUBSTR)
{
- Node zero = nm->mkConst(Rational(0));
+ Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
if (d_arithEntail.check(ne[1], false)
&& d_arithEntail.check(ne[2], true))
@@ -586,7 +586,8 @@ Node SequencesRewriter::rewriteLength(Node node)
Kind nk0 = node[0].getKind();
if (node[0].isConst())
{
- Node retNode = nm->mkConst(Rational(Word::getLength(node[0])));
+ Node retNode =
+ nm->mkConst(CONST_RATIONAL, Rational(Word::getLength(node[0])));
return returnRewrite(node, retNode, Rewrite::LEN_EVAL);
}
else if (nk0 == kind::STRING_CONCAT)
@@ -599,8 +600,8 @@ Node SequencesRewriter::rewriteLength(Node node)
{
if (tmpNode[i].isConst())
{
- node_vec.push_back(
- nm->mkConst(Rational(Word::getLength(tmpNode[i]))));
+ node_vec.push_back(nm->mkConst(
+ CONST_RATIONAL, Rational(Word::getLength(tmpNode[i]))));
}
else
{
@@ -633,7 +634,7 @@ Node SequencesRewriter::rewriteLength(Node node)
}
else if (nk0 == SEQ_UNIT)
{
- Node retNode = nm->mkConst(Rational(1));
+ Node retNode = nm->mkConst(CONST_RATIONAL, Rational(1));
return returnRewrite(node, retNode, Rewrite::LEN_SEQ_UNIT);
}
return node;
@@ -978,11 +979,17 @@ Node SequencesRewriter::rewriteAndOrRegExp(TNode node)
Assert(nk == REGEXP_UNION || nk == REGEXP_INTER);
Trace("strings-rewrite-debug")
<< "Strings::rewriteAndOrRegExp start " << node << std::endl;
+ NodeManager* nm = NodeManager::currentNM();
std::vector<Node> node_vec;
std::vector<Node> polRegExp[2];
+ // list of constant string regular expressions (str.to_re c)
+ std::vector<Node> constStrRe;
+ // list of all other regular expressions
+ std::vector<Node> otherRe;
for (const Node& ni : node)
{
- if (ni.getKind() == nk)
+ Kind nik = ni.getKind();
+ if (nik == nk)
{
for (const Node& nic : ni)
{
@@ -992,7 +999,7 @@ Node SequencesRewriter::rewriteAndOrRegExp(TNode node)
}
}
}
- else if (ni.getKind() == REGEXP_NONE)
+ else if (nik == REGEXP_NONE)
{
if (nk == REGEXP_INTER)
{
@@ -1000,7 +1007,7 @@ Node SequencesRewriter::rewriteAndOrRegExp(TNode node)
}
// otherwise, can ignore
}
- else if (ni.getKind() == REGEXP_STAR && ni[0].getKind() == REGEXP_ALLCHAR)
+ else if (nik == REGEXP_STAR && ni[0].getKind() == REGEXP_ALLCHAR)
{
if (nk == REGEXP_UNION)
{
@@ -1010,13 +1017,103 @@ Node SequencesRewriter::rewriteAndOrRegExp(TNode node)
}
else if (std::find(node_vec.begin(), node_vec.end(), ni) == node_vec.end())
{
+ if (nik == STRING_TO_REGEXP && ni[0].isConst())
+ {
+ if (nk == REGEXP_INTER)
+ {
+ if (!constStrRe.empty())
+ {
+ Assert(constStrRe[0][0] != ni[0]);
+ // (re.inter .. (str.to_re c1) .. (str.to_re c2) ..) ---> re.none
+ // for distinct constant strings c1, c2.
+ Node ret = nm->mkNode(kind::REGEXP_NONE);
+ return returnRewrite(
+ node, ret, Rewrite::RE_INTER_CONST_CONST_CONFLICT);
+ }
+ }
+ else
+ {
+ Assert(nk == REGEXP_UNION);
+ }
+ constStrRe.push_back(ni);
+ }
+ else
+ {
+ otherRe.push_back(ni);
+ uint32_t pindex = nik == REGEXP_COMPLEMENT ? 1 : 0;
+ Node nia = pindex == 1 ? ni[0] : ni;
+ polRegExp[pindex].push_back(nia);
+ }
node_vec.push_back(ni);
- uint32_t pindex = ni.getKind() == REGEXP_COMPLEMENT ? 1 : 0;
- Node nia = pindex == 1 ? ni[0] : ni;
- polRegExp[pindex].push_back(nia);
}
}
- NodeManager* nm = NodeManager::currentNM();
+ Trace("strings-rewrite-debug")
+ << "Partition constant components " << constStrRe.size() << " / "
+ << otherRe.size() << std::endl;
+ // go back and process constant strings against the others
+ if (!constStrRe.empty())
+ {
+ std::unordered_set<Node> toRemove;
+ for (const Node& c : constStrRe)
+ {
+ Assert(c.getKind() == STRING_TO_REGEXP && c[0].getKind() == CONST_STRING);
+ cvc5::String s = c[0].getConst<String>();
+ for (const Node& r : otherRe)
+ {
+ Trace("strings-rewrite-debug")
+ << "Check " << c << " vs " << r << std::endl;
+ // skip if already removing, or not constant
+ if (!RegExpEntail::isConstRegExp(r)
+ || toRemove.find(r) != toRemove.end())
+ {
+ Trace("strings-rewrite-debug") << "...skip" << std::endl;
+ continue;
+ }
+ // test whether c from (str.to_re c) is in r
+ if (RegExpEntail::testConstStringInRegExp(s, 0, r))
+ {
+ Trace("strings-rewrite-debug") << "...included" << std::endl;
+ if (nk == REGEXP_INTER)
+ {
+ // (re.inter .. (str.to_re c) .. R ..) --->
+ // (re.inter .. (str.to_re c) .. ..) when c in R
+ toRemove.insert(r);
+ }
+ else
+ {
+ // (re.union .. (str.to_re c) .. R ..) --->
+ // (re.union .. .. R ..) when c in R
+ toRemove.insert(c);
+ break;
+ }
+ }
+ else
+ {
+ Trace("strings-rewrite-debug") << "...not included" << std::endl;
+ if (nk == REGEXP_INTER)
+ {
+ // (re.inter .. (str.to_re c) .. R ..) ---> re.none
+ // if c is not a member of R.
+ Node ret = nm->mkNode(kind::REGEXP_NONE);
+ return returnRewrite(
+ node, ret, Rewrite::RE_INTER_CONST_RE_CONFLICT);
+ }
+ }
+ }
+ }
+ if (!toRemove.empty())
+ {
+ std::vector<Node> nodeVecTmp;
+ node_vec.swap(nodeVecTmp);
+ for (const Node& nvt : nodeVecTmp)
+ {
+ if (toRemove.find(nvt) == toRemove.end())
+ {
+ node_vec.push_back(nvt);
+ }
+ }
+ }
+ }
// use inclusion tests
for (const Node& negMem : polRegExp[1])
{
@@ -1214,7 +1311,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
}
else if (r.getKind() == kind::REGEXP_ALLCHAR)
{
- Node one = nm->mkConst(Rational(1));
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
Node retNode = one.eqNode(nm->mkNode(STRING_LENGTH, x));
return returnRewrite(node, retNode, Rewrite::RE_IN_SIGMA);
}
@@ -1247,7 +1344,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
Node flr = RegExpEntail::getFixedLengthForRegexp(r[0]);
if (!flr.isNull())
{
- Node one = nm->mkConst(Rational(1));
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
if (flr == one)
{
NodeBuilder nb(AND);
@@ -1310,7 +1407,7 @@ Node SequencesRewriter::rewriteMembership(TNode node)
if (constStr.isNull())
{
// x in re.++(_*, _, _) ---> str.len(x) >= 2
- Node num = nm->mkConst(Rational(allSigmaMinSize));
+ Node num = nm->mkConst(CONST_RATIONAL, Rational(allSigmaMinSize));
Node lenx = nm->mkNode(STRING_LENGTH, x);
Node retNode = nm->mkNode(allSigmaStrict ? EQUAL : GEQ, lenx, num);
return returnRewrite(node, retNode, Rewrite::RE_CONCAT_PURE_ALLCHAR);
@@ -1602,9 +1699,10 @@ TrustNode SequencesRewriter::expandDefinition(Node node)
Node s = node[0];
Node n = node[1];
// seq.nth(s, n) --> ite(0 <= n < len(s), seq.nth_total(s,n), Uf(s, n))
- Node cond = nm->mkNode(AND,
- nm->mkNode(LEQ, nm->mkConst(Rational(0)), n),
- nm->mkNode(LT, n, nm->mkNode(STRING_LENGTH, s)));
+ Node cond =
+ nm->mkNode(AND,
+ nm->mkNode(LEQ, nm->mkConst(CONST_RATIONAL, Rational(0)), n),
+ nm->mkNode(LT, n, nm->mkNode(STRING_LENGTH, s)));
Node ss = nm->mkNode(SEQ_NTH_TOTAL, s, n);
Node uf = SkolemCache::mkSkolemSeqNth(s.getType(), "Uf");
Node u = nm->mkNode(APPLY_UF, uf, s, n);
@@ -1654,7 +1752,7 @@ Node SequencesRewriter::rewriteCharAt(Node node)
{
Assert(node.getKind() == STRING_CHARAT);
NodeManager* nm = NodeManager::currentNM();
- Node one = nm->mkConst(Rational(1));
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
Node retNode = nm->mkNode(STRING_SUBSTR, node[0], node[1], one);
return returnRewrite(node, retNode, Rewrite::CHARAT_ELIM);
}
@@ -1732,7 +1830,7 @@ Node SequencesRewriter::rewriteSubstr(Node node)
}
}
}
- Node zero = nm->mkConst(cvc5::Rational(0));
+ Node zero = nm->mkConst(CONST_RATIONAL, cvc5::Rational(0));
// if entailed non-positive length or negative start point
if (d_arithEntail.check(zero, node[1], true))
@@ -2331,7 +2429,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (node[2].isConst() && node[2].getConst<Rational>().sgn() < 0)
{
// z<0 implies str.indexof( x, y, z ) --> -1
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NEG);
}
@@ -2349,7 +2447,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
// We know that, due to limitations on the size of string constants
// in our implementation, that accessing a position greater than
// rMaxInt is guaranteed to be out of bounds.
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_MAX);
}
Assert(node[2].getConst<Rational>().sgn() >= 0);
@@ -2360,12 +2458,13 @@ Node SequencesRewriter::rewriteIndexof(Node node)
std::size_t ret = Word::find(s, t, start);
if (ret != std::string::npos)
{
- Node retv = nm->mkConst(Rational(static_cast<unsigned>(ret)));
+ Node retv =
+ nm->mkConst(CONST_RATIONAL, Rational(static_cast<unsigned>(ret)));
return returnRewrite(node, retv, Rewrite::IDOF_FIND);
}
else if (children0.size() == 1)
{
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NFIND);
}
}
@@ -2377,14 +2476,14 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (node[2].getConst<Rational>().sgn() == 0)
{
// indexof( x, x, 0 ) --> 0
- Node zero = nm->mkConst(Rational(0));
+ Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
return returnRewrite(node, zero, Rewrite::IDOF_EQ_CST_START);
}
}
if (d_arithEntail.check(node[2], true))
{
// y>0 implies indexof( x, x, y ) --> -1
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_EQ_NSTART);
}
Node emp = Word::mkEmptyWord(stype);
@@ -2415,7 +2514,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
if (d_arithEntail.check(len1, len0m2, true))
{
// len(x)-z < len(y) implies indexof( x, y, z ) ----> -1
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_LEN);
}
@@ -2497,7 +2596,7 @@ Node SequencesRewriter::rewriteIndexof(Node node)
else
{
// str.contains( x, y ) --> false implies str.indexof(x,y,z) --> -1
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::IDOF_NCTN);
}
}
@@ -2552,12 +2651,12 @@ Node SequencesRewriter::rewriteIndexofRe(Node node)
Node s = node[0];
Node r = node[1];
Node n = node[2];
- Node zero = nm->mkConst(Rational(0));
+ Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
Node slen = nm->mkNode(STRING_LENGTH, s);
if (d_arithEntail.check(zero, n, true) || d_arithEntail.check(n, slen, true))
{
- Node ret = nm->mkConst(Rational(-1));
+ Node ret = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, ret, Rewrite::INDEXOF_RE_INVALID_INDEX);
}
@@ -2572,7 +2671,7 @@ Node SequencesRewriter::rewriteIndexofRe(Node node)
// We know that, due to limitations on the size of string constants
// in our implementation, that accessing a position greater than
// rMaxInt is guaranteed to be out of bounds.
- Node negone = nm->mkConst(Rational(-1));
+ Node negone = nm->mkConst(CONST_RATIONAL, Rational(-1));
return returnRewrite(node, negone, Rewrite::INDEXOF_RE_MAX_INDEX);
}
@@ -2580,6 +2679,7 @@ Node SequencesRewriter::rewriteIndexofRe(Node node)
Node rem = nm->mkConst(s.getConst<String>().substr(start));
std::pair<size_t, size_t> match = firstMatch(rem, r);
Node ret = nm->mkConst(
+ CONST_RATIONAL,
Rational(match.first == string::npos
? -1
: static_cast<int64_t>(start + match.first)));
@@ -2843,8 +2943,8 @@ Node SequencesRewriter::rewriteReplace(Node node)
nm->mkNode(kind::STRING_LENGTH, utils::mkConcat(children1, stype));
Node maxLen1 = nm->mkNode(kind::PLUS, partLen1, lastChild1[2]);
- Node zero = nm->mkConst(Rational(0));
- Node one = nm->mkConst(Rational(1));
+ Node zero = nm->mkConst(CONST_RATIONAL, Rational(0));
+ Node one = nm->mkConst(CONST_RATIONAL, Rational(1));
Node len0 = nm->mkNode(kind::STRING_LENGTH, node[0]);
Node len0_1 = nm->mkNode(kind::PLUS, len0, one);
// Check len(t) + j > len(x) + 1
@@ -3367,7 +3467,8 @@ Node SequencesRewriter::rewritePrefixSuffix(Node n)
Node val;
if (isPrefix)
{
- val = NodeManager::currentNM()->mkConst(::cvc5::Rational(0));
+ val =
+ NodeManager::currentNM()->mkConst(CONST_RATIONAL, ::cvc5::Rational(0));
}
else
{
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback