Creport2
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);
}
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
}
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 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 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
{
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
}
}
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