Skip to content

Commit 1d92c48

Browse files
Add string primitive to constrain characters
This add a constraint on all characters between given index bounds.
1 parent cb01526 commit 1d92c48

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

src/solvers/refinement/string_constraint_generator.h

+3
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,14 @@ class string_constraint_generatort final
109109

110110
void add_default_axioms(const array_string_exprt &s);
111111
exprt axiom_for_is_positive_index(const exprt &x);
112+
112113
void add_constraint_on_characters(
113114
const array_string_exprt &s,
114115
const exprt &start,
115116
const exprt &end,
116117
const std::string &char_set);
118+
exprt
119+
add_axioms_for_constrain_characters(const function_application_exprt &f);
117120

118121
// The following functions add axioms for the returned value
119122
// to be equal to the result of the function given as argument.

src/solvers/refinement/string_constraint_generator_main.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,32 @@ void string_constraint_generatort::add_constraint_on_characters(
363363
axioms.push_back(sc);
364364
}
365365

366+
/// Add axioms to ensure all characters of a string belong to a given set.
367+
///
368+
/// The axiom is: \f$\forall i \in [start, end).\ s[i] \in char_set \f$, where
369+
/// `char_set` is given by the string `char_set_string` composed of three
370+
/// characters `low_char`, `-` and `high_char`. Character `c` belongs to
371+
/// `char_set` if \f$low_char \le c \le high_char\f$.
372+
/// \param f: a function application with arguments: integer `|s|`, character
373+
/// pointer `&s[0]`, string `char_set_string`,
374+
/// optional integers `start` and `end`
375+
/// \return integer expression whose value is zero
376+
exprt string_constraint_generatort::add_axioms_for_constrain_characters(
377+
const function_application_exprt &f)
378+
{
379+
const auto &args = f.arguments();
380+
PRECONDITION(3 <= args.size() && args.size() <= 5);
381+
PRECONDITION(args[2].type().id() == ID_string);
382+
PRECONDITION(args[2].id() == ID_constant);
383+
const array_string_exprt s = char_array_of_pointer(args[1], args[0]);
384+
const irep_idt &char_set_string = to_constant_expr(args[2]).get_value();
385+
const exprt &start =
386+
args.size() >= 4 ? args[3] : from_integer(0, s.length().type());
387+
const exprt &end = args.size() >= 5 ? args[4] : s.length();
388+
add_constraint_on_characters(s, start, end, char_set_string.c_str());
389+
return from_integer(0, get_return_code_type());
390+
}
391+
366392
/// Adds creates a new array if it does not already exists
367393
/// TODO: This should be replaced by associate_char_array_to_char_pointer
368394
array_string_exprt string_constraint_generatort::char_array_of_pointer(
@@ -499,6 +525,8 @@ exprt string_constraint_generatort::add_axioms_for_function_application(
499525
res = associate_array_to_pointer(expr);
500526
else if(id == ID_cprover_associate_length_to_array_func)
501527
res = associate_length_to_array(expr);
528+
else if(id == ID_cprover_string_constrain_characters_func)
529+
res = add_axioms_for_constrain_characters(expr);
502530
else
503531
{
504532
std::string msg(

src/util/irep_ids.def

+1
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,7 @@ IREP_ID_ONE(cprover_string_concat_bool_func)
772772
IREP_ID_ONE(cprover_string_concat_double_func)
773773
IREP_ID_ONE(cprover_string_concat_float_func)
774774
IREP_ID_ONE(cprover_string_concat_code_point_func)
775+
IREP_ID_ONE(cprover_string_constrain_characters_func)
775776
IREP_ID_ONE(cprover_string_contains_func)
776777
IREP_ID_ONE(cprover_string_copy_func)
777778
IREP_ID_ONE(cprover_string_delete_func)

0 commit comments

Comments
 (0)