Invariants for methods
Jonathan M Davis
jmdavisProg at gmx.com
Thu Nov 18 09:01:37 PST 2010
On Thursday 18 November 2010 06:09:33 Jens Mueller wrote:
> Hi,
>
> I'm wondering what's a good way to do invariants for methods. In my
> example I have a rectangle and one of its methods moves the upper left
> of the rectangle. I have two invariants when moving a rectangle: The
> width and the height do not change. I could do something like the
> following:
>
> void move(...) {
> int currentWidth = width;
> int currentHeight = height;
> // moving the rectangle here
> assert(currentWidth == width);
> assert(currentHeight == height);
> }
>
> I do not like it because it won't be completely compiled away in release
> mode. The problem is that in the out contract I cannot access variables
> of the in contract. If that was possible it just becomes:
> in {
> int currentWidth = width;
> int currentHeight = height;
> }
> out {
> assert(currentWidth == width);
> assert(currentHeight == height);
> }
> body {
> // moving the rectangle here
> }
>
> Is there a solution that works right now? Are their plans to support
> something like the above? Or should I do it differently?
in blocks define prefix conditions. They can test arguments to the function,
global variables, and members of the class/struct that the function is a member
of (if it's a member of one).
out blocks define postfix conditions. They can test the return value of a function
(assuming that you use out(result) instead of just out), global variables, and
members of the class/struct that the function is a member of (if it's a member
of one).
An invariant() block defines an invariant for a class or struct and is called
before and after every public member function call. It has access to the
class/struct and global variables (why it requires parens, I don't know).
It makes no sense to talk about an invariant for a function however. All of a
function's input can be tested with its in block (including global variables and
member variables if you need to), and all of a function's output can be tested
with its out block (including global variables and member variables if you need
to). The only thing left would be checking the function's local variables, but
they obviously don't exist in the in or out block, and they don't matter outside
of the function itself. If you care about testing them as you do whatever
calculations that you're doing in the function, then you can use asserts within
the function.
The docs page on contracts is here: http://www.digitalmars.com/d/2.0/dbc.html
- Jonathan M Davis
More information about the Digitalmars-d
mailing list