对于达夫尼

时间:2019-04-17 13:57:43

标签: dafny

如果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;

  }

} 

1 个答案:

答案 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.Cachetop.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