Table
include collections
module hash_table(key,value,shard) = {
¤
Interface
Set the value of a key
action set(k:key.t, v:value)
action get(k:key.t) returns (v:value)
action extract_(lo:key.iter.t,hi:key.iter.t) returns(res:shard.t)
action incorporate(s:shard.t)
¤
Specification
function hash(X:key.t) : value
object spec = {
init hash(X) = 0
before set {
hash(k) := v
}
after get {
assert v = hash(k)
}
after extract_ {
assert shard.lo(res) = lo;
assert shard.hi(res) = hi;
assert key.iter.between(lo,X,hi)-> shard.value(res,X) = hash(X);
assert shard.valid(res)
}
before incorporate(s:shard.t) {
assert shard.valid(s);
hash(K) := shard.value(s,K)
if key.iter.between(shard.lo(s),K,shard.hi(s))
else hash(K)
}
}
¤
Implementation
object impl = {
instance tab : ordered_map(key,value)
implement set {
call tab.set(k,v)
}
implement get {
v := tab.get(k,0)
}
implement extract_ {
res.kv := shard.kvt.empty;
var idx := tab.lub(lo);
while idx < hi
invariant lo <= idx & (idx < hi -> tab.contains(idx.val))
invariant lo.between(X,idx) & tab.contains(X) ->
exists I. (res.key_at(I,X) & tab.maps(X,res.value_at(I)))
invariant res.key_at(I,X) -> lo.between(X,idx) & tab.contains(X)
invariant shard.valid(res)
{
var k := idx.val;
res.kv := res.kv.append_pair(k,tab.get(k,0));
idx := tab.next(idx)
};
res.lo := lo;
res.hi := hi
}
implement incorporate(s:shard.t) {
var lo := s.lo;
var hi := s.hi;
call tab.erase(lo,hi);
var pos:shard.index.t := 0;
while pos < s.kv.end
invariant 0 <= pos & pos <= s.kv.end
invariant lo.between(X,hi) & s.value(X) = 0 -> ~tab.contains(X)
invariant lo.between(X,hi) & 0 <= Y & Y < pos & s.key_at(Y,X) & s.value(X) ~= 0
-> tab.contains(X) & tab.maps(X,s.value(X))
invariant ~lo.between(X,hi) -> spec.tab_invar(X,Y)
invariant tab.maps(X,Y) & tab.maps(X,Z) -> Y = Z & tab.contains(X)
{
var k := s.kv.get_key(pos);
var d := s.kv.get_value(pos);
if lo.between(k,hi) & d ~= 0{
call tab.set(k,d)
};
pos := pos.next
}
}
object spec = {
function tab_invar(X,Y) =
(tab.contains(X) & tab.maps(X,Y) -> hash(X) = Y)
& (~tab.contains(X) -> hash(X) = 0)
& (tab.contains(X) -> tab.maps(X,hash(X)))
}
conjecture spec.tab_invar(X,Y)
}
}