Merge branch 'local-ocamlbuild' into local-trunk
[SXSI/xpathcomp.git] / src / nodeSet.ml
diff --git a/src/nodeSet.ml b/src/nodeSet.ml
new file mode 100644 (file)
index 0000000..2716d61
--- /dev/null
@@ -0,0 +1,231 @@
+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