Release coccinelle-0.2.3rc1
[bpt/coccinelle.git] / ctl / wrapper_ctl.ml
CommitLineData
5636bb2c
C
1(*
2 * Copyright 2005-2010, 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
9f8e26f4 23(*
ae4735db 24 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
9f8e26f4
C
25 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
26 * This file is part of Coccinelle.
27 *
28 * Coccinelle is free software: you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation, according to version 2 of the License.
31 *
32 * Coccinelle is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
39 *
40 * The authors reserve the right to distribute this or future versions of
41 * Coccinelle under other licenses.
42 *)
43
44
34e49164
C
45(* **********************************************************************
46 *
47 * Wrapping for FUNCTORS and MODULES
34e49164 48 *
ae4735db
C
49 *
50 * $Id: wrapper_ctl.ml,v 1.68 2010/01/28 14:23:46 npalix Exp $
34e49164
C
51 *
52 * **********************************************************************)
53
54type info = int
55
ae4735db 56type ('pred, 'mvar) wrapped_ctl =
34e49164
C
57 ('pred * 'mvar Ast_ctl.modif, 'mvar, info) Ast_ctl.generic_ctl
58
ae4735db 59type ('value, 'pred) wrapped_binding =
34e49164
C
60 | ClassicVal of 'value
61 | PredVal of 'pred Ast_ctl.modif
62
63type ('pred,'state,'mvar,'value) labelfunc =
ae4735db 64 'pred ->
34e49164
C
65 ('state * ('pred * ('mvar, 'value) Ast_ctl.generic_substitution)) list
66
67(* pad: what is 'wit ? *)
68type ('pred,'state,'mvar,'value,'wit) wrapped_labelfunc =
ae4735db
C
69 ('pred * 'mvar Ast_ctl.modif) ->
70 ('state *
34e49164
C
71 ('mvar,('value,'pred) wrapped_binding) Ast_ctl.generic_substitution *
72 'wit
73 ) list
74
75(* ********************************************************************** *)
76(* Module type: CTL_ENGINE_BIS (wrapper for CTL_ENGINE) *)
77(* ********************************************************************** *)
78
79(* This module must convert the labelling function passed as parameter, by
80 using convert_label. Then create a SUBST2 module handling the
81 wrapped_binding. Then it can instantiates the generic CTL_ENGINE
82 module. Call sat. And then process the witness tree to remove all that
83 is not revelevant for the transformation phase.
84*)
85
86module CTL_ENGINE_BIS =
87 functor (SUB : Ctl_engine.SUBST) ->
88 functor (G : Ctl_engine.GRAPH) ->
89 functor(P : Ctl_engine.PREDICATE) ->
90struct
91
92 exception TODO_CTL of string (* implementation still not quite done so... *)
93 exception NEVER_CTL of string (* Some things should never happen *)
94
95 module A = Ast_ctl
96
97 type predicate = P.t
98 module WRAPPER_ENV =
99 struct
100 type mvar = SUB.mvar
101 type value = (SUB.value,predicate) wrapped_binding
102 let eq_mvar = SUB.eq_mvar
ae4735db 103 let eq_val wv1 wv2 =
34e49164
C
104 match (wv1,wv2) with
105 | (ClassicVal(v1),ClassicVal(v2)) -> SUB.eq_val v1 v2
106 | (PredVal(v1),PredVal(v2)) -> v1 = v2 (* FIX ME: ok? *)
107 | _ -> false
ae4735db 108 let merge_val wv1 wv2 =
34e49164
C
109 match (wv1,wv2) with
110 | (ClassicVal(v1),ClassicVal(v2)) -> ClassicVal(SUB.merge_val v1 v2)
111 | _ -> wv1 (* FIX ME: ok? *)
112
113
114 let print_mvar x = SUB.print_mvar x
ae4735db 115 let print_value x =
34e49164
C
116 match x with
117 ClassicVal v -> SUB.print_value v
118 | PredVal(A.Modif v) -> P.print_predicate v
119 | PredVal(A.UnModif v) -> P.print_predicate v
120 | PredVal(A.Control) -> Format.print_string "no value"
121 end
122
ae4735db
C
123 module WRAPPER_PRED =
124 struct
34e49164 125 type t = P.t * SUB.mvar Ast_ctl.modif
ae4735db 126 let print_predicate (pred, modif) =
34e49164
C
127 begin
128 P.print_predicate pred;
129 (match modif with
130 Ast_ctl.Modif x | Ast_ctl.UnModif x ->
131 Format.print_string " with <modifTODO>"
132 | Ast_ctl.Control -> ())
133 end
134 end
135
136 (* Instantiate a wrapped version of CTL_ENGINE *)
137 module WRAPPER_ENGINE =
138 Ctl_engine.CTL_ENGINE (WRAPPER_ENV) (G) (WRAPPER_PRED)
139
140 (* Wrap a label function *)
ae4735db
C
141 let (wrap_label: ('pred,'state,'mvar,'value) labelfunc ->
142 ('pred,'state,'mvar,'value,'wit) wrapped_labelfunc) =
34e49164
C
143 fun oldlabelfunc ->
144 fun (p, predvar) ->
145
ae4735db 146 let penv p' =
34e49164
C
147 match predvar with
148 | A.Modif(x) -> [A.Subst(x,PredVal(A.Modif(p')))]
149 | A.UnModif(x) -> [A.Subst(x,PredVal(A.UnModif(p')))]
150 | A.Control -> [] in
151
152 let conv_sub sub =
153 match sub with
154 | A.Subst(x,v) -> A.Subst(x,ClassicVal(v))
155 | A.NegSubst(x,v) -> A.NegSubst(x,ClassicVal(v)) in
156
ae4735db
C
157 let conv_trip (s,(p',env)) =
158 (s,penv p' @ (List.map conv_sub env),[](*pad: ?*))
34e49164
C
159 in
160 List.map conv_trip (oldlabelfunc p)
161
162 (* ---------------------------------------------------------------- *)
163
164 (* FIX ME: what about negative witnesses and negative substitutions *)
165 let unwrap_wits modifonly wits =
166 let mkth th =
167 Common.map_filter
168 (function A.Subst(x,ClassicVal(v)) -> Some (x,v) | _ -> None)
169 th in
170 let rec loop neg acc = function
171 A.Wit(st,[A.Subst(x,PredVal(A.Modif(v)))],anno,wit) ->
172 (match wit with
173 [] -> [(st,acc,v)]
174 | _ -> raise (NEVER_CTL "predvar tree should have no children"))
175 | A.Wit(st,[A.Subst(x,PredVal(A.UnModif(v)))],anno,wit)
176 when not modifonly or !Flag.track_iso_usage ->
177 (match wit with
178 [] -> [(st,acc,v)]
179 | _ -> raise (NEVER_CTL "predvar tree should have no children"))
180 | A.Wit(st,th,anno,wit) ->
181 List.concat (List.map (loop neg ((mkth th) @ acc)) wit)
182 | A.NegWit(_) -> [] (* why not failure? *) in
183 List.concat (List.map (function wit -> loop false [] wit) wits)
184 ;;
185
186(*
187 (* a match can return many trees, but within each tree, there has to be
188 at most one value for each variable that is in the used_after list *)
189 let collect_used_after used_after envs =
190 let print_var var = SUB.print_mvar var; Format.print_flush() in
191 List.concat
192 (List.map
193 (function used_after_var ->
194 let vl =
195 List.fold_left
196 (function rest ->
197 function env ->
198 try
199 let vl = List.assoc used_after_var env in
200 match rest with
201 None -> Some vl
202 | Some old_vl when SUB.eq_val vl old_vl -> rest
203 | Some old_vl -> print_var used_after_var;
204 Format.print_newline();
205 SUB.print_value old_vl;
206 Format.print_newline();
207 SUB.print_value vl;
208 Format.print_newline();
209 failwith "incompatible values"
210 with Not_found -> rest)
211 None envs in
212 match vl with
213 None -> []
214 | Some vl -> [(used_after_var, vl)])
215 used_after)
216*)
217
218 (* a match can return many trees, but within each tree, there has to be
219 at most one value for each variable that is in the used_after list *)
220 (* actually, this should always be the case, because these variables
221 should be quantified at the top level. so the more complicated
222 definition above should not be needed. *)
223 let collect_used_after used_after envs =
224 List.concat
225 (List.map
226 (function used_after_var ->
227 let vl =
228 List.fold_left
229 (function rest ->
230 function env ->
231 try
232 let vl = List.assoc used_after_var env in
233 if List.exists (function x -> SUB.eq_val x vl) rest
234 then rest
235 else vl::rest
236 with Not_found -> rest)
237 [] envs in
238 List.map (function x -> (used_after_var, x)) vl)
239 used_after)
240
241 (* ----------------------------------------------------- *)
242
243 (* The wrapper for sat from the CTL_ENGINE *)
244 let satbis_noclean (grp,lab,states) (phi,reqopt) :
245 ('pred,'anno) WRAPPER_ENGINE.triples =
246 WRAPPER_ENGINE.sat (grp,wrap_label lab,states) phi reqopt
ae4735db 247
34e49164
C
248 (* Returns the "cleaned up" result from satbis_noclean *)
249 let (satbis :
250 G.cfg *
251 (predicate,G.node,SUB.mvar,SUB.value) labelfunc *
ae4735db 252 G.node list ->
34e49164
C
253 ((predicate,SUB.mvar) wrapped_ctl *
254 (WRAPPER_PRED.t list list)) ->
255 (WRAPPER_ENV.mvar list * (SUB.mvar * SUB.value) list) ->
256 ((WRAPPER_PRED.t, 'a) WRAPPER_ENGINE.triples *
257 ((G.node * (SUB.mvar * SUB.value) list * predicate)
258 list list *
259 bool *
260 (WRAPPER_ENV.mvar * SUB.value) list list))) =
261 fun m phi (used_after, binding) ->
262 let noclean = satbis_noclean m phi in
263 let witness_trees = List.map (fun (_,_,w) -> w) noclean in
264 let res = List.map (unwrap_wits true) witness_trees in
265 let new_bindings =
266 List.map
267 (function bindings_per_witness_tree ->
268 (List.map (function (_,env,_) -> env) bindings_per_witness_tree))
269 (List.map (unwrap_wits false) witness_trees) in
270 (noclean,
271 (res,not(noclean = []),
272 (* throw in the old binding. By construction it doesn't conflict
273 with any of the new things, and it is useful if there are no new
274 things. *)
275 (List.map (collect_used_after used_after) new_bindings)))
276
277let print_bench _ = WRAPPER_ENGINE.print_bench()
278
279(* END OF MODULE: CTL_ENGINE_BIS *)
280end