Skip to content

Commit a7562de

Browse files
Declare a nodet class in string_dependencies
This make it more convenient to reuse graph function, rather than using a common index for two tables.
1 parent 258f38a commit a7562de

File tree

2 files changed

+65
-108
lines changed

2 files changed

+65
-108
lines changed

src/solvers/refinement/string_refinement_util.cpp

Lines changed: 38 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ string_dependenciest::get_node(const array_string_exprt &e)
363363
if(!entry_inserted.second)
364364
return string_nodes[entry_inserted.first->second];
365365

366-
string_nodes.emplace_back();
366+
string_nodes.emplace_back(e, entry_inserted.first->second);
367367
return string_nodes.back();
368368
}
369369

@@ -467,54 +467,6 @@ static void add_dependency_to_string_subexprs(
467467
}
468468
}
469469

470-
string_dependenciest::node_indext string_dependenciest::size() const
471-
{
472-
return builtin_function_nodes.size() + string_nodes.size();
473-
}
474-
475-
/// Convert an index of a string node in `string_nodes` to the node_indext for
476-
/// the same node
477-
static std::size_t string_index_to_node_index(const std::size_t string_index)
478-
{
479-
return 2 * string_index + 1;
480-
}
481-
482-
/// Convert an index of a builtin function node to the node_indext for
483-
/// the same node
484-
static std::size_t
485-
builtin_function_index_to_node_index(const std::size_t builtin_index)
486-
{
487-
return 2 * builtin_index;
488-
}
489-
490-
string_dependenciest::node_indext
491-
string_dependenciest::node_index(const builtin_function_nodet &n) const
492-
{
493-
return builtin_function_index_to_node_index(n.index);
494-
}
495-
496-
string_dependenciest::node_indext
497-
string_dependenciest::node_index(const array_string_exprt &s) const
498-
{
499-
return string_index_to_node_index(node_index_pool.at(s));
500-
}
501-
502-
optionalt<string_dependenciest::builtin_function_nodet>
503-
string_dependenciest::get_builtin_function_node(node_indext i) const
504-
{
505-
if(i % 2 == 0)
506-
return builtin_function_nodet(i / 2);
507-
return {};
508-
}
509-
510-
optionalt<string_dependenciest::string_nodet>
511-
string_dependenciest::get_string_node(node_indext i) const
512-
{
513-
if(i % 2 == 1 && i / 2 < string_nodes.size())
514-
return string_nodes[i / 2];
515-
return {};
516-
}
517-
518470
optionalt<exprt> string_dependenciest::eval(
519471
const array_string_exprt &s,
520472
const std::function<exprt(const exprt &)> &get_value) const
@@ -583,50 +535,57 @@ bool add_node(
583535
}
584536

585537
void string_dependenciest::for_each_successor(
586-
const std::size_t &i,
587-
const std::function<void(const std::size_t &)> &f) const
538+
const nodet &node,
539+
const std::function<void(const nodet &)> &f) const
588540
{
589-
if(const auto &builtin_function_node = get_builtin_function_node(i))
541+
if(node.kind == nodet::BUILTIN)
590542
{
591-
const string_builtin_functiont &p =
592-
get_builtin_function(*builtin_function_node);
593-
std::for_each(
594-
p.string_arguments().begin(),
595-
p.string_arguments().end(),
596-
[&](const array_string_exprt &s) { f(node_index(s)); });
543+
const auto &builtin = builtin_function_nodes[node.index];
544+
for(const auto &s : builtin->string_arguments())
545+
{
546+
if(const auto node = node_at(s))
547+
f(nodet(*node));
548+
}
597549
}
598-
else if(const auto &s = get_string_node(i))
550+
else if(node.kind == nodet::STRING)
599551
{
552+
const auto &s_node = string_nodes[node.index];
600553
std::for_each(
601-
s->dependencies.begin(),
602-
s->dependencies.end(),
603-
[&](const builtin_function_nodet &p) { f(node_index(p)); });
554+
s_node.dependencies.begin(),
555+
s_node.dependencies.end(),
556+
[&](const builtin_function_nodet &p) { f(nodet(p)); });
604557
}
605558
else
606559
UNREACHABLE;
607560
}
608561

