+ let is_rec a s access =
+ List.exists
+ (fun (_,t) -> let _,_,_,f,_ = Transition.node t in
+ StateSet.mem s ((fun (_,_,x) -> x) (access (Formula.st f)))) (Hashtbl.find a.trans s)
+
+
+ let decide a c_label l_label dir_states dir =
+
+ let l = StateSet.fold
+ (fun s l ->
+ let s_rec = is_rec a s (if dir then fst else snd) in
+ let s_rec = if dir then s_rec else
+ (* right move *)
+ is_rec a s fst
+ in
+ let s_lab = labels a s in
+ let jmp,cc,ll =
+ if (not (TagSet.is_finite s_lab)) then
+ if TagSet.mem Tag.pcdata s_lab then (`ANY,Ptset.Int.empty,Ptset.Int.empty)
+ else (`ANYNOTEXT,Ptset.Int.empty,Ptset.Int.empty)
+ else
+ if s_rec
+ then (`JUMP,Ptset.Int.empty, TagSet.positive
+ (TagSet.cap (TagSet.inj_positive l_label) s_lab))
+ else (`JUMP,TagSet.positive
+ (TagSet.cap (TagSet.inj_positive c_label) s_lab),
+ Ptset.Int.empty )
+ in
+ (if jmp != `ANY
+ && jmp != `ANYNOTEXT
+ && Ptset.Int.is_empty cc
+ && Ptset.Int.is_empty ll
+ then (`NIL,Ptset.Int.empty,Ptset.Int.empty)
+ else (jmp,cc,ll))::l) dir_states []
+ in merge_jump_list l
+
+
+ end
+
+
+
+ let choose_jump (d,cl,ll) f_nil f_t1 f_s1 f_tn f_sn f_s1n f_notext f_maytext =
+ match d with
+ | `NIL -> (`NIL,f_nil)
+ | `ANYNOTEXT -> `ANY,f_notext
+ | `ANY -> `ANY,f_maytext
+ | `JUMP ->
+ if Ptset.Int.is_empty cl then
+ if Ptset.Int.is_singleton ll then
+ let tag = Ptset.Int.choose ll in
+ (`TAG(tag),mk_app_fun f_tn tag (Tag.to_string tag))
+ else
+ (`MANY(ll),mk_app_fun f_sn ll (string_of_ts ll))
+ else if Ptset.Int.is_empty ll then
+ if Ptset.Int.is_singleton cl then
+ let tag = Ptset.Int.choose cl in
+ (`TAG(tag),mk_app_fun f_t1 tag (Tag.to_string tag))
+ else
+ (`MANY(cl),mk_app_fun f_s1 cl (string_of_ts cl))
+ else
+ (`ANY,mk_app_fun2 f_s1n cl ll ((string_of_ts cl) ^ " " ^ (string_of_ts ll)))
+
+ | _ -> assert false
+
+ let choose_jump_down tree d =
+ choose_jump 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 (fun _ _ -> Tree.first_child tree) "[FIRSTCHILD]Tree.select_child_desc")
+ (mk_fun (Tree.first_element tree) "Tree.first_element")
+ (mk_fun (Tree.first_child tree) "Tree.first_child")
+
+ let choose_jump_next tree d =
+ choose_jump 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 (fun _ _ -> Tree.next_sibling_ctx tree) "[NEXTSIBLING]Tree.select_sibling_foll_ctx")
+ (mk_fun (Tree.next_element_ctx tree) "Tree.next_element_ctx")
+ (mk_fun (Tree.next_sibling_ctx tree) "Tree.node_sibling_ctx")
+
+
+ module SListTable = Hashtbl.Make(struct type t = SList.t
+ let equal = (==)
+ let hash t = t.SList.Node.id
+ end)
+ module TransCache =
+ struct
+ type 'a t = Obj.t array SListTable.t
+ let create n = SListTable.create n
+ let dummy = Obj.repr (fun _ -> assert false)
+ let find (h :'a t) tag slist : 'a =
+ let tab =
+ try
+ SListTable.find h slist
+ with
+ Not_found ->
+ SListTable.add h slist (Array.create 10000 dummy);
+ raise Not_found
+ in
+ let res = tab.(tag) in
+ if res == dummy then raise Not_found else (Obj.magic res)
+
+ let add (h : 'a t) tag slist (data : 'a) =
+ let tab =
+ try
+ SListTable.find h slist
+ with
+ Not_found ->
+ let arr = Array.create 10000 dummy in
+ SListTable.add h slist arr;
+ arr
+ in
+ tab.(tag) <- (Obj.repr data)
+
+
+ end
+
+ let td_trans = TransCache.create 10000 (* should be number of tags *number of states^2
+ in the document *)
+
+ 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
+
+
+ module Fold2ResOld = Hashtbl.Make(struct
+ type t = Formlistlist.t*SList.t*SList.t
+ let hash (f,s,t) = HASHINT3(f.Formlistlist.Node.id,
+ s.SList.Node.id,
+ t.SList.Node.id)
+ let equal (a,b,c) (d,e,f) = a==d && b == e && c == f
+ end)
+
+ module FllTable = Hashtbl.Make (struct type t = Formlistlist.t
+ let equal = (==)
+ let hash t = t.Formlistlist.Node.id
+ end)
+
+ module Fold2Res =
+ struct
+ type 'a t = 'a SListTable.t SListTable.t FllTable.t
+ let create n = Array.init 10000 (fun _ -> FllTable.create n)
+
+ let find h tag fl s1 s2 =
+ let hf = h.(tag) in
+ let hs1 = FllTable.find hf fl in
+ let hs2 = SListTable.find hs1 s1 in
+ SListTable.find hs2 s2
+
+ let add h tag fl s1 s2 data =
+ let hf = h.(tag) in
+ let hs1 =
+ try FllTable.find hf fl with
+ | Not_found ->
+ let hs1 = SListTable.create SMALL_H_SIZE
+ in FllTable.add hf fl hs1;hs1
+ in
+ let hs2 =
+ try SListTable.find hs1 s1
+ with
+ | Not_found ->
+ let hs2 = SListTable.create SMALL_H_SIZE
+ in SListTable.add hs1 s1 hs2;hs2
+ in
+ SListTable.add hs2 s2 data
+ end
+
+ let h_fold2 = Fold2Res.create SMALL_H_SIZE
+
+ let top_down ?(noright=false) a tree t slist ctx slot_size =
+ let pempty = empty_size slot_size in
+ let rempty = Array.make slot_size RS.empty in
+ (* evaluation starts from the right so we put sl1,res1 at the end *)
+ let eval_fold2_slist fll t tag (sl2,res2) (sl1,res1) =
+ let res = Array.copy rempty in
+ try
+ let r,b,btab = Fold2Res.find h_fold2 tag fll sl1 sl2 in
+ if b then for i=0 to slot_size - 1 do
+ res.(i) <- RS.merge btab.(i) t res1.(i) res2.(i);
+ done;
+ r,res
+ with
+ Not_found ->
+ let btab = Array.make slot_size (false,false,false,false) in
+ let rec fold l1 l2 fll i aq ab =
+ match fll.Formlistlist.Node.node,
+ l1.SList.Node.node,
+ l2.SList.Node.node
+ with
+ | Formlistlist.Cons(fl,fll),
+ SList.Cons(s1,ll1),
+ SList.Cons(s2,ll2) ->
+ let r',((b,_,_,_) as flags) = eval_formlist tag s1 s2 fl in
+ let _ = btab.(i) <- flags
+ in
+ fold ll1 ll2 fll (i+1) (SList.cons r' aq) (b||ab)
+ | _ -> aq,ab
+ in
+ let r,b = fold sl1 sl2 fll 0 SList.nil false in
+ Fold2Res.add h_fold2 tag fll sl1 sl2 (r,b,btab);
+ if b then for i=0 to slot_size - 1 do
+ res.(i) <- RS.merge btab.(i) t res1.(i) res2.(i);
+ done;
+ r,res
+ in
+
+ let null_result = (pempty,Array.copy rempty) 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
+ TransCache.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 (Formlistlist.cons fl fll_acc), (SList.cons ll lllacc), (SList.cons rr rllacc),ca,da,sa,fa)
+ slist (Formlistlist.nil,SList.nil,SList.nil,StateSet.empty,StateSet.empty,StateSet.empty,StateSet.empty)
+ in
+ (* Logic to chose the first and next function *)
+ let tags_child,tags_below,tags_siblings,tags_after = Tree.tags tree tag in
+ let d_f = Algebra.decide a tags_child tags_below (StateSet.union ca da) true in
+ let d_n = Algebra.decide a tags_siblings tags_after (StateSet.union sa fa) false in
+ let f_kind,first = choose_jump_down tree d_f
+ and n_kind,next = if noright then (`NIL, fun _ _ -> Tree.nil )
+ else choose_jump_next tree d_n in
+ let empty_res = null_result in
+ let cont =
+ match f_kind,n_kind with
+ | `NIL,`NIL ->
+ (fun t _ -> eval_fold2_slist fl_list t (Tree.tag tree t) empty_res empty_res)
+ | _,`NIL -> (
+ match f_kind with
+ |`TAG(tag') ->
+ (fun t _ -> eval_fold2_slist fl_list t (Tree.tag tree t) empty_res
+ (loop_tag tag' (first t) llist t ))
+ | `ANY ->
+ (fun t _ -> eval_fold2_slist fl_list t (Tree.tag tree t) empty_res
+ (loop (first t) llist t ))
+ | _ -> assert false)
+ | `NIL,_ -> (
+ match n_kind with
+ |`TAG(tag') ->
+ if SList.equal rlist slist && tag == tag' then
+ let rec loop t ctx =
+ if t == Tree.nil then empty_res else
+ let res2 = loop (next t ctx) ctx in
+ eval_fold2_slist fl_list t tag res2 empty_res
+ in loop
+ else
+ (fun t ctx -> eval_fold2_slist fl_list t (Tree.tag tree t)
+ (loop_tag tag' (next t ctx) rlist ctx ) empty_res)
+
+ | `ANY ->
+ (fun t ctx -> eval_fold2_slist fl_list t (Tree.tag tree t)
+ (loop (next t ctx) rlist ctx ) empty_res)
+
+ | _ -> assert false)
+
+ | `TAG(tag1),`TAG(tag2) ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t (Tree.tag tree t)
+ (loop_tag tag2 (next t ctx) rlist ctx )
+ (loop_tag tag1 (first t) llist t ))
+
+ | `TAG(tag'),`ANY ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t (Tree.tag tree 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 (Tree.tag tree t)
+ (loop_tag tag' (next t ctx) rlist ctx )
+ (loop (first t) llist t ))
+
+ | `ANY,`ANY ->
+ if SList.equal slist rlist && SList.equal slist llist
+ then
+ let rec loop t ctx =
+ if t == Tree.nil then empty_res else
+ let r1 = loop (first t) t
+ and r2 = loop (next t ctx) ctx
+ in
+ eval_fold2_slist fl_list t (Tree.tag tree t) r2 r1
+ in loop
+ else
+ (fun t ctx ->
+ eval_fold2_slist fl_list t (Tree.tag tree t)
+ (loop (next t ctx) rlist ctx )
+ (loop (first t) llist t ))
+ | _,_ ->
+ (fun t ctx ->
+ eval_fold2_slist fl_list t (Tree.tag tree 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 tree t (slist,a,fl_list,first,next,ctx);
+ (a,b)
+ ) ,cont)
+ in
+ (TransCache.add td_trans tag slist (Obj.repr cont) ;cont)
+ in (Obj.magic 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 "trace.html"
+ (RS.fold (fun t a -> IntSet.add (Tree.id tree 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