Adding Contracts to Ada

22
Adding Contracts to Ada Ehud Lamm Adding Design By Contract to Ada

description

Adding Contracts to Ada. Adding Design By Contract to Ada. Ehud Lamm. ADT + Contracts. type Stack is tagged private; procedure Init(S:out Stack); procedure Push(S:in out Stack; I:in Integer) at exit Size(S)=old Size(S)+1; procedure Pop(S:in out Stack;I:out Integer) - PowerPoint PPT Presentation

Transcript of Adding Contracts to Ada

Page 1: Adding Contracts to Ada

Adding Contracts to Ada

Ehud Lamm

Adding

Design By Contract

to Ada

Page 2: Adding Contracts to Ada

19.7.2002 Ada-Europe’20022

ADT + Contracts

type Stack is tagged private;

procedure Init(S:out Stack);

procedure Push(S:in out Stack; I:in Integer)

at exit Size(S)=old Size(S)+1;

procedure Pop(S:in out Stack;I:out Integer)

use when not(Is_Empty(S))

at exit Size(S)=old Size(S)-1;

function Size(S:Stack) return Natural;

function Is_Empty(S:Stack) return Boolean;

function Top(S:Stack) return Integer use when not(Is_Empty(S));

Overflow: exception;

1. Contracts are checked at runtime (detection).

2. Contract violations raise exceptions.

3. When possible use the type system instead (e.g., Size)

4. Contracts allow expressing arbitrary boollean assertions.

Page 3: Adding Contracts to Ada

19.7.2002 Ada-Europe’20023

Design By Contract

• Annotate each routine with axioms.

• Pre-Condition & Post-Condition

• (we will not talk about class invariants)

• The classic ADT approach

(Liskov, Guttag, Meyer)

Page 4: Adding Contracts to Ada

19.7.2002 Ada-Europe’20024

Design By Contract

• A contract carries mutual obligations and benefits.

• The client should only call a routine when the routine’s pre-condition is respected.

• The routine ensures that after completion its post-condition is respected.

Page 5: Adding Contracts to Ada

19.7.2002 Ada-Europe’20025

A little polymorphic programming

procedure Print_And_Empty(S: in out Stack’class) is

i:Integer;

begin

while not(Is_Empty(S)) loop

pop(S,i);

put(I);

end loop;

end;

Interface oriented

programming

Exercise: Prove termination for all possible stacks S.

Page 6: Adding Contracts to Ada

19.7.2002 Ada-Europe’20026

Oops…

type Crazy_Stack is new Stack with null record;

procedure Pop(S:in out Crazy_Stack;I:out Integer)

use when not(Is_Empty(Stack))

at exit

(old Top(S)/=9 and then Size(S)=old Size(S)-1)

or (Size(S)=old Size(S));

Does Print_And_Empty work correctly on Crazy_Stacks?

Page 7: Adding Contracts to Ada

19.7.2002 Ada-Europe’20027

Liskov Substitution PrincipleLSP

Liskov, Wing (TOPLAS, Nov. 1994)

Liskov (SIGPLAN, May 1988)

Otherwise bad use of public inheritance!

Page 8: Adding Contracts to Ada

19.7.2002 Ada-Europe’20028

Why is this important?

• The foundation for subtype polymorphism

• Bugs surface during maintenance

• Who is responsible?

Page 9: Adding Contracts to Ada

19.7.2002 Ada-Europe’20029

Assigning Blame

• Crucial for managing software production

• Possible candidates:– The original contractor (Stack)– The polymorphic routine (Print_And_Empty)– The subcontractor (Crazy_Stack)– The user of the pm routine (should know

better than to call P&E on Crazy_Stack)

Page 10: Adding Contracts to Ada

19.7.2002 Ada-Europe’200210

DbC & Inheritance

• Remember the LSP!

• “The subclass must require less and ensure more” )Meyer, OOSC)

• The only question is how to ensure this property!

Page 11: Adding Contracts to Ada

19.7.2002 Ada-Europe’200211

DbC & LSP – more formal

Assume B is derived from A,

then for each method P

pre(PA) → pre(PB) and

post(PB) → post(PA)

A

B

A

B

Page 12: Adding Contracts to Ada

19.7.2002 Ada-Europe’200212

The Eiffel Approach

• The programmer is not allowed to make an LSP error…

• require else

• ensure then

• A subclass can only use “or” in pre-cond / “and” in post-cond

• Other tools are even worse

Page 13: Adding Contracts to Ada

19.7.2002 Ada-Europe’200213

Wrong Approach

• “Ensuring” correct hierarchies

procedure p(T:A;I:Integer) use when i>0;

procedure p(T:B;I:Integer) use when i>10;

-- synthesized contract (i>0)V(i>10)

• Hierarchy is malformed, language hides error.

Page 14: Adding Contracts to Ada

19.7.2002 Ada-Europe’200214

Solution

• Interface implied contract can be deduced from code.

• Hierarchy checking is done according to run time tag of object. (Recall P&E)

(more details in the paper and references)

Page 15: Adding Contracts to Ada

19.7.2002 Ada-Europe’200215

Contract Checking - Analysis

procedure Print_And_Empty(S: in out Stack’class) is

i:Integer;

begin

while not(Is_Empty(S)) loop

pop(S,i);

put(I);

end loop;

end;

P&E is responsible for Stack’s Pop pre-condition. (Stack’s pre implies actual’s pre)

Actual’s Pop post-condition must be satisfied when Pop exits

Actual Pop’s post condition must imply Stack Pop post-condition

Page 16: Adding Contracts to Ada

19.7.2002 Ada-Europe’200216

Another example: generics

generic

with function Sqrt(X:Float) return Float

use when X>=0;

procedure Print_Quad_Solutions(A,B,C:Float);

-- use when B**2-4.0*A*C>=0;

If actual Sqrt requires X>0, who is to be blamed when P_Q_S fails?

Page 17: Adding Contracts to Ada

19.7.2002 Ada-Europe’200217

How can the language help?• Run-time enforcement• Should allow the programmer to document

contracts; in a formal, standard notation• Enforce correct contract relations when possible

(Hard!) • Identify faulty components and assign blame,

when violations occur• When you cannot use built-in contracts: types

(Think of trying to break a contract stating that the Stack contains only positive numbers)

Page 18: Adding Contracts to Ada

19.7.2002 Ada-Europe’200218

Does Ada need DbC?

• Ada, The Software Engineering Language• Good type system; support for generic

programming• Ada interface definitions are lacking (e.g., which

exceptions are raised by which routine?)• Readability and Self-Documenting code• Debugging aid• Everyone else has it (Eiffel, Java: iContract, jContractor, HandShake,

JVMAssert) …• BUT: This is a major change

Page 19: Adding Contracts to Ada

19.7.2002 Ada-Europe’200219

Conclusion

• Perhaps still too cutting edge?!• Is there market demand?• Should we do it anyway?

• Even a rudimentary implementation has important advantages.

• Simpler than extending the type system• The future lies in sw components) COTS)

Page 20: Adding Contracts to Ada

19.7.2002 Ada-Europe’200220

Ada needs DbC

Any Questions?

Page 21: Adding Contracts to Ada

19.7.2002 Ada-Europe’200221

Implementation

• Can be implemented using wrapper routines

• The exact wrapper routine invoked for each call is determined by relevant interface.

Page 22: Adding Contracts to Ada

19.7.2002 Ada-Europe’200222

Interoperability with the old language

• Old language calling new, not really an issue (but upstream contractual exceptions may be raised)

• New language calling old, not really an issue (but compiler should know that a package was compiled with no contracts)