2016-04-20 62 views
1

我正在用dafny語法掙扎。函數中的Dafny語法錯誤

searchAndReplace接收三個字符數組。我們假設line[s][n][a][k][e]; pat[n][a],並且dst是[h][i]。我想在line搜索的pat所有事件和與dst取代它導致[s][h][i][k][e]

方法find將返回的第一個字母的指數之在line等於pat

方法delete將在可變atline刪除pat返回在find,並at+p向左移動後,所有其他元素,以填補空的空間。

方法insert將騰出空間,以dst通過移動atat + pp位置向右之間的所有字符添加到lineat

我創建了一個附配的功能,這將爲了比較patdst以驗證它們是不相等的(如果他們會在情​​況pat被替換無限時間dstlineline存在) 對於現在的我米上下面的代碼部分,用於接收錯誤「then expected」內部功能checkIfEqual

if(pat.Length != dst.Length) { 
    return false; 
    } 

完整的代碼:

method searchAndReplace(line:array<char>, l:int, 
     pat:array<char>, p:int, 
     dst:array<char>, n:int)returns(nl:int) 
     requires line != null && pat!=null && dst!=null; 
     requires !checkIfEqual(pat, dst); 
     requires 0<=l<line.Length; 
     requires 0<=p<pat.Length; 
     requires 0<=n<dst.Length; 

     modifies line; 
     { 
      var at:int := 0; 
      var p:int := n; 

      while(at != -1) 
      invariant -1<=at<=l; 
      { 
      at := find(line, l, dst, n); 
      delete(line, l, at, p); 
      insert(line, l, pat, p, at); 
      } 

      var length:int := line.Length; 

      return length; 
     } 

     function checkIfEqual(pat:array<char>, dst:array<char>):bool 
     requires pat!=null && dst!=null; 
     reads pat; 
     reads dst; 
     { 

      var i:int := 0; 

      if(pat.Length != dst.Length) { 
      return false; 
      } 

      while(i<dst.Length) { 
      if(pat[i] != dst[i]){ 
       return false; 
      } 
      i := i + 1; 
      } 
      return true; 

     } 

     method insert(line:array<char>, l:int, nl:array<char>, p:int, at:int) 
      requires line != null && nl != null; 
      requires 0 <= l+p <= line.Length && 0 <= p <= nl.Length ; 
      requires 0 <= at <= l; 
      modifies line; 
      ensures forall i :: (0<=i<p) ==> line[at+i] == nl[i]; // error 
     { 
      var i:int := 0; 
      var positionAt:int := at; 
      while(i<l && positionAt < l) 
      invariant 0<=i<l+1; 
      invariant at<=positionAt<=l; 
      { 
      line[positionAt+p] := line[positionAt]; 
      line[positionAt] := ' '; 
      positionAt := positionAt + 1; 
      i := i + 1; 
      } 

      positionAt := at; 
      i := 0; 
      while(i<p && positionAt < l) 
      invariant 0<=i<=p; 
      invariant at<=positionAt<=l; 
      { 
      line[positionAt] := nl[i]; 
      positionAt := positionAt + 1; 
      i := i + 1; 
      } 
     } 

     method find(line:array<char>, l:int, pat:array<char>, p:int) returns (pos:int) 
      requires line!=null && pat!=null 
      requires 0 <= l < line.Length 
      requires 0 <= p < pat.Length 
      ensures 0 <= pos < l || pos == -1 
     { 
      var iline:int := 0; 
      var ipat:int := 0; 
      pos := -1; 

      while(iline<l && ipat<pat.Length) 
      invariant 0<=iline<=l 
      invariant 0<=ipat<=pat.Length 
      invariant -1 <= pos < iline 
      { 
       if(line[iline]==pat[ipat] && (line[iline]!=' ' && pat[ipat]!=' ')){ 
        if(pos==-1){ 
         pos := iline; 
        } 
        ipat:= ipat + 1; 
       } else { 
       if(ipat>0){ 
        if(line[iline] == pat[ipat-1]){ 
        pos := pos + 1; 
        } 
       } 
       ipat:=0; 
       pos := -1; 
       } 
       if(ipat==p) { 
        return; 
       } 
       iline := iline + 1; 
      } 
      return; 
     } 
    method delete(line:array<char>, l:nat, at:nat, p:nat) 
    requires line!=null 
    requires l <= line.Length 
    requires at+p <= l 
    modifies line 
    ensures line[..at] == old(line[..at]) 
    ensures line[at..l-p] == old(line[at+p..l]) 
{ 
    var i:nat := 0; 
    while(i < l-(at+p)) 
    invariant i <= l-(at+p) 
    invariant at+p+i >= at+i 
    invariant line[..at] == old(line[..at]) 
    invariant line[at..at+i] == old(line[at+p..at+p+i]) 
    invariant line[at+i..l] == old(line[at+i..l]) // future is untouched 
    { 
    line[at+i] := line[at+p+i]; 
    i := i+1; 
    } 
} 

回答

1

function s在Dafny中是純粹的,歸納定義的,並且使用與命令methods不同的語法。您不能在函數中使用命令式語言功能。在這種情況下,你是不允許使用:

  • 條件語句if cond { s1* } else { s2* }

  • 循環語句while cond { s1* }

取而代之的是函數的主體必須是一個表達式:

雖然在這裏不需要它,Dafny確實有一個條件表達式(ITE):

predicate checkIfEqual(pat:array<char>, dst:array<char>) 
    requires pat!=null && dst!=null; 
    reads pat; 
    reads dst; 
{ 
    if pat.Length != dst.Length then false 
    else forall i:nat :: i < pat.Length ==> pat[i] == dst[i] 
} 

需要注意的是:

  • 你不能把一個循環,一個函數體,但你可能使用遞歸

  • predicatefunction的簡寫,返回bool