@@ -6,39 +6,44 @@ function {:inline} AllLocPieces(): Set LocPiece {
66 Set_Add(Set_Add(Set_Empty(), Left()), Right())
77}
88
9+ type LocTreiberStack = KeyedLoc LocPiece;
910type LocTreiberNode = KeyedLoc LocPiece;
1011type StackElem T = Node LocTreiberNode T;
1112type StackMap T = Map LocTreiberNode (StackElem T);
1213datatype Treiber< T> { Treiber(top: Option LocTreiberNode, {:linear} nodes: StackMap T) }
1314
15+ function {:inline} LeftLocPiece(loc_piece: KeyedLoc LocPiece): KeyedLoc LocPiece {
16+ KeyedLoc(loc_piece-> l, Left())
17+ }
18+
1419type X; // module type parameter
1520
16- var {:layer 4 , 5 } TreiberPool: Map Loc (Vec X);
17- var {:layer 0 , 4 } {:linear} TreiberPoolLow: Map Loc (Treiber X);
21+ var {:layer 4 , 5 } TreiberPool: Map LocTreiberStack (Vec X);
22+ var {:layer 0 , 4 } {:linear} TreiberPoolLow: Map LocTreiberStack (Treiber X);
1823
1924/// Yield invariants
2025
21- function {:inline} Domain(ts: Map Loc (Treiber X), loc_t: Loc ): Set LocTreiberNode {
26+ function {:inline} Domain(ts: Map LocTreiberStack (Treiber X), loc_t: LocTreiberStack ): Set LocTreiberNode {
2227 ts-> val[loc_t]-> nodes-> dom
2328}
2429
2530yield invariant {:layer 1 } Yield();
2631
27- yield invariant {:layer 2 } TopInStack(loc_t: Loc );
32+ yield invariant {:layer 2 } TopInStack(loc_t: LocTreiberStack );
2833invariant Map_Contains(TreiberPoolLow, loc_t);
2934invariant (var loc_n := Map_At(TreiberPoolLow, loc_t)-> top; loc_n is None || Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n-> t));
3035invariant (forall loc_n: LocTreiberNode :: Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n) ==>
3136 (var loc_n' := Map_At(Map_At(TreiberPoolLow, loc_t)-> nodes, loc_n)-> next; loc_n' is None || Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n'-> t)));
3237
33- yield invariant {:layer 2 } LocInStackOrNone(loc_t: Loc , loc_n: Option LocTreiberNode);
38+ yield invariant {:layer 2 } LocInStackOrNone(loc_t: LocTreiberStack , loc_n: Option LocTreiberNode);
3439invariant Map_Contains(TreiberPoolLow, loc_t);
3540invariant loc_n is None || Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n-> t);
3641
37- yield invariant {:layer 3 } LocInStack(loc_t: Loc , loc_n: LocTreiberNode);
42+ yield invariant {:layer 3 } LocInStack(loc_t: LocTreiberStack , loc_n: LocTreiberNode);
3843invariant Map_Contains(TreiberPoolLow, loc_t);
3944invariant Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n);
4045
41- yield invariant {:layer 4 } ReachInStack(loc_t: Loc );
46+ yield invariant {:layer 4 } ReachInStack(loc_t: LocTreiberStack );
4247invariant Map_Contains(TreiberPoolLow, loc_t);
4348invariant (var t := TreiberPoolLow-> val[loc_t]; Between(t-> nodes-> val, t-> top, t-> top, None()));
4449invariant (var t := TreiberPoolLow-> val[loc_t]; IsSubset(BetweenSet(t-> nodes-> val, t-> top, None()), Domain(TreiberPoolLow, loc_t)-> val));
@@ -49,7 +54,7 @@ invariant Map_At(TreiberPool, loc_t) == Abs(Map_At(TreiberPoolLow, loc_t));
4954yield invariant {:layer 4 } StackDom();
5055invariant TreiberPool-> dom == TreiberPoolLow-> dom;
5156
52- yield invariant {:layer 4 } PushLocInStack(loc_t: Loc , node: StackElem X, new_loc_n: LocTreiberNode, {:linear} right_loc_piece: One LocTreiberNode);
57+ yield invariant {:layer 4 } PushLocInStack(loc_t: LocTreiberStack , node: StackElem X, new_loc_n: LocTreiberNode, {:linear} right_loc_piece: One LocTreiberNode);
5358invariant Map_Contains(TreiberPoolLow, loc_t);
5459invariant Set_Contains(Domain(TreiberPoolLow, loc_t), new_loc_n);
5560invariant new_loc_n == KeyedLoc(new_loc_n-> l, Left());
@@ -58,38 +63,44 @@ invariant (var t := TreiberPoolLow->val[loc_t]; Map_At(t->nodes, new_loc_n) == n
5863
5964/// Layered implementation
6065
61- atomic action {:layer 5 } AtomicAlloc() returns (loc_t: Loc )
66+ atomic action {:layer 5 } AtomicAlloc() returns ({:linear} one_loc_t: One LocTreiberStack )
6267modifies TreiberPool;
6368{
64- var {:linear} one_loc_t: One Loc;
69+ var loc: Loc;
70+ var {:linear} loc_pieces: Set LocTreiberNode;
71+ var {:linear} left_loc_piece: One LocTreiberNode;
6572
66- call one_loc_t := Loc_New();
67- loc_t := one_loc_t-> val;
68- assume ! Map_Contains(TreiberPool, loc_t);
69- TreiberPool := Map_Update(TreiberPool, loc_t, Vec_Empty());
73+ call loc, loc_pieces := KeyedLocSet_New(AllLocPieces());
74+ call one_loc_t := One_Get(loc_pieces, KeyedLoc(loc, Right()));
75+ call left_loc_piece := One_Get(loc_pieces, KeyedLoc(loc, Left()));
76+ assume ! Map_Contains(TreiberPool, left_loc_piece-> val);
77+ TreiberPool := Map_Update(TreiberPool, left_loc_piece-> val, Vec_Empty());
7078}
71- yield procedure {:layer 4 } Alloc() returns (loc_t: Loc )
79+ yield procedure {:layer 4 } Alloc() returns ({:linear} one_loc_t: One LocTreiberStack )
7280refines AtomicAlloc;
73- ensures call TopInStack(loc_t );
74- ensures call ReachInStack(loc_t );
81+ ensures call TopInStack(LeftLocPiece(one_loc_t- > val) );
82+ ensures call ReachInStack(LeftLocPiece(one_loc_t- > val) );
7583preserves call StackDom();
7684{
85+ var loc: Loc;
86+ var {:linear} loc_pieces: Set LocTreiberNode;
87+ var {:linear} left_loc_piece: One LocTreiberNode;
7788 var top: Option LocTreiberNode;
7889 var {:linear} stack: StackMap X;
7990 var {:linear} treiber: Treiber X;
80- var {:linear} one_loc_t: One Loc;
8191
8292 top := None();
8393 call stack := Map_MakeEmpty();
8494 treiber := Treiber(top, stack);
85- call one_loc_t := Loc_New();
86- loc_t := one_loc_t-> val;
87- call AllocTreiber#0 (one_loc_t, treiber);
88- call {:layer 4 } TreiberPool := Copy(Map_Update(TreiberPool, loc_t, Vec_Empty()));
95+ call loc, loc_pieces := KeyedLocSet_New(AllLocPieces());
96+ call one_loc_t := One_Get(loc_pieces, KeyedLoc(loc, Right()));
97+ call left_loc_piece := One_Get(loc_pieces, KeyedLoc(loc, Left()));
98+ call AllocTreiber#0 (left_loc_piece, treiber);
99+ call {:layer 4 } TreiberPool := Copy(Map_Update(TreiberPool, left_loc_piece-> val, Vec_Empty()));
89100 call {:layer 4 } AbsLemma(treiber);
90101}
91102
92- atomic action {:layer 5 } AtomicPush(loc_t: Loc , x: X) returns (success: bool)
103+ atomic action {:layer 5 } AtomicPush(loc_t: LocTreiberStack , x: X) returns (success: bool)
93104modifies TreiberPool;
94105{
95106 if (*) {
@@ -99,7 +110,7 @@ modifies TreiberPool;
99110 success := false ;
100111 }
101112}
102- yield procedure {:layer 4 } Push(loc_t: Loc , x: X) returns (success: bool)
113+ yield procedure {:layer 4 } Push(loc_t: LocTreiberStack , x: X) returns (success: bool)
103114refines AtomicPush;
104115preserves call TopInStack(loc_t);
105116preserves call ReachInStack(loc_t);
@@ -122,7 +133,7 @@ preserves call StackDom();
122133 }
123134}
124135
125- atomic action {:layer 5 } AtomicPop(loc_t: Loc ) returns (success: bool, x_opt: Option X)
136+ atomic action {:layer 5 } AtomicPop(loc_t: LocTreiberStack ) returns (success: bool, x_opt: Option X)
126137modifies TreiberPool;
127138{
128139 var stack: Vec X;
@@ -141,7 +152,7 @@ modifies TreiberPool;
141152 x_opt := None();
142153 }
143154}
144- yield procedure {:layer 4 } Pop(loc_t: Loc ) returns (success: bool, x_opt: Option X)
155+ yield procedure {:layer 4 } Pop(loc_t: LocTreiberStack ) returns (success: bool, x_opt: Option X)
145156refines AtomicPop;
146157preserves call TopInStack(loc_t);
147158preserves call ReachInStack(loc_t);
@@ -155,12 +166,12 @@ preserves call StackDom();
155166 }
156167}
157168
158- atomic action {:layer 4 } AtomicAllocNode#3 (loc_t: Loc , x: X)
169+ atomic action {:layer 4 } AtomicAllocNode#3 (loc_t: LocTreiberStack , x: X)
159170 returns (loc_n: Option LocTreiberNode, new_loc_n: LocTreiberNode, {:linear} right_loc_piece: One LocTreiberNode)
160171modifies TreiberPoolLow;
161172asserts Map_Contains(TreiberPoolLow, loc_t);
162173{
163- var {:linear} one_loc_t: One Loc ;
174+ var {:linear} one_loc_t: One LocTreiberStack ;
164175 var {:linear} treiber: Treiber X;
165176 var top: Option LocTreiberNode;
166177 var {:linear} stack: StackMap X;
@@ -179,7 +190,7 @@ asserts Map_Contains(TreiberPoolLow, loc_t);
179190 treiber := Treiber(top, stack);
180191 call Map_Put(TreiberPoolLow, one_loc_t, treiber);
181192}
182- yield procedure {:layer 3 } AllocNode#3 (loc_t: Loc , x: X)
193+ yield procedure {:layer 3 } AllocNode#3 (loc_t: LocTreiberStack , x: X)
183194 returns (loc_n: Option LocTreiberNode, new_loc_n: LocTreiberNode, {:linear} right_loc_piece: One LocTreiberNode)
184195preserves call TopInStack(loc_t);
185196ensures call LocInStackOrNone(loc_t, Some(new_loc_n));
@@ -197,10 +208,10 @@ refines AtomicAllocNode#3;
197208 call AllocNode#0 (loc_t, left_loc_piece, Node(loc_n, x));
198209}
199210
200- atomic action {:layer 4 } AtomicPopIntermediate(loc_t: Loc ) returns (success: bool, x_opt: Option X)
211+ atomic action {:layer 4 } AtomicPopIntermediate(loc_t: LocTreiberStack ) returns (success: bool, x_opt: Option X)
201212modifies TreiberPoolLow;
202213{
203- var {:linear} one_loc_t: One Loc ;
214+ var {:linear} one_loc_t: One LocTreiberStack ;
204215 var loc_n: Option LocTreiberNode;
205216 var {:linear} treiber: Treiber X;
206217 var top: Option LocTreiberNode;
@@ -227,7 +238,7 @@ modifies TreiberPoolLow;
227238 success := false ;
228239 }
229240}
230- yield procedure {:layer 3 } PopIntermediate(loc_t: Loc ) returns (success: bool, x_opt: Option X)
241+ yield procedure {:layer 3 } PopIntermediate(loc_t: LocTreiberStack ) returns (success: bool, x_opt: Option X)
231242refines AtomicPopIntermediate;
232243preserves call TopInStack(loc_t);
233244{
@@ -253,33 +264,33 @@ preserves call TopInStack(loc_t);
253264 }
254265}
255266
256- right action {:layer 3 } AtomicReadTopOfStack#Push(loc_t: Loc ) returns (loc_n: Option LocTreiberNode)
267+ right action {:layer 3 } AtomicReadTopOfStack#Push(loc_t: LocTreiberStack ) returns (loc_n: Option LocTreiberNode)
257268{
258269 assert Map_Contains(TreiberPoolLow, loc_t);
259270 assume loc_n is None || Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n-> t);
260271}
261- yield procedure {:layer 2 } ReadTopOfStack#Push(loc_t: Loc ) returns (loc_n: Option LocTreiberNode)
272+ yield procedure {:layer 2 } ReadTopOfStack#Push(loc_t: LocTreiberStack ) returns (loc_n: Option LocTreiberNode)
262273preserves call TopInStack(loc_t);
263274ensures call LocInStackOrNone(loc_t, loc_n);
264275refines AtomicReadTopOfStack#Push;
265276{
266277 call loc_n := ReadTopOfStack#0 (loc_t);
267278}
268279
269- atomic action {:layer 3 } AtomicReadTopOfStack#Pop(loc_t: Loc ) returns (loc_n: Option LocTreiberNode)
280+ atomic action {:layer 3 } AtomicReadTopOfStack#Pop(loc_t: LocTreiberStack ) returns (loc_n: Option LocTreiberNode)
270281{
271282 assert Map_Contains(TreiberPoolLow, loc_t);
272283 assume if loc_n is None then Map_At(TreiberPoolLow, loc_t)-> top is None else Set_Contains(Domain(TreiberPoolLow, loc_t), loc_n-> t);
273284}
274- yield procedure {:layer 2 } ReadTopOfStack#Pop(loc_t: Loc ) returns (loc_n: Option LocTreiberNode)
285+ yield procedure {:layer 2 } ReadTopOfStack#Pop(loc_t: LocTreiberStack ) returns (loc_n: Option LocTreiberNode)
275286preserves call TopInStack(loc_t);
276287ensures call LocInStackOrNone(loc_t, loc_n);
277288refines AtomicReadTopOfStack#Pop;
278289{
279290 call loc_n := ReadTopOfStack#0 (loc_t);
280291}
281292
282- right action {:layer 2 ,3 } AtomicLoadNode#1 (loc_t: Loc , loc_n: LocTreiberNode) returns (node: StackElem X)
293+ right action {:layer 2 ,3 } AtomicLoadNode#1 (loc_t: LocTreiberStack , loc_n: LocTreiberNode) returns (node: StackElem X)
283294{
284295 assert Map_Contains(TreiberPoolLow, loc_t);
285296 assert Map_Contains(Map_At(TreiberPoolLow, loc_t)-> nodes, loc_n);
@@ -288,11 +299,11 @@ right action {:layer 2,3} AtomicLoadNode#1(loc_t: Loc, loc_n: LocTreiberNode) re
288299
289300/// Primitives
290301
291- atomic action {:layer 1 } AtomicLoadNode#0 (loc_t: Loc , loc_n: LocTreiberNode) returns (node: StackElem X)
302+ atomic action {:layer 1 } AtomicLoadNode#0 (loc_t: LocTreiberStack , loc_n: LocTreiberNode) returns (node: StackElem X)
292303modifies TreiberPoolLow;
293304refines AtomicLoadNode#1 ;
294305{
295- var {:linear} one_loc_t: One Loc ;
306+ var {:linear} one_loc_t: One LocTreiberStack ;
296307 var {:linear} treiber: Treiber X;
297308 var top: Option LocTreiberNode;
298309 var {:linear} stack: StackMap X;
@@ -305,13 +316,13 @@ refines AtomicLoadNode#1;
305316 treiber := Treiber(top, stack);
306317 call Map_Put(TreiberPoolLow, one_loc_t, treiber);
307318}
308- yield procedure {:layer 0 } LoadNode#0 (loc_t: Loc , loc_n: LocTreiberNode) returns (node: StackElem X);
319+ yield procedure {:layer 0 } LoadNode#0 (loc_t: LocTreiberStack , loc_n: LocTreiberNode) returns (node: StackElem X);
309320refines AtomicLoadNode#0 ;
310321
311- yield procedure {:layer 0 } ReadTopOfStack#0 (loc_t: Loc ) returns (loc_n: Option LocTreiberNode);
322+ yield procedure {:layer 0 } ReadTopOfStack#0 (loc_t: LocTreiberStack ) returns (loc_n: Option LocTreiberNode);
312323refines atomic action {:layer 1 ,2 } _
313324{
314- var {:linear} one_loc_t: One Loc ;
325+ var {:linear} one_loc_t: One LocTreiberStack ;
315326 var {:linear} treiber: Treiber X;
316327
317328 call one_loc_t, treiber := Map_Get(TreiberPoolLow, loc_t);
@@ -320,10 +331,10 @@ refines atomic action {:layer 1,2} _
320331}
321332
322333yield procedure {:layer 0 } WriteTopOfStack#0 (
323- loc_t: Loc , old_loc_n: Option LocTreiberNode, new_loc_n: Option LocTreiberNode) returns (success: bool);
334+ loc_t: LocTreiberStack , old_loc_n: Option LocTreiberNode, new_loc_n: Option LocTreiberNode) returns (success: bool);
324335refines atomic action {:layer 1 ,4 } _
325336{
326- var {:linear} one_loc_t: One Loc ;
337+ var {:linear} one_loc_t: One LocTreiberStack ;
327338 var {:linear} treiber: Treiber X;
328339
329340 call one_loc_t, treiber := Map_Get(TreiberPoolLow, loc_t);
@@ -336,18 +347,18 @@ refines atomic action {:layer 1,4} _
336347 call Map_Put(TreiberPoolLow, one_loc_t, treiber);
337348}
338349
339- yield procedure {:layer 0 } AllocNode#0 (loc_t: Loc , {:linear_in} loc_piece: One LocTreiberNode, node: StackElem X);
350+ yield procedure {:layer 0 } AllocNode#0 (loc_t: LocTreiberStack , {:linear_in} loc_piece: One LocTreiberNode, node: StackElem X);
340351refines atomic action {:layer 1 ,3 } _
341352{
342- var {:linear} one_loc_t: One Loc ;
353+ var {:linear} one_loc_t: One LocTreiberStack ;
343354 var {:linear} treiber: Treiber X;
344355
345356 call one_loc_t, treiber := Map_Get(TreiberPoolLow, loc_t);
346357 call Map_Put(treiber-> nodes, loc_piece, node);
347358 call Map_Put(TreiberPoolLow, one_loc_t, treiber);
348359}
349360
350- yield procedure {:layer 0 } AllocTreiber#0 ({:linear_in} one_loc_t: One Loc , {:linear_in} treiber: Treiber X);
361+ yield procedure {:layer 0 } AllocTreiber#0 ({:linear_in} one_loc_t: One LocTreiberStack , {:linear_in} treiber: Treiber X);
351362refines atomic action {:layer 1 ,4 } _
352363{
353364 call Map_Put(TreiberPoolLow, one_loc_t, treiber);
0 commit comments