Skip to content

Commit 0b3796e

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 fb676d5 commit 0b3796e

File tree

2 files changed

+73
-108
lines changed

2 files changed

+73
-108
lines changed

src/solvers/refinement/string_refinement_util.cpp

+39-79
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ string_dependenciest::get_node(const array_string_exprt &e)
381381
if(!entry_inserted.second)
382382
return string_nodes[entry_inserted.first->second];
383383

384-
string_nodes.emplace_back();
384+
string_nodes.emplace_back(e, entry_inserted.first->second);
385385
return string_nodes.back();
386386
}
387387

@@ -485,54 +485,6 @@ static void add_dependency_to_string_subexprs(
485485
}
486486
}
487487

488-
string_dependenciest::node_indext string_dependenciest::size() const
489-
{
490-
return builtin_function_nodes.size() + string_nodes.size();
491-
}
492-
493-
/// Convert an index of a string node in `string_nodes` to the node_indext for
494-
/// the same node
495-
static std::size_t string_index_to_node_index(const std::size_t string_index)
496-
{
497-
return 2 * string_index + 1;
498-
}
499-
500-
/// Convert an index of a builtin function node to the node_indext for
501-
/// the same node
502-
static std::size_t
503-
builtin_function_index_to_node_index(const std::size_t builtin_index)
504-
{
505-
return 2 * builtin_index;
506-
}
507-
508-
string_dependenciest::node_indext
509-
string_dependenciest::node_index(const builtin_function_nodet &n) const
510-
{
511-
return builtin_function_index_to_node_index(n.index);
512-
}
513-
514-
string_dependenciest::node_indext
515-
string_dependenciest::node_index(const array_string_exprt &s) const
516-
{
517-
return string_index_to_node_index(node_index_pool.at(s));
518-
}
519-
520-
optionalt<string_dependenciest::builtin_function_nodet>
521-
string_dependenciest::get_builtin_function_node(node_indext i) const
522-
{
523-
if(i % 2 == 0)
524-
return builtin_function_nodet(i / 2);
525-
return {};
526-
}
527-
528-
optionalt<string_dependenciest::string_nodet>
529-
string_dependenciest::get_string_node(node_indext i) const
530-
{
531-
if(i % 2 == 1 && i / 2 < string_nodes.size())
532-
return string_nodes[i / 2];
533-
return {};
534-
}
535-
536488
optionalt<exprt> string_dependenciest::eval(
537489
const array_string_exprt &s,
538490
const std::function<exprt(const exprt &)> &get_value) const
@@ -601,50 +553,58 @@ bool add_node(
601553
}
602554

603555
void string_dependenciest::for_each_successor(
604-
const std::size_t &i,
605-
const std::function<void(const std::size_t &)> &f) const
556+
const nodet &node,
557+
const std::function<void(const nodet &)> &f) const
606558
{
607-
if(const auto &builtin_function_node = get_builtin_function_node(i))
559+
if(node.kind == nodet::BUILTIN)
608560
{
609-
const string_builtin_functiont &p =
610-
get_builtin_function(*builtin_function_node);
611-
std::for_each(
612-
p.string_arguments().begin(),
613-
p.string_arguments().end(),
614-
[&](const array_string_exprt &s) { f(node_index(s)); });
561+
const auto &builtin = builtin_function_nodes[node.index];
562+
for(const auto &s : builtin->string_arguments())
563+
{
564+
if(const auto node = node_at(s))
565+
f(nodet(*node));
566+
}
615567
}
616-
else if(const auto &s = get_string_node(i))
568+
else if(node.kind == nodet::STRING)
617569
{
570+
const auto &s_node = string_nodes[node.index];
618571
std::for_each(
619-
s->dependencies.begin(),
620-
s->dependencies.end(),
621-
[&](const builtin_function_nodet &p) { f(node_index(p)); });
572+
s_node.dependencies.begin(),
573+
s_node.dependencies.end(),
574+
[&](const builtin_function_nodet &p) { f(nodet(p)); });
622575
}
623576
else
624577
UNREACHABLE;
625578
}
626579

