Semantic Casts:
Contracts and Structural Subtyping in a Nominal World
Robby Findler University of Chicago Matthew Flatt University of Utah Matthias Felleisen Northeastern University
1
Semantic Casts: Contracts and Structural Subtyping in a Nominal - - PowerPoint PPT Presentation
Semantic Casts: Contracts and Structural Subtyping in a Nominal World Robby Findler University of Chicago Matthew Flatt University of Utah Matthias Felleisen Northeastern University 1 Component marketplace - McIlroy's vision (1969) -
Robby Findler University of Chicago Matthew Flatt University of Utah Matthias Felleisen Northeastern University
1
pieces of programs (components)
2
3
4
5
6
7
8
9
10
11
component economy
12
int f(int[] x, int k)
int f(int[] x, int k) // 0 <= k < x.length()
finalize is called for all objects
web server handles at least 1000 GET/sec
13
14
15
16
Queue class Q implements IQueue { void enq(int X) {...} int deq() {...} boolean empty() {...} }
17
// @pre !this.empty() // @post !this.empty() Queue class Q implements IQueue { void enq(int X) {...} int deq() {...} boolean empty() {...} }
18
// @pre !this.empty() // @post !this.empty() Queue class Q implements IQueue { void enq(int X) {...} int deq() {...} boolean empty() {...} } Good client IQueue q = new Q(); q.enq(1); q.deq();
19
// @pre !this.empty() // @post !this.empty() Queue class Q implements IQueue { void enq(int X) {...} int deq() {...} boolean empty() {...} } Good client IQueue q = new Q(); q.enq(1); q.deq(); Bad client IQueue q = new Q(); q.deq(); q.enq(1);
20
// @pre !this.empty() // @post !this.empty() Queue class Q implements IQueue { void enq(int X) {...} int deq() {...} boolean empty() {...} } Good client IQueue q = new Q(); q.enq(1); q.deq(); Bad client IQueue q = new Q(); q.deq(); q.enq(1); Blame q.deq(); in Bad Client
21
Queue with observer please: a "good" Observer class Q implements IQueue { Obs o; void enq(int X) {...} // @post !this.empty() // effect: o.onEnq(this) int deq() {...} // @pre !this.empty() // effect: o.onDeq(this) void register(Obs _o) {o = _o;} // }
22
Good observer class GoodO implements Obs { void init() {...} void onEnq(IQueue q) {...} // @post !q.empty() void onDeq(IQueue q) {...} }
23
Good observer class GoodO implements Obs { void init() {...} void onEnq(IQueue q) {...} // @post !q.empty() void onDeq(IQueue q) {...} } Bad Observer class BadO implements Obs { void init() {...} void onEnq(IQueue q) { q.deq() } void onDeq(IQueue q) {...} }
24
25
26
27
28
29
Queue with observer please: a "good" Observer class Q implements IQueue { Obs o; void enq(int X) {...} // @post !this.empty() // effect: o.onEnq(this) int deq() {...} // @pre !this.empty() // effect: o.onDeq(this) void register(Obs _o) {o = _o;} // }
30
@pre _o.onEnq(...) Queue with observer class Q implements IQueue { Obs o; void enq(int X) {...} // @post !this.empty() // effect: o.onEnq(this) int deq() {...} // @pre !this.empty() // effect: o.onDeq(this) void register(Obs _o) {o = _o;} // }
31
32
Observer contracts interface Obs { void init(); void onEnq(IQueue q); // @post !q.empty() void onDeq(IQueue q); // @pre !q.empty() } Force observers to meet pre- and post-conditions that Queue needs
33
Controlling BadO class BadO implements Obs { void init() {...} void onEnq(IQueue q) { q.deq() } void onDeq(IQueue q) {...} }
34
// @post !q.empty() Controlling BadO class BadO implements Obs { void init() {...} void onEnq(IQueue q) { q.deq() } void onDeq(IQueue q) {...} }
35
36
37
38
39
Queue Class class Q implements IQueue { ... } Positive Queue interface IPosQ { void enq(int X) {...} // @pre X >= 0 // @post !this.empty() int deq() {...} // @pre !this.empty() // @post @ret >= 0 }
40
Queue Class class Q implements IQueue { ... } Positive Queue interface IPosQ { void enq(int X) {...} // @pre X >= 0 // @post !this.empty() int deq() {...} // @pre !this.empty() // @post @ret >= 0 }
41
C++, C#, Eiffel, Java
Moby, OML, OCaml, LOOM, PolyTOIL
42
43
QClass class Q implements IQueue { ... } IQueue interface IQueue { void enq(int X) {...} // @post !this.empty() int deq() {...} // @pre !this.empty() } IPosQ interface IPosQ { void enq(int X) {...} // @pre X >= 0 // @post !this.empty() int deq() {...} // @pre !this.empty() // @post @ret >= 0 }
44
45
semanticCast(obj, I, <fromStr>, <toStr>)
46
semanticCast(obj, I, <fromStr>, <toStr>)
47
semanticCast(obj, I, <fromStr>, <toStr>)
48
semanticCast(obj, I, <fromStr>, <toStr>)
49
semanticCast(obj, I, <fromStr>, <toStr>)
50
semanticCast(obj, I, <fromStr>, <toStr>)
51
52
semanticCast (o,A, , )
53
semanticCast (o,A, , ) semanticCast (o,A', , )
54
<Queue> IQueue q = new Q(); <Client> q.enq(1); q.deq(); q.enq(-1); <PosQueue> q
55
<Queue> IQueue q = new Q(); <Client> q.enq(1); q.deq(); q.enq(-1); <PosQueue> q
56
<Queue> IQueue q = new Q(); semanticCast(q, IQueue, <Queue>, <PosQueue>) <Client> q.enq(1); q.deq(); q.enq(-1); semanticCast(q, IPosQ, <PosQueue>, <Client>) <PosQueue> q
57
<Queue> IQueue q = new Q(); semanticCast(q, IQueue, <Queue>, <PosQueue>) <Client> q.enq(1); q.deq(); q.enq(-1); semanticCast(q, IPosQ, <PosQueue>, <Client>) <PosQueue> q
58
<Queue> IQueue q = new Q(); semanticCast(q, IQueue, <Queue>, <PosQueue>) <Client> q.enq(1); q.deq(); q.enq(-1); semanticCast(q, IPosQ, <PosQueue>, <Client>) <PosQueue> q
59
<Queue> IQueue q = new Q(); semanticCast(q, IQueue, <Queue>, <PosQueue>) <Client> q.enq(1); q.deq(); q.enq(-1); semanticCast(q, IPosQ, <PosQueue>, <Client>) <PosQueue> q
60
61
62
63
64
65
66
67
68
semanticCast(o, I, <from>, <to>).m(o') = semanticCast(o.m(semanticCast o', J, <to>, <from>), K, <from>, <to>) interface I { K m(J x); } interface J { ... } interface K { ... }
69
at method calls
70
71
it didn't make a sound
72
73