@@ -50,13 +50,13 @@ get_quantifier_var_min(const exprt &var_expr, const exprt &quantifier_expr)
50
50
}
51
51
else if (quantifier_expr.id () == ID_and)
52
52
{
53
- /* *
54
- * The min variable
55
- * is in the form of "var_expr >= constant".
56
- */
53
+ // The minimum variable can be of the form `var_expr >= constant`, or
54
+ // it can be of the form `var_expr == constant` (e.g. in the case where
55
+ // the interval that bounds the variable is a singleton interval (set
56
+ // with only one element)).
57
57
for (auto &x : quantifier_expr.operands ())
58
58
{
59
- if (x.id ()!= ID_ge)
59
+ if (x.id () != ID_ge && x. id () != ID_equal )
60
60
continue ;
61
61
const auto &x_binary = to_binary_relation_expr (x);
62
62
if (expr_eq (var_expr, x_binary.lhs ()) && x_binary.rhs ().is_constant ())
@@ -106,24 +106,42 @@ get_quantifier_var_max(const exprt &var_expr, const exprt &quantifier_expr)
106
106
}
107
107
else
108
108
{
109
- /* *
110
- * The max variable
111
- * is in the form of "!(var_expr >= constant)".
112
- */
109
+ // There are two potential forms we could come across here. The first one is
110
+ // `!(var_expr >= constant)` - identified by the first if branch - and the second
111
+ // is `var_expr == constant` - identified by the second else-if branch. The
112
+ // second form could be met if previous simplification has identified a singleton
113
+ // interval - see simplify_boolean_expr.cpp.
113
114
for (auto &x : quantifier_expr.operands ())
114
115
{
115
- if (x.id ()!=ID_not)
116
- continue ;
117
- exprt y = to_not_expr (x).op ();
118
- if (y.id ()!=ID_ge)
119
- continue ;
120
- const auto &y_binary = to_binary_relation_expr (y);
121
- if (expr_eq (var_expr, y_binary.lhs ()) && y_binary.rhs ().is_constant ())
116
+ if (x.id () == ID_not)
122
117
{
123
- const constant_exprt &over_expr = to_constant_expr (y_binary.rhs ());
124
- mp_integer over_i = numeric_cast_v<mp_integer>(over_expr);
125
- over_i-=1 ;
126
- return from_integer (over_i, y_binary.rhs ().type ());
118
+ exprt y = to_not_expr (x).op ();
119
+ if (y.id () != ID_ge)
120
+ continue ;
121
+ const auto &y_binary = to_binary_relation_expr (y);
122
+ if (expr_eq (var_expr, y_binary.lhs ()) && y_binary.rhs ().is_constant ())
123
+ {
124
+ const constant_exprt &over_expr = to_constant_expr (y_binary.rhs ());
125
+ mp_integer over_i = numeric_cast_v<mp_integer>(over_expr);
126
+ over_i -= 1 ;
127
+ return from_integer (over_i, y_binary.rhs ().type ());
128
+ }
129
+ }
130
+ else if (x.id () == ID_equal)
131
+ {
132
+ const auto &y_binary = to_binary_relation_expr (x);
133
+ if (expr_eq (var_expr, y_binary.lhs ()) && y_binary.rhs ().is_constant ())
134
+ {
135
+ return to_constant_expr (y_binary.rhs ());
136
+ }
137
+ }
138
+ else
139
+ {
140
+ // If we are here, we came across a (simplified?) expression that was
141
+ // not anticipated - normally this would be a bug, but if you made changes
142
+ // to the simplifier (as an example), you would need to add an else-if
143
+ // branch that handles that type above.
144
+ continue ;
127
145
}
128
146
}
129
147
}
0 commit comments