Checking correctness properties of object-oriented programs K. Rustan M. Leino Microsoft Research, Redmond, WA Lecture 2 EEF summer school on Specification, Refinement, and Verification 20 Aug 2002, Turku, Finland
Example: union-find class UnionFind <: Object field nClasses, nElements, … method UnionFind :: init(uf, size) requires 0 <= size modifies uf.nClasses, uf.nElements, … ensures uf.nClasses = uf.nElements = size method UnionFind :: find(uf, c) returns (r) requires 0 <= c < uf.nElements ensures 0 <= r < uf.nClasses method UnionFind :: union(c, d) requires0 <= c <= uf.nElements /\ 0 <= d <= uf.nElements modifies uf.nClasses ensuresuf.nClasses = uf.nClasses 0 \/ uf.nClasses = uf.nClasses 0 - 1
Example, client var uf, r0, r1, r2 in uf := new(UnionFind); uf.init(12); uf.union(3, 8); uf.union(8, 6); uf.union(10, 11); r0 := uf.find(3); r1 := uf.find(5); r2 := uf.find(6); assert r0 r1; assert r0 = r2 end
Example, implementation class StandardUnionFind <: UnionFind mimpl StandardUnionFind :: find(uf, c) returns (r) is … class FastUnionFind <: UnionFind mimpl FastUnionFind :: find(uf, c) returns (r) is …
null istype(o, T) o = null \/ typeof(o) <: T istype(o, T) o = null \/ typeof(o) <: T x.f := E assert x null ; f[x] := E x.f := E assert x null ; f[x] := E
Type casts x := typecast(E, T) assert istype(E, T) ; x := E x := typecast(E, T) assert istype(E, T) ; x := E
Example: binary method class T <: Object method T :: equal(x, y) returns (b) requires typeof(x) = typeof(y) class U <: T mimpl U :: equal(x, y) returns b is var yy in yy := typecast(y, U); // compare x and yy … end
Types of parameters method OutputStream :: putText(wr, s) … method T :: print(t, wr) requires istype(wr, OutputStream)
Types of parameters method OutputStream :: putText(wr, s) … method T :: print(t, wr) requires istype(wr, OutputStream) method print(t: T, wr: OutputStream) …
Types of fields field T :: f: U// class T { … f: U … } ( f, T, U :: isField(f, T, U) ( o :: istype(f[o], U)))
Types of fields field T :: f: U// class T { … f: U … } ( f, T, U :: isField(f, T, U) ( o ::istype(o, T) ==> istype(f[o], U)))
Types of fields field T :: f: U// class T { … f: U … } ( f, T, U :: isField(f, T, U) ( o ::istype(o, T) ==> istype(f[o], U))) Initially: assume isField(f, T, U) havoc f havoc f ; assume isField(f, T, U)
More about allocation initially, for every parameter x: assume alloc[x] initially, for every parameter x: assume alloc[x] mimpl T :: m(x) is var y in y := new(T); assert x y end mimpl T :: m(x) is var y in y := new(T); assert x y end
Even more about allocation mimpl T :: m(x) is var y in y := new(T); assert x.f y end mimpl T :: m(x) is var y in y := new(T); assert x.f y end
Even more about allocation mimpl T :: m(x) is var y in y := new(T); assert x.f y end mimpl T :: m(x) is var y in y := new(T); assert x.f y end isField(f, T, U, a) … /\ ( o :: a[o] ==> a[f[o]] ) isField(f, T, U, a) … /\ ( o :: a[o] ==> a[f[o]] ) whenever f or alloc is changed: assume isField(f, T, U, alloc) whenever f or alloc is changed: assume isField(f, T, U, alloc)
Exercise Prove the following program correct: method p(x) modifies x.f method m(x) modifies x.f mimpl m(x) is var y in x.p(); y := new(T); assert x.f y end Prove the following program correct: method p(x) modifies x.f method m(x) modifies x.f mimpl m(x) is var y in x.p(); y := new(T); assert x.f y end
Strengthening specifications class T <: Object method T :: m(x, y, z) requires P modifies w ensures Q class U <: T method U :: m(x, y, z) requires P modifies w ensures Q /\ R … u.m(y, z) ; assert R … ?
Strengthening specifications class T <: Object method T :: m(x, y, z) returns (r) requires P modifies w ensures Q class U <: T method U :: n(x, y, z) returns (r) requires P modifies w ensures Q /\ R mimpl U :: m(x, y, z) is r := x.n(y, z) … r := u.n(y, z) ; assert R …
Modifies and objects modifies x.f modifies f ensures ( o :: o.f = o.f 0 \/ o = x) modifies x.f modifies f ensures ( o :: o.f = o.f 0 \/ o = x)
Exercise class T <: Object field f method T :: m(x, y, z) requires P modifies x.f ensures Q class U <: T field g method U :: m(x, y, z) requires P modifies x.f, x.g ensures Q ?
What else is missing? Data abstraction Data abstraction Information hiding Information hiding Programming methodology Programming methodology …
References K. Rustan M. Leino. Toward Reliable Modular Programs. PhD thesis, California Institute of Technology. Technical Report Caltech- CS-TR-95-03, Caltech, K. Rustan M. Leino. Toward Reliable Modular Programs. PhD thesis, California Institute of Technology. Technical Report Caltech- CS-TR-95-03, Caltech, K. Rustan M. Leino. Ecstatic: An object-oriented programming language with an axiomatic semantics. In Foundations of Object- Oriented Languages (FOOL 4), K. Rustan M. Leino. Ecstatic: An object-oriented programming language with an axiomatic semantics. In Foundations of Object- Oriented Languages (FOOL 4), K. Rustan M. Leino and Greg Nelson. Data abstraction and information hiding. Research Report 160, Compaq SRC, Nov To appear in TOPLAS. K. Rustan M. Leino and Greg Nelson. Data abstraction and information hiding. Research Report 160, Compaq SRC, Nov To appear in TOPLAS. K. Rustan M. Leino. Data groups: Specifying the modification of extended state. In OOPSLA 98, pp , ACM, K. Rustan M. Leino. Data groups: Specifying the modification of extended state. In OOPSLA 98, pp , ACM, 1998.