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 is_first is_next fc ns =
26 (int (ns != T.nil)) lor
27 ((int (fc != T.nil)) lsl 1) lor
28 ((int is_next) lsl 2) lor
29 ((int is_first) 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)
38 let dummy_set = StateSet.singleton State.dummy
39 let dummy_trans_list =
41 (Transition.make (State.dummy, QNameSet.empty, Formula.false_))
50 trans_cache : Ata.TransList.t Cache.N2.t;
51 td_cache : StateSet.t Cache.N6.t;
52 bu_cache : StateSet.t Cache.N6.t;
53 mark_cache : (StateSet.t*StateSet.t*StateSet.t) Cache.N4.t;
60 trans_cache = Cache.N2.create dummy_trans_list;
61 td_cache = Cache.N6.create dummy_set;
62 bu_cache = Cache.N6.create dummy_set;
63 mark_cache = Cache.N4.create (dummy_set,dummy_set,dummy_set);
68 let eval_form phi node_summary f_set n_set p_set s_set =
71 match Ata.Formula.expr phi with
74 | Or (phi1, phi2) -> loop phi1 || loop phi2
75 | And (phi1, phi2) -> loop phi1 && loop phi2
76 | Atom (a, b) -> b == Ata.(
77 match Atom.node a with
78 Is_first_child -> is_first_child node_summary
79 | Is_next_sibling -> is_next_sibling node_summary
80 | Is k -> k == kind node_summary
81 | Has_first_child -> has_first_child node_summary
82 | Has_next_sibling -> has_next_sibling node_summary
87 | `Next_sibling -> n_set
89 | `Previous_sibling -> p_set
98 let eval_trans_aux trans_list node_summary f_set n_set p_set s_set =
100 TransList.fold (fun trs acc ->
101 let q, _ , phi = Transition.node trs in
102 if eval_form phi node_summary f_set n_set p_set s_set then
105 acc) trans_list s_set
107 let eval_trans trans_list node_summary f_set n_set p_set s_set =
111 eval_trans_aux trans_list node_summary f_set n_set p_set old_s
113 if new_s == old_s then old_s else loop new_s
117 let get_trans run tag set =
118 let i = (tag.QName.id :> int) in
119 let j = (set.StateSet.id :> int) in
120 let res = Cache.N2.find run.Run.trans_cache i j in
121 if res == dummy_trans_list then begin
122 let res = Ata.get_trans run.Run.auto tag set in
123 Cache.N2.add run.Run.trans_cache i j res;
129 let eval_trans run cache set tag node_summary f_set n_set p_set s_set =
130 let i = node_summary in
131 let j = (tag.QName.id :> int) in
132 let k = (f_set.StateSet.id :> int) in
133 let l = (n_set.StateSet.id :> int) in
134 let m = (p_set.StateSet.id :> int) in
135 let n = (s_set.StateSet.id :> int) in
136 let res = Cache.N6.find cache i j k l m n in
137 if res == dummy_set then begin
138 let trans_list = get_trans run tag set in
139 let res = eval_trans trans_list node_summary f_set n_set p_set s_set in
140 Cache.N6.add cache i j k l m n res;
145 let auto_run run tree prev_nodes td_states bu_states exit_states _i =
146 let exit_id = (exit_states.StateSet.id :> int) in
147 let empty_sets = StateSet.(empty,empty,empty) in
149 let mark_node front res node set f_set n_set =
150 let i = (set.StateSet.id :> int) in
151 let j = (f_set.StateSet.id :> int) in
152 let k = (n_set.StateSet.id :> int) in
153 let (mstates, _, _) as block =
154 Cache.N4.find run.Run.mark_cache exit_id i j k
157 let mstates, ll, rr =
158 if mstates == dummy_set then begin
159 let r1 = StateSet.inter set exit_states in
160 let r2 = StateSet.inter f_set exit_states in
161 let r3 = StateSet.inter n_set exit_states in
163 Cache.N4.add run.Run.mark_cache exit_id i j k r;
168 if mstates != StateSet.empty then
169 let block = mstates, ll, rr, node in
170 if front then Sequence.push_front block res
171 else Sequence.push_back block res
173 let rec loop res node is_first is_next parent_set =
174 if node == T.nil then StateSet.empty else begin
176 if Sequence.is_empty prev_nodes then
179 let set,lset,rset, node' = Sequence.peek prev_nodes in
180 if node == node' then begin
181 ignore (Sequence.pop prev_nodes);
187 let tag = T.tag tree node in
188 let first_child = T.first_child tree node in
189 let next_sibling = T.next_sibling tree node in
191 summary tree node is_first is_next first_child next_sibling
194 eval_trans run run.Run.td_cache td_states tag node_summary lset rset parent_set set
196 let fcs = loop res first_child true false status1 in
197 let rres = Sequence.create () in
198 let nss = loop rres next_sibling false true status1 in
199 if bu_states == StateSet.empty then (* tail call *) begin
200 mark_node true res node status1 fcs StateSet.empty;
201 Sequence.append res rres;
206 eval_trans run run.Run.bu_cache bu_states tag node_summary fcs nss parent_set status1
208 if status2 != StateSet.empty then
209 mark_node true res node status2 fcs nss;
210 Sequence.append res rres;
215 let res = Sequence.create () in
216 ignore (loop res (T.root tree) false false StateSet.empty);
221 let prepare_run auto l =
222 let res = Sequence.create () in
223 let start = Ata.get_starting_states auto in
224 Sequence.iter (fun n -> Sequence.push_back (start, StateSet.empty, StateSet.empty, n) res) l;
228 let t1 = Unix.gettimeofday () in
230 let t2 = Unix.gettimeofday () in
231 let time = (t2 -. t1) *. 1000. in
232 Logger.msg `STATS "%s: %fms" msg time;
236 let main_eval auto tree nodes =
237 let s_nodes = prepare_run auto nodes in
238 let ranked_states = Ata.get_states_by_rank auto in
239 let acc = ref s_nodes in
240 let max_rank = Ata.get_max_rank auto in
241 let run = Run.create auto in
242 for i = 0 to max_rank do
244 let { td; bu; exit } = ranked_states.(i) in
246 acc := auto_run run tree !acc td bu exit i;
251 let eval auto tree nodes =
252 let res = main_eval auto tree nodes in
253 let r = Sequence.create () in
254 Sequence.iter (fun (_,_,_, n) -> Sequence.push_back n r) res;
258 let full_eval auto tree nodes =
259 let res = main_eval auto tree nodes in
260 let dummy = Sequence.create () in
261 let cache = Cache.N1.create dummy in
262 Sequence.iter (fun (set, _, _, n) ->
263 StateSet.iter (fun q ->
264 let qres = Cache.N1.find cache q in
266 if qres == dummy then begin
267 let s = Sequence.create () in
268 Cache.N1.add cache q s;
273 Sequence.push_back n qres) set )
275 let l = StateSet.fold (fun q acc ->
276 let res = Cache.N1.find cache q in
277 (q, res) :: acc) (Ata.get_selecting_states auto) []