1 (***********************************************************************)
5 (* Kim Nguyen, LRI UMR8623 *)
6 (* Université Paris-Sud & CNRS *)
8 (* Copyright 2010-2013 Université Paris-Sud and Centre National de la *)
9 (* Recherche Scientifique. All rights reserved. This file is *)
10 (* distributed under the terms of the GNU Lesser General Public *)
11 (* License, with the special exception on linking described in file *)
14 (***********************************************************************)
20 module Make (T : Tree.S) =
23 let int (x : bool) : int = Obj.magic x
24 let kint (x : Tree.NodeKind.t) : int = Obj.magic x
25 let summary tree node parent fc ns =
26 (int (ns != T.nil)) lor
27 ((int (fc != T.nil)) lsl 1) lor
28 ((int (node == T.next_sibling tree parent)) lsl 2) lor
29 ((int (node == T.first_child tree parent)) lsl 3) lor
30 ((kint (T.kind tree node)) lsl 4)
32 let has_next_sibling summary : bool = Obj.magic (summary land 1)
33 let has_first_child summary : bool = Obj.magic ((summary lsr 1) land 1)
34 let is_next_sibling summary : bool = Obj.magic ((summary lsr 2) land 1)
35 let is_first_child summary : bool = Obj.magic ((summary lsr 3) land 1)
36 let kind summary : Tree.NodeKind.t = Obj.magic (summary lsr 4)
39 let eval_form phi node_summary f_set n_set p_set s_set =
42 match Ata.Formula.expr phi with
45 | Or (phi1, phi2) -> loop phi1 || loop phi2
46 | And (phi1, phi2) -> loop phi1 && loop phi2
47 | Atom (a, b) -> b == Ata.(
48 match Atom.node a with
49 Is_first_child -> is_first_child node_summary
50 | Is_next_sibling -> is_next_sibling node_summary
51 | Is k -> k == kind node_summary
52 | Has_first_child -> has_first_child node_summary
53 | Has_next_sibling -> has_next_sibling node_summary
58 | `Next_sibling -> n_set
60 | `Previous_sibling -> p_set
69 let eval_trans_aux trans_list node_summary f_set n_set p_set s_set =
71 TransList.fold (fun trs acc ->
72 let q, _ , phi = Transition.node trs in
73 if eval_form phi node_summary f_set n_set p_set s_set then
78 let eval_trans trans_list node_summary f_set n_set p_set s_set =
82 eval_trans_aux trans_list node_summary f_set n_set p_set old_s
84 if new_s == old_s then old_s else loop new_s
88 let dummy_set = StateSet.singleton State.dummy
91 let () = at_exit (fun () -> Format.eprintf "Cache miss: %i/%i\n%!" !count !total)
93 let eval_trans auto cache set tag node_summary f_set n_set p_set s_set =
95 let i = (tag.QName.id :> int) in
96 let j = node_summary in
97 let k = (f_set.StateSet.id :> int) in
98 let l = (n_set.StateSet.id :> int) in
99 let m = (p_set.StateSet.id :> int) in
100 let n = (s_set.StateSet.id :> int) in
101 let res = Cache.N6.find cache i j k l m n in
102 if res == dummy_set then begin
104 let trans_list = Ata.get_trans auto tag set in
105 let res = eval_trans trans_list node_summary f_set n_set p_set s_set in
106 Cache.N6.add cache i j k l m n res;
112 let auto_run auto tree prev_nodes td_states bu_states exit_states _i =
114 Format.eprintf "Doing a td (with states: %a) and a bu (with states: %a), exit states are: %a @\n@."
115 StateSet.print td_states
116 StateSet.print bu_states
117 StateSet.print exit_states;
118 let td_cache = Cache.N6.create dummy_set in
119 let bu_cache = Cache.N6.create dummy_set in
120 let rec loop res node parent parent_set =
121 if node == T.nil then StateSet.empty else begin
123 if Sequence.is_empty prev_nodes then
124 StateSet.(empty,empty,empty)
126 let set,lset,rset, node' = Sequence.peek prev_nodes in
127 if node == node' then begin
128 ignore (Sequence.pop prev_nodes);
132 StateSet.(empty,empty,empty)
134 let tag = T.tag tree node in
135 let first_child = T.first_child tree node in
136 let next_sibling = T.next_sibling tree node in
137 let node_summary = summary tree node parent first_child next_sibling in
140 eval_trans auto td_cache td_states tag node_summary lset rset parent_set set
142 let fcs = loop res first_child node status1 in
143 let rres = Sequence.create () in
144 let nss = loop rres next_sibling node status1 in
147 eval_trans auto bu_cache bu_states tag node_summary fcs nss parent_set status1
149 let mstates = StateSet.inter status2 exit_states in
151 Format.eprintf "On node %i (tag : %a) status0 = %a, status1 = %a, fcs = %a, nss = %a, par = %a, status2 = %a, mstates = %a@\n@."
152 (T.preorder tree node)
155 StateSet.print status1
158 StateSet.print parent_set
159 StateSet.print status2
160 StateSet.print mstates;
162 if mstates != StateSet.empty then
163 Sequence.push_front (mstates,
164 StateSet.inter exit_states fcs,
165 StateSet.inter exit_states nss, node) res;
166 Sequence.append res rres;
170 let res = Sequence.create () in
171 ignore (loop res (T.root tree) T.nil StateSet.empty);
172 if false then Format.eprintf "Finished pass: %i @\n-----------------------@\n@." _i;
177 let prepare_run auto l =
178 let res = Sequence.create () in
179 let start = Ata.get_starting_states auto in
180 Sequence.iter (fun n -> Sequence.push_back (start, StateSet.empty, StateSet.empty, n) res) l;
184 let main_eval auto tree nodes =
185 let s_nodes = prepare_run auto nodes in
187 let ranked_states = Ata.get_states_by_rank auto in
188 let acc = ref s_nodes in
189 let max_rank = Ata.get_max_rank auto in
190 for i = 0 to max_rank do
192 let { td; bu; exit } = ranked_states.(i) in
193 acc := auto_run auto tree !acc td bu exit i;
195 Format.eprintf "Intermediate result is: @\n";
196 Sequence.iter (fun (s,_,_, n) ->
197 Format.eprintf "{%a, %i (%a)} "
200 QName.print (T.tag tree n)) !acc;
201 Format.eprintf "@\n@.";
207 let eval auto tree nodes =
208 let res = main_eval auto tree nodes in
209 let r = Sequence.create () in
210 Sequence.iter (fun (_,_,_, n) -> Sequence.push_back n r) res;
213 let full_eval auto tree nodes =
214 let res = main_eval auto tree nodes in
215 let dummy = Sequence.create () in
216 let cache = Cache.N1.create dummy in
217 Sequence.iter (fun (set, _, _, n) ->
218 StateSet.iter (fun q ->
219 let qres = Cache.N1.find cache q in
221 if qres == dummy then begin
222 let s = Sequence.create () in
223 Cache.N1.add cache q s;
228 Sequence.push_back n qres) set )
230 let l = StateSet.fold (fun q acc ->
231 let res = Cache.N1.find cache q in
232 (q, res) :: acc) (Ata.get_selecting_states auto) []