INCLUDE "debug.ml" INCLUDE "utils.ml" module type S = sig type t type elt = Tree.node val empty : t val singleton : elt -> t val cons : elt -> t -> t val snoc : t -> elt -> t val concat : t -> t -> t val concat3 : t -> t -> t -> t val concat4 : t -> t -> t -> t -> t val conscat : elt -> t -> t -> t val conscat3 : elt -> t -> t -> t -> t val conscat4 : elt -> t -> t -> t -> t -> t val subtree_tags : Tree.t -> elt -> Tag.t -> t val subtree_elements : Tree.t -> elt -> t val iter : ( elt -> unit) -> t -> unit val fold : ( elt -> 'a -> 'a) -> t -> 'a -> 'a val length : t -> int val serialize : string -> Tree.t -> t -> unit end module Count : S with type t = int = struct type t = int type elt = Tree.node let empty = 0 let singleton _ = 1 let cons _ x = x+1 let snoc x _ = x+1 let concat x y = x + y let concat3 x y z = x + y + z let concat4 x y z t = x + y + z + t let conscat _ x y = 1 + x + y let conscat3 _ x y z = 1 + x + y + z let conscat4 _ x y z t = 1 + x + y + z + t let subtree_tags tree node tag = Tree.subtree_tags tree node tag let subtree_elements tree node = Tree.subtree_elements tree node let iter _ _ = failwith "iter not implemented" let fold _ _ _ = failwith "fold not implemented" let map _ _ = failwith "map not implemented" let length x = x let serialize _ _ _ = () end type clist = | Nil | Cons of Tree.node * clist | Concat of clist * clist | ConsCat of Tree.node * clist * clist | SubtreeTags of Tree.t * Tree.node * Tag.t | SubtreeElts of Tree.t * Tree.node type 'a mat = { mutable clist : clist; mutable length : int } module Mat : S with type t = Tree.node mat = struct type t = Tree.node mat type elt = Tree.node let empty = { clist = Nil; length = 0 } let singleton e = { clist = Cons(e, Nil) ; length = 1 } let cons e l = { clist = Cons(e, l.clist); length = l.length + 1 } let concat l1 l2 = let ll1 = l1.length in if ll1 == 0 then l2 else let ll2 = l2.length in if ll2 == 0 then l1 else { clist = Concat(l1.clist, l2.clist); length = ll1 + ll2 } let snoc l e = concat l (singleton e) (* let _total = ref 0 let _empty = ref 0 let () = at_exit (fun () -> Printf.eprintf "Dummy concatenations: %i/%i\n%!" !_empty !_total) let concat l1 l2 = let l = concat l1 l2 in if l.length == 0 then incr _empty; incr _total; l *) let concat3 l1 l2 l3 = concat l1 (concat l2 l3) let concat4 l1 l2 l3 l4 = concat (concat l1 l2) (concat l3 l4) let conscat e l1 l2 = let ll1 = l1.length in if ll1 == 0 then cons e l2 else let ll2 = l2.length in if ll2 == 0 then cons e l1 else { clist = ConsCat(e, l1.clist, l2.clist); length = 1 + ll1 + ll2 } (* let conscat e l1 l2 = cons e (concat l1 l2) *) let conscat3 e l1 l2 l3 = conscat e l1 (concat l2 l3) let conscat4 e l1 l2 l3 l4 = conscat e l1 (concat l2 (concat l3 l4)) let subtree_tags tree node tag = { clist = SubtreeTags(tree, node, tag); length = Tree.subtree_tags tree node tag } let subtree_elements tree node = { clist = SubtreeElts(tree, node); length = Tree.subtree_elements tree node } let fst_tagged tree t tag = if Tree.tag tree t == tag then t else Tree.tagged_descendant tree t tag let fst_element tree t = let tag = Tree.tag tree t in let t = if Ptset.Int.mem tag (Ptset.Int.remove Tag.document_node (Tree.element_tags tree)) then t else Tree.first_element tree t in Tree.first_element tree t let element_fold f tree t acc = let rec loop node acc = if node == Tree.nil then acc else let acc = f node acc in let acc' = loop (Tree.first_element tree node) acc in loop (Tree.next_element tree node) acc' in loop (fst_element tree t) acc let element_iter f tree t = let rec loop node = if node != Tree.nil then begin f node; loop (Tree.first_element tree node); loop (Tree.next_element tree node) end in let t' = fst_element tree t in loop t' let tag_fold f tree t tag acc = let rec loop close node acc = if node == Tree.nil then acc else let acc = f node acc in let acc' = loop close (Tree.tagged_descendant tree node tag) acc in loop close (Tree.tagged_following_before tree node tag close) acc' in let t = fst_tagged tree t tag in loop (Tree.closing tree t) t acc let tag_iter f tree t tag = let rec loop close node = if node != Tree.nil then begin f node; loop close (Tree.tagged_descendant tree node tag); loop close (Tree.tagged_following_before tree node tag close); end in let t' = fst_tagged tree t tag in loop (Tree.closing tree t) t' let fold f l acc = let rec loop l acc = match l with | Nil -> acc | Cons(e, ll) -> loop ll (f e acc) | Concat(l1, l2) -> loop l2 (loop l1 acc) | ConsCat(e, l1, l2) -> loop l2 (loop l1 (f e acc)) | SubtreeTags(tree, t, tag) -> tag_fold f tree t tag acc | SubtreeElts(tree, t) -> element_fold f tree t acc in loop l.clist acc let iter f l = let rec loop l = match l with | Nil -> () | Cons(e, l) -> f e; loop l | Concat(l1, l2) -> loop l1; loop l2 | ConsCat(e, l1, l2) -> f e; loop l1; loop l2 | SubtreeTags(tree, t, tag) -> tag_iter f tree t tag | SubtreeElts(tree, t) -> element_iter f tree t in loop l.clist let length l = l.length let serialize name v l = let fd, finish = if name = "-" then Unix.stdout, ignore else Unix.openfile name [ Unix.O_WRONLY; Unix.O_TRUNC; Unix.O_CREAT ] 0o666, Unix.close in iter (fun node -> Tree.print_xml v node fd) l; Tree.flush v fd; finish fd end let rec debug_clist = function Nil -> Printf.eprintf "Nil" | Cons(e, clist) -> Printf.eprintf "Cons(%i," (Obj.magic e); debug_clist clist; Printf.eprintf ")"; | Concat(clist1, clist2) -> Printf.eprintf "Concat("; debug_clist clist1; Printf.eprintf ","; debug_clist clist2; Printf.eprintf ")"; | ConsCat(_, clist1, clist2) -> Printf.eprintf "Concat("; debug_clist clist1; Printf.eprintf ","; debug_clist clist2; Printf.eprintf ")"; | SubtreeTags(tree, node, tag) -> Printf.eprintf "SubtreeTags(tree, %i, %s)" (Obj.magic node) (Tag.to_string tag); | SubtreeElts(tree, node) -> Printf.eprintf "SubtreeElts(tree, %i)" (Obj.magic node) let debug l = debug_clist l.clist