Page 1
Challenges in increasing tool support for programmingK. Rustan M. LeinoMicrosoft Research, Redmond, WA, USA
23 Sep 2004ICTACGuiyang, Guizhou, PRC
joint work with Mike Barnett, Bor-Yuh Evan Chang, Robert DeLine, Manuel Fähndrich, Peter Müller, David A. Naumann, Wolfram Schulte, andHerman Venter
Page 2
Software engineering problem
Building and maintaining large systems that are correct
Page 3
Approach
• Specifications record design decisions– bridge intent and code
• Tools amplify human effort– manage details– find inconsistencies– ensure quality
Page 5
Challenge areas
0. Program verification1. A better language2. Methodology
Page 6
0. Program verification
an extreme form ofmanaging the details
Page 7
Basic architecture of a verifier
verification conditiongenerator
theorem prover
verification condition
program with specifications
“correct” or list of errors
Page 8
Generating verification conditions
int AbsX(Robot c)requires c ≠ null;ensures 0 ≤ result;
{if (0 ≤ c.x) {
a := c.x;} else {
a := −c.x;}return a;
}
Weakest preconditions
0 ≤ result
0 ≤ a
c ≠ null 0 ≤ −sel(c,x)
c ≠ null 0 ≤ sel(c,x)
c ≠ null (0 ≤ c.x c ≠ null 0 ≤ sel(c,x)) (¬(0 ≤ c.x) c ≠ null 0 ≤ −sel(c,x))
c ≠ null c ≠ null (0 ≤ c.x c ≠ null 0 ≤ sel(c,x)) (¬(0 ≤ c.x) c ≠ null 0 ≤ −sel(c,x))
Page 9
Analyzing verification conditions• Automatic theorem prover
– can be hidden from programmer– generates counterexamples
• Interactive theorem prover– requires gurus– not limited by built-in decision
procedures
Page 10
Theory opportunities
• Developing good encodings of verification conditions
• Combining inference techniques for different domains
• Combining inference and proving
Page 11
Spec# verifier architecture
V.C. generator
automatictheorem prover
verification condition
Spec#
“correct” or list of errors
Spec# compiler
MSIL (“bytecode”)
translator
Boogie PL
inference engine
Boogie
Page 12
the programming languageis the software engineer'sprimary thinking and working tool
1. A better language
Page 13
Designing more rigor into the language
• Type system– impose coarse-grained restrictions– easy to understand and use– sound efficient checking
• General specifications– enforce by mix of dynamic and static
checking– don’t worry about completeness or
decidability
• Develop good defaults
non-null types
requires Pre;modifies Frame;ensures Post;
Examples
requires this.Valid;modifies this.*;ensures true;
Page 14
Enforcing specifications
• Dynamic checking– may leave out expensive checks, if not
required for soundness• example: modifies clauses
• Static checking– requires more effort from the user
• example: modifies clauses
– modular checking a necessity
Page 15
Language design problem: example
procedure P (Robot c) {int a := c.x;
error: possible null dereference
Page 16
Language design problem: example
procedure P (Robot c) {Robot d := new Robot();int a := d.x;if (c ≠ null) {
a := c.x;if (c.f ≠ null) {
a := sqrt(a); OpenFile(“b.txt”); c.M();
a := c.f.g;}
}error?
Page 17
Migration problems
• To the new language– how does the language compare to
existing ones?
• From (!) the new language– development organizations may have
process requirements
Page 18
2. Programming methodology
light-weight rules forsimpler reasoning
Page 19
Pre/post are not enoughclass C {
private int x;private int y;
public void Update(int z)requires 0 ≤ z && x ≤ y;
{T[ ] a := new T[z];T[ ] b := new T[y – x];…
}…
}
Page 20
Object invariantsclass C {
private int x;private int y;invariant x ≤ y;public void Update(int z)
requires 0 ≤ z;{
T[ ] a := new T[z];T[ ] b := new T[y – x];…
}…
}
Page 21
The reentrance problem
class C {int x;int y;invariant x ≤ y;public void M() {
x++;P(…);y++;
}…
}
invariant may betemporarily broken here
invariant is restored here
what if P calls back into M?
invariant assumedto hold on entry
invariant checkedto hold on exit
Page 22
The reentrance solutionclass C {
int x;int y;invariant x ≤ y;
public void M()requires this.inv = Valid;
{expose (this) {
x++;P(…);y++;
}}…
}
represent explicitlythat invariant holds(without revealing
what the invariant is)
change this.invfrom Valid to Mutable
check invariant;then, change this.invfrom Mutable to Valid
field updates allowedonly on Mutable objects
Page 23
The abstraction problemclass Set {
Hashtable h;invariant h ≠ null;
public void Add(Element e)requires this.inv = Valid;
{expose (this) {
h.Add(e, e);}
}…
}class Hashtable {
public void Add(object o) requires this.inv = Valid;…
}
how do we know his Valid here?
Page 24
The abstraction solutionclass Set {
owned Hashtable h;invariant h ≠ null;
public void Add(Element e)requires this.inv = Valid;
{expose (this) {
h.Add(e, e);}
}…
}class Hashtable {
public void Add(object o) requires this.inv = Valid;…
}
• set uniquely owns set.h• set.inv=Valid implies set.h.inv=Valid
ownership temporarilyrelinquished here
ownership re-obtainedhere
Page 25
Wanted: methodology for
• advanced invariants• multiple owners• delegates (“closures”)• events• …
Page 26
Conclusions• Because of tool support, we’re ready for
programming at the next level of rigor• Still requires theory support
– language design– program semantics– specification techniques– inference algorithms– decision procedures– …
• Methodology is underdeveloped– “Can programming theory yet fully explain why real
big programs work?”– programming theory has not kept up with practice
Some papers at http://research.microsoft.com/~leino