15
15
#include < util/deprecate.h>
16
16
17
17
// / Add axioms stating that the returned expression is true exactly when the
18
- // / first string is a prefix of the second one, starting at position offset.
18
+ // / offset is greater or equal to 0 and the first string is a prefix of the
19
+ // / second one, starting at position offset.
19
20
// /
20
21
// / These axioms are:
21
- // / 1. \f$ {\tt isprefix} \Rightarrow |str| \ge |{\tt prefix}|+offset \f$
22
- // / 2. \f$ \forall 0 \le qvar<|{\tt prefix}|.\ {\tt isprefix}
23
- // / \Rightarrow s0[witness+{\tt offset}]=s2[witness] \f$
24
- // / 3. \f$ !{\tt isprefix} \Rightarrow |{\tt str}|<|{\tt prefix}|+{\tt offset}
25
- // / \lor (0 \le witness<|{\tt prefix}|
26
- // / \land {\tt str}[witness+{\tt offset}] \ne {\tt prefix}[witness])\f$
22
+ // / 1. isprefix => offset_within_bounds
23
+ // / 2. forall qvar in [0, |prefix|).
24
+ // / isprefix => str[qvar + offset] = prefix[qvar]
25
+ // / 3. !isprefix => !offset_within_bounds
26
+ // / || 0 <= witness < |prefix|
27
+ // / && str[witness+offset] != prefix[witness]
28
+ // /
29
+ // / where offset_within_bounds is:
30
+ // / offset >= 0 && offset <= |str| && |str| - offset >= |prefix|
27
31
// /
28
32
// / \param prefix: an array of characters
29
33
// / \param str: an array of characters
@@ -34,34 +38,39 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix(
34
38
const array_string_exprt &str,
35
39
const exprt &offset)
36
40
{
37
- symbol_exprt isprefix=fresh_boolean (" isprefix" );
38
- const typet &index_type=str.length ().type ();
41
+ const symbol_exprt isprefix = fresh_boolean (" isprefix" );
42
+ const typet &index_type = str.length ().type ();
43
+ const exprt offset_within_bounds = and_exprt (
44
+ binary_relation_exprt (offset, ID_ge, from_integer (0 , offset.type ())),
45
+ binary_relation_exprt (offset, ID_le, str.length ()),
46
+ binary_relation_exprt (
47
+ minus_exprt (str.length (), offset), ID_ge, prefix.length ()));
39
48
40
49
// Axiom 1.
41
- lemmas.push_back (
42
- implies_exprt (
43
- isprefix, str.axiom_for_length_ge (plus_exprt (prefix.length (), offset))));
44
-
45
- symbol_exprt qvar=fresh_univ_index (" QA_isprefix" , index_type);
46
- string_constraintt a2 (
47
- qvar,
48
- prefix.length (),
49
- implies_exprt (
50
- isprefix, equal_exprt (str[plus_exprt (qvar, offset)], prefix[qvar])));
51
- constraints.push_back (a2);
52
-
53
- symbol_exprt witness=fresh_exist_index (" witness_not_isprefix" , index_type);
54
- and_exprt witness_diff (
55
- axiom_for_is_positive_index (witness),
56
- and_exprt (
50
+ lemmas.push_back (implies_exprt (isprefix, offset_within_bounds));
51
+
52
+ // Axiom 2.
53
+ constraints.push_back ([&] {
54
+ const symbol_exprt qvar = fresh_univ_index (" QA_isprefix" , index_type);
55
+ const exprt body = implies_exprt (
56
+ isprefix, equal_exprt (str[plus_exprt (qvar, offset)], prefix[qvar]));
57
+ return string_constraintt (qvar, prefix.length (), body);
58
+ }());
59
+
60
+ // Axiom 3.
61
+ lemmas.push_back ([&] {
62
+ const exprt witness = fresh_exist_index (" witness_not_isprefix" , index_type);
63
+ const exprt strings_differ_at_witness = and_exprt (
64
+ axiom_for_is_positive_index (witness),
57
65
prefix.axiom_for_length_gt (witness),
58
- notequal_exprt (str[plus_exprt (witness, offset)], prefix[witness])));
59
- or_exprt s0_notpref_s1 (
60
- not_exprt (str.axiom_for_length_ge (plus_exprt (prefix.length (), offset))),
61
- witness_diff);
66
+ notequal_exprt (str[plus_exprt (witness, offset)], prefix[witness]));
67
+ const exprt s1_does_not_start_with_s0 = or_exprt (
68
+ not_exprt (offset_within_bounds),
69
+ not_exprt (str.axiom_for_length_ge (plus_exprt (prefix.length (), offset))),
70
+ strings_differ_at_witness);
71
+ return implies_exprt (not_exprt (isprefix), s1_does_not_start_with_s0);
72
+ }());
62
73
63
- implies_exprt a3 (not_exprt (isprefix), s0_notpref_s1);
64
- lemmas.push_back (a3);
65
74
return isprefix;
66
75
}
67
76
@@ -135,6 +144,7 @@ exprt string_constraint_generatort::add_axioms_for_is_empty(
135
144
// / \param swap_arguments: boolean flag telling whether the suffix is the second
136
145
// / argument or the first argument
137
146
// / \return Boolean expression `issuffix`
147
+ DEPRECATED (" should use `strings_startwith(s0, s1, s1.length - s0.length)`" )
138
148
exprt string_constraint_generatort::add_axioms_for_is_suffix(
139
149
const function_application_exprt &f, bool swap_arguments)
140
150
{
0 commit comments