/* 22c181: Formal Methods in Software Engineering Fall 2013 The University of Iowa Instructor: Cesare Tinelli */ class Queue { ghost var Contents: seq; var a:array; var n:nat; predicate Valid() reads this, a; { // concrete state invariants a != null && n <= a.Length && a.Length > 0 && // connection between abstract and concrete state Contents == a[0..n] } constructor init() modifies this, a; ensures Contents == []; ensures Valid(); { a := new T[5]; n := 0; Contents := []; } method enqueue(e:T) modifies a, this; requires Valid(); ensures Valid(); ensures Contents == old(Contents) + [e]; { assert Contents == a[0..n]; if (n == a.Length) { var b := new T[2*a.Length]; // use keyword "forall" instead of "parallel" with newer versions of Dafny parallel (i | 0 <= i < n) { b[i] := a[i]; } a := b; } a[n] := e; n := n+1; Contents := a[0..n]; } method dequeue() returns (e:T) modifies this, a; requires Valid(); requires Contents != []; ensures Valid(); ensures [e] + Contents == old(Contents); { e := a[0]; // use keyword "forall" instead of "parallel" with newer versions of Dafny parallel (i | 0 <= i < n-1 ) { a[i] := a[i+1]; } n := n - 1; Contents := a[0..n]; } }