Coccinelle release 1.0.0-rc12
[bpt/coccinelle.git] / engine / postprocess_transinfo.ml
CommitLineData
f537ebc4 1(*
17ba0788
C
2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
f537ebc4
C
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
9 *
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
13 *
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
24 *)
25
26
feec80c3 27# 0 "./postprocess_transinfo.ml"
34e49164
C
28(* two goals: first drop from the environments things that are not used,
29 and second prompt for the names of fresh variables that are used *)
30
31(* have to add in the whole inherited env because inherited variables are
32not returned by get_fvs. It would be better if that were the case, but
33since at the moment I think we can only inherit one value per variable,
34perhaps it doesn't matter - these bindings will always be the same no matter
35how we reached a particular match *)
36
37module Ast = Ast_cocci
38
39let extra_counter = ref 0
40let get_extra _ =
41 let ctr = !extra_counter in
42 extra_counter := !extra_counter + 1;
43 "__extra_counter__"^(string_of_int ctr)
44
b1b2de81
C
45let get_seeded seed =
46 let ctr = !extra_counter in
47 extra_counter := !extra_counter + 1;
48 seed^(string_of_int ctr)
49
50let read_fresh_id _ =
ae4735db 51 try
34e49164 52 let s = read_line () in
485bce71 53 match Parse_c.tokens_of_string s with
34e49164 54 [Parser_c.TIdent _; Parser_c.EOF _] -> s
b1b2de81 55 | [Parser_c.EOF _] -> get_extra()
34e49164
C
56 | _ -> failwith ("wrong fresh id: " ^ s)
57 with End_of_file -> get_extra()
58
59let get_vars = function
60 Lib_engine.Match(re) -> (Ast.get_fvs re, Ast.get_fresh re)
61 | _ -> ([],[])
62
5636bb2c 63let string2val str = Lib_engine.NormalMetaVal(Ast_c.MetaIdVal(str,[]))
34e49164
C
64
65(* ----------------------------------------------------------------------- *)
66(* Get values for fresh variables *)
67
68let process_tree inherited_env l =
69 let (all_fresh,local_freshs,new_triples) =
70 List.fold_left
71 (function (all_fresh,local_freshs,new_triples) ->
72 function (node,env,pred) ->
73 let (other,fresh) = get_vars pred in
74 let env = List.filter (function (x,_) -> List.mem x other) env in
75 (Common.union_set fresh all_fresh,
76 fresh::local_freshs,
77 (node,env@inherited_env,pred)::new_triples))
78 ([],[],[]) l in
79 let local_freshs = List.rev local_freshs in
80 let new_triples = List.rev new_triples in
81 let fresh_env =
82 List.map
b1b2de81 83 (function
978fd7e5 84 ((r,n) as fresh,Ast.NoVal) ->
b1b2de81
C
85 Printf.printf "%s: name for %s: " r n; (* not debugging code!!! *)
86 flush stdout;
978fd7e5
C
87 (fresh,let v = string2val(read_fresh_id()) in function _ -> v)
88 | ((r,n) as fresh,Ast.StringSeed seed) ->
89 (fresh,let v = string2val(get_seeded seed) in function _ -> v)
90 | ((r,n) as fresh,Ast.ListSeed seed) ->
91 (fresh,
92 function env ->
93 let strings =
94 List.map
95 (function
96 Ast.SeedString s -> s
97 | Ast.SeedId id ->
98 try
99 (match List.assoc id env with
5636bb2c 100 Lib_engine.NormalMetaVal(Ast_c.MetaIdVal(str,_)) ->
978fd7e5
C
101 str
102 | _ -> failwith "bad id value")
103 with
8babbc8f
C
104 Not_found ->
105 failwith
106 ("fresh: no binding for meta "^(Dumper.dump id)))
978fd7e5
C
107 seed in
108 string2val(String.concat "" strings)))
34e49164
C
109 all_fresh in
110 let (_,res) =
111 List.split
112 (List.fold_left
113 (function freshs_node_env_preds ->
978fd7e5 114 function (fresh,fn) ->
34e49164
C
115 List.map
116 (function (freshs,((node,env,pred) as cur)) ->
b1b2de81
C
117 try
118 let _ = List.assoc fresh freshs in
978fd7e5 119 (freshs,(node,(fresh,fn env)::env,pred))
b1b2de81 120 with Not_found -> (freshs,cur))
34e49164
C
121 freshs_node_env_preds)
122 (List.combine local_freshs new_triples)
123 fresh_env) in
124 (List.rev res, fresh_env)
125
126(* ----------------------------------------------------------------------- *)
127(* Create the environment to be used afterwards *)
978fd7e5
C
128(* anything that a used after fresh variable refers to has to have a unique
129value, by virtue of the placement of the quantifier. thus we augment
130inherited env with the first element of l, if any *)
131
132let collect_used_after used_after envs l inherited_env =
133 List.map2
134 (function env -> function l ->
135 let inherited_env =
136 match l with
137 [] -> inherited_env
138 | (_,fse,_)::_ ->
139 (* l represents the result from a single tree. fse is a complete
140 environment in that tree. for a fresh seed, the environments
141 for all leaves contain the same information *)
142 fse@inherited_env in
143 List.map
144 (function (v,vl) -> (v,vl inherited_env))
145 (List.filter (function (v,vl) -> List.mem v used_after) env))
146 envs l
34e49164 147
708f4980
C
148(* ----------------------------------------------------------------------- *)
149(* distinguish between distinct witness trees, each gets an index n *)
8babbc8f
C
150(* index should be global, so that it can extend over environments *)
151
152let index = ref (-1)
153
154let fold_left_with_index f acc =
155 let rec fold_lwi_aux acc = function
156 | [] -> acc
157 | x::xs ->
158 let n = !index in
159 index := !index + 1;
160 fold_lwi_aux (f acc x n) xs
161 in fold_lwi_aux acc
708f4980
C
162
163let numberify trees =
164 let trees =
8babbc8f 165 fold_left_with_index
708f4980
C
166 (function acc -> function xs -> function n ->
167 (List.map (function x -> (n,x)) xs) @ acc)
168 [] trees in
8babbc8f 169 List.fold_left
708f4980
C
170 (function res ->
171 function (n,x) ->
172 let (same,diff) = List.partition (function (ns,xs) -> x = xs) res in
173 match same with
174 [(ns,xs)] -> (n::ns,xs)::diff
175 | _ -> ([n],x)::res)
176 [] trees
177
34e49164
C
178(* ----------------------------------------------------------------------- *)
179(* entry point *)
180
181let process used_after inherited_env l =
34e49164
C
182 let (trees, fresh_envs) =
183 List.split (List.map (process_tree inherited_env) l) in
708f4980 184 let trees = numberify trees in
978fd7e5 185 (trees, collect_used_after used_after fresh_envs l inherited_env)