/* CS:5810 Formal Methods in Software Engineering Fall 2014 The University of Iowa Instructor: Cesare Tinelli */ class Cell { var data: int; } class Counter { // public variable ghost var Val: int; ghost var R: set; // private variables var incs: Cell; var decs: Cell; function Valid(): bool reads this, R; { this in R && incs in R && decs in R && null !in R && incs != decs && Val == incs.data - decs.data } constructor Init() modifies this; ensures Valid(); ensures fresh(R - { this }); ensures Val == 0; { incs := new Cell; decs := new Cell; incs.data := 0; decs.data := 0; Val := 0; R := { this }; R := R + { incs, decs }; } method GetVal() returns (x: int) requires Valid(); ensures x == Val; { x := incs.data - decs.data; } method Inc() requires Valid(); modifies R; ensures Valid(); ensures R == old(R); ensures Val == old(Val) + 1; { incs.data := incs.data + 1; Val := Val + 1; } method Dec() requires Valid(); modifies R; ensures Valid(); ensures R == old(R); ensures Val == old(Val) - 1; { decs.data := decs.data + 1; Val := Val - 1; } } method Main() { var c := new Counter.Init(); c.Inc(); c.Inc(); c.Dec(); c.Inc(); assert c.Val == 2; }