Skip to content

Commit f4285e7

Browse files
Add builtin support for string_set_char
1 parent 2a8ea0f commit f4285e7

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

src/solvers/refinement/string_builtin_function.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,37 @@ optionalt<exprt> string_concat_char_builtin_functiont::eval(
156156
return make_string(input_opt.value(), type);
157157
}
158158

159+
optionalt<exprt> string_set_char_builtin_functiont::eval(
160+
const std::function<exprt(const exprt &)> &get_value) const
161+
{
162+
auto input_opt = eval_string(input, get_value);
163+
const auto char_opt = numeric_cast<mp_integer>(get_value(character));
164+
const auto position_opt = numeric_cast<mp_integer>(get_value(position));
165+
if(!input_opt || !char_opt || !position_opt)
166+
return {};
167+
if(0 <= *position_opt && *position_opt < input_opt.value().size())
168+
input_opt.value()[numeric_cast_v<std::size_t>(*position_opt)] = *char_opt;
169+
const auto length =
170+
from_integer(input_opt.value().size(), result.length().type());
171+
const array_typet type(result.type().subtype(), length);
172+
return make_string(input_opt.value(), type);
173+
}
174+
175+
exprt string_set_char_builtin_functiont::length_constraint() const
176+
{
177+
const exprt out_of_bounds = or_exprt(
178+
binary_relation_exprt(position, ID_ge, input.length()),
179+
binary_relation_exprt(
180+
position, ID_le, from_integer(0, input.length().type())));
181+
const exprt return_value = if_exprt(
182+
out_of_bounds,
183+
from_integer(1, return_code.type()),
184+
from_integer(0, return_code.type()));
185+
return and_exprt(
186+
equal_exprt(result.length(), input.length()),
187+
equal_exprt(return_code, return_value));
188+
}
189+
159190
std::vector<mp_integer> string_insertion_builtin_functiont::eval(
160191
const std::vector<mp_integer> &input1_value,
161192
const std::vector<mp_integer> &input2_value,

src/solvers/refinement/string_builtin_function.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,48 @@ class string_concat_char_builtin_functiont
135135
}
136136
};
137137

138+
/// Setting a character at a particular position of a string
139+
class string_set_char_builtin_functiont
140+
: public string_transformation_builtin_functiont
141+
{
142+
public:
143+
exprt position;
144+
exprt character;
145+
146+
/// Constructor from arguments of a function application.
147+
/// The arguments in `fun_args` should be in order:
148+
/// an integer `result.length`, a character pointer `&result[0]`,
149+
/// a string `arg1` of type refined_string_typet, a position and a character.
150+
string_set_char_builtin_functiont(
151+
const exprt &return_code,
152+
const std::vector<exprt> &fun_args,
153+
array_poolt &array_pool)
154+
: string_transformation_builtin_functiont(return_code, fun_args, array_pool)
155+
{
156+
PRECONDITION(fun_args.size() == 5);
157+
position = fun_args[3];
158+
character = fun_args[4];
159+
}
160+
161+
optionalt<exprt>
162+
eval(const std::function<exprt(const exprt &)> &get_value) const override;
163+
164+
std::string name() const override
165+
{
166+
return "set_char";
167+
}
168+
169+
exprt add_constraints(string_constraint_generatort &generator) const override
170+
{
171+
return generator.add_axioms_for_set_char(
172+
result, input, position, character);
173+
}
174+
175+
// \todo: length_constraint is not the best possible name because we also
176+
// \todo: add constraint about the return code
177+
exprt length_constraint() const override;
178+
};
179+
138180
/// String inserting a string into another one
139181
class string_insertion_builtin_functiont : public string_builtin_functiont
140182
{

src/solvers/refinement/string_refinement_util.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ static std::unique_ptr<string_builtin_functiont> to_string_builtin_function(
228228
return util_make_unique<string_of_int_builtin_functiont>(
229229
return_code, fun_app.arguments(), array_pool);
230230

231+
if(id == ID_cprover_string_char_set_func)
232+
return util_make_unique<string_set_char_builtin_functiont>(
233+
return_code, fun_app.arguments(), array_pool);
234+
231235
return util_make_unique<string_builtin_function_with_no_evalt>(
232236
return_code, fun_app, array_pool);
233237
}

0 commit comments

Comments
 (0)