- module PL = Set.Make (Pair (Ptset) (Ptset))
-
-
- let pr_st ppf l = Format.fprintf ppf "{";
- begin
- match l with
- | [] -> ()
- | [s] -> Format.fprintf ppf " %i" s
- | p::r -> Format.fprintf ppf " %i" p;
- List.iter (fun i -> Format.fprintf ppf "; %i" i) r
- end;
- Format.fprintf ppf " }"
- let rec pr_frm ppf f = match f.pos with
- | True -> Format.fprintf ppf "⊤"
- | False -> Format.fprintf ppf "⊥"
- | And(f1,f2) ->
- Format.fprintf ppf "(";
- (pr_frm ppf f1);
- Format.fprintf ppf ") ∧ (";
- (pr_frm ppf f2);
- Format.fprintf ppf ")"
- | Or(f1,f2) ->
- (pr_frm ppf f1);
- Format.fprintf ppf " ∨ ";
- (pr_frm ppf f2);
- | Atom(dir,b,s) -> Format.fprintf ppf "%s%s[%i]"
- (if b then "" else "¬")
- (match dir with
- | `Left -> "↓₁"
- | `Right -> "↓₂"
- | `LLeft -> "⇓₁"
- | `RRight -> "⇓₂") s
-
- let dnf_hash = Hashtbl.create 17
-
- let rec dnf_aux f = match f.pos with
- | False -> PL.empty
- | True -> PL.singleton (Ptset.empty,Ptset.empty)
- | Atom((`Left|`LLeft),_,s) -> PL.singleton (Ptset.singleton s,Ptset.empty)
- | Atom((`Right|`RRight),_,s) -> PL.singleton (Ptset.empty,Ptset.singleton s)
- | Or(f1,f2) -> PL.union (dnf f1) (dnf f2)
- | And(f1,f2) ->
- let pl1 = dnf f1
- and pl2 = dnf f2
- in
- PL.fold (fun (s1,s2) acc ->
- PL.fold ( fun (s1', s2') acc' ->
- (PL.add
- ((Ptset.union s1 s1'),
- (Ptset.union s2 s2')) acc') )
- pl2 acc )
- pl1 PL.empty
-
-
- and dnf f =
- try
- Hashtbl.find dnf_hash f.fid
- with
- Not_found ->
- let d = dnf_aux f in
- Hashtbl.add dnf_hash f.fid d;d
-
-
- let can_top_down f =
- let nf = dnf f in
- if (PL.cardinal nf > 3)then None
- else match PL.elements nf with
- | [(s1,s2); (t1,t2); (u1,u2)] when
- Ptset.is_empty s1 && Ptset.is_empty s2 && Ptset.is_empty t1 && Ptset.is_empty u2
- -> Some(true,t2,u1)
- | [(t1,t2); (u1,u2)] when Ptset.is_empty t1 && Ptset.is_empty u2
- -> Some(false,t2,u1)
- | _ -> None
-
-
- let equal_form f1 f2 =
- (f1.fid == f2.fid) || (FormNode.equal f1 f2) || (PL.equal (dnf f1) (dnf f2))
-
- let dump ppf a =
- Format.fprintf ppf "Automaton (%i) :\n" a.id;
- Format.fprintf ppf "States : "; pr_st ppf (Ptset.elements a.states);
- Format.fprintf ppf "\nInitial states : "; pr_st ppf (Ptset.elements a.init);
- Format.fprintf ppf "\nFinal states : "; pr_st ppf (Ptset.elements a.final);
- Format.fprintf ppf "\nUniversal states : "; pr_st ppf (Ptset.elements a.universal);
- Format.fprintf ppf "\nAlternating transitions :\n------------------------------\n";
- let l = Hashtbl.fold (fun k t acc ->
- (List.map (fun (t,(m,f,p)) -> (t,k),(m,f,p)) t)@ acc) a.phi [] in
- let l = List.sort (fun ((tsx,x),_) ((tsy,y),_) -> if x-y == 0 then TagSet.compare tsx tsy else x-y) l in
- List.iter (fun ((ts,q),(b,f,_)) ->
-
- let s =
- if TagSet.is_finite ts
- then "{" ^ (TagSet.fold (fun t a -> a ^ " '" ^ (Tag.to_string t)^"'") ts "") ^" }"
- else let cts = TagSet.neg ts in
- if TagSet.is_empty cts then "*" else
- (TagSet.fold (fun t a -> a ^ " " ^ (Tag.to_string t)) cts "*\\{"
- )^ "}"
+ let iter f l =
+ let rec loop = function
+ | Nil -> ()
+ | Cons (e,t) -> f e; loop t
+ | Concat(t1,t2) -> loop t1;loop t2
+ in loop l.node
+
+ let map f l =
+ let rec loop = function
+ | Nil -> Nil
+ | Cons(e,t) -> Cons(f e, loop t)
+ | Concat(t1,t2) -> Concat(loop t1,loop t2)
+ in
+ { l with node = loop l.node }
+
+ let merge conf t res1 res2 =
+ match conf with
+ NO -> empty
+ | MARK -> cons t empty
+ | ONLY1 -> res1
+ | ONLY2 -> res2
+ | ONLY12 -> { node = (Concat(res1.node,res2.node));
+ length = res1.length + res2.length ;}
+ | MARK12 -> { node = Cons(t,(Concat(res1.node,res2.node)));
+ length = res1.length + res2.length + 1;}
+ | MARK1 -> { node = Cons(t,res1.node);
+ length = res1.length + 1;}
+ | MARK2 -> { node = Cons(t,res2.node);
+ length = res2.length + 1;}
+
+ let mk_quick_tag_loop f _ _ _ _ = f
+ let mk_quick_star_loop f _ _ _ = f
+ end
+ module GResult(Doc : sig val doc : Tree.t end) = struct
+ type bits
+ type elt = [` Tree] Tree.node
+ external create_empty : int -> bits = "caml_result_set_create" "noalloc"
+ external set : bits -> int -> unit = "caml_result_set_set" "noalloc"
+ external next : bits -> int -> int = "caml_result_set_next" "noalloc"
+ external count : bits -> int = "caml_result_set_count" "noalloc"
+ external clear : bits -> elt -> elt -> unit = "caml_result_set_clear" "noalloc"
+
+ external set_tag_bits : bits -> Tag.t -> Tree.t -> elt -> elt = "caml_set_tag_bits" "noalloc"
+ type t =
+ { segments : elt list;
+ bits : bits;
+ }
+
+ let ebits =
+ let size = (Tree.subtree_size Doc.doc Tree.root) in
+ create_empty (size*2+1)
+
+ let empty = { segments = [];
+ bits = ebits }
+
+ let cons e t =
+ let rec loop l = match l with
+ | [] -> { bits = (set t.bits (Obj.magic e);t.bits);
+ segments = [ e ] }
+ | p::r ->
+ if Tree.is_binary_ancestor Doc.doc e p then
+ loop r
+ else
+ { bits = (set t.bits (Obj.magic e);t.bits);
+ segments = e::l }
+ in
+ loop t.segments
+
+ let concat t1 t2 =
+ if t2.segments == [] then t1
+ else
+ if t1.segments == [] then t2
+ else
+ let h2 = List.hd t2.segments in
+ let rec loop l = match l with
+ | [] -> t2.segments
+ | p::r ->
+ if Tree.is_binary_ancestor Doc.doc p h2 then
+ l
+ else
+ p::(loop r)
+ in
+ { bits = t1.bits;
+ segments = loop t1.segments
+ }
+
+ let iter f t =
+ let rec loop i =
+ if i == -1 then ()
+ else (f ((Obj.magic i):elt);loop (next t.bits i))
+ in loop (next t.bits 0)
+
+ let fold f t acc =
+ let rec loop i acc =
+ if i == -1 then acc
+ else loop (next t.bits i) (f ((Obj.magic i):elt) acc)
+ in loop (next t.bits 0) acc
+
+ let map _ _ = failwith "noop"
+ (*let length t = let cpt = ref 0 in
+ iter (fun _ -> incr cpt) t; !cpt *)
+ let length t = count t.bits
+
+ let clear_bits t =
+ let rec loop l = match l with
+ [] -> ()
+ | idx::ll ->
+ clear t.bits idx (Tree.closing Doc.doc idx); loop ll
+ in
+ loop t.segments;empty
+
+ let merge (rb,rb1,rb2,mark) elt t1 t2 =
+ if rb then
+(* let _ = Printf.eprintf "Lenght before merging is %i %i\n"
+ (List.length t1.segments) (List.length t2.segments)
+ in *)
+ match t1.segments,t2.segments with
+ [],[] -> if mark then cons elt empty else empty
+ | [_],[] when rb1 -> if mark then cons elt t1 else t1
+ | [], [_] when rb2 -> if mark then cons elt t2 else t2
+ | [_],[_] when rb1 && rb2 -> if mark then cons elt empty else
+ concat t1 t2
+ | _ ->
+ let t1 = if rb1 then t1 else clear_bits t1
+ and t2 = if rb2 then t2 else clear_bits t2
+ in
+ (if mark then cons elt (concat t1 t2)
+ else concat t1 t2)
+ else
+ let _ = clear_bits t1 in
+ clear_bits t2
+
+ let merge conf t t1 t2 =
+ match t1.segments,t2.segments,conf with
+ | _,_,NO -> let _ = clear_bits t1 in clear_bits t2
+ | [],[],(MARK1|MARK2|MARK12|MARK) -> cons t empty
+ | [],[],_ -> empty
+ | [_],[],(ONLY1|ONLY12) -> t1
+ | [_],[],(MARK1|MARK12) -> cons t t1
+ | [],[_],(ONLY2|ONLY12) -> t2
+ | [],[_],(MARK2|MARK12) -> cons t t2
+ | [_],[_],ONLY12 -> concat t1 t2
+ | [_],[_],MARK12 -> cons t empty
+ | _,_,MARK -> let _ = clear_bits t2 in cons t (clear_bits t1)
+ | _,_,ONLY1 -> let _ = clear_bits t2 in t1
+ | _,_,ONLY2 -> let _ = clear_bits t1 in t2
+ | _,_,ONLY12 -> concat t1 t2
+ | _,_,MARK1 -> let _ = clear_bits t2 in cons t t1
+ | _,_,MARK2 -> let _ = clear_bits t1 in cons t t2
+ | _,_,MARK12 -> cons t (concat t1 t2)
+
+ let mk_quick_tag_loop _ sl ss tree tag = ();
+ fun t _ ->
+ let res = empty in
+ let first = set_tag_bits empty.bits tag tree t in
+ let res =
+ if first == Tree.nil then res else
+ cons first res
+ in
+ (sl, Array.make ss res)
+
+ let mk_quick_star_loop f _ _ _ = f
+ end
+ module Run (RS : ResultSet) =
+ struct
+
+ module SList = struct
+ include Hlist.Make (StateSet)
+ let print ppf l =
+ Format.fprintf ppf "[ ";
+ begin
+ match l.Node.node with
+ | Nil -> ()
+ | Cons(s,ll) ->
+ StateSet.print ppf s;
+ iter (fun s -> Format.fprintf ppf "; ";
+ StateSet.print ppf s) ll
+ end;
+ Format.fprintf ppf "]%!"
+
+
+ end
+
+
+IFDEF DEBUG
+THEN
+ module IntSet = Set.Make(struct type t = int let compare = (-) end)
+INCLUDE "html_trace.ml"
+
+END
+ module Trace =
+ struct
+ module HFname = Hashtbl.Make (struct
+ type t = Obj.t
+ let hash = Hashtbl.hash
+ let equal = (==)
+ end)
+
+ let h_fname = HFname.create 401
+
+ let register_funname f s =
+ HFname.add h_fname (Obj.repr f) s
+ let get_funname f = try HFname.find h_fname (Obj.repr f) with _ -> "[anon_fun]"
+
+
+
+ let mk_fun f s = register_funname f s;f
+ let mk_app_fun f arg s =
+ let g = f arg in
+ register_funname g ((get_funname f) ^ " " ^ s); g
+ let mk_app_fun2 f arg1 arg2 s =
+ let g = f arg1 arg2 in
+ register_funname g ((get_funname f) ^ " " ^ s); g
+
+ end
+
+ let string_of_ts tags = (Ptset.Int.fold (fun t a -> a ^ " " ^ (Tag.to_string t) ) tags "{")^ " }"
+
+
+ module Algebra =
+ struct
+ type jump = [ `NIL | `ANY |`ANYNOTEXT | `JUMP ]
+ type t = jump*Ptset.Int.t*Ptset.Int.t
+ let jts = function
+ | `JUMP -> "JUMP"
+ | `NIL -> "NIL"
+ | `ANY -> "ANY"
+ | `ANYNOTEXT -> "ANYNOTEXT"
+ let merge_jump (j1,c1,l1) (j2,c2,l2) =
+ match j1,j2 with
+ | _,`NIL -> (j1,c1,l1)
+ | `NIL,_ -> (j2,c2,l2)
+ | `ANY,_ -> (`ANY,Ptset.Int.empty,Ptset.Int.empty)
+ | _,`ANY -> (`ANY,Ptset.Int.empty,Ptset.Int.empty)
+ | `ANYNOTEXT,_ ->
+ if Ptset.Int.mem Tag.pcdata (Ptset.Int.union c2 l2) then
+ (`ANY,Ptset.Int.empty,Ptset.Int.empty)
+ else
+ (`ANYNOTEXT,Ptset.Int.empty,Ptset.Int.empty)
+ | _,`ANYNOTEXT ->
+ if Ptset.Int.mem Tag.pcdata (Ptset.Int.union c1 l1) then
+ (`ANY,Ptset.Int.empty,Ptset.Int.empty)
+ else
+ (`ANYNOTEXT,Ptset.Int.empty,Ptset.Int.empty)
+ | `JUMP,`JUMP -> (`JUMP, Ptset.Int.union c1 c2,Ptset.Int.union l1 l2)
+
+ let merge_jump_list = function
+ | [] -> `NIL,Ptset.Int.empty,Ptset.Int.empty
+ | p::r ->
+ List.fold_left (merge_jump) p r
+
+ let labels a s =
+ Hashtbl.fold
+ (
+ fun q l acc ->
+ if (q == s)
+ then
+
+ (List.fold_left
+ (fun acc (ts,f) ->
+ let _,_,_,_,bur = Transition.node f in
+ if bur then acc else TagSet.cup acc ts)
+ acc l)
+ else acc ) a.trans TagSet.empty
+ exception Found
+
+ 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 is_final_marking a s =
+ List.exists (fun (_,t) -> let _,_,m,f,_ = Transition.node t in m&& (Formula.is_true 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),Trace.mk_app_fun f_tn tag (Tag.to_string tag))
+ else
+ (`MANY(ll),Trace.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),Trace.mk_app_fun f_t1 tag (Tag.to_string tag))
+ else
+ (`MANY(cl),Trace.mk_app_fun f_s1 cl (string_of_ts cl))
+ else
+ (`ANY,Trace.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
+ (Trace.mk_fun (fun _ -> Tree.nil) "Tree.mk_nil")
+ (Trace.mk_fun (Tree.tagged_child tree) "Tree.tagged_child")
+ (Trace.mk_fun (Tree.select_child tree) "Tree.select_child")
+ (Trace.mk_fun (Tree.tagged_descendant tree) "Tree.tagged_desc")
+ (Trace.mk_fun (Tree.select_descendant tree) "Tree.select_desc")
+ (Trace.mk_fun (fun _ _ -> Tree.first_child tree) "[FIRSTCHILD]Tree.select_child_desc")
+ (Trace.mk_fun (Tree.first_element tree) "Tree.first_element")
+ (Trace.mk_fun (Tree.first_child tree) "Tree.first_child")
+
+ let choose_jump_next tree d =
+ choose_jump d
+ (Trace.mk_fun (fun _ _ -> Tree.nil) "Tree.mk_nil2")
+ (Trace.mk_fun (Tree.tagged_following_sibling_below tree) "Tree.tagged_sibling_ctx")
+ (Trace.mk_fun (Tree.select_following_sibling_below tree) "Tree.select_sibling_ctx")
+ (Trace.mk_fun (Tree.tagged_following_below tree) "Tree.tagged_foll_ctx")
+ (Trace.mk_fun (Tree.select_following_below tree) "Tree.select_foll_ctx")
+ (Trace.mk_fun (fun _ _ -> Tree.next_sibling_below tree) "[NEXTSIBLING]Tree.select_sibling_foll_ctx")
+ (Trace.mk_fun (Tree.next_element_below tree) "Tree.next_element_ctx")
+ (Trace.mk_fun (Tree.next_sibling_below tree) "Tree.node_sibling_ctx")
+
+
+
+
+ module CodeCache =
+ struct
+ let get = Array.unsafe_get
+ let set = Array.set
+
+ type fun_tree = [`Tree] Tree.node -> [`Tree] Tree.node -> SList.t -> Tag.t -> bool -> SList.t*RS.t array
+ type t = fun_tree array array
+
+ let dummy = fun _ _ _ _ _ -> failwith "Uninitializd CodeCache"
+ let default_line = Array.create 1024 dummy (* 1024 = max_tag *)
+ let create n = Array.create n default_line
+ let init f =
+ for i = 0 to (Array.length default_line) - 1
+ do
+ default_line.(i) <- f
+ done
+
+ let get_fun h slist tag =
+ get (get h (Uid.to_int slist.SList.Node.id)) tag
+
+ let set_fun (h : t) slist tag (data : fun_tree) =
+ let tab = get h (Uid.to_int slist.SList.Node.id) in
+ let line = if tab == default_line then
+ let x = Array.copy tab in
+ (set h (Uid.to_int slist.SList.Node.id) x;x)
+ else tab
+ in
+ set line tag data
+
+ end
+
+ 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 Fold2Res = struct
+ let get = Array.unsafe_get
+ let set = Array.set
+ external field1 : Obj.t -> int = "%field1"
+ type t = Obj.t array array array array
+ let dummy_val = Obj.repr ((),2,())
+
+ let default_line3 = Array.create BIG_A_SIZE dummy_val
+ let default_line2 = Array.create BIG_A_SIZE default_line3
+ let default_line1 = Array.create BIG_A_SIZE default_line2
+
+ let create n = Array.create n default_line1
+
+ let find h tag fl s1 s2 : SList.t*bool*(merge_conf array) =
+ let l1 = get h tag in
+ let l2 = get l1 (Uid.to_int fl.Formlistlist.Node.id) in
+ let l3 = get l2 (Uid.to_int s1.SList.Node.id) in
+ Obj.magic (get l3 (Uid.to_int s2.SList.Node.id))
+
+ let is_valid b = (Obj.magic b) != 2
+ let get_replace tab idx default =
+ let e = get tab idx in
+ if e == default then
+ let ne = Array.copy e in (set tab idx ne;ne)
+ else e
+
+ let add h tag fl s1 s2 (data: SList.t*bool*(merge_conf array)) =
+ let l1 = get_replace h tag default_line1 in
+ let l2 = get_replace l1 (Uid.to_int fl.Formlistlist.Node.id) default_line2 in
+ let l3 = get_replace l2 (Uid.to_int s1.SList.Node.id) default_line3 in
+ set l3 (Uid.to_int s2.SList.Node.id) (Obj.repr data)
+ end
+
+
+
+
+ let top_down ?(noright=false) a tree t slist ctx slot_size td_trans h_fold2=
+ 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
+ let r,b,btab = Fold2Res.find h_fold2 tag fll sl1 sl2 in
+ if Fold2Res.is_valid b then
+ begin
+ if b then for i=0 to slot_size - 1 do
+ res.(0) <- RS.merge btab.(0) t res1.(0) res2.(0);
+ done;
+ r,res
+ end
+ else
+ begin
+ let btab = Array.make slot_size NO 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',conf = eval_formlist tag s1 s2 fl in
+ let _ = btab.(i) <- conf