Skip to content

Commit 0a0e30b

Browse files
Merge pull request #4841 from romainbrenguier/refactor/expr_skeleton
Define and use an expr_skeletont class
2 parents ec90bba + c852e72 commit 0a0e30b

File tree

7 files changed

+107
-69
lines changed

7 files changed

+107
-69
lines changed

src/goto-symex/goto_symex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,6 @@ void goto_symext::symex_assign(statet &state, const code_assignt &code)
8080

8181
exprt::operandst lhs_if_then_else_conditions;
8282
symex_assignt{state, assignment_type, ns, symex_config, target}.assign_rec(
83-
lhs, nil_exprt(), rhs, lhs_if_then_else_conditions);
83+
lhs, expr_skeletont{}, rhs, lhs_if_then_else_conditions);
8484
}
8585
}

src/goto-symex/symex_assign.cpp

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,19 @@ constexpr bool use_update()
3131
#endif
3232
}
3333

34-
/// Store the \p what expression by recursively descending into the operands
35-
/// of \p lhs until the first operand \c op0 is _nil_: this _nil_ operand
36-
/// is then replaced with \p what.
37-
/// \param lhs: Non-symbol pointed-to expression
38-
/// \param what: The expression to be added to the \p lhs
39-
/// \return The resulting expression
40-
static exprt add_to_lhs(const exprt &lhs, const exprt &what)
34+
expr_skeletont expr_skeletont::remove_op0(exprt e)
4135
{
42-
PRECONDITION(lhs.id() != ID_symbol);
43-
exprt tmp_what=what;
44-
45-
if(tmp_what.id()!=ID_symbol)
46-
{
47-
PRECONDITION(tmp_what.operands().size() >= 1);
48-
tmp_what.op0().make_nil();
49-
}
50-
51-
exprt new_lhs=lhs;
36+
PRECONDITION(e.id() != ID_symbol);
37+
PRECONDITION(e.operands().size() >= 1);
38+
e.op0().make_nil();
39+
return expr_skeletont{std::move(e)};
40+
}
5241

53-
exprt *p=&new_lhs;
42+
exprt expr_skeletont::apply(exprt expr) const
43+
{
44+
PRECONDITION(skeleton.id() != ID_symbol);
45+
exprt result = skeleton;
46+
exprt *p = &result;
5447

5548
while(p->is_not_nil())
5649
{
@@ -60,18 +53,23 @@ static exprt add_to_lhs(const exprt &lhs, const exprt &what)
6053
INVARIANT(
6154
p->operands().size() >= 1,
6255
"expected pointed-to expression to have at least one operand");
63-
p=&p->op0();
56+
p = &p->op0();
6457
}
6558

6659
INVARIANT(p->is_nil(), "expected pointed-to expression to be nil");
6760

68-
*p=tmp_what;
69-
return new_lhs;
61+
*p = std::move(expr);
62+
return result;
63+
}
64+
65+
expr_skeletont expr_skeletont::compose(expr_skeletont other) const
66+
{
67+
return expr_skeletont(apply(other.skeleton));
7068
}
7169

