1515#include < util/deprecate.h>
1616
1717// / 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.
1920// /
2021// / 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|
2731// /
2832// / \param prefix: an array of characters
2933// / \param str: an array of characters
@@ -34,34 +38,39 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix(
3438 const array_string_exprt &str,
3539 const exprt &offset)
3640{
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 ()));
3948
4049 // 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),
5765 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+ }());
6273
63- implies_exprt a3 (not_exprt (isprefix), s0_notpref_s1);
64- lemmas.push_back (a3);
6574 return isprefix;
6675}
6776
@@ -135,6 +144,7 @@ exprt string_constraint_generatort::add_axioms_for_is_empty(
135144// / \param swap_arguments: boolean flag telling whether the suffix is the second
136145// / argument or the first argument
137146// / \return Boolean expression `issuffix`
147+ DEPRECATED (" should use `strings_startwith(s0, s1, s1.length - s0.length)`" )
138148exprt string_constraint_generatort::add_axioms_for_is_suffix(
139149 const function_application_exprt &f, bool swap_arguments)
140150{
0 commit comments