2014-04-01 70 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