Branch data Line data Source code
1 : : /******************************************************************************
2 : : * Top contributors (to current version):
3 : : * Aina Niemetz, Andres Noetzli, Andrew Reynolds
4 : : *
5 : : * This file is part of the cvc5 project.
6 : : *
7 : : * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
8 : : * in the top-level source directory and their institutional affiliations.
9 : : * All rights reserved. See the file COPYING in the top-level source
10 : : * directory for licensing information.
11 : : * ****************************************************************************
12 : : *
13 : : * Unit tests for the strings/sequences rewriter.
14 : : */
15 : :
16 : : #include <iostream>
17 : : #include <memory>
18 : : #include <vector>
19 : :
20 : : #include "expr/node.h"
21 : : #include "expr/node_manager.h"
22 : : #include "expr/sequence.h"
23 : : #include "test_smt.h"
24 : : #include "theory/rewriter.h"
25 : : #include "theory/strings/arith_entail.h"
26 : : #include "theory/strings/sequences_rewriter.h"
27 : : #include "theory/strings/strings_entail.h"
28 : : #include "theory/strings/strings_rewriter.h"
29 : : #include "util/rational.h"
30 : : #include "util/string.h"
31 : :
32 : : using namespace cvc5::internal::kind;
33 : : using namespace cvc5::internal::theory;
34 : : using namespace cvc5::internal::theory::strings;
35 : :
36 : : namespace cvc5::internal {
37 : : namespace test {
38 : :
39 : : class TestTheoryWhiteSequencesRewriter : public TestSmt
40 : : {
41 : : protected:
42 : 19 : void SetUp() override
43 : : {
44 : 19 : TestSmt::SetUp();
45 : 38 : Options opts;
46 : 19 : d_rewriter = d_slvEngine->getEnv().getRewriter();
47 : 19 : d_seqRewriter.reset(
48 : 19 : new SequencesRewriter(d_nodeManager, d_rewriter, nullptr));
49 : 19 : }
50 : :
51 : : Rewriter* d_rewriter;
52 : : std::unique_ptr<SequencesRewriter> d_seqRewriter;
53 : :
54 : 2 : void inNormalForm(Node t)
55 : : {
56 : 2 : Node res_t = d_rewriter->extendedRewrite(t);
57 : :
58 : 2 : std::cout << std::endl;
59 : 2 : std::cout << t << " ---> " << res_t << std::endl;
60 [ - + ]: 2 : ASSERT_EQ(t, res_t);
61 : : }
62 : :
63 : 103 : void sameNormalForm(Node t1, Node t2)
64 : : {
65 : 103 : Node res_t1 = d_rewriter->extendedRewrite(t1);
66 : 103 : Node res_t2 = d_rewriter->extendedRewrite(t2);
67 : :
68 : 103 : std::cout << std::endl;
69 : 103 : std::cout << t1 << " ---> " << res_t1 << std::endl;
70 : 103 : std::cout << t2 << " ---> " << res_t2 << std::endl;
71 [ - + ]: 103 : ASSERT_EQ(res_t1, res_t2);
72 : : }
73 : :
74 : 8 : void differentNormalForms(Node t1, Node t2)
75 : : {
76 : 8 : Node res_t1 = d_rewriter->extendedRewrite(t1);
77 : 8 : Node res_t2 = d_rewriter->extendedRewrite(t2);
78 : :
79 : 8 : std::cout << std::endl;
80 : 8 : std::cout << t1 << " ---> " << res_t1 << std::endl;
81 : 8 : std::cout << t2 << " ---> " << res_t2 << std::endl;
82 [ - + ]: 8 : ASSERT_NE(res_t1, res_t2);
83 : : }
84 : : };
85 : :
86 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_length_one)
87 : : {
88 : 1 : StringsEntail& se = d_seqRewriter->getStringsEntail();
89 : 1 : TypeNode intType = d_nodeManager->integerType();
90 : 1 : TypeNode strType = d_nodeManager->stringType();
91 : :
92 : 1 : Node a = d_nodeManager->mkConst(String("A"));
93 : 1 : Node abcd = d_nodeManager->mkConst(String("ABCD"));
94 : 1 : Node aaad = d_nodeManager->mkConst(String("AAAD"));
95 : 1 : Node b = d_nodeManager->mkConst(String("B"));
96 : 2 : Node x = d_nodeManager->mkVar("x", strType);
97 : 2 : Node y = d_nodeManager->mkVar("y", strType);
98 : 1 : Node negOne = d_nodeManager->mkConstInt(Rational(-1));
99 : 1 : Node zero = d_nodeManager->mkConstInt(Rational(0));
100 : 1 : Node one = d_nodeManager->mkConstInt(Rational(1));
101 : 1 : Node two = d_nodeManager->mkConstInt(Rational(2));
102 : 1 : Node three = d_nodeManager->mkConstInt(Rational(3));
103 : 2 : Node i = d_nodeManager->mkVar("i", intType);
104 : :
105 [ - + ]: 1 : ASSERT_TRUE(se.checkLengthOne(a));
106 [ - + ]: 1 : ASSERT_TRUE(se.checkLengthOne(a, true));
107 : :
108 : 2 : Node substr = d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, zero, one);
109 [ - + ]: 1 : ASSERT_TRUE(se.checkLengthOne(substr));
110 [ - + ]: 1 : ASSERT_FALSE(se.checkLengthOne(substr, true));
111 : :
112 : : substr =
113 : 4 : d_nodeManager->mkNode(Kind::STRING_SUBSTR,
114 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, x),
115 : : zero,
116 : 1 : one);
117 [ - + ]: 1 : ASSERT_TRUE(se.checkLengthOne(substr));
118 [ - + ]: 1 : ASSERT_TRUE(se.checkLengthOne(substr, true));
119 : :
120 : 1 : substr = d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, zero, two);
121 [ - + ]: 1 : ASSERT_FALSE(se.checkLengthOne(substr));
122 [ - + ]: 1 : ASSERT_FALSE(se.checkLengthOne(substr, true));
123 : : }
124 : :
125 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_arith)
126 : : {
127 : 1 : ArithEntail& ae = d_seqRewriter->getArithEntail();
128 : 1 : TypeNode intType = d_nodeManager->integerType();
129 : 1 : TypeNode strType = d_nodeManager->stringType();
130 : :
131 : 2 : Node z = d_nodeManager->mkVar("z", strType);
132 : 2 : Node n = d_nodeManager->mkVar("n", intType);
133 : 1 : Node one = d_nodeManager->mkConstInt(Rational(1));
134 : :
135 : : // 1 >= (str.len (str.substr z n 1)) ---> true
136 : 1 : Node substr_z = d_nodeManager->mkNode(
137 : : Kind::STRING_LENGTH,
138 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, z, n, one));
139 [ - + ]: 1 : ASSERT_TRUE(ae.check(one, substr_z));
140 : :
141 : : // (str.len (str.substr z n 1)) >= 1 ---> false
142 [ - + ]: 1 : ASSERT_FALSE(ae.check(substr_z, one));
143 : : }
144 : :
145 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, check_entail_with_with_assumption)
146 : : {
147 : 1 : ArithEntail& ae = d_seqRewriter->getArithEntail();
148 : 1 : TypeNode intType = d_nodeManager->integerType();
149 : 1 : TypeNode strType = d_nodeManager->stringType();
150 : :
151 : 2 : Node x = d_nodeManager->mkVar("x", intType);
152 : 2 : Node y = d_nodeManager->mkVar("y", strType);
153 : 2 : Node z = d_nodeManager->mkVar("z", intType);
154 : :
155 : 1 : Node zero = d_nodeManager->mkConstInt(Rational(0));
156 : 1 : Node one = d_nodeManager->mkConstInt(Rational(1));
157 : :
158 : 1 : Node empty = d_nodeManager->mkConst(String(""));
159 : 1 : Node a = d_nodeManager->mkConst(String("A"));
160 : :
161 : 1 : Node slen_y = d_nodeManager->mkNode(Kind::STRING_LENGTH, y);
162 : 2 : Node x_plus_slen_y = d_nodeManager->mkNode(Kind::ADD, x, slen_y);
163 : 1 : Node x_plus_slen_y_eq_zero = d_rewriter->rewrite(
164 : 2 : d_nodeManager->mkNode(Kind::EQUAL, x_plus_slen_y, zero));
165 : :
166 : : // x + (str.len y) = 0 |= 0 >= x --> true
167 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(x_plus_slen_y_eq_zero, zero, x, false));
168 : :
169 : : // x + (str.len y) = 0 |= 0 > x --> false
170 [ - + ]: 1 : ASSERT_FALSE(ae.checkWithAssumption(x_plus_slen_y_eq_zero, zero, x, true));
171 : :
172 : 3 : Node x_plus_slen_y_plus_z_eq_zero = d_rewriter->rewrite(d_nodeManager->mkNode(
173 : 4 : Kind::EQUAL, d_nodeManager->mkNode(Kind::ADD, x_plus_slen_y, z), zero));
174 : :
175 : : // x + (str.len y) + z = 0 |= 0 > x --> false
176 [ - + ]: 1 : ASSERT_FALSE(
177 : : ae.checkWithAssumption(x_plus_slen_y_plus_z_eq_zero, zero, x, true));
178 : :
179 : : Node x_plus_slen_y_plus_slen_y_eq_zero =
180 : 3 : d_rewriter->rewrite(d_nodeManager->mkNode(
181 : : Kind::EQUAL,
182 : 2 : d_nodeManager->mkNode(Kind::ADD, x_plus_slen_y, slen_y),
183 : 2 : zero));
184 : :
185 : : // x + (str.len y) + (str.len y) = 0 |= 0 >= x --> true
186 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(
187 : : x_plus_slen_y_plus_slen_y_eq_zero, zero, x, false));
188 : :
189 : 1 : Node five = d_nodeManager->mkConstInt(Rational(5));
190 : 1 : Node six = d_nodeManager->mkConstInt(Rational(6));
191 : 2 : Node x_plus_five = d_nodeManager->mkNode(Kind::ADD, x, five);
192 : : Node x_plus_five_lt_six =
193 : 2 : d_rewriter->rewrite(d_nodeManager->mkNode(Kind::LT, x_plus_five, six));
194 : :
195 : : // x + 5 < 6 |= 0 >= x --> true
196 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(x_plus_five_lt_six, zero, x, false));
197 : :
198 : : // x + 5 < 6 |= 0 > x --> false
199 [ - + ]: 1 : ASSERT_TRUE(!ae.checkWithAssumption(x_plus_five_lt_six, zero, x, true));
200 : :
201 : 1 : Node neg_x = d_nodeManager->mkNode(Kind::NEG, x);
202 : : Node x_plus_five_lt_five =
203 : 2 : d_rewriter->rewrite(d_nodeManager->mkNode(Kind::LT, x_plus_five, five));
204 : :
205 : : // x + 5 < 5 |= -x >= 0 --> true
206 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(x_plus_five_lt_five, neg_x, zero, false));
207 : :
208 : : // x + 5 < 5 |= 0 > x --> true
209 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(x_plus_five_lt_five, zero, x, false));
210 : :
211 : : // 0 < x |= x >= (str.len (int.to.str x))
212 : 2 : Node assm = d_rewriter->rewrite(d_nodeManager->mkNode(Kind::LT, zero, x));
213 [ - + ]: 1 : ASSERT_TRUE(ae.checkWithAssumption(
214 : : assm,
215 : : x,
216 : : d_nodeManager->mkNode(Kind::STRING_LENGTH,
217 : : d_nodeManager->mkNode(Kind::STRING_ITOS, x)),
218 : : false));
219 : : }
220 : :
221 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_nth)
222 : : {
223 : 2 : TypeNode intType = d_nodeManager->integerType();
224 : :
225 : 3 : Node x = d_nodeManager->mkVar("x", intType);
226 : 3 : Node y = d_nodeManager->mkVar("y", intType);
227 : 3 : Node z = d_nodeManager->mkVar("z", intType);
228 : 3 : Node w = d_nodeManager->mkVar("w", intType);
229 : 3 : Node v = d_nodeManager->mkVar("v", intType);
230 : :
231 : 2 : Node zero = d_nodeManager->mkConstInt(0);
232 : 2 : Node one = d_nodeManager->mkConstInt(1);
233 : : // Position that is greater than the maximum value that can be represented
234 : : // with a uint32_t
235 : 1 : Node largePos = d_nodeManager->mkConstInt(
236 : 2 : static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1);
237 : :
238 : 5 : Node s01 = d_nodeManager->mkConst(Sequence(intType, {zero, one}));
239 : 2 : Node sx = d_nodeManager->mkNode(Kind::SEQ_UNIT, x);
240 : 2 : Node sy = d_nodeManager->mkNode(Kind::SEQ_UNIT, y);
241 : 2 : Node sz = d_nodeManager->mkNode(Kind::SEQ_UNIT, z);
242 : 2 : Node sw = d_nodeManager->mkNode(Kind::SEQ_UNIT, w);
243 : 2 : Node sv = d_nodeManager->mkNode(Kind::SEQ_UNIT, v);
244 : 3 : Node xyz = d_nodeManager->mkNode(Kind::STRING_CONCAT, sx, sy, sz);
245 : 3 : Node wv = d_nodeManager->mkNode(Kind::STRING_CONCAT, sw, sv);
246 : :
247 : : {
248 : : // Same normal form for:
249 : : //
250 : : // (seq.nth (seq.unit x) 0)
251 : : //
252 : : // x
253 : 2 : Node n = d_nodeManager->mkNode(Kind::SEQ_NTH, sx, zero);
254 : 1 : sameNormalForm(n, x);
255 : : }
256 : :
257 : : {
258 : : // Same normal form for:
259 : : //
260 : : // (seq.nth (seq.++ (seq.unit x) (seq.unit y) (seq.unit z)) 0)
261 : : //
262 : : // x
263 : 2 : Node n = d_nodeManager->mkNode(Kind::SEQ_NTH, xyz, zero);
264 : 1 : sameNormalForm(n, x);
265 : : }
266 : :
267 : : {
268 : : // Same normal form for:
269 : : //
270 : : // (seq.nth (seq.++ (seq.unit x) (seq.unit y) (seq.unit z)) 0)
271 : : //
272 : : // x
273 : 2 : Node n = d_nodeManager->mkNode(Kind::SEQ_NTH, xyz, one);
274 : 1 : sameNormalForm(n, y);
275 : : }
276 : :
277 : : {
278 : : // Check that there are no errors when trying to rewrite
279 : : // (seq.nth (seq.++ (seq.unit 0) (seq.unit 1)) n) where n cannot be
280 : : // represented as a 32-bit integer
281 : 2 : Node n = d_nodeManager->mkNode(Kind::SEQ_NTH, s01, largePos);
282 : 1 : sameNormalForm(n, n);
283 : : }
284 : 1 : }
285 : :
286 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_substr)
287 : : {
288 : 1 : StringsRewriter sr(d_nodeManager, d_rewriter, nullptr);
289 : 1 : TypeNode intType = d_nodeManager->integerType();
290 : 1 : TypeNode strType = d_nodeManager->stringType();
291 : :
292 : 1 : Node empty = d_nodeManager->mkConst(String(""));
293 : 1 : Node a = d_nodeManager->mkConst(String("A"));
294 : 1 : Node b = d_nodeManager->mkConst(String("B"));
295 : 1 : Node abcd = d_nodeManager->mkConst(String("ABCD"));
296 : 1 : Node negone = d_nodeManager->mkConstInt(Rational(-1));
297 : 1 : Node zero = d_nodeManager->mkConstInt(Rational(0));
298 : 1 : Node one = d_nodeManager->mkConstInt(Rational(1));
299 : 1 : Node two = d_nodeManager->mkConstInt(Rational(2));
300 : 1 : Node three = d_nodeManager->mkConstInt(Rational(3));
301 : :
302 : 2 : Node s = d_nodeManager->mkVar("s", strType);
303 : 2 : Node s2 = d_nodeManager->mkVar("s2", strType);
304 : 2 : Node x = d_nodeManager->mkVar("x", intType);
305 : 2 : Node y = d_nodeManager->mkVar("y", intType);
306 : :
307 : : // (str.substr "A" x x) --> ""
308 : 2 : Node n = d_nodeManager->mkNode(Kind::STRING_SUBSTR, a, x, x);
309 : 1 : Node res = sr.rewriteSubstr(n);
310 [ - + ]: 1 : ASSERT_EQ(res, empty);
311 : :
312 : : // (str.substr "A" (+ x 1) x) -> ""
313 : 3 : n = d_nodeManager->mkNode(
314 : : Kind::STRING_SUBSTR,
315 : : a,
316 : 2 : d_nodeManager->mkNode(
317 : 2 : Kind::ADD, x, d_nodeManager->mkConstInt(Rational(1))),
318 : 1 : x);
319 : 1 : sameNormalForm(n, empty);
320 : :
321 : : // (str.substr "A" (+ x (str.len s2)) x) -> ""
322 : 3 : n = d_nodeManager->mkNode(
323 : : Kind::STRING_SUBSTR,
324 : : a,
325 : 2 : d_nodeManager->mkNode(
326 : 2 : Kind::ADD, x, d_nodeManager->mkNode(Kind::STRING_LENGTH, s)),
327 : 1 : x);
328 : 1 : sameNormalForm(n, empty);
329 : :
330 : : // (str.substr "A" x y) -> (str.substr "A" x y)
331 : 1 : n = d_nodeManager->mkNode(Kind::STRING_SUBSTR, a, x, y);
332 : 1 : res = sr.rewriteSubstr(n);
333 [ - + ]: 1 : ASSERT_EQ(res, n);
334 : :
335 : : // (str.substr "ABCD" (+ x 3) x) -> ""
336 : 3 : n = d_nodeManager->mkNode(
337 : 3 : Kind::STRING_SUBSTR, abcd, d_nodeManager->mkNode(Kind::ADD, x, three), x);
338 : 1 : sameNormalForm(n, empty);
339 : :
340 : : // (str.substr "ABCD" (+ x 2) x) -> (str.substr "ABCD" (+ x 2) x)
341 : 3 : n = d_nodeManager->mkNode(
342 : 3 : Kind::STRING_SUBSTR, abcd, d_nodeManager->mkNode(Kind::ADD, x, two), x);
343 : 1 : res = sr.rewriteSubstr(n);
344 : 1 : sameNormalForm(res, n);
345 : :
346 : : // (str.substr (str.substr s x x) x x) -> ""
347 : 4 : n = d_nodeManager->mkNode(Kind::STRING_SUBSTR,
348 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, s, x, x),
349 : : x,
350 : 1 : x);
351 : 1 : sameNormalForm(n, empty);
352 : :
353 : : // Same normal form for:
354 : : //
355 : : // (str.substr (str.replace "" s "B") x x)
356 : : //
357 : : // (str.replace "" s (str.substr "B" x x)))
358 : 1 : Node lhs = d_nodeManager->mkNode(
359 : : Kind::STRING_SUBSTR,
360 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, s, b),
361 : : x,
362 : 5 : x);
363 : 1 : Node rhs = d_nodeManager->mkNode(
364 : : Kind::STRING_REPLACE,
365 : : empty,
366 : : s,
367 : 3 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, b, x, x));
368 : 1 : sameNormalForm(lhs, rhs);
369 : :
370 : : // Same normal form:
371 : : //
372 : : // (str.substr (str.replace s "A" "B") 0 x)
373 : : //
374 : : // (str.replace (str.substr s 0 x) "A" "B")
375 : 1 : Node substr_repl = d_nodeManager->mkNode(
376 : : Kind::STRING_SUBSTR,
377 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, s, a, b),
378 : : zero,
379 : 5 : x);
380 : 1 : Node repl_substr = d_nodeManager->mkNode(
381 : : Kind::STRING_REPLACE,
382 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, s, zero, x),
383 : : a,
384 : 5 : b);
385 : 1 : sameNormalForm(substr_repl, repl_substr);
386 : :
387 : : // Same normal form:
388 : : //
389 : : // (str.substr (str.replace s (str.substr (str.++ s2 "A") 0 1) "B") 0 x)
390 : : //
391 : : // (str.replace (str.substr s 0 x) (str.substr (str.++ s2 "A") 0 1) "B")
392 : : Node substr_y =
393 : 1 : d_nodeManager->mkNode(Kind::STRING_SUBSTR,
394 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, s2, a),
395 : : zero,
396 : 5 : one);
397 : 4 : substr_repl = d_nodeManager->mkNode(
398 : : Kind::STRING_SUBSTR,
399 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, s, substr_y, b),
400 : : zero,
401 : 1 : x);
402 : 4 : repl_substr = d_nodeManager->mkNode(
403 : : Kind::STRING_REPLACE,
404 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, s, zero, x),
405 : : substr_y,
406 : 1 : b);
407 : 1 : sameNormalForm(substr_repl, repl_substr);
408 : :
409 : : // (str.substr (str.int.to.str x) x x) ---> empty
410 : 1 : Node substr_itos = d_nodeManager->mkNode(
411 : 3 : Kind::STRING_SUBSTR, d_nodeManager->mkNode(Kind::STRING_ITOS, x), x, x);
412 : 1 : sameNormalForm(substr_itos, empty);
413 : :
414 : : // (str.substr s (* (- 1) (str.len s)) 1) ---> empty
415 : 1 : Node substr = d_nodeManager->mkNode(
416 : : Kind::STRING_SUBSTR,
417 : : s,
418 : 2 : d_nodeManager->mkNode(
419 : 2 : Kind::MULT, negone, d_nodeManager->mkNode(Kind::STRING_LENGTH, s)),
420 : 3 : one);
421 : 1 : sameNormalForm(substr, empty);
422 : : }
423 : :
424 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_update)
425 : : {
426 : 2 : TypeNode intType = d_nodeManager->integerType();
427 : :
428 : 3 : Node x = d_nodeManager->mkVar("x", intType);
429 : 3 : Node y = d_nodeManager->mkVar("y", intType);
430 : 3 : Node z = d_nodeManager->mkVar("z", intType);
431 : 3 : Node w = d_nodeManager->mkVar("w", intType);
432 : 3 : Node v = d_nodeManager->mkVar("v", intType);
433 : :
434 : 2 : Node negOne = d_nodeManager->mkConstInt(-1);
435 : 2 : Node zero = d_nodeManager->mkConstInt(0);
436 : 2 : Node one = d_nodeManager->mkConstInt(1);
437 : 2 : Node three = d_nodeManager->mkConstInt(3);
438 : :
439 : 2 : Node sx = d_nodeManager->mkNode(Kind::SEQ_UNIT, x);
440 : 2 : Node sy = d_nodeManager->mkNode(Kind::SEQ_UNIT, y);
441 : 2 : Node sz = d_nodeManager->mkNode(Kind::SEQ_UNIT, z);
442 : 2 : Node sw = d_nodeManager->mkNode(Kind::SEQ_UNIT, w);
443 : 2 : Node sv = d_nodeManager->mkNode(Kind::SEQ_UNIT, v);
444 : 3 : Node xyz = d_nodeManager->mkNode(Kind::STRING_CONCAT, sx, sy, sz);
445 : 3 : Node wv = d_nodeManager->mkNode(Kind::STRING_CONCAT, sw, sv);
446 : :
447 : : {
448 : : // Same normal form for:
449 : : //
450 : : // (seq.update
451 : : // (seq.unit x))
452 : : // 0
453 : : // (seq.unit w))
454 : : //
455 : : // (seq.unit w)
456 : 2 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, sx, zero, sw);
457 : 1 : sameNormalForm(n, sw);
458 : : }
459 : :
460 : : {
461 : : // Same normal form for:
462 : : //
463 : : // (seq.update
464 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
465 : : // 0
466 : : // (seq.unit w))
467 : : //
468 : : // (seq.++ (seq.unit w) (seq.unit y) (seq.unit z))
469 : 3 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, xyz, zero, sw);
470 : 2 : Node wyz = d_nodeManager->mkNode(Kind::STRING_CONCAT, sw, sy, sz);
471 : 1 : sameNormalForm(n, wyz);
472 : : }
473 : :
474 : : {
475 : : // Same normal form for:
476 : : //
477 : : // (seq.update
478 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
479 : : // 1
480 : : // (seq.unit w))
481 : : //
482 : : // (seq.++ (seq.unit x) (seq.unit w) (seq.unit z))
483 : 3 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, xyz, one, sw);
484 : 2 : Node xwz = d_nodeManager->mkNode(Kind::STRING_CONCAT, sx, sw, sz);
485 : 1 : sameNormalForm(n, xwz);
486 : : }
487 : :
488 : : {
489 : : // Same normal form for:
490 : : //
491 : : // (seq.update
492 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
493 : : // 1
494 : : // (seq.++ (seq.unit w) (seq.unit v)))
495 : : //
496 : : // (seq.++ (seq.unit x) (seq.unit w) (seq.unit v))
497 : 3 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, xyz, one, wv);
498 : 2 : Node xwv = d_nodeManager->mkNode(Kind::STRING_CONCAT, sx, sw, sv);
499 : 1 : sameNormalForm(n, xwv);
500 : : }
501 : :
502 : : {
503 : : // Same normal form for:
504 : : //
505 : : // (seq.update
506 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
507 : : // -1
508 : : // (seq.++ (seq.unit w) (seq.unit v)))
509 : : //
510 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
511 : 2 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, xyz, negOne, wv);
512 : 1 : sameNormalForm(n, xyz);
513 : : }
514 : :
515 : : {
516 : : // Same normal form for:
517 : : //
518 : : // (seq.update
519 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
520 : : // 3
521 : : // w)
522 : : //
523 : : // (seq.++ (seq.unit x) (seq.unit y) (seq.unit z))
524 : 2 : Node n = d_nodeManager->mkNode(Kind::STRING_UPDATE, xyz, three, sw);
525 : 1 : sameNormalForm(n, xyz);
526 : : }
527 : 1 : }
528 : :
529 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_concat)
530 : : {
531 : 2 : TypeNode intType = d_nodeManager->integerType();
532 : 2 : TypeNode strType = d_nodeManager->stringType();
533 : :
534 : 2 : Node empty = d_nodeManager->mkConst(String(""));
535 : 2 : Node a = d_nodeManager->mkConst(String("A"));
536 : 2 : Node zero = d_nodeManager->mkConstInt(Rational(0));
537 : 2 : Node three = d_nodeManager->mkConstInt(Rational(3));
538 : :
539 : 3 : Node i = d_nodeManager->mkVar("i", intType);
540 : 3 : Node s = d_nodeManager->mkVar("s", strType);
541 : 3 : Node x = d_nodeManager->mkVar("x", strType);
542 : 3 : Node y = d_nodeManager->mkVar("y", strType);
543 : :
544 : : // Same normal form for:
545 : : //
546 : : // (str.++ (str.replace "A" x "") "A")
547 : : //
548 : : // (str.++ "A" (str.replace "A" x ""))
549 : 3 : Node repl_a_x_e = d_nodeManager->mkNode(Kind::STRING_REPLACE, a, x, empty);
550 : 3 : Node repl_a = d_nodeManager->mkNode(Kind::STRING_CONCAT, repl_a_x_e, a);
551 : 3 : Node a_repl = d_nodeManager->mkNode(Kind::STRING_CONCAT, a, repl_a_x_e);
552 : 1 : sameNormalForm(repl_a, a_repl);
553 : :
554 : : // Same normal form for:
555 : : //
556 : : // (str.++ y (str.replace "" x (str.substr y 0 3)) (str.substr y 0 3) "A"
557 : : // (str.substr y 0 3))
558 : : //
559 : : // (str.++ y (str.substr y 0 3) (str.replace "" x (str.substr y 0 3)) "A"
560 : : // (str.substr y 0 3))
561 : 3 : Node z = d_nodeManager->mkNode(Kind::STRING_SUBSTR, y, zero, three);
562 : 3 : Node repl_e_x_z = d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, z);
563 [ + + ][ - - ]: 6 : repl_a = d_nodeManager->mkNode(Kind::STRING_CONCAT, {y, repl_e_x_z, z, a, z});
564 [ + + ][ - - ]: 6 : a_repl = d_nodeManager->mkNode(Kind::STRING_CONCAT, {y, z, repl_e_x_z, a, z});
565 : 1 : sameNormalForm(repl_a, a_repl);
566 : :
567 : : // Same normal form for:
568 : : //
569 : : // (str.++ "A" (str.replace "A" x "") (str.substr "A" 0 i))
570 : : //
571 : : // (str.++ (str.substr "A" 0 i) (str.replace "A" x "") "A")
572 : 3 : Node substr_a = d_nodeManager->mkNode(Kind::STRING_SUBSTR, a, zero, i);
573 : : Node a_substr_repl =
574 : 3 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, substr_a, repl_a_x_e);
575 : : Node substr_repl_a =
576 : 3 : d_nodeManager->mkNode(Kind::STRING_CONCAT, substr_a, repl_a_x_e, a);
577 : 1 : sameNormalForm(a_substr_repl, substr_repl_a);
578 : :
579 : : // Same normal form for:
580 : : //
581 : : // (str.++ (str.replace "" x (str.substr "A" 0 i)) (str.substr "A" 0 i)
582 : : // (str.at "A" i))
583 : : //
584 : : // (str.++ (str.at "A" i) (str.replace "" x (str.substr "A" 0 i)) (str.substr
585 : : // "A" 0 i))
586 : 3 : Node charat_a = d_nodeManager->mkNode(Kind::STRING_CHARAT, a, i);
587 : : Node repl_e_x_s =
588 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, substr_a);
589 : 1 : Node repl_substr_a = d_nodeManager->mkNode(
590 : 3 : Kind::STRING_CONCAT, repl_e_x_s, substr_a, charat_a);
591 : 1 : Node a_repl_substr = d_nodeManager->mkNode(
592 : 2 : Kind::STRING_CONCAT, charat_a, repl_e_x_s, substr_a);
593 : 1 : sameNormalForm(repl_substr_a, a_repl_substr);
594 : 1 : }
595 : :
596 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, length_preserve_rewrite)
597 : : {
598 : 1 : StringsRewriter sr(d_nodeManager, d_rewriter, nullptr);
599 : 1 : TypeNode intType = d_nodeManager->integerType();
600 : 1 : TypeNode strType = d_nodeManager->stringType();
601 : :
602 : 1 : Node empty = d_nodeManager->mkConst(String(""));
603 : 1 : Node abcd = d_nodeManager->mkConst(String("ABCD"));
604 : 1 : Node f = d_nodeManager->mkConst(String("F"));
605 : 1 : Node gh = d_nodeManager->mkConst(String("GH"));
606 : 1 : Node ij = d_nodeManager->mkConst(String("IJ"));
607 : :
608 : 2 : Node i = d_nodeManager->mkVar("i", intType);
609 : 2 : Node s = d_nodeManager->mkVar("s", strType);
610 : 2 : Node x = d_nodeManager->mkVar("x", strType);
611 : 2 : Node y = d_nodeManager->mkVar("y", strType);
612 : :
613 : : // Same length preserving rewrite for:
614 : : //
615 : : // (str.++ "ABCD" (str.++ x x))
616 : : //
617 : : // (str.++ "GH" (str.repl "GH" "IJ") "IJ")
618 : : Node concat1 =
619 : 1 : d_nodeManager->mkNode(Kind::STRING_CONCAT,
620 : : abcd,
621 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x));
622 : 1 : Node concat2 = d_nodeManager->mkNode(
623 : : Kind::STRING_CONCAT,
624 : 6 : {gh, x, d_nodeManager->mkNode(Kind::STRING_REPLACE, x, gh, ij), ij});
625 : 1 : Node res_concat1 = sr.lengthPreserveRewrite(concat1);
626 : 1 : Node res_concat2 = sr.lengthPreserveRewrite(concat2);
627 [ - + ]: 1 : ASSERT_EQ(res_concat1, res_concat2);
628 : : }
629 : :
630 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_indexOf)
631 : : {
632 : 2 : TypeNode intType = d_nodeManager->integerType();
633 : 2 : TypeNode strType = d_nodeManager->stringType();
634 : :
635 : 2 : Node a = d_nodeManager->mkConst(String("A"));
636 : 2 : Node abcd = d_nodeManager->mkConst(String("ABCD"));
637 : 2 : Node aaad = d_nodeManager->mkConst(String("AAAD"));
638 : 2 : Node b = d_nodeManager->mkConst(String("B"));
639 : 2 : Node c = d_nodeManager->mkConst(String("C"));
640 : 2 : Node ccc = d_nodeManager->mkConst(String("CCC"));
641 : 3 : Node x = d_nodeManager->mkVar("x", strType);
642 : 3 : Node y = d_nodeManager->mkVar("y", strType);
643 : 2 : Node negOne = d_nodeManager->mkConstInt(Rational(-1));
644 : 2 : Node zero = d_nodeManager->mkConstInt(Rational(0));
645 : 2 : Node one = d_nodeManager->mkConstInt(Rational(1));
646 : 2 : Node two = d_nodeManager->mkConstInt(Rational(2));
647 : 2 : Node three = d_nodeManager->mkConstInt(Rational(3));
648 : 3 : Node i = d_nodeManager->mkVar("i", intType);
649 : 3 : Node j = d_nodeManager->mkVar("j", intType);
650 : :
651 : : // Same normal form for:
652 : : //
653 : : // (str.to.int (str.indexof "A" x 1))
654 : : //
655 : : // (str.to.int (str.indexof "B" x 1))
656 : 3 : Node a_idof_x = d_nodeManager->mkNode(Kind::STRING_INDEXOF, a, x, two);
657 : 2 : Node itos_a_idof_x = d_nodeManager->mkNode(Kind::STRING_ITOS, a_idof_x);
658 : 3 : Node b_idof_x = d_nodeManager->mkNode(Kind::STRING_INDEXOF, b, x, two);
659 : 2 : Node itos_b_idof_x = d_nodeManager->mkNode(Kind::STRING_ITOS, b_idof_x);
660 : 1 : sameNormalForm(itos_a_idof_x, itos_b_idof_x);
661 : :
662 : : // Same normal form for:
663 : : //
664 : : // (str.indexof (str.++ "ABCD" x) y 3)
665 : : //
666 : : // (str.indexof (str.++ "AAAD" x) y 3)
667 : : Node idof_abcd =
668 : 1 : d_nodeManager->mkNode(Kind::STRING_INDEXOF,
669 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, abcd, x),
670 : : y,
671 : 5 : three);
672 : : Node idof_aaad =
673 : 1 : d_nodeManager->mkNode(Kind::STRING_INDEXOF,
674 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, aaad, x),
675 : : y,
676 : 5 : three);
677 : 1 : sameNormalForm(idof_abcd, idof_aaad);
678 : :
679 : : // (str.indexof (str.substr x 1 i) "A" i) ---> -1
680 : 1 : Node idof_substr = d_nodeManager->mkNode(
681 : : Kind::STRING_INDEXOF,
682 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, i),
683 : : a,
684 : 5 : i);
685 : 1 : sameNormalForm(idof_substr, negOne);
686 : :
687 : : {
688 : : // Same normal form for:
689 : : //
690 : : // (str.indexof (str.++ "B" "C" "A" x y) "A" 0)
691 : : //
692 : : // (+ 2 (str.indexof (str.++ "A" x y) "A" 0))
693 : 1 : Node lhs = d_nodeManager->mkNode(
694 : : Kind::STRING_INDEXOF,
695 : 8 : d_nodeManager->mkNode(Kind::STRING_CONCAT, {b, c, a, x, y}),
696 : : a,
697 : 5 : zero);
698 : 1 : Node rhs = d_nodeManager->mkNode(
699 : : Kind::ADD,
700 : : two,
701 : 4 : d_nodeManager->mkNode(
702 : : Kind::STRING_INDEXOF,
703 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, x, y),
704 : : a,
705 : 2 : zero));
706 : 1 : sameNormalForm(lhs, rhs);
707 : : }
708 : 1 : }
709 : :
710 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace)
711 : : {
712 : 2 : TypeNode intType = d_nodeManager->integerType();
713 : 2 : TypeNode strType = d_nodeManager->stringType();
714 : :
715 : 2 : Node empty = d_nodeManager->mkConst(String(""));
716 : 2 : Node a = d_nodeManager->mkConst(String("A"));
717 : 2 : Node ab = d_nodeManager->mkConst(String("AB"));
718 : 2 : Node b = d_nodeManager->mkConst(String("B"));
719 : 2 : Node c = d_nodeManager->mkConst(String("C"));
720 : 2 : Node d = d_nodeManager->mkConst(String("D"));
721 : 3 : Node x = d_nodeManager->mkVar("x", strType);
722 : 3 : Node y = d_nodeManager->mkVar("y", strType);
723 : 3 : Node z = d_nodeManager->mkVar("z", strType);
724 : 2 : Node zero = d_nodeManager->mkConstInt(Rational(0));
725 : 2 : Node one = d_nodeManager->mkConstInt(Rational(1));
726 : 3 : Node n = d_nodeManager->mkVar("n", intType);
727 : :
728 : : // (str.replace (str.replace x "B" x) x "A") -->
729 : : // (str.replace (str.replace x "B" "A") x "A")
730 : 1 : Node repl_repl = d_nodeManager->mkNode(
731 : : Kind::STRING_REPLACE,
732 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, b, x),
733 : : x,
734 : 5 : a);
735 : 1 : Node repl_repl_short = d_nodeManager->mkNode(
736 : : Kind::STRING_REPLACE,
737 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, b, a),
738 : : x,
739 : 5 : a);
740 : 1 : sameNormalForm(repl_repl, repl_repl_short);
741 : :
742 : : // (str.replace "A" (str.replace "B", x, "C") "D") --> "A"
743 : 3 : repl_repl = d_nodeManager->mkNode(
744 : : Kind::STRING_REPLACE,
745 : : a,
746 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, b, x, c),
747 : 1 : d);
748 : 1 : sameNormalForm(repl_repl, a);
749 : :
750 : : // (str.replace "A" (str.replace "B", x, "A") "D") -/-> "A"
751 : 3 : repl_repl = d_nodeManager->mkNode(
752 : : Kind::STRING_REPLACE,
753 : : a,
754 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, b, x, a),
755 : 1 : d);
756 : 1 : differentNormalForms(repl_repl, a);
757 : :
758 : : // Same normal form for:
759 : : //
760 : : // (str.replace x (str.++ x y z) y)
761 : : //
762 : : // (str.replace x (str.++ x y z) z)
763 : 3 : Node xyz = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y, z);
764 : 3 : Node repl_x_xyz = d_nodeManager->mkNode(Kind::STRING_REPLACE, x, xyz, y);
765 : 3 : Node repl_x_zyx = d_nodeManager->mkNode(Kind::STRING_REPLACE, x, xyz, z);
766 : 1 : sameNormalForm(repl_x_xyz, repl_x_zyx);
767 : :
768 : : // (str.replace "" (str.++ x x) x) --> ""
769 : : Node repl_empty_xx =
770 : 1 : d_nodeManager->mkNode(Kind::STRING_REPLACE,
771 : : empty,
772 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x),
773 : 4 : x);
774 : 1 : sameNormalForm(repl_empty_xx, empty);
775 : :
776 : : // (str.replace "AB" (str.++ x "A") x) --> (str.replace "AB" (str.++ x "A")
777 : : // "")
778 : : Node repl_ab_xa_x =
779 : 1 : d_nodeManager->mkNode(Kind::STRING_REPLACE,
780 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, b),
781 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, a),
782 : 6 : x);
783 : : Node repl_ab_xa_e =
784 : 1 : d_nodeManager->mkNode(Kind::STRING_REPLACE,
785 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, b),
786 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, a),
787 : 6 : empty);
788 : 1 : sameNormalForm(repl_ab_xa_x, repl_ab_xa_e);
789 : :
790 : : // (str.replace "AB" (str.++ x "A") x) -/-> (str.replace "AB" (str.++ "A" x)
791 : : // "")
792 : : Node repl_ab_ax_e =
793 : 1 : d_nodeManager->mkNode(Kind::STRING_REPLACE,
794 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, b),
795 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, x),
796 : 6 : empty);
797 : 1 : differentNormalForms(repl_ab_ax_e, repl_ab_xa_e);
798 : :
799 : : // (str.replace "" (str.replace y x "A") y) ---> ""
800 : 3 : repl_repl = d_nodeManager->mkNode(
801 : : Kind::STRING_REPLACE,
802 : : empty,
803 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, y, x, a),
804 : 1 : y);
805 : 1 : sameNormalForm(repl_repl, empty);
806 : :
807 : : // (str.replace "" (str.replace x y x) x) ---> ""
808 : 3 : repl_repl = d_nodeManager->mkNode(
809 : : Kind::STRING_REPLACE,
810 : : empty,
811 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
812 : 1 : x);
813 : 1 : sameNormalForm(repl_repl, empty);
814 : :
815 : : // (str.replace "" (str.substr x 0 1) x) ---> ""
816 : 3 : repl_repl = d_nodeManager->mkNode(
817 : : Kind::STRING_REPLACE,
818 : : empty,
819 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, zero, one),
820 : 1 : x);
821 : 1 : sameNormalForm(repl_repl, empty);
822 : :
823 : : // Same normal form for:
824 : : //
825 : : // (str.replace "" (str.replace x y x) y)
826 : : //
827 : : // (str.replace "" x y)
828 : 3 : repl_repl = d_nodeManager->mkNode(
829 : : Kind::STRING_REPLACE,
830 : : empty,
831 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
832 : 1 : y);
833 : 3 : Node repl = d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, y);
834 : 1 : sameNormalForm(repl_repl, repl);
835 : :
836 : : // Same normal form:
837 : : //
838 : : // (str.replace "B" (str.replace x "A" "B") "B")
839 : : //
840 : : // (str.replace "B" x "B"))
841 : 3 : repl_repl = d_nodeManager->mkNode(
842 : : Kind::STRING_REPLACE,
843 : : b,
844 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, b),
845 : 1 : b);
846 : 1 : repl = d_nodeManager->mkNode(Kind::STRING_REPLACE, b, x, b);
847 : 1 : sameNormalForm(repl_repl, repl);
848 : :
849 : : // Different normal forms for:
850 : : //
851 : : // (str.replace "B" (str.replace "" x "A") "B")
852 : : //
853 : : // (str.replace "B" x "B")
854 : 3 : repl_repl = d_nodeManager->mkNode(
855 : : Kind::STRING_REPLACE,
856 : : b,
857 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, a),
858 : 1 : b);
859 : 1 : repl = d_nodeManager->mkNode(Kind::STRING_REPLACE, b, x, b);
860 : 1 : differentNormalForms(repl_repl, repl);
861 : :
862 : : {
863 : : // Same normal form:
864 : : //
865 : : // (str.replace (str.++ "AB" x) "C" y)
866 : : //
867 : : // (str.++ "AB" (str.replace x "C" y))
868 : : Node lhs =
869 : 1 : d_nodeManager->mkNode(Kind::STRING_REPLACE,
870 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, ab, x),
871 : : c,
872 : 5 : y);
873 : 1 : Node rhs = d_nodeManager->mkNode(
874 : : Kind::STRING_CONCAT,
875 : : ab,
876 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, c, y));
877 : 1 : sameNormalForm(lhs, rhs);
878 : : }
879 : 1 : }
880 : :
881 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace_re)
882 : : {
883 : 2 : TypeNode intType = d_nodeManager->integerType();
884 : 2 : TypeNode strType = d_nodeManager->stringType();
885 : :
886 : 2 : std::vector<Node> emptyVec;
887 : 1 : Node sigStar = d_nodeManager->mkNode(
888 : 3 : Kind::REGEXP_STAR, d_nodeManager->mkNode(Kind::REGEXP_ALLCHAR, emptyVec));
889 : 2 : Node foo = d_nodeManager->mkConst(String("FOO"));
890 : 2 : Node a = d_nodeManager->mkConst(String("A"));
891 : 2 : Node b = d_nodeManager->mkConst(String("B"));
892 : : Node re =
893 : 1 : d_nodeManager->mkNode(Kind::REGEXP_CONCAT,
894 : 2 : d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, a),
895 : : sigStar,
896 : 5 : d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, b));
897 : :
898 : : // Same normal form:
899 : : //
900 : : // (str.replace_re
901 : : // "AZZZB"
902 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
903 : : // "FOO")
904 : : //
905 : : // "FOO"
906 : : {
907 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
908 : 2 : d_nodeManager->mkConst(String("AZZZB")),
909 : : re,
910 : 5 : foo);
911 : 1 : Node res = d_nodeManager->mkConst(String("FOO"));
912 : 1 : sameNormalForm(t, res);
913 : : }
914 : :
915 : : // Same normal form:
916 : : //
917 : : // (str.replace_re
918 : : // "ZAZZZBZZB"
919 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
920 : : // "FOO")
921 : : //
922 : : // "ZFOOZZB"
923 : : {
924 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
925 : 2 : d_nodeManager->mkConst(String("ZAZZZBZZB")),
926 : : re,
927 : 5 : foo);
928 : 1 : Node res = d_nodeManager->mkConst(String("ZFOOZZB"));
929 : 1 : sameNormalForm(t, res);
930 : : }
931 : :
932 : : // Same normal form:
933 : : //
934 : : // (str.replace_re
935 : : // "ZAZZZBZAZB"
936 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
937 : : // "FOO")
938 : : //
939 : : // "ZFOOZAZB"
940 : : {
941 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
942 : 2 : d_nodeManager->mkConst(String("ZAZZZBZAZB")),
943 : : re,
944 : 5 : foo);
945 : 1 : Node res = d_nodeManager->mkConst(String("ZFOOZAZB"));
946 : 1 : sameNormalForm(t, res);
947 : : }
948 : :
949 : : // Same normal form:
950 : : //
951 : : // (str.replace_re
952 : : // "ZZZ"
953 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
954 : : // "FOO")
955 : : //
956 : : // "ZZZ"
957 : : {
958 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
959 : 2 : d_nodeManager->mkConst(String("ZZZ")),
960 : : re,
961 : 5 : foo);
962 : 1 : Node res = d_nodeManager->mkConst(String("ZZZ"));
963 : 1 : sameNormalForm(t, res);
964 : : }
965 : :
966 : : // Same normal form:
967 : : //
968 : : // (str.replace_re
969 : : // "ZZZ"
970 : : // re.all
971 : : // "FOO")
972 : : //
973 : : // "FOOZZZ"
974 : : {
975 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
976 : 2 : d_nodeManager->mkConst(String("ZZZ")),
977 : : sigStar,
978 : 5 : foo);
979 : 1 : Node res = d_nodeManager->mkConst(String("FOOZZZ"));
980 : 1 : sameNormalForm(t, res);
981 : : }
982 : :
983 : : // Same normal form:
984 : : //
985 : : // (str.replace_re
986 : : // ""
987 : : // re.all
988 : : // "FOO")
989 : : //
990 : : // "FOO"
991 : : {
992 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE,
993 : 2 : d_nodeManager->mkConst(String("")),
994 : : sigStar,
995 : 5 : foo);
996 : 1 : Node res = d_nodeManager->mkConst(String("FOO"));
997 : 1 : sameNormalForm(t, res);
998 : : }
999 : 1 : }
1000 : :
1001 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_replace_all)
1002 : : {
1003 : 2 : TypeNode intType = d_nodeManager->integerType();
1004 : 2 : TypeNode strType = d_nodeManager->stringType();
1005 : :
1006 : 2 : std::vector<Node> emptyVec;
1007 : 1 : Node sigStar = d_nodeManager->mkNode(
1008 : 3 : Kind::REGEXP_STAR, d_nodeManager->mkNode(Kind::REGEXP_ALLCHAR, emptyVec));
1009 : 2 : Node foo = d_nodeManager->mkConst(String("FOO"));
1010 : 2 : Node a = d_nodeManager->mkConst(String("A"));
1011 : 2 : Node b = d_nodeManager->mkConst(String("B"));
1012 : : Node re =
1013 : 1 : d_nodeManager->mkNode(Kind::REGEXP_CONCAT,
1014 : 2 : d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, a),
1015 : : sigStar,
1016 : 5 : d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, b));
1017 : :
1018 : : // Same normal form:
1019 : : //
1020 : : // (str.replace_re
1021 : : // "AZZZB"
1022 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
1023 : : // "FOO")
1024 : : //
1025 : : // "FOO"
1026 : : {
1027 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1028 : 2 : d_nodeManager->mkConst(String("AZZZB")),
1029 : : re,
1030 : 5 : foo);
1031 : 1 : Node res = d_nodeManager->mkConst(String("FOO"));
1032 : 1 : sameNormalForm(t, res);
1033 : : }
1034 : :
1035 : : // Same normal form:
1036 : : //
1037 : : // (str.replace_re
1038 : : // "ZAZZZBZZB"
1039 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
1040 : : // "FOO")
1041 : : //
1042 : : // "ZFOOZZB"
1043 : : {
1044 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1045 : 2 : d_nodeManager->mkConst(String("ZAZZZBZZB")),
1046 : : re,
1047 : 5 : foo);
1048 : 1 : Node res = d_nodeManager->mkConst(String("ZFOOZZB"));
1049 : 1 : sameNormalForm(t, res);
1050 : : }
1051 : :
1052 : : // Same normal form:
1053 : : //
1054 : : // (str.replace_re
1055 : : // "ZAZZZBZAZB"
1056 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
1057 : : // "FOO")
1058 : : //
1059 : : // "ZFOOZFOO"
1060 : : {
1061 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1062 : 2 : d_nodeManager->mkConst(String("ZAZZZBZAZB")),
1063 : : re,
1064 : 5 : foo);
1065 : 1 : Node res = d_nodeManager->mkConst(String("ZFOOZFOO"));
1066 : 1 : sameNormalForm(t, res);
1067 : : }
1068 : :
1069 : : // Same normal form:
1070 : : //
1071 : : // (str.replace_re
1072 : : // "ZZZ"
1073 : : // (re.++ (str.to_re "A") re.all (str.to_re "B"))
1074 : : // "FOO")
1075 : : //
1076 : : // "ZZZ"
1077 : : {
1078 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1079 : 2 : d_nodeManager->mkConst(String("ZZZ")),
1080 : : re,
1081 : 5 : foo);
1082 : 1 : Node res = d_nodeManager->mkConst(String("ZZZ"));
1083 : 1 : sameNormalForm(t, res);
1084 : : }
1085 : :
1086 : : // Same normal form:
1087 : : //
1088 : : // (str.replace_re
1089 : : // "ZZZ"
1090 : : // re.all
1091 : : // "FOO")
1092 : : //
1093 : : // "FOOFOOFOO"
1094 : : {
1095 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1096 : 2 : d_nodeManager->mkConst(String("ZZZ")),
1097 : : sigStar,
1098 : 5 : foo);
1099 : 1 : Node res = d_nodeManager->mkConst(String("FOOFOOFOO"));
1100 : 1 : sameNormalForm(t, res);
1101 : : }
1102 : :
1103 : : // Same normal form:
1104 : : //
1105 : : // (str.replace_re
1106 : : // ""
1107 : : // re.all
1108 : : // "FOO")
1109 : : //
1110 : : // ""
1111 : : {
1112 : 1 : Node t = d_nodeManager->mkNode(Kind::STRING_REPLACE_RE_ALL,
1113 : 2 : d_nodeManager->mkConst(String("")),
1114 : : sigStar,
1115 : 5 : foo);
1116 : 1 : Node res = d_nodeManager->mkConst(String(""));
1117 : 1 : sameNormalForm(t, res);
1118 : : }
1119 : 1 : }
1120 : :
1121 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_contains)
1122 : : {
1123 : 2 : TypeNode intType = d_nodeManager->integerType();
1124 : 2 : TypeNode strType = d_nodeManager->stringType();
1125 : :
1126 : 2 : Node empty = d_nodeManager->mkConst(String(""));
1127 : 2 : Node a = d_nodeManager->mkConst(String("A"));
1128 : 2 : Node ab = d_nodeManager->mkConst(String("AB"));
1129 : 2 : Node b = d_nodeManager->mkConst(String("B"));
1130 : 2 : Node c = d_nodeManager->mkConst(String("C"));
1131 : 2 : Node e = d_nodeManager->mkConst(String("E"));
1132 : 2 : Node h = d_nodeManager->mkConst(String("H"));
1133 : 2 : Node j = d_nodeManager->mkConst(String("J"));
1134 : 2 : Node p = d_nodeManager->mkConst(String("P"));
1135 : 2 : Node abc = d_nodeManager->mkConst(String("ABC"));
1136 : 2 : Node def = d_nodeManager->mkConst(String("DEF"));
1137 : 2 : Node ghi = d_nodeManager->mkConst(String("GHI"));
1138 : 3 : Node x = d_nodeManager->mkVar("x", strType);
1139 : 3 : Node y = d_nodeManager->mkVar("y", strType);
1140 : 3 : Node xy = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y);
1141 : 3 : Node yx = d_nodeManager->mkNode(Kind::STRING_CONCAT, y, x);
1142 : 3 : Node z = d_nodeManager->mkVar("z", strType);
1143 : 3 : Node n = d_nodeManager->mkVar("n", intType);
1144 : 3 : Node m = d_nodeManager->mkVar("m", intType);
1145 : 2 : Node one = d_nodeManager->mkConstInt(Rational(1));
1146 : 2 : Node two = d_nodeManager->mkConstInt(Rational(2));
1147 : 2 : Node three = d_nodeManager->mkConstInt(Rational(3));
1148 : 2 : Node four = d_nodeManager->mkConstInt(Rational(4));
1149 : 2 : Node t = d_nodeManager->mkConst(true);
1150 : 2 : Node f = d_nodeManager->mkConst(false);
1151 : :
1152 : : // Same normal form for:
1153 : : //
1154 : : // (str.replace "A" (str.substr x 1 3) y z)
1155 : : //
1156 : : // (str.replace "A" (str.substr x 1 4) y z)
1157 : 1 : Node substr_3 = d_nodeManager->mkNode(
1158 : : Kind::STRING_REPLACE,
1159 : : a,
1160 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, three),
1161 : 4 : z);
1162 : 1 : Node substr_4 = d_nodeManager->mkNode(
1163 : : Kind::STRING_REPLACE,
1164 : : a,
1165 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, four),
1166 : 4 : z);
1167 : 1 : sameNormalForm(substr_3, substr_4);
1168 : :
1169 : : // Same normal form for:
1170 : : //
1171 : : // (str.replace "A" (str.++ y (str.substr x 1 3)) y z)
1172 : : //
1173 : : // (str.replace "A" (str.++ y (str.substr x 1 4)) y z)
1174 : 1 : Node concat_substr_3 = d_nodeManager->mkNode(
1175 : : Kind::STRING_REPLACE,
1176 : : a,
1177 : 2 : d_nodeManager->mkNode(
1178 : : Kind::STRING_CONCAT,
1179 : : y,
1180 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, three)),
1181 : 4 : z);
1182 : 1 : Node concat_substr_4 = d_nodeManager->mkNode(
1183 : : Kind::STRING_REPLACE,
1184 : : a,
1185 : 2 : d_nodeManager->mkNode(
1186 : : Kind::STRING_CONCAT,
1187 : : y,
1188 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, four)),
1189 : 4 : z);
1190 : 1 : sameNormalForm(concat_substr_3, concat_substr_4);
1191 : :
1192 : : // (str.contains "A" (str.++ a (str.replace "B", x, "C")) --> false
1193 : 1 : Node ctn_repl = d_nodeManager->mkNode(
1194 : : Kind::STRING_CONTAINS,
1195 : : a,
1196 : 2 : d_nodeManager->mkNode(
1197 : : Kind::STRING_CONCAT,
1198 : : a,
1199 : 5 : d_nodeManager->mkNode(Kind::STRING_REPLACE, b, x, c)));
1200 : 1 : sameNormalForm(ctn_repl, f);
1201 : :
1202 : : // (str.contains x (str.++ x x)) --> (= x "")
1203 : : Node x_cnts_x_x =
1204 : 1 : d_nodeManager->mkNode(Kind::STRING_CONTAINS,
1205 : : x,
1206 : 3 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x));
1207 : 1 : sameNormalForm(x_cnts_x_x, d_nodeManager->mkNode(Kind::EQUAL, x, empty));
1208 : :
1209 : : // Same normal form for:
1210 : : //
1211 : : // (str.contains (str.++ y x) (str.++ x z y))
1212 : : //
1213 : : // (and (str.contains (str.++ y x) (str.++ x y)) (= z ""))
1214 : 1 : Node yx_cnts_xzy = d_nodeManager->mkNode(
1215 : : Kind::STRING_CONTAINS,
1216 : : yx,
1217 : 3 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, z, y));
1218 : 1 : Node yx_cnts_xy = d_nodeManager->mkNode(
1219 : : Kind::AND,
1220 : 2 : d_nodeManager->mkNode(Kind::EQUAL, z, empty),
1221 : 5 : d_nodeManager->mkNode(Kind::STRING_CONTAINS, yx, xy));
1222 : 1 : sameNormalForm(yx_cnts_xzy, yx_cnts_xy);
1223 : :
1224 : : // Same normal form for:
1225 : : //
1226 : : // (str.contains (str.substr x n (str.len y)) y)
1227 : : //
1228 : : // (= (str.substr x n (str.len y)) y)
1229 : 1 : Node ctn_substr = d_nodeManager->mkNode(
1230 : : Kind::STRING_CONTAINS,
1231 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR,
1232 : : x,
1233 : : n,
1234 : 2 : d_nodeManager->mkNode(Kind::STRING_LENGTH, y)),
1235 : 4 : y);
1236 : 1 : Node substr_eq = d_nodeManager->mkNode(
1237 : : Kind::EQUAL,
1238 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR,
1239 : : x,
1240 : : n,
1241 : 2 : d_nodeManager->mkNode(Kind::STRING_LENGTH, y)),
1242 : 4 : y);
1243 : 1 : sameNormalForm(ctn_substr, substr_eq);
1244 : :
1245 : : // Same normal form for:
1246 : : //
1247 : : // (str.contains x (str.replace y x y))
1248 : : //
1249 : : // (str.contains x y)
1250 : 1 : Node ctn_repl_y_x_y = d_nodeManager->mkNode(
1251 : : Kind::STRING_CONTAINS,
1252 : : x,
1253 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, y, x, y));
1254 : 3 : Node ctn_x_y = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, y);
1255 : 1 : sameNormalForm(ctn_repl_y_x_y, ctn_repl_y_x_y);
1256 : :
1257 : : // Same normal form for:
1258 : : //
1259 : : // (str.contains x (str.replace x y x))
1260 : : //
1261 : : // (= x (str.replace x y x))
1262 : 1 : Node ctn_repl_self = d_nodeManager->mkNode(
1263 : : Kind::STRING_CONTAINS,
1264 : : x,
1265 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x));
1266 : 1 : Node eq_repl = d_nodeManager->mkNode(
1267 : 3 : Kind::EQUAL, x, d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x));
1268 : 1 : sameNormalForm(ctn_repl_self, eq_repl);
1269 : :
1270 : : // (str.contains x (str.++ "A" (str.replace x y x))) ---> false
1271 : 1 : Node ctn_repl_self_f = d_nodeManager->mkNode(
1272 : : Kind::STRING_CONTAINS,
1273 : : x,
1274 : 2 : d_nodeManager->mkNode(
1275 : : Kind::STRING_CONCAT,
1276 : : a,
1277 : 5 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x)));
1278 : 1 : sameNormalForm(ctn_repl_self_f, f);
1279 : :
1280 : : // Same normal form for:
1281 : : //
1282 : : // (str.contains x (str.replace "" x y))
1283 : : //
1284 : : // (= "" (str.replace "" x y))
1285 : 1 : Node ctn_repl_empty = d_nodeManager->mkNode(
1286 : : Kind::STRING_CONTAINS,
1287 : : x,
1288 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, y));
1289 : 1 : Node eq_repl_empty = d_nodeManager->mkNode(
1290 : : Kind::EQUAL,
1291 : : empty,
1292 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, y));
1293 : 1 : sameNormalForm(ctn_repl_empty, eq_repl_empty);
1294 : :
1295 : : // Same normal form for:
1296 : : //
1297 : : // (str.contains x (str.++ x y))
1298 : : //
1299 : : // (= "" y)
1300 : : Node ctn_x_x_y =
1301 : 1 : d_nodeManager->mkNode(Kind::STRING_CONTAINS,
1302 : : x,
1303 : 3 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y));
1304 : 3 : Node eq_emp_y = d_nodeManager->mkNode(Kind::EQUAL, empty, y);
1305 : 1 : sameNormalForm(ctn_x_x_y, eq_emp_y);
1306 : :
1307 : : // Same normal form for:
1308 : : //
1309 : : // (str.contains (str.++ y x) (str.++ x y))
1310 : : //
1311 : : // (= (str.++ y x) (str.++ x y))
1312 : 3 : Node ctn_yxxy = d_nodeManager->mkNode(Kind::STRING_CONTAINS, yx, xy);
1313 : 3 : Node eq_yxxy = d_nodeManager->mkNode(Kind::EQUAL, yx, xy);
1314 : 1 : sameNormalForm(ctn_yxxy, eq_yxxy);
1315 : :
1316 : : // (str.contains (str.replace x y x) x) ---> true
1317 : 3 : ctn_repl = d_nodeManager->mkNode(
1318 : : Kind::STRING_CONTAINS,
1319 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
1320 : 1 : x);
1321 : 1 : sameNormalForm(ctn_repl, t);
1322 : :
1323 : : // (str.contains (str.replace (str.++ x y) z (str.++ y x)) x) ---> true
1324 : 3 : ctn_repl = d_nodeManager->mkNode(
1325 : : Kind::STRING_CONTAINS,
1326 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, xy, z, yx),
1327 : 1 : x);
1328 : 1 : sameNormalForm(ctn_repl, t);
1329 : :
1330 : : // (str.contains (str.++ z (str.replace (str.++ x y) z (str.++ y x))) x)
1331 : : // ---> true
1332 : 3 : ctn_repl = d_nodeManager->mkNode(
1333 : : Kind::STRING_CONTAINS,
1334 : 2 : d_nodeManager->mkNode(
1335 : : Kind::STRING_CONCAT,
1336 : : z,
1337 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, xy, z, yx)),
1338 : 1 : x);
1339 : 1 : sameNormalForm(ctn_repl, t);
1340 : :
1341 : : // Same normal form for:
1342 : : //
1343 : : // (str.contains (str.replace x y x) y)
1344 : : //
1345 : : // (str.contains x y)
1346 : 1 : Node lhs = d_nodeManager->mkNode(
1347 : : Kind::STRING_CONTAINS,
1348 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
1349 : 4 : y);
1350 : 3 : Node rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, y);
1351 : 1 : sameNormalForm(lhs, rhs);
1352 : :
1353 : : // Same normal form for:
1354 : : //
1355 : : // (str.contains (str.replace x y x) "B")
1356 : : //
1357 : : // (str.contains x "B")
1358 : 3 : lhs = d_nodeManager->mkNode(
1359 : : Kind::STRING_CONTAINS,
1360 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
1361 : 1 : b);
1362 : 1 : rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, b);
1363 : 1 : sameNormalForm(lhs, rhs);
1364 : :
1365 : : // Same normal form for:
1366 : : //
1367 : : // (str.contains (str.replace x y x) (str.substr z n 1))
1368 : : //
1369 : : // (str.contains x (str.substr z n 1))
1370 : 3 : Node substr_z = d_nodeManager->mkNode(Kind::STRING_SUBSTR, z, n, one);
1371 : 3 : lhs = d_nodeManager->mkNode(
1372 : : Kind::STRING_CONTAINS,
1373 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, x),
1374 : 1 : substr_z);
1375 : 1 : rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, substr_z);
1376 : 1 : sameNormalForm(lhs, rhs);
1377 : :
1378 : : // Same normal form for:
1379 : : //
1380 : : // (str.contains (str.replace x y z) z)
1381 : : //
1382 : : // (str.contains (str.replace x z y) y)
1383 : 3 : lhs = d_nodeManager->mkNode(
1384 : : Kind::STRING_CONTAINS,
1385 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, z),
1386 : 1 : z);
1387 : 3 : rhs = d_nodeManager->mkNode(
1388 : : Kind::STRING_CONTAINS,
1389 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, z, y),
1390 : 1 : y);
1391 : 1 : sameNormalForm(lhs, rhs);
1392 : :
1393 : : // Same normal form for:
1394 : : //
1395 : : // (str.contains (str.replace x "A" "B") "A")
1396 : : //
1397 : : // (str.contains (str.replace x "A" "") "A")
1398 : 3 : lhs = d_nodeManager->mkNode(
1399 : : Kind::STRING_CONTAINS,
1400 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, b),
1401 : 1 : a);
1402 : 3 : rhs = d_nodeManager->mkNode(
1403 : : Kind::STRING_CONTAINS,
1404 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, empty),
1405 : 1 : a);
1406 : 1 : sameNormalForm(lhs, rhs);
1407 : :
1408 : : {
1409 : : // (str.contains (str.++ x "A") (str.++ "B" x)) ---> false
1410 : : Node ctn =
1411 : 1 : d_nodeManager->mkNode(Kind::STRING_CONTAINS,
1412 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, a),
1413 : 4 : d_nodeManager->mkNode(Kind::STRING_CONCAT, b, x));
1414 : 1 : sameNormalForm(ctn, f);
1415 : : }
1416 : :
1417 : : {
1418 : : // Same normal form for:
1419 : : //
1420 : : // (str.contains (str.replace x "ABC" "DEF") "GHI")
1421 : : //
1422 : : // (str.contains x "GHI")
1423 : 3 : lhs = d_nodeManager->mkNode(
1424 : : Kind::STRING_CONTAINS,
1425 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, abc, def),
1426 : 1 : ghi);
1427 : 1 : rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, ghi);
1428 : 1 : sameNormalForm(lhs, rhs);
1429 : : }
1430 : :
1431 : : {
1432 : : // Different normal forms for:
1433 : : //
1434 : : // (str.contains (str.replace x "ABC" "DEF") "B")
1435 : : //
1436 : : // (str.contains x "B")
1437 : 3 : lhs = d_nodeManager->mkNode(
1438 : : Kind::STRING_CONTAINS,
1439 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, abc, def),
1440 : 1 : b);
1441 : 1 : rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, b);
1442 : 1 : differentNormalForms(lhs, rhs);
1443 : : }
1444 : :
1445 : : {
1446 : : // Different normal forms for:
1447 : : //
1448 : : // (str.contains (str.replace x "B" "DEF") "ABC")
1449 : : //
1450 : : // (str.contains x "ABC")
1451 : 3 : lhs = d_nodeManager->mkNode(
1452 : : Kind::STRING_CONTAINS,
1453 : 2 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, b, def),
1454 : 1 : abc);
1455 : 1 : rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, abc);
1456 : 1 : differentNormalForms(lhs, rhs);
1457 : : }
1458 : :
1459 : : {
1460 : : // Same normal form for:
1461 : : //
1462 : : // (str.contains "ABC" (str.at x n))
1463 : : //
1464 : : // (or (= x "")
1465 : : // (= x "A") (= x "B") (= x "C"))
1466 : 2 : Node cat = d_nodeManager->mkNode(Kind::STRING_CHARAT, x, n);
1467 : 1 : lhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, abc, cat);
1468 [ + + ][ - - ]: 9 : rhs = d_nodeManager->mkNode(Kind::OR,
1469 : 2 : {d_nodeManager->mkNode(Kind::EQUAL, cat, empty),
1470 : 2 : d_nodeManager->mkNode(Kind::EQUAL, cat, a),
1471 : 2 : d_nodeManager->mkNode(Kind::EQUAL, cat, b),
1472 : 7 : d_nodeManager->mkNode(Kind::EQUAL, cat, c)});
1473 : 1 : sameNormalForm(lhs, rhs);
1474 : : }
1475 : 1 : }
1476 : :
1477 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, infer_eqs_from_contains)
1478 : : {
1479 : 1 : StringsEntail& se = d_seqRewriter->getStringsEntail();
1480 : 1 : TypeNode strType = d_nodeManager->stringType();
1481 : :
1482 : 1 : Node empty = d_nodeManager->mkConst(String(""));
1483 : 1 : Node a = d_nodeManager->mkConst(String("A"));
1484 : 1 : Node b = d_nodeManager->mkConst(String("B"));
1485 : 2 : Node x = d_nodeManager->mkVar("x", strType);
1486 : 2 : Node y = d_nodeManager->mkVar("y", strType);
1487 : 2 : Node xy = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y);
1488 : 1 : Node f = d_nodeManager->mkConst(false);
1489 : :
1490 : : // inferEqsFromContains("", (str.++ x y)) returns something equivalent to
1491 : : // (= "" y)
1492 : : Node empty_x_y =
1493 : 1 : d_nodeManager->mkNode(Kind::AND,
1494 : 2 : d_nodeManager->mkNode(Kind::EQUAL, empty, x),
1495 : 4 : d_nodeManager->mkNode(Kind::EQUAL, empty, y));
1496 : 1 : sameNormalForm(se.inferEqsFromContains(empty, xy), empty_x_y);
1497 : :
1498 : : // inferEqsFromContains(x, (str.++ x y)) returns false
1499 : 5 : Node bxya = d_nodeManager->mkNode(Kind::STRING_CONCAT, {b, y, x, a});
1500 : 1 : sameNormalForm(se.inferEqsFromContains(x, bxya), f);
1501 : :
1502 : : // inferEqsFromContains(x, y) returns null
1503 : 2 : Node n = se.inferEqsFromContains(x, y);
1504 [ - + ]: 1 : ASSERT_TRUE(n.isNull());
1505 : :
1506 : : // inferEqsFromContains(x, x) returns something equivalent to (= x x)
1507 : 3 : Node eq_x_x = d_nodeManager->mkNode(Kind::EQUAL, x, x);
1508 : 1 : sameNormalForm(se.inferEqsFromContains(x, x), eq_x_x);
1509 : :
1510 : : // inferEqsFromContains((str.replace x "B" "A"), x) returns something
1511 : : // equivalent to (= (str.replace x "B" "A") x)
1512 : 3 : Node repl = d_nodeManager->mkNode(Kind::STRING_REPLACE, x, b, a);
1513 : 3 : Node eq_repl_x = d_nodeManager->mkNode(Kind::EQUAL, repl, x);
1514 : 1 : sameNormalForm(se.inferEqsFromContains(repl, x), eq_repl_x);
1515 : :
1516 : : // inferEqsFromContains(x, (str.replace x "B" "A")) returns something
1517 : : // equivalent to (= (str.replace x "B" "A") x)
1518 : 2 : Node eq_x_repl = d_nodeManager->mkNode(Kind::EQUAL, x, repl);
1519 : 1 : sameNormalForm(se.inferEqsFromContains(x, repl), eq_x_repl);
1520 : : }
1521 : :
1522 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_prefix_suffix)
1523 : : {
1524 : 2 : TypeNode strType = d_nodeManager->stringType();
1525 : :
1526 : 2 : Node empty = d_nodeManager->mkConst(String(""));
1527 : 2 : Node a = d_nodeManager->mkConst(String("A"));
1528 : 3 : Node x = d_nodeManager->mkVar("x", strType);
1529 : 3 : Node y = d_nodeManager->mkVar("y", strType);
1530 : 3 : Node xx = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x);
1531 : 3 : Node xxa = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x, a);
1532 : 3 : Node xy = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y);
1533 : 2 : Node f = d_nodeManager->mkConst(false);
1534 : :
1535 : : // Same normal form for:
1536 : : //
1537 : : // (str.prefix (str.++ x y) x)
1538 : : //
1539 : : // (= y "")
1540 : 3 : Node p_xy = d_nodeManager->mkNode(Kind::STRING_PREFIX, xy, x);
1541 : 3 : Node empty_y = d_nodeManager->mkNode(Kind::EQUAL, y, empty);
1542 : 1 : sameNormalForm(p_xy, empty_y);
1543 : :
1544 : : // Same normal form for:
1545 : : //
1546 : : // (str.suffix (str.++ x x) x)
1547 : : //
1548 : : // (= x "")
1549 : 3 : Node p_xx = d_nodeManager->mkNode(Kind::STRING_SUFFIX, xx, x);
1550 : 3 : Node empty_x = d_nodeManager->mkNode(Kind::EQUAL, x, empty);
1551 : 1 : sameNormalForm(p_xx, empty_x);
1552 : :
1553 : : // (str.suffix x (str.++ x x "A")) ---> false
1554 : 2 : Node p_xxa = d_nodeManager->mkNode(Kind::STRING_SUFFIX, xxa, x);
1555 : 1 : sameNormalForm(p_xxa, f);
1556 : 1 : }
1557 : :
1558 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_equality_ext)
1559 : : {
1560 : 2 : TypeNode strType = d_nodeManager->stringType();
1561 : 2 : TypeNode intType = d_nodeManager->integerType();
1562 : :
1563 : 2 : Node empty = d_nodeManager->mkConst(String(""));
1564 : 2 : Node a = d_nodeManager->mkConst(String("A"));
1565 : 2 : Node aaa = d_nodeManager->mkConst(String("AAA"));
1566 : 2 : Node b = d_nodeManager->mkConst(String("B"));
1567 : 2 : Node ba = d_nodeManager->mkConst(String("BA"));
1568 : 3 : Node w = d_nodeManager->mkVar("w", strType);
1569 : 3 : Node x = d_nodeManager->mkVar("x", strType);
1570 : 3 : Node y = d_nodeManager->mkVar("y", strType);
1571 : 3 : Node z = d_nodeManager->mkVar("z", strType);
1572 : 3 : Node xxa = d_nodeManager->mkNode(Kind::STRING_CONCAT, x, x, a);
1573 : 2 : Node f = d_nodeManager->mkConst(false);
1574 : 3 : Node n = d_nodeManager->mkVar("n", intType);
1575 : 2 : Node zero = d_nodeManager->mkConstInt(Rational(0));
1576 : 2 : Node one = d_nodeManager->mkConstInt(Rational(1));
1577 : 2 : Node three = d_nodeManager->mkConstInt(Rational(3));
1578 : :
1579 : : // Same normal form for:
1580 : : //
1581 : : // (= "" (str.replace "" x "B"))
1582 : : //
1583 : : // (not (= x ""))
1584 : 1 : Node empty_repl = d_nodeManager->mkNode(
1585 : : Kind::EQUAL,
1586 : : empty,
1587 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, x, b));
1588 : 1 : Node empty_x = d_nodeManager->mkNode(
1589 : 3 : Kind::NOT, d_nodeManager->mkNode(Kind::EQUAL, x, empty));
1590 : 1 : sameNormalForm(empty_repl, empty_x);
1591 : :
1592 : : // Same normal form for:
1593 : : //
1594 : : // (= "" (str.replace x y (str.++ x x "A")))
1595 : : //
1596 : : // (and (= x "") (not (= y "")))
1597 : 1 : Node empty_repl_xaa = d_nodeManager->mkNode(
1598 : : Kind::EQUAL,
1599 : : empty,
1600 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, y, xxa));
1601 : 1 : Node empty_xy = d_nodeManager->mkNode(
1602 : : Kind::AND,
1603 : 2 : d_nodeManager->mkNode(Kind::EQUAL, x, empty),
1604 : 2 : d_nodeManager->mkNode(Kind::NOT,
1605 : 7 : d_nodeManager->mkNode(Kind::EQUAL, y, empty)));
1606 : 1 : sameNormalForm(empty_repl_xaa, empty_xy);
1607 : :
1608 : : // (= "" (str.replace (str.++ x x "A") x y)) ---> false
1609 : 1 : Node empty_repl_xxaxy = d_nodeManager->mkNode(
1610 : : Kind::EQUAL,
1611 : : empty,
1612 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, xxa, x, y));
1613 : 1 : Node eq_xxa_repl = d_nodeManager->mkNode(
1614 : : Kind::EQUAL,
1615 : : xxa,
1616 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, y, x));
1617 : 1 : sameNormalForm(empty_repl_xxaxy, f);
1618 : :
1619 : : // Same normal form for:
1620 : : //
1621 : : // (= "" (str.replace "A" x y))
1622 : : //
1623 : : // (= "A" (str.replace "" y x))
1624 : 1 : Node empty_repl_axy = d_nodeManager->mkNode(
1625 : 3 : Kind::EQUAL, empty, d_nodeManager->mkNode(Kind::STRING_REPLACE, a, x, y));
1626 : 1 : Node eq_a_repl = d_nodeManager->mkNode(
1627 : 3 : Kind::EQUAL, a, d_nodeManager->mkNode(Kind::STRING_REPLACE, empty, y, x));
1628 : 1 : sameNormalForm(empty_repl_axy, eq_a_repl);
1629 : :
1630 : : // Same normal form for:
1631 : : //
1632 : : // (= "" (str.replace x "A" ""))
1633 : : //
1634 : : // (str.prefix x "A")
1635 : 1 : Node empty_repl_a = d_nodeManager->mkNode(
1636 : : Kind::EQUAL,
1637 : : empty,
1638 : 3 : d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, empty));
1639 : 3 : Node prefix_a = d_nodeManager->mkNode(Kind::STRING_PREFIX, x, a);
1640 : 1 : sameNormalForm(empty_repl_a, prefix_a);
1641 : :
1642 : : // Same normal form for:
1643 : : //
1644 : : // (= "" (str.substr x 1 2))
1645 : : //
1646 : : // (<= (str.len x) 1)
1647 : 1 : Node empty_substr = d_nodeManager->mkNode(
1648 : : Kind::EQUAL,
1649 : : empty,
1650 : 3 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, one, three));
1651 : 1 : Node leq_len_x = d_nodeManager->mkNode(
1652 : 3 : Kind::LEQ, d_nodeManager->mkNode(Kind::STRING_LENGTH, x), one);
1653 : 1 : sameNormalForm(empty_substr, leq_len_x);
1654 : :
1655 : : // Different normal form for:
1656 : : //
1657 : : // (= "" (str.substr x 0 n))
1658 : : //
1659 : : // (<= n 0)
1660 : 1 : Node empty_substr_x = d_nodeManager->mkNode(
1661 : : Kind::EQUAL,
1662 : : empty,
1663 : 3 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, zero, n));
1664 : 3 : Node leq_n = d_nodeManager->mkNode(Kind::LEQ, n, zero);
1665 : 1 : differentNormalForms(empty_substr_x, leq_n);
1666 : :
1667 : : // Same normal form for:
1668 : : //
1669 : : // (= "" (str.substr "A" 0 n))
1670 : : //
1671 : : // (<= n 0)
1672 : 1 : Node empty_substr_a = d_nodeManager->mkNode(
1673 : : Kind::EQUAL,
1674 : : empty,
1675 : 3 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, a, zero, n));
1676 : 1 : sameNormalForm(empty_substr_a, leq_n);
1677 : :
1678 : : // Same normal form for:
1679 : : //
1680 : : // (= (str.++ x x a) (str.replace y (str.++ x x a) y))
1681 : : //
1682 : : // (= (str.++ x x a) y)
1683 : 1 : Node eq_xxa_repl_y = d_nodeManager->mkNode(
1684 : 3 : Kind::EQUAL, xxa, d_nodeManager->mkNode(Kind::STRING_REPLACE, y, xxa, y));
1685 : 3 : Node eq_xxa_y = d_nodeManager->mkNode(Kind::EQUAL, xxa, y);
1686 : 1 : sameNormalForm(eq_xxa_repl_y, eq_xxa_y);
1687 : :
1688 : : // (= (str.++ x x a) (str.replace (str.++ x x a) "A" "B")) ---> false
1689 : 1 : Node eq_xxa_repl_xxa = d_nodeManager->mkNode(
1690 : 3 : Kind::EQUAL, xxa, d_nodeManager->mkNode(Kind::STRING_REPLACE, xxa, a, b));
1691 : 1 : sameNormalForm(eq_xxa_repl_xxa, f);
1692 : :
1693 : : // Same normal form for:
1694 : : //
1695 : : // (= (str.replace x "A" "B") "")
1696 : : //
1697 : : // (= x "")
1698 : 1 : Node eq_repl = d_nodeManager->mkNode(
1699 : 3 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, b), empty);
1700 : 3 : Node eq_x = d_nodeManager->mkNode(Kind::EQUAL, x, empty);
1701 : 1 : sameNormalForm(eq_repl, eq_x);
1702 : :
1703 : : {
1704 : : // Same normal form for:
1705 : : //
1706 : : // (= (str.replace y "A" "B") "B")
1707 : : //
1708 : : // (= (str.replace y "B" "A") "A")
1709 : 1 : Node lhs = d_nodeManager->mkNode(
1710 : 3 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, b), b);
1711 : 1 : Node rhs = d_nodeManager->mkNode(
1712 : 2 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_REPLACE, x, b, a), a);
1713 : 1 : sameNormalForm(lhs, rhs);
1714 : : }
1715 : :
1716 : : {
1717 : : // Same normal form for:
1718 : : //
1719 : : // (= (str.++ x "A" y) (str.++ "A" "A" (str.substr "AAA" 0 n)))
1720 : : //
1721 : : // (= (str.++ y x) (str.++ (str.substr "AAA" 0 n) "A"))
1722 : 1 : Node lhs = d_nodeManager->mkNode(
1723 : : Kind::EQUAL,
1724 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, a, y),
1725 : 2 : d_nodeManager->mkNode(
1726 : : Kind::STRING_CONCAT,
1727 : : a,
1728 : : a,
1729 : 7 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, aaa, zero, n)));
1730 : 1 : Node rhs = d_nodeManager->mkNode(
1731 : : Kind::EQUAL,
1732 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, y),
1733 : 3 : d_nodeManager->mkNode(
1734 : : Kind::STRING_CONCAT,
1735 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, aaa, zero, n),
1736 : 4 : a));
1737 : 1 : sameNormalForm(lhs, rhs);
1738 : : }
1739 : :
1740 : : {
1741 : : // Same normal form for:
1742 : : //
1743 : : // (= (str.++ "A" x) "A")
1744 : : //
1745 : : // (= x "")
1746 : 1 : Node lhs = d_nodeManager->mkNode(
1747 : 3 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_CONCAT, a, x), a);
1748 : 2 : Node rhs = d_nodeManager->mkNode(Kind::EQUAL, x, empty);
1749 : 1 : sameNormalForm(lhs, rhs);
1750 : : }
1751 : :
1752 : : {
1753 : : // (= (str.++ x "A") "") ---> false
1754 : 1 : Node eq = d_nodeManager->mkNode(
1755 : 2 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_CONCAT, x, a), empty);
1756 : 1 : sameNormalForm(eq, f);
1757 : : }
1758 : :
1759 : : {
1760 : : // (= (str.++ x "B") "AAA") ---> false
1761 : 1 : Node eq = d_nodeManager->mkNode(
1762 : 2 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_CONCAT, x, b), aaa);
1763 : 1 : sameNormalForm(eq, f);
1764 : : }
1765 : :
1766 : : {
1767 : : // (= (str.++ x "AAA") "A") ---> false
1768 : 1 : Node eq = d_nodeManager->mkNode(
1769 : 2 : Kind::EQUAL, d_nodeManager->mkNode(Kind::STRING_CONCAT, x, aaa), a);
1770 : 1 : sameNormalForm(eq, f);
1771 : : }
1772 : :
1773 : : {
1774 : : // (= (str.++ "AAA" (str.substr "A" 0 n)) (str.++ x "B")) ---> false
1775 : 1 : Node eq = d_nodeManager->mkNode(
1776 : : Kind::EQUAL,
1777 : 2 : d_nodeManager->mkNode(
1778 : : Kind::STRING_CONCAT,
1779 : : aaa,
1780 : 2 : d_nodeManager->mkNode(
1781 : : Kind::STRING_CONCAT,
1782 : : a,
1783 : : a,
1784 : 2 : d_nodeManager->mkNode(Kind::STRING_SUBSTR, x, zero, n))),
1785 : 4 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, b));
1786 : 1 : sameNormalForm(eq, f);
1787 : : }
1788 : :
1789 : : {
1790 : : // (= (str.++ "A" (int.to.str n)) "A") -/-> false
1791 : 1 : Node eq = d_nodeManager->mkNode(
1792 : : Kind::EQUAL,
1793 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT,
1794 : : a,
1795 : 2 : d_nodeManager->mkNode(Kind::STRING_ITOS, n)),
1796 : 3 : a);
1797 : 1 : differentNormalForms(eq, f);
1798 : : }
1799 : :
1800 : : {
1801 : : // (= (str.++ "A" x y) (str.++ x "B" z)) --> false
1802 : 1 : Node eq = d_nodeManager->mkNode(
1803 : : Kind::EQUAL,
1804 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, x, y),
1805 : 4 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, b, z));
1806 : 1 : sameNormalForm(eq, f);
1807 : : }
1808 : :
1809 : : {
1810 : : // (= (str.++ "B" x y) (str.++ x "AAA" z)) --> false
1811 : 1 : Node eq = d_nodeManager->mkNode(
1812 : : Kind::EQUAL,
1813 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, b, x, y),
1814 : 4 : d_nodeManager->mkNode(Kind::STRING_CONCAT, x, aaa, z));
1815 : 1 : sameNormalForm(eq, f);
1816 : : }
1817 : :
1818 : : {
1819 : 3 : Node xrepl = d_nodeManager->mkNode(Kind::STRING_REPLACE, x, a, b);
1820 : :
1821 : : // Same normal form for:
1822 : : //
1823 : : // (= (str.++ "B" (str.replace x "A" "B") z y w)
1824 : : // (str.++ z x "BA" z))
1825 : : //
1826 : : // (and (= (str.++ "B" (str.replace x "A" "B") z)
1827 : : // (str.++ z x "B"))
1828 : : // (= (str.++ y w) (str.++ "A" z)))
1829 : 1 : Node lhs = d_nodeManager->mkNode(
1830 : : Kind::EQUAL,
1831 : 8 : d_nodeManager->mkNode(Kind::STRING_CONCAT, {b, xrepl, z, y, w}),
1832 : 9 : d_nodeManager->mkNode(Kind::STRING_CONCAT, {z, x, ba, z}));
1833 : 1 : Node rhs = d_nodeManager->mkNode(
1834 : : Kind::AND,
1835 : 4 : d_nodeManager->mkNode(
1836 : : Kind::EQUAL,
1837 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, b, xrepl, z),
1838 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, z, x, b)),
1839 : 4 : d_nodeManager->mkNode(
1840 : : Kind::EQUAL,
1841 : 2 : d_nodeManager->mkNode(Kind::STRING_CONCAT, y, w),
1842 : 6 : d_nodeManager->mkNode(Kind::STRING_CONCAT, a, z)));
1843 : 1 : sameNormalForm(lhs, rhs);
1844 : : }
1845 : 1 : }
1846 : :
1847 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, strip_constant_endpoints)
1848 : : {
1849 : 1 : StringsEntail& se = d_seqRewriter->getStringsEntail();
1850 : 1 : TypeNode intType = d_nodeManager->integerType();
1851 : 1 : TypeNode strType = d_nodeManager->stringType();
1852 : :
1853 : 1 : Node empty = d_nodeManager->mkConst(String(""));
1854 : 1 : Node a = d_nodeManager->mkConst(String("A"));
1855 : 1 : Node ab = d_nodeManager->mkConst(String("AB"));
1856 : 1 : Node abc = d_nodeManager->mkConst(String("ABC"));
1857 : 1 : Node abcd = d_nodeManager->mkConst(String("ABCD"));
1858 : 1 : Node bc = d_nodeManager->mkConst(String("BC"));
1859 : 1 : Node c = d_nodeManager->mkConst(String("C"));
1860 : 1 : Node cd = d_nodeManager->mkConst(String("CD"));
1861 : 2 : Node x = d_nodeManager->mkVar("x", strType);
1862 : 2 : Node y = d_nodeManager->mkVar("y", strType);
1863 : 2 : Node n = d_nodeManager->mkVar("n", intType);
1864 : :
1865 : : {
1866 : : // stripConstantEndpoints({ "" }, { "A" }, {}, {}, 0) ---> false
1867 : 3 : std::vector<Node> n1 = {empty};
1868 : 3 : std::vector<Node> n2 = {a};
1869 : 1 : std::vector<Node> nb;
1870 : 1 : std::vector<Node> ne;
1871 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, 0);
1872 [ - + ]: 1 : ASSERT_FALSE(res);
1873 : : }
1874 : :
1875 : : {
1876 : : // stripConstantEndpoints({ "A" }, { "A". (int.to.str n) }, {}, {}, 0)
1877 : : // ---> false
1878 : 3 : std::vector<Node> n1 = {a};
1879 : 5 : std::vector<Node> n2 = {a, d_nodeManager->mkNode(Kind::STRING_ITOS, n)};
1880 : 1 : std::vector<Node> nb;
1881 : 1 : std::vector<Node> ne;
1882 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, 0);
1883 [ - + ]: 1 : ASSERT_FALSE(res);
1884 : : }
1885 : :
1886 : : {
1887 : : // stripConstantEndpoints({ "ABCD" }, { "C" }, {}, {}, 1)
1888 : : // ---> true
1889 : : // n1 is updated to { "CD" }
1890 : : // nb is updated to { "AB" }
1891 : 3 : std::vector<Node> n1 = {abcd};
1892 : 3 : std::vector<Node> n2 = {c};
1893 : 1 : std::vector<Node> nb;
1894 : 1 : std::vector<Node> ne;
1895 : 3 : std::vector<Node> n1r = {cd};
1896 : 3 : std::vector<Node> nbr = {ab};
1897 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, 1);
1898 [ - + ]: 1 : ASSERT_TRUE(res);
1899 [ - + ]: 1 : ASSERT_EQ(n1, n1r);
1900 [ - + ]: 1 : ASSERT_EQ(nb, nbr);
1901 : : }
1902 : :
1903 : : {
1904 : : // stripConstantEndpoints({ "ABC", x }, { "CD" }, {}, {}, 1)
1905 : : // ---> true
1906 : : // n1 is updated to { "C", x }
1907 : : // nb is updated to { "AB" }
1908 : 4 : std::vector<Node> n1 = {abc, x};
1909 : 3 : std::vector<Node> n2 = {cd};
1910 : 1 : std::vector<Node> nb;
1911 : 1 : std::vector<Node> ne;
1912 : 4 : std::vector<Node> n1r = {c, x};
1913 : 3 : std::vector<Node> nbr = {ab};
1914 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, 1);
1915 [ - + ]: 1 : ASSERT_TRUE(res);
1916 [ - + ]: 1 : ASSERT_EQ(n1, n1r);
1917 [ - + ]: 1 : ASSERT_EQ(nb, nbr);
1918 : : }
1919 : :
1920 : : {
1921 : : // stripConstantEndpoints({ "ABC" }, { "A" }, {}, {}, -1)
1922 : : // ---> true
1923 : : // n1 is updated to { "A" }
1924 : : // nb is updated to { "BC" }
1925 : 3 : std::vector<Node> n1 = {abc};
1926 : 3 : std::vector<Node> n2 = {a};
1927 : 1 : std::vector<Node> nb;
1928 : 1 : std::vector<Node> ne;
1929 : 3 : std::vector<Node> n1r = {a};
1930 : 3 : std::vector<Node> ner = {bc};
1931 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, -1);
1932 [ - + ]: 1 : ASSERT_TRUE(res);
1933 [ - + ]: 1 : ASSERT_EQ(n1, n1r);
1934 [ - + ]: 1 : ASSERT_EQ(ne, ner);
1935 : : }
1936 : :
1937 : : {
1938 : : // stripConstantEndpoints({ x, "ABC" }, { y, "A" }, {}, {}, -1)
1939 : : // ---> true
1940 : : // n1 is updated to { x, "A" }
1941 : : // nb is updated to { "BC" }
1942 : 4 : std::vector<Node> n1 = {x, abc};
1943 : 4 : std::vector<Node> n2 = {y, a};
1944 : 1 : std::vector<Node> nb;
1945 : 1 : std::vector<Node> ne;
1946 : 4 : std::vector<Node> n1r = {x, a};
1947 : 3 : std::vector<Node> ner = {bc};
1948 : 1 : bool res = se.stripConstantEndpoints(n1, n2, nb, ne, -1);
1949 [ - + ]: 1 : ASSERT_TRUE(res);
1950 [ - + ]: 1 : ASSERT_EQ(n1, n1r);
1951 [ - + ]: 1 : ASSERT_EQ(ne, ner);
1952 : : }
1953 : : }
1954 : :
1955 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_membership)
1956 : : {
1957 : 2 : TypeNode strType = d_nodeManager->stringType();
1958 : :
1959 : 2 : std::vector<Node> vec_empty;
1960 : 2 : Node abc = d_nodeManager->mkConst(String("ABC"));
1961 : 2 : Node re_abc = d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, abc);
1962 : 3 : Node x = d_nodeManager->mkVar("x", strType);
1963 : :
1964 : : {
1965 : : // Same normal form for:
1966 : : //
1967 : : // (str.in.re x (re.++ (re.* re.allchar)
1968 : : // (re.* re.allchar)
1969 : : // (str.to.re "ABC")
1970 : : // (re.* re.allchar)))
1971 : : //
1972 : : // (str.contains x "ABC")
1973 : 1 : Node sig_star = d_nodeManager->mkNode(
1974 : : Kind::REGEXP_STAR,
1975 : 3 : d_nodeManager->mkNode(Kind::REGEXP_ALLCHAR, vec_empty));
1976 : 1 : Node lhs = d_nodeManager->mkNode(
1977 : : Kind::STRING_IN_REGEXP,
1978 : : x,
1979 : 2 : d_nodeManager->mkNode(Kind::REGEXP_CONCAT,
1980 : 7 : {sig_star, sig_star, re_abc, sig_star}));
1981 : 2 : Node rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, abc);
1982 : 1 : sameNormalForm(lhs, rhs);
1983 : : }
1984 : :
1985 : : {
1986 : : // Different normal forms for:
1987 : : //
1988 : : // (str.in.re x (re.++ (re.* re.allchar) (str.to.re "ABC")))
1989 : : //
1990 : : // (str.contains x "ABC")
1991 : 1 : Node sig_star = d_nodeManager->mkNode(
1992 : : Kind::REGEXP_STAR,
1993 : 3 : d_nodeManager->mkNode(Kind::REGEXP_ALLCHAR, vec_empty));
1994 : 1 : Node lhs = d_nodeManager->mkNode(
1995 : : Kind::STRING_IN_REGEXP,
1996 : : x,
1997 : 3 : d_nodeManager->mkNode(Kind::REGEXP_CONCAT, sig_star, re_abc));
1998 : 2 : Node rhs = d_nodeManager->mkNode(Kind::STRING_CONTAINS, x, abc);
1999 : 1 : differentNormalForms(lhs, rhs);
2000 : : }
2001 : 1 : }
2002 : :
2003 : 2 : TEST_F(TestTheoryWhiteSequencesRewriter, rewrite_regexp_concat)
2004 : : {
2005 : 2 : TypeNode strType = d_nodeManager->stringType();
2006 : :
2007 : 2 : std::vector<Node> emptyArgs;
2008 : 3 : Node x = d_nodeManager->mkVar("x", strType);
2009 : 3 : Node y = d_nodeManager->mkVar("y", strType);
2010 : 1 : Node allStar = d_nodeManager->mkNode(
2011 : : Kind::REGEXP_STAR,
2012 : 3 : d_nodeManager->mkNode(Kind::REGEXP_ALLCHAR, emptyArgs));
2013 : 2 : Node xReg = d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, x);
2014 : 2 : Node yReg = d_nodeManager->mkNode(Kind::STRING_TO_REGEXP, y);
2015 : :
2016 : : {
2017 : : // In normal form:
2018 : : //
2019 : : // (re.++ (re.* re.allchar) (re.union (str.to.re x) (str.to.re y)))
2020 : 1 : Node n = d_nodeManager->mkNode(
2021 : : Kind::REGEXP_CONCAT,
2022 : : allStar,
2023 : 2 : d_nodeManager->mkNode(Kind::REGEXP_UNION, xReg, yReg));
2024 : 1 : inNormalForm(n);
2025 : : }
2026 : :
2027 : : {
2028 : : // In normal form:
2029 : : //
2030 : : // (re.++ (str.to.re x) (re.* re.allchar))
2031 : 2 : Node n = d_nodeManager->mkNode(Kind::REGEXP_CONCAT, xReg, allStar);
2032 : 1 : inNormalForm(n);
2033 : : }
2034 : 1 : }
2035 : : } // namespace test
2036 : : } // namespace cvc5::internal
|