-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLimitedStack.dfy
165 lines (131 loc) · 3.78 KB
/
LimitedStack.dfy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
class {:autocontracts} LimitedStack
{
//Abstração
ghost const g_MaxSize: nat;
ghost var g_Stack: seq<nat>;
//Implementação
var stackArray: array<nat>;
const max: nat;
var tail: nat;
//Invariante de classe
predicate Valid() reads this
{
max > 0
&& stackArray.Length == max
&& 0 <= tail <= max
&& g_MaxSize == max
&& g_Stack == stackArray[0..tail]
}
constructor (m:nat) requires m > 0 ensures g_MaxSize == m ensures g_Stack == []
{
max := m;
stackArray := new nat[m];
tail := 0;
g_MaxSize := max;
g_Stack := [];
}
method add(e:nat) returns (b:bool)
ensures b != (old(|g_Stack|) >= g_MaxSize)
ensures ((b == false && (g_Stack == old(g_Stack))) || (b == true && (g_Stack == (old(g_Stack) + [e]))))
{
if tail >= max{
b := false;
}else {
stackArray[tail] := e;
tail := tail + 1;
g_Stack := g_Stack + [e];
b := true;
}
}
method remove() returns (e:nat)
requires |g_Stack| > 0
ensures e == old(g_Stack)[|old(g_Stack)|-1]
ensures g_Stack == old(g_Stack)[..|old(g_Stack)|-1]
{
e := stackArray[tail-1];
tail := tail - 1;
g_Stack := g_Stack[..|g_Stack|-1];
}
// method reverse()
// requires |g_Stack| > 0
// ensures forall k | 0 == k < |g_Stack| :: g_Stack[k] == old(g_Stack)[|old(g_Stack)|-1-k]
// {
// var aux := new nat[max];
// forall k | 0 == k < stackArray.Length
// {
// aux[k] := stackArray[stackArray.Length-1-k];
// }
// a := aux;
// g_Stack := stackArray[0..];
// }
method get() returns (e:nat)
requires 0 < |g_Stack| <= g_MaxSize
ensures e == g_Stack[|g_Stack|-1]
ensures g_Stack == old(g_Stack)
{
e := stackArray[tail-1];
}
method isFull() returns (b:bool)
ensures ((b == false && (|g_Stack| < g_MaxSize)) || (b == true && (|g_Stack| == g_MaxSize)))
ensures g_Stack == old(g_Stack)
{
b := !!(max <= tail);
}
method isEmpty() returns (b:bool)
ensures ((b == false && (|g_Stack| > 0)) || (b == true && (|g_Stack| == 0)))
ensures g_Stack == old(g_Stack)
{
b := !!(tail == 0);
}
method count() returns (n:nat)
ensures n == |g_Stack|
ensures g_Stack == old(g_Stack)
{
return tail;
}
method maxSize() returns (n:nat)
ensures n == g_MaxSize
ensures g_Stack == old(g_Stack)
{
return max;
}
}
method Main()
{
// tests
var max := 2;
var stack := new LimitedStack(max);
var size := stack.maxSize();
assert size == 2;
var empty := stack.isEmpty();
assert empty == true;
var result := stack.add(1);
assert result == true;
var count := stack.count();
assert count == 1;
var get1 := stack.get();
assert get1 == 1;
var full := stack.isFull();
assert full == false;
var empty2 := stack.isEmpty();
assert empty2 == false;
var result2 := stack.add(2);
assert result2 == true;
var count2 := stack.count();
assert count2 == 2;
var full2 := stack.isFull();
assert full2 == true;
var poped := stack.remove();
assert poped == 2;
var get2 := stack.get();
assert get2 == 1;
var size2 := stack.maxSize();
assert size2 == 2;
/////////////////////////////////////////
var testStack := new LimitedStack(2);
var t1 := testStack.add(1);
var cc := testStack.add(2);
//testStack.reverse();
var get := testStack.get();
assert get == 2;
}