2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
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.
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.
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.
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/>.
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
27 #
0 "./wrapper_ctl.ml"
28 (* **********************************************************************
30 * Wrapping for FUNCTORS and MODULES
35 * **********************************************************************)
39 type ('pred
, 'mvar
) wrapped_ctl
=
40 ('pred
* 'mvar
Ast_ctl.modif
, 'mvar
, info
) Ast_ctl.generic_ctl
42 type ('
value, 'pred
) wrapped_binding
=
43 | ClassicVal
of '
value
44 | PredVal
of 'pred
Ast_ctl.modif
46 type ('pred
,'state
,'mvar
,'
value) labelfunc
=
48 ('state
* ('pred
* ('mvar
, '
value) Ast_ctl.generic_substitution
)) list
50 (* pad: what is 'wit ? *)
51 type ('pred
,'state
,'mvar
,'
value,'wit
) wrapped_labelfunc
=
52 ('pred
* 'mvar
Ast_ctl.modif
) ->
54 ('mvar
,('
value,'pred
) wrapped_binding
) Ast_ctl.generic_substitution
*
58 (* ********************************************************************** *)
59 (* Module type: CTL_ENGINE_BIS (wrapper for CTL_ENGINE) *)
60 (* ********************************************************************** *)
62 (* This module must convert the labelling function passed as parameter, by
63 using convert_label. Then create a SUBST2 module handling the
64 wrapped_binding. Then it can instantiates the generic CTL_ENGINE
65 module. Call sat. And then process the witness tree to remove all that
66 is not revelevant for the transformation phase.
69 module CTL_ENGINE_BIS
=
70 functor (SUB
: Ctl_engine.SUBST
) ->
71 functor (G
: Ctl_engine.GRAPH
) ->
72 functor(P
: Ctl_engine.PREDICATE
) ->
75 exception TODO_CTL
of string (* implementation still not quite done so... *)
76 exception NEVER_CTL
of string (* Some things should never happen *)
84 type value = (SUB.value,predicate
) wrapped_binding
85 let eq_mvar = SUB.eq_mvar
88 | (ClassicVal
(v1
),ClassicVal
(v2
)) -> SUB.eq_val v1 v2
89 | (PredVal
(v1
),PredVal
(v2
)) -> v1
= v2
(* FIX ME: ok? *)
91 let merge_val wv1 wv2
=
93 | (ClassicVal
(v1
),ClassicVal
(v2
)) -> ClassicVal
(SUB.merge_val v1 v2
)
94 | _
-> wv1
(* FIX ME: ok? *)
97 let print_mvar x
= SUB.print_mvar x
100 ClassicVal v
-> SUB.print_value v
101 | PredVal
(A.Modif v
) -> P.print_predicate v
102 | PredVal
(A.UnModif v
) -> P.print_predicate v
103 | PredVal
(A.Control
) -> Format.print_string
"no value"
106 module WRAPPER_PRED
=
108 type t
= P.t
* SUB.mvar
Ast_ctl.modif
109 let print_predicate (pred
, modif
) =
111 P.print_predicate pred
;
113 Ast_ctl.Modif x
| Ast_ctl.UnModif x
->
114 Format.print_string
" with <modifTODO>"
115 | Ast_ctl.Control
-> ())
119 (* Instantiate a wrapped version of CTL_ENGINE *)
120 module WRAPPER_ENGINE
=
121 Ctl_engine.CTL_ENGINE
(WRAPPER_ENV
) (G
) (WRAPPER_PRED
)
123 (* Wrap a label function *)
124 let (wrap_label
: ('pred
,'state
,'mvar
,'
value) labelfunc
->
125 ('pred
,'state
,'mvar
,'
value,'wit
) wrapped_labelfunc
) =
131 | A.Modif
(x
) -> [A.Subst
(x
,PredVal
(A.Modif
(p'
)))]
132 | A.UnModif
(x
) -> [A.Subst
(x
,PredVal
(A.UnModif
(p'
)))]
137 | A.Subst
(x
,v
) -> A.Subst
(x
,ClassicVal
(v
))
138 | A.NegSubst
(x
,v
) -> A.NegSubst
(x
,ClassicVal
(v
)) in
140 let conv_trip (s
,(p'
,env
)) =
141 (s
,penv p'
@ (List.map
conv_sub env
),[](*pad: ?*))
143 List.map
conv_trip (oldlabelfunc p
)
145 (* ---------------------------------------------------------------- *)
147 (* FIX ME: what about negative witnesses and negative substitutions *)
148 let unwrap_wits modifonly wits
=
151 (function A.Subst
(x
,ClassicVal
(v
)) -> Some
(x
,v
) | _
-> None
)
153 let rec loop neg acc
= function
154 A.Wit
(st
,[A.Subst
(x
,PredVal
(A.Modif
(v
)))],anno
,wit
) ->
157 | _
-> raise
(NEVER_CTL
"predvar tree should have no children"))
158 | A.Wit
(st
,[A.Subst
(x
,PredVal
(A.UnModif
(v
)))],anno
,wit
)
159 when not modifonly
or !Flag.track_iso_usage
->
162 | _
-> raise
(NEVER_CTL
"predvar tree should have no children"))
163 | A.Wit
(st
,th
,anno
,wit
) ->
164 List.concat
(List.map
(loop neg
((mkth th
) @ acc
)) wit
)
165 | A.NegWit
(_
) -> [] (* why not failure? *) in
166 List.concat
(List.map
(function wit
-> loop false [] wit
) wits
)
170 (* a match can return many trees, but within each tree, there has to be
171 at most one value for each variable that is in the used_after list *)
172 let collect_used_after used_after envs
=
173 let print_var var
= SUB.print_mvar var
; Format.print_flush
() in
176 (function used_after_var
->
182 let vl = List.assoc used_after_var env
in
185 | Some old_vl
when SUB.eq_val vl old_vl
-> rest
186 | Some old_vl
-> print_var used_after_var
;
187 Format.print_newline
();
188 SUB.print_value old_vl
;
189 Format.print_newline
();
191 Format.print_newline
();
192 failwith
"incompatible values"
193 with Not_found
-> rest
)
197 | Some
vl -> [(used_after_var
, vl)])
201 (* a match can return many trees, but within each tree, there has to be
202 at most one value for each variable that is in the used_after list *)
203 (* actually, this should always be the case, because these variables
204 should be quantified at the top level. so the more complicated
205 definition above should not be needed. *)
206 let collect_used_after used_after envs
=
209 (function used_after_var
->
215 let vl = List.assoc used_after_var env
in
216 if List.exists
(function x
-> SUB.eq_val x
vl) rest
219 with Not_found
-> rest
)
221 List.map
(function x
-> (used_after_var
, x
)) vl)
224 (* ----------------------------------------------------- *)
226 (* The wrapper for sat from the CTL_ENGINE *)
227 let satbis_noclean (grp
,lab
,states
) (phi
,reqopt
) :
228 ('pred
,'anno
) WRAPPER_ENGINE.triples
=
229 WRAPPER_ENGINE.sat
(grp
,wrap_label lab
,states
) phi reqopt
231 (* Returns the "cleaned up" result from satbis_noclean *)
234 (predicate
,G.node
,SUB.mvar
,SUB.value) labelfunc
*
236 ((predicate
,SUB.mvar
) wrapped_ctl
*
237 (WRAPPER_PRED.t list list
)) ->
238 (WRAPPER_ENV.mvar list
* (SUB.mvar
* SUB.value) list
) ->
239 ((WRAPPER_PRED.t
, 'a
) WRAPPER_ENGINE.triples
*
240 ((G.node
* (SUB.mvar
* SUB.value) list
* predicate
)
243 (WRAPPER_ENV.mvar
* SUB.value) list list
))) =
244 fun m phi
(used_after
, binding
) ->
245 let noclean = satbis_noclean m phi
in
246 let witness_trees = List.map
(fun (_
,_
,w
) -> w
) noclean in
247 let res = List.map
(unwrap_wits true) witness_trees in
250 (function bindings_per_witness_tree
->
251 (List.map
(function (_
,env
,_
) -> env
) bindings_per_witness_tree
))
252 (List.map
(unwrap_wits false) witness_trees) in
254 (res,not
(noclean = []),
255 (* throw in the old binding. By construction it doesn't conflict
256 with any of the new things, and it is useful if there are no new
258 (List.map
(collect_used_after used_after
) new_bindings)))
260 let print_bench _
= WRAPPER_ENGINE.print_bench()
262 (* END OF MODULE: CTL_ENGINE_BIS *)