580+
void string_dependenciest::for_each_node(
581+
const std::function<void(const nodet &)> &f) const
582+
{
583+
for(const auto string_node : string_nodes)
584+
f(nodet(string_node));
585+
for(std::size_t i = 0; i < builtin_function_nodes.size(); ++i)
586+
f(nodet(builtin_function_nodet(i)));
587+
}
588+
627589
void string_dependenciest::output_dot(std::ostream &stream) const
628590
{
629-
const auto for_each_node =
630-
[&](const std::function<void(const std::size_t &)> &f) { // NOLINT
631-
for(std::size_t i = 0; i < string_nodes.size(); ++i)
632-
f(string_index_to_node_index(i));
633-
for(std::size_t i = 0; i < builtin_function_nodes.size(); ++i)
634-
f(builtin_function_index_to_node_index(i));
591+
const auto for_each =
592+
[&](const std::function<void(const nodet &)> &f) { // NOLINT
593+
for_each_node(f);
635594
};
636-
637-
const auto for_each_succ = [&](
638-
const std::size_t &i,
639-
const std::function<void(const std::size_t &)> &f) { // NOLINT
640-
for_each_successor(i, f);
641-
};
642-
643-
const auto node_to_string = [&](const std::size_t &i) { // NOLINT
644-
return std::to_string(i);
595+
const auto for_each_succ =
596+
[&](const nodet &n, const std::function<void(const nodet &)> &f) { // NOLINT
597+
for_each_successor(n, f);
598+
};
599+
const auto node_to_string = [&](const nodet &n) { // NOLINT
600+
std::stringstream ostream;
601+
if(n.kind == nodet::BUILTIN)
602+
ostream << "builtin_" << n.index;
603+
else
604+
ostream << '"' << format(string_nodes[n.index].expr) << '"';
605+
return ostream.str();
645606
};
646607
stream << "digraph dependencies {\n";
647-
output_dot_generic<std::size_t>(
648-
stream, for_each_node, for_each_succ, node_to_string);
608+
output_dot_generic<nodet>(stream, for_each, for_each_succ, node_to_string);
649609
stream << '}' << std::endl;
650610
}

src/solvers/refinement/string_refinement_util.h

+34-29
Original file line numberDiff line numberDiff line change
@@ -310,10 +310,19 @@ class string_dependenciest
310310
class string_nodet
311311
{
312312
public:
313+
// expression the node corresponds to
314+
array_string_exprt expr;
315+
// index in the string_nodes vector
316+
std::size_t index;
317+
// builtin functions on which it depends
313318
std::vector<builtin_function_nodet> dependencies;
314-
315319
// In case it depends on a builtin_function we don't support yet
316320
bool depends_on_unknown_builtin_function = false;
321+
322+
explicit string_nodet(array_string_exprt e, const std::size_t index)
323+
: expr(std::move(e)), index(index)
324+
{
325+
}
317326
};
318327

319328
string_nodet &get_node(const array_string_exprt &e);
@@ -357,45 +366,41 @@ class string_dependenciest
357366
/// Set of nodes representing strings
358367
std::vector<string_nodet> string_nodes;
359368

360-
mutable std::vector<optionalt<exprt>> eval_string_cache;
361-
362369
/// Nodes describing dependencies of a string: values of the map correspond
363370
/// to indexes in the vector `string_nodes`.
364371
std::unordered_map<array_string_exprt, std::size_t, irep_hash>
365372
node_index_pool;
366373

367-
/// Common index for all nodes (both strings and builtin_functions) so that we
368-
/// can reuse generic algorithms of util/graph.h
369-
/// Even indexes correspond to builtin_function nodes, odd indexes to string
370-
/// nodes.
371-
typedef std::size_t node_indext;
372-
373-
/// \return total number of nodes
374-
node_indext size() const;
374+
class nodet
375+
{
376+
public:
377+
enum
378+
{
379+
BUILTIN,
380+
STRING
381+
} kind;
382+
std::size_t index;
375383

376-
/// \param n: builtin function node
377-
/// \return index corresponding to builtin function node `n`
378-
node_indext node_index(const builtin_function_nodet &n) const;
384+
explicit nodet(const builtin_function_nodet &builtin)
385+
: kind(BUILTIN), index(builtin.index)
386+
{
387+
}
379388

380-
/// \param s: array expression representing a string
381-
/// \return index corresponding to an string exprt s
382-
node_indext node_index(const array_string_exprt &s) const;
389+
explicit nodet(const string_nodet &string_node)
390+
: kind(STRING), index(string_node.index)
391+
{
392+
}
393+
};
383394

384-
/// \param i: index of a node
385-
/// \return corresponding node if the index corresponds to a builtin function
386-
/// node, empty optional otherwise
387-
optionalt<builtin_function_nodet>
388-
get_builtin_function_node(node_indext i) const;
395+
mutable std::vector<optionalt<exprt>> eval_string_cache;
389396

390-
/// \param i: index of a node
391-
/// \return corresponding node if the index corresponds to a string
392-
/// node, empty optional otherwise
393-
optionalt<string_nodet> get_string_node(node_indext i) const;
397+
/// Applies `f` on all nodes
398+
void for_each_node(const std::function<void(const nodet &)> &f) const;
394399

395-
/// Applies `f` on all successors of the node with index `i`
400+
/// Applies `f` on all successors of the node n
396401
void for_each_successor(
397-
const node_indext &i,
398-
const std::function<void(const node_indext &)> &f) const;
402+
const nodet &i,
403+
const std::function<void(const nodet &)> &f) const;
399404
};
400405

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

0 commit comments

Comments
 (0)