Skip to content

Commit c884bbf

Browse files
committed
SVA_to_LTL now throws exception
SVA_to_LTL(expr) now throws an exception when given an expression that does not map to LTL. The exception includes a subexpression that is not convertible.
1 parent bf112c1 commit c884bbf

File tree

6 files changed

+87
-96
lines changed

6 files changed

+87
-96
lines changed

src/ebmc/bdd_engine.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,11 +475,15 @@ std::optional<exprt> bdd_enginet::property_supported(const exprt &expr)
475475
if(is_SVA(expr))
476476
{
477477
// We can map some SVA to LTL. In turn, some of that can be mapped to CTL.
478-
auto ltl_opt = SVA_to_LTL(expr);
479-
if(ltl_opt.has_value())
480-
return property_supported(ltl_opt.value());
481-
else
478+
try
479+
{
480+
auto ltl = SVA_to_LTL(expr);
481+
return property_supported(ltl);
482+
}
483+
catch(sva_to_ltl_unsupportedt)
484+
{
482485
return {};
486+
}
483487
}
484488

485489
return {};

src/ebmc/output_smv_word_level.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,16 @@ static void smv_properties(
192192
else if(is_SVA(property.normalized_expr))
193193
{
194194
// we can turn some SVA properties into LTL
195-
auto ltl_opt = SVA_to_LTL(property.normalized_expr);
196-
if(ltl_opt.has_value())
197-
out << "LTLSPEC " << expr2smv(ltl_opt.value(), ns);
198-
else
199-
out << "-- " << property.identifier << ": SVA not converted\n";
195+
try
196+
{
197+
auto ltl = SVA_to_LTL(property.normalized_expr);
198+
out << "LTLSPEC " << expr2smv(ltl, ns);
199+
}
200+
catch(sva_to_ltl_unsupportedt error)
201+
{
202+
out << "-- " << property.identifier << ": SVA " << error.expr.id()
203+
<< " not converted\n";
204+
}
200205
}
201206
else
202207
out << "-- " << property.identifier << ": not converted\n";

src/temporal-logic/sva_to_ltl.cpp

Lines changed: 41 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -39,100 +39,78 @@ static exprt ltl(const sva_sequence_matcht &match)
3939
return conjunction(conjuncts);
4040
}
4141

