如果forall内部的语句是要更新诸如c.arr [i] .d之类的变量,并且与字段和数组元素访问混合在一起,那么我对Dafny的forall语句感到困惑。例如,下面的示例无法编译。
我认为,明确指出modify子句非常乏味,我需要指出:modify top,modify top.Cache [i]
datatype CACHE_STATE = I| S| E
datatype MSG_CMD = Empty| ReqS| ReqE| Inv| InvAck| GntS| GntE
type NODE=nat
type DATA=nat
type boolean=bool
class class_0 {
var
Data : DATA,
Cmd : MSG_CMD
}
class class_1 {
var
Data : DATA,
State : CACHE_STATE
}
class TopC{
var
AuxData : DATA,
MemData : DATA,
CurPtr : NODE,
CurCmd : MSG_CMD,
ExGntd : boolean,
ShrSet : array<boolean>,
InvSet : array<boolean>,
Chan3 : array<class_0 > ,
Chan2 : array<class_0 > ,
Chan1 : array<class_0 > ,
Cache : array<class_1 > }
method n_RecvReqS(top:TopC,i:nat, N0:nat )
requires 0<= i<N0
requires top.Chan1.Length ==N0
requires N0>0
requires top.InvSet.Length ==N0
requires N0>0
requires top.ShrSet.Length ==N0
requires N0>0
requires top.Cache.Length ==N0
requires ((top.Chan1[i].Cmd == ReqS) && (top.CurCmd == Empty))
modifies top.Chan1[i]
modifies top.InvSet
modifies top.ShrSet
modifies top
modifies top.Cache
{
top.CurCmd := ReqS;
top.CurPtr := i;
top.Chan1[i].Cmd := Empty;
forall j | 0<= j< N0 {
top.InvSet[j] := top.ShrSet[j];
}
forall j | 0<= j< N0 {
top.Cache[j].State:= I;
}
}
答案 0 :(得分:0)
了解方法对堆的影响对于验证至关重要,尽管编写modifies
子句可能很乏味。在您的情况下,您需要考虑方法n_RecvReqS
执行的所有修改。您已经注意到,这包括所有top.Cache[j]
的每个j
对象。
将这些内容包含在modifies
子句中的一种方法是使用集合理解:
modifies set j | 0 <= j < top.Cache.Length :: top.Cache[j]
这表示对象top.Cache[j]
的集合,其中j
在满足0 <= j < top.Cache.Length
的值之间。
继续阅读以了解更多选项。
如果您经常这样做,并且您认为所有这些缓存都是TopC
对象表示形式的一部分,那么您可能希望抽象出许多状态并将它们放入一个组。如果您在Dafny测试套件中搜索像这样的声明
ghost var Repr: set<object>
您会找到一些示例。然后,整个modifies
子句就是
modifies Repr
如果您还没有准备好使用这样的Repr
集合,那么可以编写另一个简单的modifies
子句来编写程序中的缓存修改。如果您在modifies
子句中列出对象的序列,Dafny将自动将其转换为相应的对象的 set 。您可以通过表达式top.Cache
将top.Cache[..]
的所有数组元素转换为序列。因此,要说明您的forall
语句中的更新,您可以编写
modifies top.Cache[..]
不幸的是,Dafny不会自动意识到top.Cache[j]
语句主体中的每个forall
确实是由序列top.Cache[..]
形成的集合的元素。可以协助验证者证明这一点,但是这样做会使forall
语句更加混乱。这是我的操作方式:
forall j | 0 <= j < N0 {
(assert top.Cache[j] in top.Cache[..]; top.Cache[j]).State:= I;
}
Rustan