Skip to content

Commit a778372

Browse files
Petr BauchPetr Bauch
authored andcommitted
Add functional visitor to exprt
Includes unit test.
1 parent 8c16edb commit a778372

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

src/util/expr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,20 @@ void exprt::visit(const_expr_visitort &visitor) const
279279
}
280280
}
281281

282+
void exprt::visit(const std::function<void(const exprt &)> &f) const
283+
{
284+
std::stack<const exprt *> stack;
285+
stack.push(this);
286+
while(!stack.empty())
287+
{
288+
const exprt &expr = *stack.top();
289+
stack.pop();
290+
f(expr);
291+
forall_operands(it, expr)
292+
stack.push(&(*it));
293+
}
294+
}
295+
282296
depth_iteratort exprt::depth_begin()
283297
{ return depth_iteratort(*this); }
284298
depth_iteratort exprt::depth_end()

src/util/expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,12 @@ class exprt:public irept
305305
void visit(class expr_visitort &visitor);
306306
void visit(class const_expr_visitort &visitor) const;
307307

308+
/// Recursively traverse the expression tree (via operands) and call \p f on
309+
/// every subexpressions, including `this`. The input function has
310+
/// side-effects and does not modify the expression.
311+
/// \param f: The function to be call on subexpressions
312+
void visit(const std::function<void(const exprt &)> &f) const;
313+
308314
depth_iteratort depth_begin();
309315
depth_iteratort depth_end();
310316
const_depth_iteratort depth_begin() const;

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ SRC += analyses/ai/ai.cpp \
5656
util/string_utils/strip_string.cpp \
5757
util/symbol_table.cpp \
5858
util/unicode.cpp \
59+
util/visit.cpp \
5960
# Empty last line
6061

6162
INCLUDES= -I ../src/ -I.

unit/util/visit.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test for expr.h/visit
4+
5+
Author: Diffblue Ltd
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
11+
#include <util/arith_tools.h>
12+
#include <util/expr.h>
13+
#include <util/std_expr.h>
14+
#include <util/std_types.h>
15+
16+
SCENARIO("visiting reaches all subnodes", "[core][util][expr]")
17+
{
18+
GIVEN("An exprt representing a binary relation")
19+
{
20+
const typet type1 = signedbv_typet(32);
21+
irep_idt symbol_name = "a";
22+
symbol_exprt varx(symbol_name, type1);
23+
exprt val10 = from_integer(10, type1);
24+
binary_relation_exprt x_le_10(varx, ID_le, val10);
25+
26+
THEN("counting nodes should return 3")
27+
{
28+
size_t count = 0;
29+
x_le_10.visit([&](const exprt &) { count++; });
30+
REQUIRE(count == 3);
31+
}
32+
THEN("counting symbol should return 1")
33+
{
34+
size_t count = 0;
35+
x_le_10.visit([&](const exprt &e) {
36+
if(e.id() == ID_symbol)
37+
count++;
38+
});
39+
REQUIRE(count == 1);
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)