562+
void string_dependenciest::for_each_node(
563+
const std::function<void(const nodet &)> &f) const
564+
{
565+
for(const auto string_node : string_nodes)
566+
f(nodet(string_node));
567+
for(std::size_t i = 0; i < builtin_function_nodes.size(); ++i)
568+
f(nodet(builtin_function_nodet(i)));
569+
}
570+
609571
void string_dependenciest::output_dot(std::ostream &stream) const
610572
{
611-
const auto for_each_node =
612-
[&](const std::function<void(const std::size_t &)> &f) { // NOLINT
613-
for(std::size_t i = 0; i < string_nodes.size(); ++i)
614-
f(string_index_to_node_index(i));
615-
for(std::size_t i = 0; i < builtin_function_nodes.size(); ++i)
616-
f(builtin_function_index_to_node_index(i));
573+
const auto for_each = [&](const std::function<void(const nodet &)> &f) { // NOLINT
574+
for_each_node(f);
617575
};
618-
619-
const auto for_each_succ = [&](
620-
const std::size_t &i,
621-
const std::function<void(const std::size_t &)> &f) { // NOLINT
622-
for_each_successor(i, f);
623-
};
624-
625-
const auto node_to_string = [&](const std::size_t &i) { // NOLINT
626-
return std::to_string(i);
576+
const auto for_each_succ =
577+
[&](const nodet &n, const std::function<void(const nodet &)> &f) { // NOLINT
578+
for_each_successor(n, f);
579+
};
580+
const auto node_to_string = [&](const nodet &n) { // NOLINT
581+
std::stringstream ostream;
582+
if(n.kind == nodet::BUILTIN)
583+
ostream << "builtin_" << n.index;
584+
else
585+
ostream << '"' << format(string_nodes[n.index].expr) << '"';
586+
return ostream.str();
627587
};
628588
stream << "digraph dependencies {\n";
629-
output_dot_generic<std::size_t>(
630-
stream, for_each_node, for_each_succ, node_to_string);
589+
output_dot_generic<nodet>(stream, for_each, for_each_succ, node_to_string);
631590
stream << '}' << std::endl;
632591
}

src/solvers/refinement/string_refinement_util.h

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,18 @@ class string_dependenciest
303303
class string_nodet
304304
{
305305
public:
306+
// expression the node corresponds to
307+
array_string_exprt expr;
308+
// index in the string_nodes vector
309+
std::size_t index;
310+
// builtin functions on which it depends
306311
std::vector<builtin_function_nodet> dependencies;
307-
308312
// In case it depends on a builtin_function we don't support yet
309313
bool depends_on_unknown_builtin_function = false;
314+
315+
explicit string_nodet(array_string_exprt e, const std::size_t index)
316+
: expr(std::move(e)), index(index)
317+
{ }
310318
};
311319

312320
string_nodet &get_node(const array_string_exprt &e);
@@ -350,45 +358,35 @@ class string_dependenciest
350358
/// Set of nodes representing strings
351359
std::vector<string_nodet> string_nodes;
352360

353-
mutable std::vector<optionalt<exprt>> eval_string_cache;
354-
355361
/// Nodes describing dependencies of a string: values of the map correspond
356362
/// to indexes in the vector `string_nodes`.
357363
std::unordered_map<array_string_exprt, std::size_t, irep_hash>
358364
node_index_pool;
359365

360-
/// Common index for all nodes (both strings and builtin_functions) so that we
361-
/// can reuse generic algorithms of util/graph.h
362-
/// Even indexes correspond to builtin_function nodes, odd indexes to string
363-
/// nodes.
364-
typedef std::size_t node_indext;
365-
366-
/// \return total number of nodes
367-
node_indext size() const;
366+
class nodet
367+
{
368+
public:
369+
enum { BUILTIN, STRING} kind;
370+
std::size_t index;
368371

369-
/// \param n: builtin function node
370-
/// \return index corresponding to builtin function node `n`
371-
node_indext node_index(const builtin_function_nodet &n) const;
372+
nodet(const builtin_function_nodet &builtin) :
373+
kind(BUILTIN), index(builtin.index)
374+
{}
372375

373-
/// \param s: array expression representing a string
374-
/// \return index corresponding to an string exprt s
375-
node_indext node_index(const array_string_exprt &s) const;
376+
nodet(const string_nodet &string_node):
377+
kind(STRING), index(string_node.index)
378+
{}
379+
};
376380

377-
/// \param i: index of a node
378-
/// \return corresponding node if the index corresponds to a builtin function
379-
/// node, empty optional otherwise
380-
optionalt<builtin_function_nodet>
381-
get_builtin_function_node(node_indext i) const;
381+
mutable std::vector<optionalt<exprt>> eval_string_cache;
382382

383-
/// \param i: index of a node
384-
/// \return corresponding node if the index corresponds to a string
385-
/// node, empty optional otherwise
386-
optionalt<string_nodet> get_string_node(node_indext i) const;
383+
/// Applies `f` on all nodes
384+
void for_each_node(const std::function<void(const nodet &)> &f) const;
387385

388-
/// Applies `f` on all successors of the node with index `i`
386+
/// Applies `f` on all successors of the node n
389387
void for_each_successor(
390-
const node_indext &i,
391-
const std::function<void(const node_indext &)> &f) const;
388+
const nodet &i,
389+
const std::function<void(const nodet &)> &f) const;
392390
};
393391

394392
/// When right hand side of equation is a builtin_function add

0 commit comments

Comments
 (0)