Skip to content

Commit 095d57b

Browse files
Add concat_char builtin function for strings
1 parent 44693e8 commit 095d57b

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/solvers/refinement/string_refinement_util.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,44 @@ equation_symbol_mappingt::find_equations(const exprt &expr)
173173
return equations_containing[expr];
174174
}
175175

176+
string_transformation_builtin_functiont::
177+
string_transformation_builtin_functiont(
178+
const std::vector<exprt> &fun_args,
179+
array_poolt &array_pool)
180+
{
181+
PRECONDITION(fun_args.size() > 2);
182+
const auto arg1 = expr_checked_cast<struct_exprt>(fun_args[2]);
183+
input = array_pool.find(arg1.op1(), arg1.op0());
184+
result = array_pool.find(fun_args[1], fun_args[0]);
185+
args.insert(args.end(), fun_args.begin() + 3, fun_args.end());
186+
}
187+
188+
optionalt<exprt> string_transformation_builtin_functiont::eval(
189+
const std::function<exprt(const exprt &)> &get_value) const
190+
{
191+
const auto &input_value = eval_string(input, get_value);
192+
if(!input_value.has_value())
193+
return {};
194+
195+
std::vector<mp_integer> arg_values;
196+
const auto &insert = std::back_inserter(arg_values);
197+
const mp_integer unknown('?');
198+
std::transform(
199+
args.begin(), args.end(), insert, [&](const exprt &e) { // NOLINT
200+
if(const auto val = numeric_cast<mp_integer>(get_value(e)))
201+
return *val;
202+
INVARIANT(
203+
get_value(e).id() == ID_unknown,
204+
"array valuation should only contain constants and unknown");
205+
return unknown;
206+
});
207+
208+
const auto result_value = eval(*input_value, arg_values);
209+
const auto length = from_integer(result_value.size(), result.length().type());
210+
const array_typet type(result.type().subtype(), length);
211+
return make_string(result_value, type);
212+
}
213+
176214
string_insertion_builtin_functiont::string_insertion_builtin_functiont(
177215
const std::vector<exprt> &fun_args,
178216
array_poolt &array_pool)
@@ -254,6 +292,16 @@ std::vector<mp_integer> string_concatenation_builtin_functiont::eval(
254292
return result;
255293
}
256294

295+
std::vector<mp_integer> string_concat_char_builtin_functiont::eval(
296+
const std::vector<mp_integer> &input_value,
297+
const std::vector<mp_integer> &args_value) const
298+
{
299+
PRECONDITION(args_value.size() == 1);
300+
std::vector<mp_integer> result(input_value);
301+
result.push_back(args_value[0]);
302+
return result;
303+
}
304+
257305
std::vector<mp_integer> string_insertion_builtin_functiont::eval(
258306
const std::vector<mp_integer> &input1_value,
259307
const std::vector<mp_integer> &input2_value,
@@ -319,6 +367,10 @@ static std::unique_ptr<string_builtin_functiont> to_string_builtin_function(
319367
return util_make_unique<string_concatenation_builtin_functiont>(
320368
fun_app.arguments(), array_pool);
321369

370+
if(id == ID_cprover_string_concat_char_func)
371+
return util_make_unique<string_concat_char_builtin_functiont>(
372+
fun_app.arguments(), array_pool);
373+
322374
return {};
323375
}
324376

src/solvers/refinement/string_refinement_util.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ class string_transformation_builtin_functiont : public string_builtin_functiont
170170
array_string_exprt input;
171171
std::vector<exprt> args;
172172
exprt return_code;
173+
174+
/// Constructor from arguments of a function application
175+
string_transformation_builtin_functiont(
176+
const std::vector<exprt> &fun_args,
177+
array_poolt &array_pool);
178+
173179
optionalt<array_string_exprt> string_result() const override
174180
{
175181
return result;
@@ -178,6 +184,31 @@ class string_transformation_builtin_functiont : public string_builtin_functiont
178184
{
179185
return {input};
180186
}
187+
188+
/// Evaluate the result from a concrete valuation of the arguments
189+
virtual std::vector<mp_integer> eval(
190+
const std::vector<mp_integer> &input_value,
191+
const std::vector<mp_integer> &args_value) const = 0;
192+
193+
optionalt<exprt>
194+
eval(const std::function<exprt(const exprt &)> &get_value) const override;
195+
};
196+
197+
/// Adding a character at the end of a string
198+
class string_concat_char_builtin_functiont
199+
: public string_transformation_builtin_functiont
200+
{
201+
public:
202+
string_concat_char_builtin_functiont(
203+
const std::vector<exprt> &fun_args,
204+
array_poolt &array_pool)
205+
: string_transformation_builtin_functiont(fun_args, array_pool)
206+
{
207+
}
208+
209+
std::vector<mp_integer> eval(
210+
const std::vector<mp_integer> &input_value,
211+
const std::vector<mp_integer> &args_value) const override;
181212
};
182213

183214
/// String inserting a string into another one

0 commit comments

Comments
 (0)