42-
/// takes an SVA property as input, and returns an equivalent LTL property,
43-
/// or otherwise {}.
44-
std::optional<exprt> SVA_to_LTL(exprt expr)
42+
/// takes an SVA property as input, and returns an equivalent LTL property
43+
exprt SVA_to_LTL(exprt expr)
4544
{
4645
// Some SVA is directly mappable to LTL
4746
if(expr.id() == ID_sva_always)
4847
{
4948
auto rec = SVA_to_LTL(to_sva_always_expr(expr).op());
50-
if(rec.has_value())
51-
return G_exprt{rec.value()};
52-
else
53-
return {};
49+
return G_exprt{rec};
5450
}
5551
else if(expr.id() == ID_sva_ranged_always)
5652
{
5753
auto &ranged_always = to_sva_ranged_always_expr(expr);
5854
auto rec = SVA_to_LTL(ranged_always.op());
59-
if(rec.has_value())
60-
{
61-
// always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
62-
auto from_int = numeric_cast_v<mp_integer>(ranged_always.from());
55+
// always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
56+
auto from_int = numeric_cast_v<mp_integer>(ranged_always.from());
6357

64-
// Is there an upper end of the range?
65-
if(ranged_always.to().is_constant())
66-
{
67-
// upper end set
68-
auto to_int =
69-
numeric_cast_v<mp_integer>(to_constant_expr(ranged_always.to()));
70-
PRECONDITION(to_int >= from_int);
71-
auto diff = to_int - from_int;
58+
// Is there an upper end of the range?
59+
if(ranged_always.to().is_constant())
60+
{
61+
// upper end set
62+
auto to_int =
63+
numeric_cast_v<mp_integer>(to_constant_expr(ranged_always.to()));
64+
PRECONDITION(to_int >= from_int);
65+
auto diff = to_int - from_int;
7266

73-
exprt::operandst conjuncts;
67+
exprt::operandst conjuncts;
7468

75-
for(auto i = 0; i <= diff; i++)
76-
conjuncts.push_back(n_Xes(i, rec.value()));
69+
for(auto i = 0; i <= diff; i++)
70+
conjuncts.push_back(n_Xes(i, rec));
7771

78-
return n_Xes(from_int, conjunction(conjuncts));
79-
}
80-
else if(ranged_always.to().id() == ID_infinity)
81-
{
82-
// always [l:$] op ---> X ... X G op
83-
return n_Xes(from_int, G_exprt{rec.value()});
84-
}
85-
else
86-
PRECONDITION(false);
72+
return n_Xes(from_int, conjunction(conjuncts));
73+
}
74+
else if(ranged_always.to().id() == ID_infinity)
75+
{
76+
// always [l:$] op ---> X ... X G op
77+
return n_Xes(from_int, G_exprt{rec});
8778
}
8879
else
89-
return {};
80+
PRECONDITION(false);
9081
}
9182
else if(expr.id() == ID_sva_s_always)
9283
{
9384
auto &ranged_always = to_sva_s_always_expr(expr);
9485
auto rec = SVA_to_LTL(ranged_always.op());
95-
if(rec.has_value())
96-
{
97-
// s_always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
98-
auto from_int = numeric_cast_v<mp_integer>(ranged_always.from());
99-
auto to_int = numeric_cast_v<mp_integer>(ranged_always.to());
100-
PRECONDITION(to_int >= from_int);
101-
auto diff = to_int - from_int;
10286

103-
exprt::operandst conjuncts;
87+
// s_always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
88+
auto from_int = numeric_cast_v<mp_integer>(ranged_always.from());
89+
auto to_int = numeric_cast_v<mp_integer>(ranged_always.to());
90+
PRECONDITION(to_int >= from_int);
91+
auto diff = to_int - from_int;
10492

105-
for(auto i = 0; i <= diff; i++)
106-
conjuncts.push_back(n_Xes(i, rec.value()));
93+
exprt::operandst conjuncts;
10794

108-
return n_Xes(from_int, conjunction(conjuncts));
109-
}
110-
else
111-
return {};
95+
for(auto i = 0; i <= diff; i++)
96+
conjuncts.push_back(n_Xes(i, rec));
97+
98+
return n_Xes(from_int, conjunction(conjuncts));
11299
}
113100
else if(expr.id() == ID_sva_s_eventually)
114101
{
115102
auto rec = SVA_to_LTL(to_sva_s_eventually_expr(expr).op());
116-
if(rec.has_value())
117-
return F_exprt{rec.value()};
118-
else
119-
return {};
103+
return F_exprt{std::move(rec)};
120104
}
121105
else if(expr.id() == ID_sva_s_nexttime)
122106
{
123107
auto rec = SVA_to_LTL(to_sva_s_nexttime_expr(expr).op());
124-
if(rec.has_value())
125-
return X_exprt{rec.value()};
126-
else
127-
return {};
108+
return X_exprt{std::move(rec)};
128109
}
129110
else if(expr.id() == ID_sva_nexttime)
130111
{
131112
auto rec = SVA_to_LTL(to_sva_nexttime_expr(expr).op());
132-
if(rec.has_value())
133-
return X_exprt{rec.value()};
134-
else
135-
return {};
113+
return X_exprt{std::move(rec)};
136114
}
137115
else if(
138116
expr.id() == ID_sva_overlapped_implication ||
@@ -150,9 +128,6 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
150128

151129
auto property_rec = SVA_to_LTL(implication.property());
152130

153-
if(!property_rec.has_value())
154-
return {};
155-
156131
for(auto &match : matches)
157132
{
158133
const auto overlapped = expr.id() == ID_sva_overlapped_implication;
@@ -163,7 +138,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
163138
else
164139
{
165140
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
166-
auto delayed_property = n_Xes(delay, property_rec.value());
141+
auto delayed_property = n_Xes(delay, property_rec);
167142
conjuncts.push_back(implies_exprt{ltl(match), delayed_property});
168143
}
169144
}
@@ -191,9 +166,6 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
191166

192167
auto property_rec = SVA_to_LTL(followed_by.property());
193168

194-
if(!property_rec.has_value())
195-
return {};
196-
197169
for(auto &match : matches)
198170
{
199171
const auto overlapped = expr.id() == ID_sva_overlapped_followed_by;
@@ -204,7 +176,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
204176
else
205177
{
206178
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
207-
auto delayed_property = n_Xes(delay, property_rec.value());
179+
auto delayed_property = n_Xes(delay, property_rec);
208180
disjuncts.push_back(and_exprt{ltl(match), delayed_property});
209181
}
210182
}
@@ -252,21 +224,15 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
252224
auto &until = to_sva_s_until_expr(expr);
253225
auto rec_lhs = SVA_to_LTL(until.lhs());
254226
auto rec_rhs = SVA_to_LTL(until.rhs());
255-
if(rec_lhs.has_value() && rec_rhs.has_value())
256-
return U_exprt{rec_lhs.value(), rec_rhs.value()};
257-
else
258-
return {};
227+
return U_exprt{rec_lhs, rec_rhs};
259228
}
260229
else if(expr.id() == ID_sva_s_until_with)
261230
{
262231
// This is release with swapped operands
263232
auto &until_with = to_sva_s_until_with_expr(expr);
264233
auto rec_lhs = SVA_to_LTL(until_with.lhs());
265234
auto rec_rhs = SVA_to_LTL(until_with.rhs());
266-
if(rec_lhs.has_value() && rec_rhs.has_value())
267-
return R_exprt{rec_rhs.value(), rec_lhs.value()}; // swapped
268-
else
269-
return {};
235+
return R_exprt{rec_rhs, rec_lhs}; // swapped
270236
}
271237
else if(!has_temporal_operator(expr))
272238
{
@@ -279,9 +245,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
279245
for(auto &op : expr.operands())
280246
{
281247
auto rec = SVA_to_LTL(op);
282-
if(!rec.has_value())
283-
return {};
284-
op = rec.value();
248+
op = rec;
285249
}
286250
return expr;
287251
}

src/temporal-logic/sva_to_ltl.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,18 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include <util/expr.h>
1313

14+
class sva_to_ltl_unsupportedt
15+
{
16+
public:
17+
explicit sva_to_ltl_unsupportedt(exprt __expr) : expr(std::move(__expr))
18+
{
19+
}
20+
21+
exprt expr;
22+
};
23+
1424
/// If possible, this maps an SVA expression to an equivalent LTL
15-
/// expression, or otherwise returns {}.
16-
std::optional<exprt> SVA_to_LTL(exprt);
25+
/// expression, or otherwise throws \ref sva_to_ltl_unsupportedt.
26+
exprt SVA_to_LTL(exprt);
1727

1828
#endif

src/trans-netlist/instantiate_netlist.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,15 @@ std::optional<exprt> netlist_property(
179179
else if(is_SVA_operator(expr))
180180
{
181181
// Try to turn into LTL
182-
auto LTL_opt = SVA_to_LTL(expr);
183-
if(LTL_opt.has_value())
184-
return netlist_property(solver, var_map, *LTL_opt, ns, message_handler);
185-
else
182+
try
183+
{
184+
auto LTL = SVA_to_LTL(expr);
185+
return netlist_property(solver, var_map, LTL, ns, message_handler);
186+
}
187+
catch(sva_to_ltl_unsupportedt)
188+
{
186189
return {};
190+
}
187191
}
188192
else
189193
return {};

src/trans-netlist/trans_to_netlist.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,15 @@ convert_trans_to_netlistt::convert_property(const exprt &expr)
391391
else if(is_SVA_operator(expr))
392392
{
393393
// Try to turn into LTL
394-
auto LTL_opt = SVA_to_LTL(expr);
395-
if(LTL_opt.has_value())
396-
return convert_property(*LTL_opt);
397-
else
394+
try
395+
{
396+
auto LTL = SVA_to_LTL(expr);
397+
return convert_property(LTL);
398+
}
399+
catch(sva_to_ltl_unsupportedt)
400+
{
398401
return {};
402+
}
399403
}
400404
else
401405
return {};

0 commit comments

Comments
 (0)