我有以下zaMap(请参阅此处的完整代码:http://rise4fun.com/Dafny/LCaM):
class zaMap {
var busybits :array<bool>;
var keys : array<int>;
var values : array<int>;
predicate wellformed ()
reads busybits, keys, values, this
{
busybits != null && keys != null && values != null &&
keys != values &&
busybits.Length == keys.Length &&
keys.Length == values.Length
}
// ... more predicates and methods follow
method put(k : int, v : int) returns (success : bool)
requires wellformed()
modifies busybits, keys, values
ensures !success ==> full()
ensures success ==> mapsto(k, v)
{
var i := findEmpty();
if (i < 0)
{
success := false;
return;
}
assert !busybits[i];
busybits[i] := true;
keys[i] := k;
values[i] := v;
success := true;
}
//...
现在我想为put
方法添加更多规范。例如,我想ensure
,如果返回值为success == true
,则在函数调用之前映射为!full()
,或者等效地如果映射不是full()
,它保证在那里put
。
问题是,在前提条件下,需要&#34;我还不知道它将会返回什么,并且在后置条件下确保&#34;我不再拥有原始地图了。人们对此做了什么?
答案 0 :(得分:1)
您可以使用old
关键字。我们来看一个例子吧。以下方法将包含元素x
的数组的所有位置设置为零,并将其余部分保持原样。这是代码:
method setToZero(a: array<int>, x : int )
requires a != null;
modifies a;
ensures forall i :: 0 <= i < a.Length && old(a[i]) == x ==> a[i] == 0;
ensures forall i :: 0 <= i < a.Length && old(a[i]) != x ==> a[i] == old(a[i]);
{
var j := 0;
while (j < a.Length)
invariant 0 <= j <= a.Length;
invariant forall i :: 0 <= i < j && old(a[i]) == x ==> a[i] == 0;
invariant forall i :: 0 <= i < j && old(a[i]) != x ==> a[i] == old(a[i]);
invariant forall i :: j <= i < a.Length ==> a[i] == old(a[i]);
{
if (a[j] == x) {
a[j] := 0;
}
j := j + 1;
}
}