-
Notifications
You must be signed in to change notification settings - Fork 274
Changes to intervals needed to merge VSD #5203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
(INT) Interval values
Also fix wrong placing of parentheses in output
As it stands in conflicted with the method from exprt
So they don't conflict with the exprt methods
Also, mark them as explicit where appropriate and add some documentation
Also replace some asserts with INVARIANT, PRECONDITION or UNREACHABLE
Also left some comments for things that need to be cleaned up in the future
Also, refactor minus and correct a typo in the comments
And also add tests for it.
and add tests for them and eval.
Previously the typecast operator for interval_exprt simply set the type on the bounds; This yielded incorrect results for widening or narrowing casts. This delegates the typecast handling to simplify_expr instead.
@@ -0,0 +1,95 @@ | |||
/*******************************************************************\ | |||
Module: Unit tests for variable/sensitivity/abstract_object::merge | |||
Author: DiffBlue Limited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it turns out it’s spelled Diffblue actually, oops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
Worth pointing out that this has... limitations w.r.t. to floating point numbers. |
@hannes-steffenhagen-diffblue Thanks for the note about floating-point. Yes, there are still things to do on this code but I would like to get VSD merged and then improve. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a number of ways the intervals code could be improved to help maintainability, but in the interest of getting something merged I suggest focusing on two priorities and address the other points in due course:
- ensure that testing covers 100% of the file - there is so much code here it seems like there will be a few typos that a complete set of unit tests will surely catch.
- minimize and tidy the public API as this will be hard to do after the fact (as code gets added, removing it later will be harder).
I will rebase this now so that we can see the codecov report, and add a commit eliminating parts of the interface that probably aren't required.
rhs_i=lhs_i; | ||
if(rhs_i.is_bottom()) | ||
make_bottom(); | ||
if(id == ID_lt && !lhs_i.is_less_than(rhs_i)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ I'd expect to see an equivalent for ID_gt
and ID_ge
?
{ | ||
} | ||
|
||
explicit min_exprt(const exprt &_expr) : exprt(ID_min, _expr.type()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ What is the reason for this constructor?
PRECONDITION(is_well_formed()); | ||
} | ||
|
||
constant_interval_exprt(const constant_interval_exprt &x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ Why the manual copy constructor? Seems like the default would work
|
||
bool is_well_formed() const | ||
{ | ||
bool b = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ b
-> well_formed
;
💡 I'd probably just ditch the overall local variable and introduce a few locals:
const bool valid_type = is_numeric() || type.id() == ID_bool ...
...
retur valid_type && matching_type && valid_bounds
return b; | ||
} | ||
|
||
bool is_valid_bound(const exprt &expr) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ This can be static if expr.type()
is used
WHEN("Something") | ||
{ | ||
THEN("Something else") | ||
{ | ||
REQUIRE( | ||
constant_interval_exprt(CEV(4), CEV(8)) | ||
.left_shift(constant_interval_exprt(CEV(1))) == | ||
constant_interval_exprt(CEV(8), CEV(16))); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks incomplete and maybe tested elsewhere?
@@ -143,6 +143,47 @@ template<class T> class interval_templatet | |||
} | |||
} | |||
|
|||
void make_bottom() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ I need to see why these changes are introduced - they seem unrelated to the rest of the PR>
/// or min_exprt for the lower bound | ||
/// or max_exprt for the upper bound | ||
/// Also, lower bound should always be <= upper bound | ||
class constant_interval_exprt : public binary_exprt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ from an "is-a" relation, I don't think an interval really is a binary expr? Not sure...
if(equal(get_upper(), o.get_upper()) && equal(get_upper(), o.get_upper())) | ||
{ | ||
return tvt(true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong. For one, it appears to be if(A && A)
and if the intention is whether upper == o.upper && lower ==o.lower, this is wrong. I think this should always be unknown unless the intersection is empty, then false, or one element, then true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH the semantics of this are confusing, do you expect [a, b] == [a, b] to be true or unknown The docs appear to suggest unknown, this behaviour appears to suggest true. I think depending on context you will want one or the other, so probably much safer to not guess and implement two clearly different methods: range_equal
which returns true or false if the ranges are exactly the same, and value_equal which returns a tvt - but this can be left for now and fixed in the follow up PR
However, given that the VSD is based on this interface - I think it actually makes more sense to merge this, and then tidy up the interface along with changes required to the VSD in subsequent PR. Instead i will dimiss comments to this effect - and will focus on the testing component |
Just noting here #5362 has now also been merged. |
Similar to #5202 this is a series of commits pulled out of the variable-sensitivity-domain branch. As some of the patches have been squashed and cherry-picked multiple times I am not 100% sure of who wrote what but I think the full set of authors is correct. Again, squashing and editing of the commit messages are probably needed but let's look at the code first.