I am new in OCaml and here is my original code:
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
......
Because after pattern matching of Set (lv, e, _)
, I still need to pattern match both on lv
and e
, so I am thinking to re-write it in this way ( to get rid of annoying begin...end block):
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
I tried to compile it but
Error: Syntax error: operator expected.
occured...
So Basically it is possible to write it in this way? If so, which part should I adjust?
==================update===============
Here is what I did just now:
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
Is it good enough? Is there any more elegant way?
let Set ... = i
are in fact non-exhaustive pattern-matchings, as the compiler should have warned you (even if in that case you know that the pattern is the correct one). Triggering compiler warnings is rarely a good idea. The answer from Benoît Guédas using theas
binder is the best solution in my opinion. A small optimization could be to useCil.isPointerType
instead of the locally-definedisPtr
, but that's all. – Virgile