7270
void symex_assignt::assign_rec(
7371
const exprt &lhs,
74-
const exprt &full_lhs,
72+
const expr_skeletont &full_lhs,
7573
const exprt &rhs,
7674
exprt::operandst &guard)
7775
{
@@ -349,7 +347,7 @@ static assignmentt shift_indexed_access_to_lhs(
349347
/// \param guard: guard conjuncts that must hold for this assignment to be made
350348
void symex_assignt::assign_from_struct(
351349
const ssa_exprt &lhs, // L1
352-
const exprt &full_lhs,
350+
const expr_skeletont &full_lhs,
353351
const struct_exprt &rhs,
354352
const exprt::operandst &guard)
355353
{
@@ -371,7 +369,7 @@ void symex_assignt::assign_from_struct(
371369

372370
void symex_assignt::assign_non_struct_symbol(
373371
const ssa_exprt &lhs, // L1
374-
const exprt &full_lhs,
372+
const expr_skeletont &full_lhs,
375373
const exprt &rhs,
376374
const exprt::operandst &guard)
377375
{
@@ -409,8 +407,7 @@ void symex_assignt::assign_non_struct_symbol(
409407
.get();
410408

411409
state.record_events.push(false);
412-
const exprt l2_full_lhs =
413-
state.rename(add_to_lhs(full_lhs, l2_lhs), ns).get();
410+
const exprt l2_full_lhs = state.rename(full_lhs.apply(l2_lhs), ns).get();
414411
state.record_events.pop();
415412

416413
auto current_assignment_type =
@@ -443,7 +440,7 @@ void symex_assignt::assign_non_struct_symbol(
443440

444441
void symex_assignt::assign_symbol(
445442
const ssa_exprt &lhs, // L1
446-
const exprt &full_lhs,
443+
const expr_skeletont &full_lhs,
447444
const exprt &rhs,
448445
const exprt::operandst &guard)
449446
{
@@ -456,21 +453,21 @@ void symex_assignt::assign_symbol(
456453

457454
void symex_assignt::assign_typecast(
458455
const typecast_exprt &lhs,
459-
const exprt &full_lhs,
456+
const expr_skeletont &full_lhs,
460457
const exprt &rhs,
461458
exprt::operandst &guard)
462459
{
463460
// these may come from dereferencing on the lhs
464461
exprt rhs_typecasted = typecast_exprt::conditional_cast(rhs, lhs.op().type());
465-
466-
exprt new_full_lhs=add_to_lhs(full_lhs, lhs);
467-
assign_rec(lhs.op(), new_full_lhs, rhs_typecasted, guard);
462+
expr_skeletont new_skeleton =
463+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
464+
assign_rec(lhs.op(), new_skeleton, rhs_typecasted, guard);
468465
}
469466

470467
template <bool use_update>
471468
void symex_assignt::assign_array(
472469
const index_exprt &lhs,
473-
const exprt &full_lhs,
470+
const expr_skeletont &full_lhs,
474471
const exprt &rhs,
475472
exprt::operandst &guard)
476473
{
@@ -487,8 +484,9 @@ void symex_assignt::assign_array(
487484
// into
488485
// a'==UPDATE(a, [i], e)
489486
const update_exprt new_rhs{lhs_array, index_designatort(lhs_index), rhs};
490-
const exprt new_full_lhs = add_to_lhs(full_lhs, lhs);
491-
assign_rec(lhs_array, new_full_lhs, new_rhs, guard);
487+
const expr_skeletont new_skeleton =
488+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
489+
assign_rec(lhs, new_skeleton, new_rhs, guard);
492490
}
493491
else
494492
{
@@ -497,15 +495,16 @@ void symex_assignt::assign_array(
497495
// into
498496
// a'==a WITH [i:=e]
499497
const with_exprt new_rhs{lhs_array, lhs_index, rhs};
500-
const exprt new_full_lhs = add_to_lhs(full_lhs, lhs);
501-
assign_rec(lhs_array, new_full_lhs, new_rhs, guard);
498+
const expr_skeletont new_skeleton =
499+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
500+
assign_rec(lhs_array, new_skeleton, new_rhs, guard);
502501
}
503502
}
504503

505504
template <bool use_update>
506505
void symex_assignt::assign_struct_member(
507506
const member_exprt &lhs,
508-
const exprt &full_lhs,
507+
const expr_skeletont &full_lhs,
509508
const exprt &rhs,
510509
exprt::operandst &guard)
511510
{
@@ -546,8 +545,9 @@ void symex_assignt::assign_struct_member(
546545
// a'==UPDATE(a, .c, e)
547546
const update_exprt new_rhs{
548547
lhs_struct, member_designatort(component_name), rhs};
549-
const exprt new_full_lhs = add_to_lhs(full_lhs, lhs);
550-
assign_rec(lhs_struct, new_full_lhs, new_rhs, guard);
548+
const expr_skeletont new_skeleton =
549+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
550+
assign_rec(lhs_struct, new_skeleton, new_rhs, guard);
551551
}
552552
else
553553
{
@@ -558,15 +558,15 @@ void symex_assignt::assign_struct_member(
558558

559559
with_exprt new_rhs(lhs_struct, exprt(ID_member_name), rhs);
560560
new_rhs.where().set(ID_component_name, component_name);
561-
562-
exprt new_full_lhs = add_to_lhs(full_lhs, lhs);
563-
assign_rec(lhs_struct, new_full_lhs, new_rhs, guard);
561+
const expr_skeletont new_skeleton =
562+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
563+
assign_rec(lhs_struct, new_skeleton, new_rhs, guard);
564564
}
565565
}
566566

567567
void symex_assignt::assign_if(
568568
const if_exprt &lhs,
569-
const exprt &full_lhs,
569+
const expr_skeletont &full_lhs,
570570
const exprt &rhs,
571571
exprt::operandst &guard)
572572
{
@@ -592,7 +592,7 @@ void symex_assignt::assign_if(
592592

593593
void symex_assignt::assign_byte_extract(
594594
const byte_extract_exprt &lhs,
595-
const exprt &full_lhs,
595+
const expr_skeletont &full_lhs,
596596
const exprt &rhs,
597597
exprt::operandst &guard)
598598
{
@@ -608,6 +608,7 @@ void symex_assignt::assign_byte_extract(
608608
UNREACHABLE;
609609

610610
const byte_update_exprt new_rhs{byte_update_id, lhs.op(), lhs.offset(), rhs};
611-
exprt new_full_lhs=add_to_lhs(full_lhs, lhs);
612-
assign_rec(lhs.op(), new_full_lhs, new_rhs, guard);
611+
const expr_skeletont new_skeleton =
612+
full_lhs.compose(expr_skeletont::remove_op0(lhs));
613+
assign_rec(lhs.op(), new_skeleton, new_rhs, guard);
613614
}

src/goto-symex/symex_assign.h

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,49 @@ class byte_extract_exprt;
2020
class ssa_exprt;
2121
struct symex_configt;
2222

23+
/// Expression in which some part is missing and can be substituted for another
24+
/// expression.
25+
///
26+
/// For instance, a skeleton `☐[index]` where `☐` is the missing part, can be
27+
/// applied to an expression `x` to get `x[index]` (see
28+
/// \ref expr_skeletont::apply). It can also be composed with another skeleton,
29+
/// let say `☐.some_field` which would give the skeleton `☐.some_field[index]`
30+
/// (see \ref expr_skeletont::compose).
31+
class expr_skeletont final
32+
{
33+
public:
34+
/// Empty skeleton. Applying it to an expression would give the same
35+
/// expression unchanged
36+
expr_skeletont() : skeleton(nil_exprt{})
37+
{
38+
}
39+
40+
/// Replace the missing part of the current skeleton by another skeleton,
41+
/// ending in a bigger skeleton corresponding to the two combined.
42+
expr_skeletont compose(expr_skeletont other) const;
43+
44+
/// Replace the missing part by the given expression, to end-up with a
45+
/// complete expression
46+
exprt apply(exprt expr) const;
47+
48+
/// Create a skeleton by removing the first operand of \p e. For instance,
49+
/// remove_op0 on `array[index]` would give a skeleton in which `array` is
50+
/// missing, and applying that skeleton to `array2` would give
51+
/// `array2[index]`.
52+
static expr_skeletont remove_op0(exprt e);
53+
54+
private:
55+
/// In \c skeleton, nil_exprt is used to mark the sub expression to be
56+
/// substituted. The nil_exprt always appears recursively following the first
57+
/// operands because the only way to get a skeleton is by removing the first
58+
/// operand.
59+
exprt skeleton;
60+
61+
explicit expr_skeletont(exprt e) : skeleton(std::move(e))
62+
{
63+
}
64+
};
65+
2366
/// Functor for symex assignment
2467
class symex_assignt
2568
{
@@ -44,13 +87,13 @@ class symex_assignt
4487
/// respectively.
4588
void assign_symbol(
4689
const ssa_exprt &lhs, // L1
47-
const exprt &full_lhs,
90+
const expr_skeletont &full_lhs,
4891
const exprt &rhs,
4992
const exprt::operandst &guard);
5093

5194
void assign_rec(
5295
const exprt &lhs,
53-
const exprt &full_lhs,
96+
const expr_skeletont &full_lhs,
5497
const exprt &rhs,
5598
exprt::operandst &guard);
5699

@@ -63,13 +106,13 @@ class symex_assignt
63106

64107
void assign_from_struct(
65108
const ssa_exprt &lhs, // L1
66-
const exprt &full_lhs,
109+
const expr_skeletont &full_lhs,
67110
const struct_exprt &rhs,
68111
const exprt::operandst &guard);
69112

70113
void assign_non_struct_symbol(
71114
const ssa_exprt &lhs, // L1
72-
const exprt &full_lhs,
115+
const expr_skeletont &full_lhs,
73116
const exprt &rhs,
74117
const exprt::operandst &guard);
75118

@@ -78,7 +121,7 @@ class symex_assignt
78121
template <bool use_update>
79122
void assign_array(
80123
const index_exprt &lhs,
81-
const exprt &full_lhs,
124+
const expr_skeletont &full_lhs,
82125
const exprt &rhs,
83126
exprt::operandst &guard);
84127

@@ -87,25 +130,25 @@ class symex_assignt
87130
template <bool use_update>
88131
void assign_struct_member(
89132
const member_exprt &lhs,
90-
const exprt &full_lhs,
133+
const expr_skeletont &full_lhs,
91134
const exprt &rhs,
92135
exprt::operandst &guard);
93136

94137
void assign_if(
95138
const if_exprt &lhs,
96-
const exprt &full_lhs,
139+
const expr_skeletont &full_lhs,
97140
const exprt &rhs,
98141
exprt::operandst &guard);
99142

100143
void assign_typecast(
101144
const typecast_exprt &lhs,
102-
const exprt &full_lhs,
145+
const expr_skeletont &full_lhs,
103146
const exprt &rhs,
104147
exprt::operandst &guard);
105148

106149
void assign_byte_extract(
107150
const byte_extract_exprt &lhs,
108-
const exprt &full_lhs,
151+
const expr_skeletont &full_lhs,
109152
const exprt &rhs,
110153
exprt::operandst &guard);
111154
};

src/goto-symex/symex_clean_expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void goto_symext::lift_let(statet &state, const let_exprt &let_expr)
188188
state, symex_targett::assignment_typet::HIDDEN, ns, symex_config, target}
189189
.assign_symbol(
190190
to_ssa_expr(state.rename<L1>(let_expr.symbol(), ns).get()),
191-
nil_exprt(),
191+
expr_skeletont{},
192192
let_value,
193193
value_assignment_guard);
194194

src/goto-symex/symex_function_call.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void goto_symext::parameter_assignments(
141141

142142
exprt::operandst lhs_conditions;
143143
symex_assignt{state, assignment_type, ns, symex_config, target}
144-
.assign_rec(lhs, nil_exprt(), rhs, lhs_conditions);
144+
.assign_rec(lhs, expr_skeletont{}, rhs, lhs_conditions);
145145
}
146146

147147
if(it1!=arguments.end())

src/goto-symex/symex_start_thread.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void goto_symext::symex_start_thread(statet &state)
8989
state.record_events.push(false);
9090
symex_assignt{
9191
state, symex_targett::assignment_typet::HIDDEN, ns, symex_config, target}
92-
.assign_symbol(lhs_l1, nil_exprt(), rhs, lhs_conditions);
92+
.assign_symbol(lhs_l1, expr_skeletont{}, rhs, lhs_conditions);
9393
state.record_events.pop();
9494
}
9595

@@ -122,6 +122,6 @@ void goto_symext::symex_start_thread(statet &state)
122122
exprt::operandst lhs_conditions;
123123
symex_assignt{
124124
state, symex_targett::assignment_typet::HIDDEN, ns, symex_config, target}
125-
.assign_symbol(lhs, nil_exprt(), rhs, lhs_conditions);
125+
.assign_symbol(lhs, expr_skeletont{}, rhs, lhs_conditions);
126126
}
127127
}

0 commit comments

Comments
 (0)