#include "options/strings_options.h"
#include "smt/logic_exception.h"
#include "theory/arith/arith_msum.h"
+#include "theory/strings/theory_strings_utils.h"
#include "theory/theory.h"
#include "util/integer.h"
#include "util/rational.h"
std::vector< Node > mchildren_s;
std::vector< Node > children_s;
mchildren_s.push_back( xc );
- getConcat( rc[i], children_s );
+ utils::getConcat(rc[i], children_s);
Node ret = simpleRegexpConsume( mchildren_s, children_s, t );
if( !ret.isNull() ){
// one conjunct cannot be satisfied, return false
std::reverse( mchildren_s.begin(), mchildren_s.end() );
}
std::vector< Node > children_s;
- getConcat( rc[0], children_s );
+ utils::getConcat(rc[0], children_s);
Trace("regexp-ext-rewrite-debug")
<< "...recursive call on body of star" << std::endl;
Node ret = simpleRegexpConsume( mchildren_s, children_s, t );
std::vector<Node> c[2];
for (unsigned i = 0; i < 2; i++)
{
- strings::TheoryStringsRewriter::getConcat(node[i], c[i]);
+ utils::getConcat(node[i], c[i]);
}
// check if the prefix, suffix mismatches
Node new_ret;
for (unsigned i = 0; i < 2; i++)
{
- getConcat(node[i], c[i]);
+ utils::getConcat(node[i], c[i]);
}
// ------- equality unification
bool changed = false;
if (changed)
{
// e.g. x++y = x++z ---> y = z, "AB" ++ x = "A" ++ y --> "B" ++ x = y
- Node s1 = mkConcat(STRING_CONCAT, c[0]);
- Node s2 = mkConcat(STRING_CONCAT, c[1]);
+ Node s1 = utils::mkConcat(STRING_CONCAT, c[0]);
+ Node s2 = utils::mkConcat(STRING_CONCAT, c[1]);
new_ret = s1.eqNode(s2);
node = returnRewrite(node, new_ret, "str-eq-unify");
}
}
}
- Node lhs = mkConcat(STRING_CONCAT, trimmed[i]);
- Node ss = mkConcat(STRING_CONCAT, trimmed[1 - i]);
+ Node lhs = utils::mkConcat(STRING_CONCAT, trimmed[i]);
+ Node ss = utils::mkConcat(STRING_CONCAT, trimmed[1 - i]);
if (lhs != node[i] || ss != node[1 - i])
{
// e.g.
}
std::sort(node_vec.begin() + lastIdx, node_vec.end());
- retNode = mkConcat( kind::STRING_CONCAT, node_vec );
+ retNode = utils::mkConcat(STRING_CONCAT, node_vec);
Trace("strings-rewrite-debug")
<< "Strings::rewriteConcat end " << retNode << std::endl;
return retNode;
else if (!preReStr.empty())
{
// this groups consecutive strings a++b ---> ab
- Node acc =
- nm->mkNode(STRING_TO_REGEXP, mkConcat(STRING_CONCAT, preReStr));
+ Node acc = nm->mkNode(STRING_TO_REGEXP,
+ utils::mkConcat(STRING_CONCAT, preReStr));
cvec.push_back(acc);
preReStr.clear();
}
}
}
Assert(!cvec.empty());
- retNode = mkConcat(REGEXP_CONCAT, cvec);
+ retNode = utils::mkConcat(REGEXP_CONCAT, cvec);
if (retNode != node)
{
// handles all cases where consecutive re constants are combined, and cases
for (unsigned j = l; j < u; j++)
{
vec_nodes.push_back(r);
- n = mkConcat(REGEXP_CONCAT, vec_nodes);
+ n = utils::mkConcat(REGEXP_CONCAT, vec_nodes);
vec2.push_back(n);
}
retNode = nm->mkNode(REGEXP_UNION, vec2);
if( r.getKind()==kind::REGEXP_STAR ){
for( unsigned dir=0; dir<=1; dir++ ){
std::vector< Node > mchildren;
- getConcat( x, mchildren );
+ utils::getConcat(x, mchildren);
bool success = true;
while( success ){
success = false;
std::vector< Node > children;
- getConcat( r[0], children );
+ utils::getConcat(r[0], children);
Node scn = simpleRegexpConsume( mchildren, children, dir );
if( !scn.isNull() ){
Trace("regexp-ext-rewrite") << "Regexp star : const conflict : " << node << std::endl;
Trace("regexp-ext-rewrite") << "Regexp star : full consume : " << node << std::endl;
return NodeManager::currentNM()->mkConst( true );
}else{
- retNode = NodeManager::currentNM()->mkNode( kind::STRING_IN_REGEXP, mkConcat( kind::STRING_CONCAT, mchildren ), r );
+ retNode = nm->mkNode(STRING_IN_REGEXP,
+ utils::mkConcat(STRING_CONCAT, mchildren),
+ r);
success = true;
}
}
}
}else{
std::vector< Node > children;
- getConcat( r, children );
+ utils::getConcat(r, children);
std::vector< Node > mchildren;
- getConcat( x, mchildren );
+ utils::getConcat(x, mchildren);
unsigned prevSize = children.size() + mchildren.size();
Node scn = simpleRegexpConsume( mchildren, children );
if( !scn.isNull() ){
// Given a membership (str.++ x1 ... xn) in (re.++ r1 ... rm),
// above, we strip components to construct an equivalent membership:
// (str.++ xi .. xj) in (re.++ rk ... rl).
- Node xn = mkConcat(kind::STRING_CONCAT, mchildren);
+ Node xn = utils::mkConcat(STRING_CONCAT, mchildren);
Node emptyStr = nm->mkConst(String(""));
if( children.empty() ){
// If we stripped all components on the right, then the left is
}else{
// otherwise, construct the updated regular expression
retNode = nm->mkNode(
- STRING_IN_REGEXP, xn, mkConcat(REGEXP_CONCAT, children));
+ STRING_IN_REGEXP, xn, utils::mkConcat(REGEXP_CONCAT, children));
}
Trace("regexp-ext-rewrite") << "Regexp : rewrite : " << node << " -> " << retNode << std::endl;
return returnRewrite(node, retNode, "re-simple-consume");
}
std::vector<Node> n1;
- getConcat(node[0], n1);
+ utils::getConcat(node[0], n1);
// definite inclusion
if (node[1] == zero)
if (curr != zero && !n1.empty())
{
childrenr.push_back(nm->mkNode(kind::STRING_SUBSTR,
- mkConcat(kind::STRING_CONCAT, n1),
+ utils::mkConcat(STRING_CONCAT, n1),
node[1],
curr));
}
- Node ret = mkConcat(kind::STRING_CONCAT, childrenr);
+ Node ret = utils::mkConcat(STRING_CONCAT, childrenr);
return returnRewrite(node, ret, "ss-len-include");
}
}
if (r == 0)
{
Node ret = nm->mkNode(kind::STRING_SUBSTR,
- mkConcat(kind::STRING_CONCAT, n1),
+ utils::mkConcat(STRING_CONCAT, n1),
curr,
node[2]);
return returnRewrite(node, ret, "ss-strip-start-pt");
else
{
Node ret = nm->mkNode(kind::STRING_SUBSTR,
- mkConcat(kind::STRING_CONCAT, n1),
+ utils::mkConcat(STRING_CONCAT, n1),
node[1],
node[2]);
return returnRewrite(node, ret, "ss-strip-end-pt");
if (node[0].getKind() == STRING_CONCAT)
{
std::vector<Node> nc1;
- getConcat(node[0], nc1);
+ utils::getConcat(node[0], nc1);
NodeBuilder<> nb(OR);
for (const Node& ncc : nc1)
{
}
}
std::vector<Node> nc1;
- getConcat(node[0], nc1);
+ utils::getConcat(node[0], nc1);
std::vector<Node> nc2;
- getConcat(node[1], nc2);
+ utils::getConcat(node[1], nc2);
// component-wise containment
std::vector<Node> nc1rb;
if (stripConstantEndpoints(nc1, nc2, nb, ne))
{
Node ret = NodeManager::currentNM()->mkNode(
- kind::STRING_STRCTN, mkConcat(kind::STRING_CONCAT, nc1), node[1]);
+ kind::STRING_STRCTN, utils::mkConcat(STRING_CONCAT, nc1), node[1]);
return returnRewrite(node, ret, "ctn-strip-endpt");
}
if (s.noOverlapWith(t))
{
std::vector<Node> nc0;
- getConcat(node[0], nc0);
+ utils::getConcat(node[0], nc0);
std::vector<Node> spl[2];
spl[0].insert(spl[0].end(), nc0.begin(), nc0.begin() + i);
Assert(i < nc0.size() - 1);
kind::OR,
NodeManager::currentNM()->mkNode(
kind::STRING_STRCTN,
- mkConcat(kind::STRING_CONCAT, spl[0]),
+ utils::mkConcat(STRING_CONCAT, spl[0]),
node[1]),
NodeManager::currentNM()->mkNode(
kind::STRING_STRCTN,
- mkConcat(kind::STRING_CONCAT, spl[1]),
+ utils::mkConcat(STRING_CONCAT, spl[1]),
node[1]));
return returnRewrite(node, ret, "ctn-split");
}
// evaluation and simple cases
std::vector<Node> children0;
- getConcat(node[0], children0);
+ utils::getConcat(node[0], children0);
if (children0[0].isConst() && node[1].isConst() && node[2].isConst())
{
CVC4::Rational rMaxInt(CVC4::String::maxSize());
<< fstr << ", " << node[1] << ")" << std::endl;
Trace("strings-rewrite-debug") << "...got " << cmp_conr << std::endl;
std::vector<Node> children1;
- getConcat(node[1], children1);
+ utils::getConcat(node[1], children1);
if (!cmp_conr.isNull())
{
if (cmp_conr.getConst<bool>())
{
// For example:
// str.indexof(str.++(x,y,z),y,0) ---> str.indexof(str.++(x,y),y,0)
- Node nn = mkConcat(kind::STRING_CONCAT, children0);
+ Node nn = utils::mkConcat(STRING_CONCAT, children0);
Node ret = nm->mkNode(kind::STRING_STRIDOF, nn, node[1], node[2]);
return returnRewrite(node, ret, "idof-def-ctn");
}
Node ret =
nm->mkNode(kind::PLUS,
nm->mkNode(kind::STRING_LENGTH,
- mkConcat(kind::STRING_CONCAT, nb)),
+ utils::mkConcat(STRING_CONCAT, nb)),
nm->mkNode(kind::STRING_STRIDOF,
- mkConcat(kind::STRING_CONCAT, children0),
+ utils::mkConcat(STRING_CONCAT, children0),
node[1],
node[2]));
return returnRewrite(node, ret, "idof-strip-cnst-endpts");
// implies
// str.indexof( str.++( x1, x2 ), y, z ) --->
// str.len( x1 ) + str.indexof( x2, y, z-str.len(x1) )
- Node nn = mkConcat(kind::STRING_CONCAT, children0);
+ Node nn = utils::mkConcat(STRING_CONCAT, children0);
Node ret =
nm->mkNode(kind::PLUS,
nm->mkNode(kind::MINUS, node[2], new_len),
// For example:
// str.indexof(str.++("ABCD", x), y, 3) --->
// str.indexof(str.++("AAAD", x), y, 3)
- Node nodeNr = mkConcat(kind::STRING_CONCAT, nr);
+ Node nodeNr = utils::mkConcat(STRING_CONCAT, nr);
Node normNr = lengthPreserveRewrite(nodeNr);
if (normNr != nodeNr)
{
std::vector<Node> normNrChildren;
- getConcat(normNr, normNrChildren);
+ utils::getConcat(normNr, normNrChildren);
std::vector<Node> children(normNrChildren);
children.insert(children.end(), children0.begin(), children0.end());
- Node nn = mkConcat(kind::STRING_CONCAT, children);
+ Node nn = utils::mkConcat(STRING_CONCAT, children);
Node res = nm->mkNode(kind::STRING_STRIDOF, nn, node[1], node[2]);
return returnRewrite(node, res, "idof-norm-prefix");
}
std::vector<Node> ce;
if (stripConstantEndpoints(children0, children1, cb, ce, -1))
{
- Node ret = mkConcat(kind::STRING_CONCAT, children0);
+ Node ret = utils::mkConcat(STRING_CONCAT, children0);
ret = nm->mkNode(STRING_STRIDOF, ret, node[1], node[2]);
// For example:
// str.indexof( str.++( x, "A" ), "B", 0 ) ---> str.indexof( x, "B", 0 )
}
std::vector<Node> children0;
- getConcat(node[0], children0);
+ utils::getConcat(node[0], children0);
if (node[1].isConst() && children0[0].isConst())
{
children.push_back(node[2]);
children.push_back(ns3);
children.insert(children.end(), children0.begin() + 1, children0.end());
- Node ret = mkConcat(kind::STRING_CONCAT, children);
+ Node ret = utils::mkConcat(STRING_CONCAT, children);
return returnRewrite(node, ret, "rpl-const-find");
}
}
if (allEmptyEqs)
{
- Node nn1 = mkConcat(STRING_CONCAT, emptyNodes);
+ Node nn1 = utils::mkConcat(STRING_CONCAT, emptyNodes);
if (node[1] != nn1)
{
Node ret = nm->mkNode(STRING_STRREPL, node[0], nn1, node[2]);
}
std::vector<Node> children1;
- getConcat(node[1], children1);
+ utils::getConcat(node[1], children1);
// check if contains definitely does (or does not) hold
Node cmp_con = nm->mkNode(kind::STRING_STRCTN, node[0], node[1]);
std::vector<Node> cres;
cres.push_back(node[2]);
cres.insert(cres.end(), ce.begin(), ce.end());
- Node ret = mkConcat(kind::STRING_CONCAT, cres);
+ Node ret = utils::mkConcat(STRING_CONCAT, cres);
return returnRewrite(node, ret, "rpl-cctn-rpl");
}
else if (!ce.empty())
std::vector<Node> cc;
cc.push_back(NodeManager::currentNM()->mkNode(
kind::STRING_STRREPL,
- mkConcat(kind::STRING_CONCAT, children0),
+ utils::mkConcat(STRING_CONCAT, children0),
node[1],
node[2]));
cc.insert(cc.end(), ce.begin(), ce.end());
- Node ret = mkConcat(kind::STRING_CONCAT, cc);
+ Node ret = utils::mkConcat(STRING_CONCAT, cc);
return returnRewrite(node, ret, "rpl-cctn");
}
}
if (node[0] == empty && allEmptyEqs)
{
std::vector<Node> emptyNodesList(emptyNodes.begin(), emptyNodes.end());
- Node nn1 = mkConcat(STRING_CONCAT, emptyNodesList);
+ Node nn1 = utils::mkConcat(STRING_CONCAT, emptyNodesList);
if (nn1 != node[1] || nn2 != node[2])
{
Node res = nm->mkNode(kind::STRING_STRREPL, node[0], nn1, nn2);
cc.insert(cc.end(), cb.begin(), cb.end());
cc.push_back(NodeManager::currentNM()->mkNode(
kind::STRING_STRREPL,
- mkConcat(kind::STRING_CONCAT, children0),
+ utils::mkConcat(STRING_CONCAT, children0),
node[1],
node[2]));
cc.insert(cc.end(), ce.begin(), ce.end());
- Node ret = mkConcat(kind::STRING_CONCAT, cc);
+ Node ret = utils::mkConcat(STRING_CONCAT, cc);
return returnRewrite(node, ret, "rpl-pull-endpt");
}
}
}
children1.clear();
- getConcat(node[1], children1);
+ utils::getConcat(node[1], children1);
Node lastChild1 = children1[children1.size() - 1];
if (lastChild1.getKind() == kind::STRING_SUBSTR)
{
children1.pop_back();
// Length of the non-substr components in the second argument
Node partLen1 = nm->mkNode(kind::STRING_LENGTH,
- mkConcat(kind::STRING_CONCAT, children1));
+ utils::mkConcat(STRING_CONCAT, children1));
Node maxLen1 = nm->mkNode(kind::PLUS, partLen1, lastChild1[2]);
Node zero = nm->mkConst(Rational(0));
kind::PLUS, len0, one, nm->mkNode(kind::UMINUS, partLen1))));
Node res = nm->mkNode(kind::STRING_STRREPL,
node[0],
- mkConcat(kind::STRING_CONCAT, children1),
+ utils::mkConcat(STRING_CONCAT, children1),
node[2]);
return returnRewrite(node, res, "repl-subst-idx");
}
std::vector<Node> checkLhs;
checkLhs.insert(
checkLhs.end(), children0.begin(), children0.begin() + checkIndex);
- Node lhs = mkConcat(STRING_CONCAT, checkLhs);
+ Node lhs = utils::mkConcat(STRING_CONCAT, checkLhs);
Node rhs = children0[checkIndex];
Node ctn = checkEntailContains(lhs, rhs);
if (!ctn.isNull() && ctn.getConst<bool>())
{
std::vector<Node> remc(children0.begin() + lastCheckIndex,
children0.end());
- Node rem = mkConcat(STRING_CONCAT, remc);
+ Node rem = utils::mkConcat(STRING_CONCAT, remc);
Node ret =
nm->mkNode(STRING_CONCAT,
nm->mkNode(STRING_STRREPL, lastLhs, node[1], node[2]),
}
} while (curr != std::string::npos && curr < s.size());
// constant evaluation
- Node res = mkConcat(STRING_CONCAT, children);
+ Node res = utils::mkConcat(STRING_CONCAT, children);
return returnRewrite(node, res, "replall-const");
}
}
std::vector<Node> n1;
- getConcat(n[0], n1);
+ utils::getConcat(n[0], n1);
std::vector<Node> n2;
- getConcat(n[1], n2);
+ utils::getConcat(n[1], n2);
Assert(!n1.empty() && !n2.empty());
// constant prefixes
return n;
}
-void TheoryStringsRewriter::getConcat( Node n, std::vector< Node >& c ) {
- if( n.getKind()==kind::STRING_CONCAT || n.getKind()==kind::REGEXP_CONCAT ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- c.push_back( n[i] );
- }
- }else{
- c.push_back( n );
- }
-}
-
-Node TheoryStringsRewriter::mkConcat( Kind k, std::vector< Node >& c ){
- Assert( !c.empty() || k==kind::STRING_CONCAT );
- return c.size()>1 ? NodeManager::currentNM()->mkNode( k, c ) : ( c.size()==1 ? c[0] : NodeManager::currentNM()->mkConst( ::CVC4::String("") ) );
-}
-
Node TheoryStringsRewriter::splitConstant( Node a, Node b, int& index, bool isRev ) {
Assert( a.isConst() && b.isConst() );
index = a.getConst<String>().size() <= b.getConst<String>().size() ? 1 : 0;
if( isRev ){
std::reverse( c.begin(), c.end() );
}
- Node cc = Rewriter::rewrite( mkConcat( kind::STRING_CONCAT, c ) );
+ Node cc = Rewriter::rewrite(utils::mkConcat(STRING_CONCAT, c));
Assert( cc.isConst() );
return cc;
}else{
return Node::null();
}
std::vector<Node> snChildren;
- getConcat(sn, snChildren);
+ utils::getConcat(sn, snChildren);
concatBuilder.append(snChildren);
}
res = concatBuilder.constructNode();
Node nRep = canonicalStrForSymbolicLength(len[1]);
std::vector<Node> nRepChildren;
- getConcat(nRep, nRepChildren);
+ utils::getConcat(nRep, nRepChildren);
NodeBuilder<> concatBuilder(kind::STRING_CONCAT);
for (size_t i = 0, reps = intReps.getUnsignedInt(); i < reps; i++)
{
NodeManager* nm = NodeManager::currentNM();
std::vector<Node> avec;
- getConcat(getMultisetApproximation(a), avec);
+ utils::getConcat(getMultisetApproximation(a), avec);
std::vector<Node> bvec;
- getConcat(b, bvec);
+ utils::getConcat(b, bvec);
std::map<Node, unsigned> num_nconst[2];
std::map<Node, unsigned> num_const[2];
NodeManager* nm = NodeManager::currentNM();
std::vector<Node> avec;
- getConcat(getMultisetApproximation(a), avec);
+ utils::getConcat(getMultisetApproximation(a), avec);
bool cValid = false;
unsigned c = 0;
// (= x (str.++ y1' ... ym'))
if (!cs.empty())
{
- nb << nm->mkNode(EQUAL, x, mkConcat(STRING_CONCAT, cs));
+ nb << nm->mkNode(EQUAL, x, utils::mkConcat(STRING_CONCAT, cs));
}
// (= y1'' "") ... (= yk'' "")
for (const Node& zeroLen : zeroLens)