/* CS:5810 Formal Methods in Software Engineering Fall 2015 The University of Iowa Instructor: Cesare Tinelli Credits: Example courtesy of Rajeev Joshi, NASA JPL */ class IntegerSet { // Abstract state, visible to clients ghost var s: set ; // Concrete state, hidden from clients var a:array ; var n:nat ; // Predicate defining the object invariant. // Typically, this would be hidden from clients (and // added implicitly to pre- and post-conditions). // But Dafny doesn't provide a mechanism to do this // currently. predicate Valid() reads this, a ; { a != null && n <= a.Length && (forall x:int :: x in s <==> exists j:nat :: j a[i] != a[j]) } // Constructor called when an instance of "IntegerSet" is first // allocated. Note that this constructor is anonymous. constructor () ensures s == {} ; modifies this ; ensures Valid() ; ensures fresh(a) ; { a := new int[10] ; n := 0 ; s := {} ; } // Test if set contains the given element method contains(x:int) returns (b:bool) requires Valid() ; ensures Valid() ; ensures b <==> x in s ; { var i:nat := 0 ; while (i < n) invariant i <= n ; invariant (forall j:nat :: j a[j] != x) ; { if (a[i] == x) { return true ; } i := i + 1 ; } return false ; } // This is a private method for resizing the array method resize() requires Valid() ; modifies this ; ensures Valid() ; ensures s == old(s) && n == old(n) ; ensures a.Length > old(a.Length) ; ensures fresh(a) ; ensures (forall i:nat :: i a[i] == old(a[i])) ; { var anew := new int[2 * a.Length + 1] ; // copy all elements from a into anew var i:nat := 0 ; while (i < n) invariant a != null && i <= n ; invariant forall j:nat :: j anew[j] == a[j] ; modifies anew ; { anew[i] := a[i] ; i := i + 1 ; } a := anew ; } // Public method for adding an element to the set. // The underlying array is grown if necessary. method add(x:int) requires Valid() ; modifies this, a ; ensures Valid() ; ensures s == old(s) + { x } ; { var i:nat := 0 ; while (i < n) invariant i <= n ; invariant forall j:nat :: j a[j] != x ; invariant Valid() ; { if (a[i] == x) { return ; } i := i + 1 ; } if (i >= a.Length) { resize() ; } a[i] := x ; n := n + 1 ; s := s + { x } ; } } method Main() { var s1 := new IntegerSet.init() ; s1.add(3) ; var b := s1.contains(3) ; assert b == true ; }