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