forked from kenmcmil/ivy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreport2.ivy
217 lines (185 loc) · 6.62 KB
/
creport2.ivy
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#lang ivy1.7
include order
include collections
include deduction
module shift_theory(idx) = {
relation r(T : idx, X : idx, Y : idx)
action f(t:idx,x:idx) returns (y:idx)
action b(t:idx,x:idx) returns (y:idx)
specification {
property r(T,X,Y) & r(T,X,Y1) -> Y = Y1
property r(T,X,Y) & r(T,X1,Y) -> X = X1
property r(T,X1,Y1) & r(T,X2,Y2) & X1 < X2 -> Y1 < Y2
property r(T1,X,Y1) & r(T2,X,Y2) & T1 < T2 -> Y2 < Y1
property r(T,X1,Y1) & idx.succ(X1,X2) & idx.succ(Y1,Y2) -> r(T,X2,Y2)
property r(0,X,X)
property r(X,X,0)
property r(T,X,Y) -> Y <= X & T <= X
theorem [into] {property X >= T -> exists Y. r(T,X,Y)}
proof {
apply introImp;
apply introE with witness = X - T
}
around f {
require t <= x;
...
ensure r(t,x,y)
}
after b {
ensure r(t,y,x)
}
} # end specification section
implementation {
definition r(T,X,Y) = (X = Y + T)
implement f {
y := x - t
}
implement b {
y := x + t
}
}
isolate iso = this with idx.impl
}
module mysegment(domain,range,none) = {
type this
relation value(S:this,D:domain,R:range)
relation begin(S:this,D:domain)
relation end(S:this,D:domain)
action set(w:this, i:domain, v:range) returns (w:this)
action read(w:this, i:domain) returns (v:range)
action trim(w:this, i:domain) returns (w:this)
action empty(i:domain) returns (w:this)
action merge(w: this, max_w: this) returns (max_w: this)
action getBegin(w:this) returns (i:domain)
action getEnd(w:this) returns (i:domain)
specification {
after init {
}
around set {
require v ~= none;
require exists I. begin(w, I) & I <= i;
...
ensure I = i -> (value(w, I, V) <-> V = v);
ensure I ~= i & value(old w, I, V) -> value(w, I, V)
}
around read {
require exists I. begin(w, I) & I <= i;
...
ensure value(w, i, v);
}
around trim {
require exists I. begin(w, I) & I <= i;
...
ensure begin(w, I) <-> I = i;
ensure i <= I & value(old w, I, V) -> value(w, I, V)
proof assume shift.into with T = i, X = I;
ensure I < i -> (value(w, I, V) <-> V = none);
}
# after empty {
# ensure value(w, I, V, O) <-> V = none;
# ensure begin(w, I) <-> I = i;
# }
# around getBegin {
# ...
# ensure begin(w, i);
# }
# around getEnd {
# ...
# ensure forall I. i <= I -> value(w, I, none);
# }
property value(W, I, V1) & value(W, I, V2) -> V1 = V2
property value(W, I, V) -> 0 <= I
property begin(W, I) & begin(W, I2) -> I = I2
# property end(W, IE) & I >= IE -> value(W, I, none)
}
implementation {
instance shift : shift_theory(slot)
instance arr : array(domain,range)
destructor elems(W:this) : arr
destructor offset(W:this) : domain
property X < offset(W) -> value(W,X,none)
property shift.r(offset(W),X,Y) & Y < elems(W).end -> value(W,X,elems(W).value(Y))
# property shift.r(offset(W),X,Y) & Y >= elems(W).end -> value(W,X,none)
property value(W, I, V1) & value(W, I, V2) -> V1 = V2
property value(W, I, V) -> 0 <= I
# definition value(w:this,x:domain,v:range) =
# (exists Y. shift.r(offset(w),x,Y) &
# (v = elems(w).value(Y) if Y < elems(w).end else none))
# | x < offset(w) & v = none
definition value(w:this,x:domain,v:range) =
(exists Y. shift.r(offset(w),x,Y) &
(v = elems(w).value(Y) if Y < elems(w).end else none))
| x < offset(w) & v = none
definition begin(W,I) = (I = offset(W))
definition end(W,I) = shift.r(offset(W),I,elems(W).end)
implement set {
var index := shift.f(offset(w), i);
if w.elems.end <= index {
w.elems := w.elems.resize(index.next, none);
};
w.elems := w.elems.set(index, v);
}
implement read {
var index := shift.f(offset(w),i);
v := none if (index >= w.elems.end) else w.elems.value(index)
}
implement trim {
var bound := shift.b(offset(w),w.elems.end);
var j := i;
if j < bound {
while j < bound
invariant i <= j & j <= bound
invariant shift.r(offset(old w),bound,old w.elems.end)
invariant j <= X & X < bound & shift.r(offset(old w),X,Y) -> value(old w,X,w.elems.value(Y))
invariant X < j & shift.r(i,X,Y) -> value(old w,X,w.elems.value(Y))
invariant w.offset <= j & w.offset = offset(old w)
invariant w.elems.end = elems(old w).end
# invariant shift.r(i,j,X) -> X < w.elems.end
{
w.elems := w.elems.set(shift.f(i,j),w.elems.value(shift.f(w.offset,j)));
j := j.next;
};
w.elems := w.elems.resize(shift.f(i,bound),0);
w.offset := i
}
else {
assume false;
w.elems := arr.empty;
w.offset := i;
};
bound := shift.b(offset(w),w.elems.end) # just for a witness
}
# implement trim {
# var j := i;
# if j <= bound(w) {
# while j < bound(w)
# invariant i <= j
# invariant j <= bound(w)
# invariant shift.r(offset(w),bound(w),content(w).end)
# invariant j <= X & X < bound(w) & shift.r(offset(w),X,Y) -> value(old w, X, maxview(content(w).value(Y)), maxop(content(w).value(Y)))
# invariant i <= X & X < j & shift.r(i,X,Y) -> value(old w, X, maxview(content(w).value(Y)), maxop(content(w).value(Y)) )
# invariant bound(w) = bound(old w)
# invariant offset(w) = offset(old w)
# invariant content(w).end = content(old w).end
# {
# content(w) := content(w).set(shift.f(i,j),content(w).value(shift.f(offset(w),j)));
# j := j.next;
# };
# content(w) := content(w).resize(shift.f(i,bound(w)),0);
# offset(w) := i
# } else {
# content(w) := arr.empty;
# offset(w) := i;
# bound(w) := i;
# }
# }
}
isolate iso = this with domain
}
instance slot : unbounded_sequence
type data
individual none : data
instance foo : mysegment(slot,data,none)
export foo.set
export foo.read
export foo.trim