+ module SList = struct
+ include Hlist.Make (StateSet)
+ type data = t node
+ let make _ = failwith "make"
+ end
+
+
+
+IFDEF DEBUG
+THEN
+ module IntSet = Set.Make(struct type t = int let compare = (-) end)
+INCLUDE "html_trace.ml"
+
+END
+ let mk_fun f s = D_IGNORE_(register_funname f s,f)
+ let mk_app_fun f arg s = let g = f arg in
+ D_IGNORE_(register_funname g ((get_funname f) ^ " " ^ s), g)
+
+ let string_of_ts tags = (Ptset.Int.fold (fun t a -> a ^ " " ^ (Tag.to_string t) ) tags "{")^ " }"
+
+
+ let choose_jump tagset qtags1 qtagsn a f_nil f_t1 f_s1 f_tn f_sn f_notext f_maytext =
+ let tags1,hastext1,fin1 = inter_text tagset (tags a qtags1) in
+ let tagsn,hastextn,finn = inter_text tagset (tags a qtagsn) in
+ (*if (hastext1||hastextn) then (`ANY,f_text) (* jumping to text nodes doesn't work really well *)
+ else*)
+ if (Ptset.Int.is_empty tags1) && (Ptset.Int.is_empty tagsn) then (`NIL,f_nil)
+ else if (Ptset.Int.is_empty tagsn) then
+ if (Ptset.Int.is_singleton tags1)
+ then (* TaggedChild/Sibling *)
+ let tag = (Ptset.Int.choose tags1) in (`TAG(tag),mk_app_fun f_t1 tag (Tag.to_string tag))
+ else (* SelectChild/Sibling *)
+ (`ANY,mk_app_fun f_s1 tags1 (string_of_ts tags1))
+ else if (Ptset.Int.is_empty tags1) then
+ if (Ptset.Int.is_singleton tagsn)
+ then (* TaggedDesc/Following *)
+ let tag = (Ptset.Int.choose tagsn) in (`TAG(tag),mk_app_fun f_tn tag (Tag.to_string tag))
+ else (* SelectDesc/Following *)
+ (`ANY,mk_app_fun f_sn tagsn (string_of_ts tagsn))
+ else if (hastext1||hastextn) then (`ANY,f_maytext)
+ else (`ANY,f_notext)
+
+ let choose_jump_down tree a b c d =
+ choose_jump a b c d
+ (mk_fun (fun _ -> Tree.nil) "Tree.mk_nil")
+ (mk_fun (Tree.tagged_child tree) "Tree.tagged_child")
+ (mk_fun (Tree.select_child tree) "Tree.select_child")
+ (mk_fun (Tree.tagged_desc tree) "Tree.tagged_desc")
+ (mk_fun (Tree.select_desc tree) "Tree.select_desc")
+ (mk_fun (Tree.first_element tree) "Tree.first_element")
+ (mk_fun (Tree.first_child tree) "Tree.first_child")
+
+ let choose_jump_next tree a b c d =
+ choose_jump a b c d
+ (mk_fun (fun _ _ -> Tree.nil) "Tree.mk_nil2")
+ (mk_fun (Tree.tagged_sibling_ctx tree) "Tree.tagged_sibling_ctx")
+ (mk_fun (Tree.select_sibling_ctx tree) "Tree.select_sibling_ctx")
+ (mk_fun (Tree.tagged_foll_ctx tree) "Tree.tagged_foll_ctx")
+ (mk_fun (Tree.select_foll_ctx tree) "Tree.select_foll_ctx")
+ (mk_fun (Tree.next_element_ctx tree) "Tree.node_element_ctx")
+ (mk_fun (Tree.next_sibling_ctx tree) "Tree.node_sibling_ctx")
+
+
+ module SetTagKey =
+ struct
+ type t = Tag.t*SList.t
+ let equal (t1,s1) (t2,s2) = t1 == t2 && s1 == s2
+ let hash (t,s) = HASHINT2(t,SList.uid s)
+ end
+
+ module CachedTransTable = Hashtbl.Make(SetTagKey)
+ let td_trans = CachedTransTable.create 4093
+
+
+ let empty_size n =
+ let rec loop acc = function 0 -> acc
+ | n -> loop (SList.cons StateSet.empty acc) (n-1)
+ in loop SList.nil n
+
+ let merge rb rb1 rb2 mark t res1 res2 =
+ if rb then
+ let res1 = if rb1 then res1 else RS.empty
+ and res2 = if rb2 then res2 else RS.empty
+ in
+ if mark then RS.cons t (RS.concat res1 res2)
+ else RS.concat res1 res2
+ else RS.empty
+
+
+ let top_down ?(noright=false) a tree t slist ctx slot_size =
+ let pempty = empty_size slot_size in
+ (* evaluation starts from the right so we put sl1,res1 at the end *)
+ let eval_fold2_slist fll t (sl2,res2) (sl1,res1) =
+ let res = Array.copy res1 in
+ let rec fold l1 l2 fll i aq =
+ match SList.node l1,SList.node l2, fll with
+ | SList.Cons(s1,ll1),
+ SList.Cons(s2,ll2),
+ fl::fll ->
+ let r',flags = eval_formlist s1 s2 fl in
+ let _ = res.(i) <- RS.merge flags t res1.(i) res2.(i)
+ in
+ fold ll1 ll2 fll (i+1) (SList.cons r' aq)
+
+ | SList.Nil, SList.Nil,[] -> aq,res
+ | _ -> assert false
+ in
+ fold sl1 sl2 fll 0 SList.nil
+ in
+ let null_result() = (pempty,Array.make slot_size RS.empty) in
+
+ let rec loop t slist ctx =
+ if t == Tree.nil then null_result() else get_trans t slist (Tree.tag tree t) ctx
+
+ and loop_tag tag t slist ctx =
+ if t == Tree.nil then null_result() else get_trans t slist tag ctx
+ and loop_no_right t slist ctx =
+ if t == Tree.nil then null_result() else get_trans ~noright:true t slist (Tree.tag tree t) ctx
+ and get_trans ?(noright=false) t slist tag ctx =
+ let cont =
+ try
+ CachedTransTable.find td_trans (tag,slist)
+ with
+ | Not_found ->
+ let fl_list,llist,rlist,ca,da,sa,fa =
+ SList.fold
+ (fun set (fll_acc,lllacc,rllacc,ca,da,sa,fa) -> (* For each set *)
+ let fl,ll,rr,ca,da,sa,fa =
+ StateSet.fold
+ (fun q acc ->
+ List.fold_left
+ (fun ((fl_acc,ll_acc,rl_acc,c_acc,d_acc,s_acc,f_acc) as acc)
+ (ts,t) ->
+ if (TagSet.mem tag ts)
+ then
+ let _,_,f,_ = Transition.node t in
+ let (child,desc,below),(sibl,foll,after) = Formula.st f in
+ (Formlist.cons t fl_acc,
+ StateSet.union ll_acc below,
+ StateSet.union rl_acc after,
+ StateSet.union child c_acc,
+ StateSet.union desc d_acc,
+ StateSet.union sibl s_acc,
+ StateSet.union foll f_acc)
+ else acc ) acc (
+ try Hashtbl.find a.trans q
+ with
+ Not_found -> Printf.eprintf "Looking for state %i, doesn't exist!!!\n%!"
+ q;[]
+ )
+
+ ) set (Formlist.nil,StateSet.empty,StateSet.empty,ca,da,sa,fa)
+ in fl::fll_acc, (SList.cons ll lllacc), (SList.cons rr rllacc),ca,da,sa,fa)
+ slist ([],SList.nil,SList.nil,StateSet.empty,StateSet.empty,StateSet.empty,StateSet.empty)
+ in
+ (* Logic to chose the first and next function *)
+ let _,tags_below,_,tags_after = Tree.tags tree tag in
+ let f_kind,first = choose_jump_down tree tags_below ca da a
+ and n_kind,next = if noright then (`NIL, fun _ _ -> Tree.nil )
+ else choose_jump_next tree tags_after sa fa a in
+ let empty_res = null_result() in
+ let cont =
+ match f_kind,n_kind with
+ | `NIL,`NIL ->
+ (fun _ _ -> eval_fold2_slist fl_list t empty_res empty_res )
+ | _,`NIL -> (
+ match f_kind with
+ |`TAG(tag) ->
+ (fun t _ -> eval_fold2_slist fl_list t empty_res
+ (loop_tag tag (first t) llist t))
+ | `ANY ->
+ (fun t _ -> eval_fold2_slist fl_list t empty_res
+ (loop (first t) llist t))
+ | _ -> assert false)
+
+ | `NIL,_ -> (
+ match n_kind with
+ |`TAG(tag) ->
+ (fun t ctx -> eval_fold2_slist fl_list t
+ (loop_tag tag (next t ctx) rlist ctx) empty_res)
+
+ | `ANY ->
+ (fun t ctx -> eval_fold2_slist fl_list t
+ (loop (next t ctx) rlist ctx) empty_res)
+
+ | _ -> assert false)
+
+ | `TAG(tag1),`TAG(tag2) ->
+ (fun t ctx -> eval_fold2_slist fl_list t
+ (loop (next t ctx) rlist ctx)
+ (loop (first t) llist t))
+
+ | `TAG(tag),`ANY ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t
+ (loop (next t ctx) rlist ctx)
+ (loop_tag tag (first t) llist t))
+ | `ANY,`TAG(tag) ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t
+ (loop_tag tag (next t ctx) rlist ctx)
+ (loop (first t) llist t) )
+ | `ANY,`ANY ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t
+ (loop (next t ctx) rlist ctx)
+ (loop (first t) llist t) )
+ | _ -> assert false
+ in
+ let cont = D_IF_( (fun t ctx ->
+ let a,b = cont t ctx in
+ register_trace t (slist,a,fl_list,first,next,ctx);
+ (a,b)
+ ) ,cont)
+ in
+ (CachedTransTable.add td_trans (tag,slist) cont;cont)
+ in cont t ctx
+
+ in
+ (if noright then loop_no_right else loop) t slist ctx
+
+
+ let run_top_down a tree =
+ let init = SList.cons a.init SList.nil in
+ let _,res = top_down a tree Tree.root init Tree.root 1
+ in
+ D_IGNORE_(
+ output_trace a tree root "trace.html"
+ (RS.fold (fun t a -> IntSet.add (Tree.id t) a) res.(0) IntSet.empty),
+ res.(0))
+ ;;
+
+ module Configuration =
+ struct
+ module Ptss = Set.Make(StateSet)
+ module IMap = Map.Make(StateSet)
+ type t = { hash : int;
+ sets : Ptss.t;
+ results : RS.t IMap.t }
+ let empty = { hash = 0;
+ sets = Ptss.empty;
+ results = IMap.empty;
+ }
+ let is_empty c = Ptss.is_empty c.sets
+ let add c s r =
+ if Ptss.mem s c.sets then
+ { c with results = IMap.add s (RS.concat r (IMap.find s c.results)) c.results}
+ else
+ { hash = HASHINT2(c.hash,Ptset.Int.uid s);
+ sets = Ptss.add s c.sets;
+ results = IMap.add s r c.results
+ }
+
+ let pr fmt c = Format.fprintf fmt "{";
+ Ptss.iter (fun s -> StateSet.print fmt s;
+ Format.fprintf fmt " ") c.sets;
+ Format.fprintf fmt "}\n%!";
+ IMap.iter (fun k d ->
+ StateSet.print fmt k;
+ Format.fprintf fmt "-> %i\n" (RS.length d)) c.results;
+ Format.fprintf fmt "\n%!"
+
+ let merge c1 c2 =
+ let acc1 = IMap.fold (fun s r acc ->
+ IMap.add s
+ (try
+ RS.concat r (IMap.find s acc)
+ with
+ | Not_found -> r) acc) c1.results IMap.empty