Skip to content

Commit 46c4f71

Browse files
committed
two lists example
1 parent b2fb1be commit 46c4f71

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

Test/civl/samples/two-lists.bpl

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// RUN: %parallel-boogie -lib:base -lib:node -vcsSplitOnEveryAssert "%s" > "%t"
2+
// RUN: %diff "%s.expect" "%t"
3+
4+
type ListElem T = Node Loc T;
5+
6+
datatype Queue<T> { Queue(head: Loc, tail: Loc, {:linear} nodes: Map Loc (ListElem T)) }
7+
8+
var {:linear} {:layer 0, 1} lists: Map Loc (Queue int);
9+
10+
var {:linear} {:layer 0, 1} pos: One (TaggedLoc Unit);
11+
var {:linear} {:layer 0, 1} neg: One (TaggedLoc Unit);
12+
13+
yield procedure {:layer 0} ReadPos() returns (loc: Loc);
14+
refines both action {:layer 1} _ {
15+
loc := pos->val->loc;
16+
}
17+
18+
yield procedure {:layer 0} ReadNeg() returns (loc: Loc);
19+
refines both action {:layer 1} _ {
20+
loc := neg->val->loc;
21+
}
22+
23+
yield procedure {:layer 0} Enqueue(loc_q: Loc, i: int);
24+
refines action {:layer 1} _
25+
{
26+
var {:linear} one_loc_q: One Loc;
27+
var {:linear} queue: Queue int;
28+
var head, tail: Loc;
29+
var {:linear} nodes: Map Loc (ListElem int);
30+
var {:linear} one_loc_n, new_one_loc_n: One Loc;
31+
var node: ListElem int;
32+
33+
call one_loc_q, queue := Map_Get(lists, loc_q);
34+
Queue(head, tail, nodes) := queue;
35+
36+
call new_one_loc_n := Loc_New();
37+
call Map_Put(nodes, new_one_loc_n, Node(None(), 0));
38+
39+
call one_loc_n, node := Map_Get(nodes, tail);
40+
node := Node(Some(new_one_loc_n->val), i);
41+
call Map_Put(nodes, one_loc_n, node);
42+
43+
queue := Queue(head, new_one_loc_n->val, nodes);
44+
call Map_Put(lists, one_loc_q, queue);
45+
}
46+
47+
yield procedure {:layer 0} Dequeue(loc_q: Loc) returns (i: int);
48+
refines action {:layer 1} _
49+
{
50+
var {:linear} one_loc_q: One Loc;
51+
var {:linear} queue: Queue int;
52+
var head, tail: Loc;
53+
var {:linear} nodes: Map Loc (ListElem int);
54+
var {:linear} one_loc_n: One Loc;
55+
var node: ListElem int;
56+
var next: Option Loc;
57+
58+
call one_loc_q, queue := Map_Get(lists, loc_q);
59+
Queue(head, tail, nodes) := queue;
60+
61+
assume head != tail;
62+
call one_loc_n, node := Map_Get(nodes, head);
63+
Node(next, i) := node;
64+
65+
assert next is Some;
66+
queue := Queue(next->t, tail, nodes);
67+
call Map_Put(lists, one_loc_q, queue);
68+
}
69+
70+
71+
function {:inline} IsAcyclic(q: Queue int): bool
72+
{
73+
Between(q->nodes->val, Some(q->head), Some(q->tail), None())
74+
}
75+
76+
function {:inline} QueueElems(q: Queue int): [Loc]bool
77+
{
78+
BetweenSet(q->nodes->val, Some(q->head), Some(q->tail))
79+
}
80+
81+
yield invariant {:layer 1} PosInv();
82+
invariant Map_Contains(lists, pos->val->loc);
83+
invariant (var q := Map_At(lists, pos->val->loc); IsAcyclic(q) &&
84+
(forall loc_n: Loc:: QueueElems(q)[loc_n] ==>
85+
Map_Contains(q->nodes, loc_n) &&
86+
(loc_n == q->tail || (var node := Map_At(q->nodes, loc_n); node->val > 0))));
87+
88+
yield invariant {:layer 1} NegInv();
89+
invariant Map_Contains(lists, neg->val->loc);
90+
invariant (var q := Map_At(lists, neg->val->loc); IsAcyclic(q) &&
91+
(forall loc_n: Loc:: QueueElems(q)[loc_n] ==>
92+
Map_Contains(q->nodes, loc_n) &&
93+
(loc_n == q->tail || (var node := Map_At(q->nodes, loc_n); node->val < 0))));
94+
95+
96+
yield procedure {:layer 1} Producer(i: int)
97+
preserves call PosInv();
98+
preserves call NegInv();
99+
{
100+
var loc: Loc;
101+
102+
assert {:layer 1} pos->val->loc != neg->val->loc;
103+
if (i == 0) {
104+
return;
105+
}
106+
if (i > 0) {
107+
call loc := ReadPos();
108+
} else {
109+
call loc := ReadNeg();
110+
}
111+
call Enqueue(loc, i);
112+
}
113+
114+
yield procedure {:layer 1} PosConsumer()
115+
preserves call PosInv();
116+
{
117+
var loc: Loc;
118+
var i: int;
119+
120+
call loc := ReadPos();
121+
call i := Dequeue(loc);
122+
assert {:layer 1} i > 0;
123+
}
124+
125+
yield procedure {:layer 1} NegConsumer()
126+
preserves call NegInv();
127+
{
128+
var loc: Loc;
129+
var i: int;
130+
131+
call loc := ReadNeg();
132+
call i := Dequeue(loc);
133+
assert {:layer 1} i < 0;
134+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
Boogie program verifier finished with 3 verified, 0 errors

0 commit comments

Comments
 (0)