@@ -82,6 +82,90 @@ string_constraint_generatort::add_axioms_for_index_of(
82
82
return {index , std::move (constraints)};
83
83
}
84
84
85
+ // / Add axioms stating that the returned value is the index within `haystack`
86
+ // / (`str`) of the first occurrence of `needle` (`c`) starting the search at
87
+ // / `from_index`, or is `-1` if no such character occurs at or after position
88
+ // / `from_index`.
89
+ // / \todo Make argument names match whose of add_axioms_for_index_of_string
90
+ // /
91
+ // / These axioms are:
92
+ // / 1a. \f$-1 \le {\tt index} < {\tt terminating_zero} \f$
93
+ // / 1b. \f${\tt terminating_zero} < |{\tt haystack}| \f$
94
+ // / 2a. \f$ \lnot contains \Leftrightarrow {\tt index} = -1 \f$
95
+ // / 2b. \f$ {\tt haystack}{\tt terminating_zero} = '\0' \f$
96
+ // / 3. \f$ contains \Rightarrow {\tt from\_index} \le {\tt index}
97
+ // / \land {\tt haystack}[{\tt index}] = {\tt needle} \f$
98
+ // / 4. \f$ \forall i \in [{\tt from\_index}, {\tt index}).\ contains
99
+ // / \Rightarrow {\tt haystack}[i] \ne {\tt needle} \f$
100
+ // / 5. \f$ \forall m, n \in [{\tt from\_index}, {\tt terminating_zero+1})
101
+ // / .\ \lnot contains \Rightarrow {\tt haystack}[m] \ne {\tt needle}
102
+ // / \f$
103
+ // / \param str: an array of characters expression
104
+ // / \param c: a character expression
105
+ // / \param from_index: an integer expression
106
+ // / \return integer expression `index`
107
+ std::pair<exprt, string_constraintst>
108
+ string_constraint_generatort::add_axioms_for_c_index_of (
109
+ const array_string_exprt &str,
110
+ const exprt &c,
111
+ const exprt &from_index)
112
+ {
113
+ string_constraintst constraints;
114
+ const typet &index_type = str.length_type ();
115
+ symbol_exprt index = fresh_symbol (" index_of" , index_type);
116
+ symbol_exprt contains = fresh_symbol (" contains_in_index_of" );
117
+ symbol_exprt terminating_zero = fresh_symbol (" zero_in_index_of" , index_type);
118
+
119
+ exprt minus1 = from_integer (-1 , index_type);
120
+ and_exprt a1 (
121
+ binary_relation_exprt (index , ID_ge, minus1),
122
+ binary_relation_exprt (index , ID_le, terminating_zero),
123
+ binary_relation_exprt (
124
+ terminating_zero, ID_lt, array_pool.get_or_create_length (str)));
125
+ constraints.existential .push_back (a1);
126
+
127
+ equal_exprt a2 (not_exprt (contains), equal_exprt (index , minus1));
128
+ constraints.existential .push_back (a2);
129
+
130
+ const exprt lower_bound (zero_if_negative (from_index));
131
+ // make sure that terminating zero exists (and is the smallest index after from
132
+ // that has a 0 character)
133
+ constraints.existential .push_back (
134
+ equal_exprt{str[terminating_zero], from_integer (0 , c.type ())});
135
+ symbol_exprt k = fresh_symbol (" QA_index_of" , index_type);
136
+ const string_constraintt a0 = string_constraintt{
137
+ k,
138
+ lower_bound,
139
+ zero_if_negative (terminating_zero),
140
+ not_exprt{equal_exprt{str[k], from_integer (0 , c.type ())}}};
141
+ constraints.universal .push_back (a0);
142
+
143
+ implies_exprt a3 (
144
+ contains,
145
+ and_exprt (
146
+ binary_relation_exprt (from_index, ID_le, index ),
147
+ equal_exprt (str[index ], c)));
148
+ constraints.existential .push_back (a3);
149
+
150
+ symbol_exprt n = fresh_symbol (" QA_index_of" , index_type);
151
+ string_constraintt a4{n,
152
+ lower_bound,
153
+ zero_if_negative (index ),
154
+ implies_exprt{contains, notequal_exprt{str[n], c}}};
155
+ constraints.universal .push_back (a4);
156
+
157
+ symbol_exprt m = fresh_symbol (" QA_index_of" , index_type);
158
+ string_constraintt a5 (
159
+ m,
160
+ lower_bound,
161
+ zero_if_negative (
162
+ plus_exprt{terminating_zero, from_integer (1 , terminating_zero.type ())}),
163
+ implies_exprt (not_exprt (contains), not_exprt (equal_exprt (str[m], c))));
164
+ constraints.universal .push_back (a5);
165
+
166
+ return {index , std::move (constraints)};
167
+ }
168
+
85
169
// / Add axioms stating that the returned value `index` is the index within
86
170
// / `haystack` of the first occurrence of `needle` starting the search at
87
171
// / `from_index`, or `-1` if needle does not occur at or after position
@@ -329,6 +413,37 @@ string_constraint_generatort::add_axioms_for_index_of(
329
413
}
330
414
}
331
415
416
+ // / Index of the first occurence of a target inside the string
417
+ // /
418
+ // / If the target is a character:
419
+ // NOLINTNEXTLINE
420
+ // / \copybrief add_axioms_for_index_of(const array_string_exprt&,const exprt&,const exprt&)
421
+ // NOLINTNEXTLINE
422
+ // / \link add_axioms_for_index_of(const array_string_exprt&,const exprt&,const exprt&)
423
+ // / (More...) \endlink
424
+ // /
425
+ // / If the target is a refined_string:
426
+ // / \copybrief add_axioms_for_index_of_string
427
+ // / \link add_axioms_for_index_of_string (More...)
428
+ // / \endlink
429
+ // / \warning slow for string targets
430
+ // / \param f: function application with arguments refined_string `haystack`,
431
+ // / refined_string or character `needle`, and optional integer `from_index`
432
+ // / with default value `0`
433
+ // / \return integer expression
434
+ std::pair<exprt, string_constraintst>
435
+ string_constraint_generatort::add_axioms_for_c_index_of (
436
+ const function_application_exprt &f)
437
+ {
438
+ auto const &str = f.arguments ().at (0 );
439
+ auto const &c = f.arguments ().at (1 );
440
+ auto const str_array = get_string_expr (array_pool, str);
441
+ return add_axioms_for_c_index_of (
442
+ str_array,
443
+ typecast_exprt{c, str_array.content ().type ().subtype ()},
444
+ from_integer (0 , str_array.length_type ()));
445
+ }
446
+
332
447
// / Add axioms stating that the returned value is the index within `haystack`
333
448
// / (`str`) of the last occurrence of `needle` (`c`) starting the search
334
449
// / backward at `from_index`, or `-1` if no such character occurs at or before
0 commit comments