@@ -13,6 +13,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com
13
13
14
14
#include < solvers/refinement/string_refinement_invariant.h>
15
15
#include < solvers/refinement/string_constraint_generator.h>
16
+ #include " expr_cast.h"
16
17
17
18
// / add axioms to say that the returned string expression `res` has length `k`
18
19
// / and characters at position `i` in `res` are equal to the character at
@@ -359,38 +360,70 @@ string_exprt string_constraint_generatort::add_axioms_for_char_set(
359
360
return res;
360
361
}
361
362
362
- // / add axioms corresponding to the String.replace java function
363
- // / \par parameters: function application with three arguments, the first is a
364
- // / string,
365
- // / the second and the third are characters
363
+ // / Convert two expressions to pair of chars
364
+ // / If both expressions are characters, return pair of them
365
+ // / If both expressions are 1-length strings, return first character of each
366
+ // / Otherwise return empty optional
367
+ // / \param expr1 First expression
368
+ // / \param expr2 Second expression
369
+ // / \return Optional pair of two expressions
370
+ static optionalt<std::pair<exprt, exprt>> to_char_pair (
371
+ exprt expr1, exprt expr2)
372
+ {
373
+ if ((expr1.type ().id ()==ID_unsignedbv
374
+ || expr1.type ().id ()==ID_char)
375
+ && (expr2.type ().id ()==ID_char
376
+ || expr2.type ().id ()==ID_unsignedbv))
377
+ return std::make_pair (expr1, expr2);
378
+ const auto expr1_str=to_string_expr (expr1);
379
+ const auto expr2_str=to_string_expr (expr2);
380
+ const auto expr1_length=expr_cast<size_t >(expr1_str.length ());
381
+ const auto expr2_length=expr_cast<size_t >(expr2_str.length ());
382
+ if (expr1_length && expr2_length && *expr1_length==1 && *expr2_length==1 )
383
+ return std::make_pair (exprt (expr1_str[0 ]), exprt (expr2_str[0 ]));
384
+ return { };
385
+ }
386
+
387
+ // / Add axioms corresponding to the String.replace java function
388
+ // / Only supports String.replace(char, char) and
389
+ // / String.replace(String, String) for single-character strings
390
+ // / Returns original string in every other case (that behaviour is to
391
+ // / be fixed in the future)
392
+ // / \param f function application with three arguments, the first is a
393
+ // / string, the second and the third are either pair of characters or
394
+ // / a pair of strings
366
395
// / \return a new string expression
367
396
string_exprt string_constraint_generatort::add_axioms_for_replace (
368
397
const function_application_exprt &f)
369
398
{
370
399
string_exprt str=get_string_expr (args (f, 3 )[0 ]);
371
400
const refined_string_typet &ref_type=to_refined_string_type (str.type ());
372
- const exprt &old_char=args (f, 3 )[1 ];
373
- const exprt &new_char=args (f, 3 )[2 ];
374
- string_exprt res=fresh_string (ref_type);
375
-
376
- // We add axioms:
377
- // a1 : |res| = |str|
378
- // a2 : forall qvar, 0<=qvar<|res|,
379
- // str[qvar]=oldChar => res[qvar]=newChar
380
- // !str[qvar]=oldChar => res[qvar]=str[qvar]
381
-
382
- m_axioms.push_back (res.axiom_for_has_same_length_as (str));
383
-
384
- symbol_exprt qvar=fresh_univ_index (" QA_replace" , ref_type.get_index_type ());
385
- implies_exprt case1 (
386
- equal_exprt (str[qvar], old_char),
387
- equal_exprt (res[qvar], new_char));
388
- implies_exprt case2 (
389
- not_exprt (equal_exprt (str[qvar], old_char)),
390
- equal_exprt (res[qvar], str[qvar]));
391
- string_constraintt a2 (qvar, res.length (), and_exprt (case1, case2));
392
- m_axioms.push_back (a2);
393
- return res;
401
+ if (const auto maybe_chars=to_char_pair (args (f, 3 )[1 ], args (f, 3 )[2 ]))
402
+ {
403
+ const auto old_char=maybe_chars->first ;
404
+ const auto new_char=maybe_chars->second ;
405
+ string_exprt res=fresh_string (ref_type);
406
+
407
+ // We add axioms:
408
+ // a1 : |res| = |str|
409
+ // a2 : forall qvar, 0<=qvar<|res|,
410
+ // str[qvar]=oldChar => res[qvar]=newChar
411
+ // !str[qvar]=oldChar => res[qvar]=str[qvar]
412
+
413
+ m_axioms.push_back (res.axiom_for_has_same_length_as (str));
414
+
415
+ symbol_exprt qvar=fresh_univ_index (" QA_replace" , ref_type.get_index_type ());
416
+ implies_exprt case1 (
417
+ equal_exprt (str[qvar], old_char),
418
+ equal_exprt (res[qvar], new_char));
419
+ implies_exprt case2 (
420
+ not_exprt (equal_exprt (str[qvar], old_char)),
421
+ equal_exprt (res[qvar], str[qvar]));
422
+ string_constraintt a2 (qvar, res.length (), and_exprt (case1, case2));
423
+ m_axioms.push_back (a2);
424
+ return res;
425
+ }
426
+ return str;
394
427
}
395
428
396
429
// / add axioms corresponding to the StringBuilder.deleteCharAt java function
0 commit comments