Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / parsing_cocci / comm_assoc.ml
1 (* searches for E op ..., for any commutative and associative binary
2 operator. When this satisfies the isomorphism conditions (ie all minus, or
3 context for the op and ...), then this is converted to Nested(E,op).
4 Nested is not used before this phase. *)
5
6 module Ast = Ast_cocci
7 module Ast0 = Ast0_cocci
8 module V0 = Visitor_ast0
9 module VT0 = Visitor_ast0_types
10
11 let comm_assoc =
12 [Ast.Arith(Ast.Plus);Ast.Arith(Ast.Mul);Ast.Arith(Ast.And);Ast.Arith(Ast.Or);
13 Ast.Logical(Ast.AndLog);Ast.Logical(Ast.OrLog)]
14
15 let is_minus e =
16 match Ast0.get_mcodekind e with Ast0.MINUS(cell) -> true | _ -> false
17
18 let is_context e =
19 !Flag.sgrep_mode2 or (* everything is context for sgrep *)
20 (match Ast0.get_mcodekind e with
21 Ast0.CONTEXT(cell) -> true
22 | _ -> false)
23
24 let nopos mc =
25 match Ast0.get_pos mc with Ast0.MetaPos _ -> false | Ast0.NoMetaPos -> true
26
27 let process_binops rule_name =
28 let expr r k e1 =
29 let e = k e1 in
30 match Ast0.unwrap e with
31 Ast0.Binary(left,op,right)
32 when List.mem (Ast0.unwrap_mcode op) comm_assoc ->
33 (match Ast0.unwrap right with
34 Ast0.Edots(d,None) ->
35 if (is_minus e || (is_context e && is_context right))
36 && nopos op && nopos d
37 (* keep dots to record required modif *)
38 then Ast0.rewrap e (Ast0.Nested(left,op,right))
39 else
40 (Printf.printf
41 "%s: position variables or mixed modifs interfere with comm_assoc iso" rule_name;
42 Unparse_ast0.expression e1;
43 Format.print_newline();
44 e)
45 | Ast0.Edots(d,_) ->
46 (Printf.printf
47 "%s: whencode interferes with comm_assoc iso" rule_name;
48 Unparse_ast0.expression e1;
49 Format.print_newline();
50 e)
51 | _ -> e)
52 | _ -> e in
53 V0.rebuilder {V0.rebuilder_functions with VT0.rebuilder_exprfn = expr}
54
55 let comm_assoc rule rule_name dropped_isos =
56 if List.mem "comm_assoc" dropped_isos
57 then rule
58 else List.map (process_binops rule_name).VT0.rebuilder_rec_top_level rule