1414#include < solvers/refinement/string_constraint_generator.h>
1515
1616// / Add axioms enforcing that `res` is the concatenation of `s1` with
17- // / the substring of `s2` starting at index `start_index` and ending
18- // / at index `end_index`.
19- // /
20- // / If `start_index >= end_index`, the value returned is `s1`.
21- // / If `end_index > |s2|` and/or `start_index < 0`, the appended string will
22- // / be of length `end_index - start_index` and padded with non-deterministic
23- // / values.
17+ // / the substring of `s2` starting at index `start_index'` and ending
18+ // / at index `end_index'`.
19+ // / Where start_index' is max(0, start_index) and end_index' is
20+ // / max(min(end_index, s2.length), start_index')
2421// /
2522// / These axioms are:
26- // / 1. \f$end\_index > start\_index \Rightarrow |res| = |s_1| + end\_index -
27- // / start\_index
28- // / \f$
29- // / 2. \f$end\_index \le start\_index \Rightarrow res = s_1 \f$
30- // / 3. \f$\forall i<|s_1|. res[i]=s_1[i] \f$
31- // / 4. \f$\forall i< end\_index - start\_index.\ res[i+|s_1|]
32- // / = s_2[start\_index+i]\f$
23+ // / 1. \f$|res| = |s_1| + end\_index' - start\_index' \f$
24+ // / 2. \f$\forall i<|s_1|. res[i]=s_1[i] \f$
25+ // / 3. \f$\forall i< end\_index' - start\_index'.\ res[i+|s_1|]
26+ // / = s_2[start\_index'+i]\f$
3327// /
3428// / \param res: an array of characters expression
3529// / \param s1: an array of characters expression
@@ -44,28 +38,33 @@ exprt string_constraint_generatort::add_axioms_for_concat_substr(
4438 const exprt &start_index,
4539 const exprt &end_index)
4640{
47- binary_relation_exprt prem (end_index, ID_gt, start_index);
48-
49- exprt res_length=plus_exprt_with_overflow_check (
50- s1.length (), minus_exprt (end_index, start_index));
51- implies_exprt a1 (prem, equal_exprt (res.length (), res_length));
52- lemmas.push_back (a1);
53-
54- implies_exprt a2 (not_exprt (prem), equal_exprt (res.length (), s1.length ()));
55- lemmas.push_back (a2);
41+ const typet &index_type = start_index.type ();
42+ const exprt start1 = maximum (start_index, from_integer (0 , index_type));
43+ const exprt end1 = maximum (minimum (end_index, s2.length ()), start1);
44+
45+ // Axiom 1.
46+ lemmas.push_back ([&] { // NOLINT
47+ const plus_exprt res_length (s1.length (), minus_exprt (end1, start1));
48+ return equal_exprt (res.length (), res_length);
49+ }());
50+
51+ // Axiom 2.
52+ constraints.push_back ([&] { // NOLINT
53+ const symbol_exprt idx =
54+ fresh_univ_index (" QA_index_concat" , res.length ().type ());
55+ return string_constraintt (idx, s1.length (), equal_exprt (s1[idx], res[idx]));
56+ }());
57+
58+ // Axiom 3.
59+ constraints.push_back ([&] { // NOLINT
60+ const symbol_exprt idx2 =
61+ fresh_univ_index (" QA_index_concat2" , res.length ().type ());
62+ const equal_exprt res_eq (
63+ res[plus_exprt (idx2, s1.length ())], s2[plus_exprt (start1, idx2)]);
64+ return string_constraintt (idx2, minus_exprt (end1, start1), res_eq);
65+ }());
5666
57- symbol_exprt idx=fresh_univ_index (" QA_index_concat" , res.length ().type ());
58- string_constraintt a3 (idx, s1.length (), equal_exprt (s1[idx], res[idx]));
59- constraints.push_back (a3);
60-
61- symbol_exprt idx2=fresh_univ_index (" QA_index_concat2" , res.length ().type ());
62- equal_exprt res_eq (
63- res[plus_exprt (idx2, s1.length ())], s2[plus_exprt (start_index, idx2)]);
64- string_constraintt a4 (idx2, minus_exprt (end_index, start_index), res_eq);
65- constraints.push_back (a4);
66-
67- // We should have a enum type for the possible error codes
68- return from_integer (0 , res.length ().type ());
67+ return from_integer (0 , get_return_code_type ());
6968}
7069
7170// / Add axioms enforcing that `res` is the concatenation of `s1` with
0 commit comments