2014-04-01 74 views
1

我OCaml中是新的,這裏是我的原代碼:我可以用這種方式寫「OCAML模式匹配」嗎?

method vinst(i) = 
    match i with 
    | Set (lv , e, _) -> 
     let (host, _) = lv in 
     match host with 
     | Mem _ -> 
      ( self#queueInstr [mkPtrLVal (addressOf lv) e]; 
      ChangeTo []) 
     | _ -> SkipChildren 
     ...... 

由於Set (lv, e, _)模式匹配後,我還需要在lve模式匹配兩者,所以我想重新把它寫在這種方式(擺脫惱人的開始...結束塊):

 method vinst(i) = 
    match i with 
    | Set (lv , e, _) when (Mem _, _) = lv -> (* see I re-write it this way *) 
      ( self#queueInstr [mkPtrLVal (addressOf lv) e]; 
      ChangeTo []) 
    | Set (lv , e, _) when (Lval (Mem _, _)) = lv -> 
     ( self#queueInstr [mkPtrE (addressOf lv) e]; 
      ChangeTo []) 
    | Set (lv , e, _) when (TPtr _) = typeOf e-> 
     (self#queueInstr [mkPtrE (addressOf lv) e]; 
      ChangeTo []) 
    | _ -> DoChildren 

我試圖編譯它,但

錯誤:語法錯誤:運營商的預期。

發生......

所以基本上就可以把它寫這樣?如果是這樣,我應該調整哪一部分?

==================更新===============

這裏是我做剛纔:

method vinst(i) = 
    match i with 
    | Set ((Mem _, _), e, _) -> (* pattern 1 *) 
      let Set (lv, e, _) = i in 
      ( self#queueInstr [mkPtrLVal (addressOf lv) e]; 
      ChangeTo []) 
    | Set (_, Lval (Mem _, _), _) -> (* pattern 2 *) 
      let Set (lv, e, _) = i in 
     ( self#queueInstr [mkPtrE (addressOf lv) e]; 
      ChangeTo []) 
    | Set (lv , e, _) -> (* pattern 3 *) 
     begin 
     match typeOf e with 
     | TPtr _ -> 
      (self#queueInstr [mkPtrE (addressOf lv) e]; 
      ChangeTo []) 
     | _ -> SkipChildren 
    end 
    | _ -> DoChildren 

是不是不夠好?有沒有更優雅的方式?

+1

關於你的更新,你的'讓集... = i'其實都是非詳盡的圖案匹配問題,因爲編譯器應該警告過你(即使在這種情況下,你知道該模式是正確的)。觸發編譯器警告很少是一個好主意。在我看來,BenoîtGuédas使用'as'結合的答案是最好的解決方案。一個小的優化可以使用'Cil.isPointerType'而不是本地定義的'isPtr',但就是這樣。 – Virgile

回答

4

代替再次解構i以獲得lve,則可以使用as關鍵字的別名。您也可以定義一個函數isPtr返回一個布爾值,而不是直接使用typeOf

method vinst i = 
    let isPtr e = match typeOf e with 
    | TPtr _ -> true 
    | _ -> false in 
    match i with 
    | Set (((Mem _, _) as lv), e, _) -> 
     ( self#queueInstr [mkPtrLVal (addressOf lv) e]; 
     ChangeTo []) 
    | Set ((_ as lv), (Lval (Mem _, _) as e), _) -> 
     ( self#queueInstr [mkPtrE (addressOf lv) e]; 
     ChangeTo []) 
    | Set (lv , e, _) when isPtr e -> 
     ( self#queueInstr [mkPtrE (addressOf lv) e]; 
     ChangeTo []) 
    | Set (lv , e, _) -> SkipChildren 
    | _ -> DoChildren 
2

你可以做進一步的圖案的when左側匹配(以正確的應該是一個boolean,所以這將是對元組/構造的進一步解構了不合適的地方),

| Set ((Mem _,_), e, _) -> ... 
+0

嗨nlucaroni,謝謝你的回答,我只是這樣做......但一個問題是,在第三種模式,我必須檢查** typeOf e **,它不能直接放入任何模式(我是對吧?)然後我只用另一場比賽......用第三種模式......這足夠好嗎? – computereasy

+0

用你提供的東西是正確的。我不知道'typeOf'做了什麼或者'e'是如何構造的以知道它是否可以直接匹配。 – nlucaroni