Fast closure branch
[SXSI/xpathcomp.git] / ata.ml
diff --git a/ata.ml b/ata.ml
index 3959ccf..9197cbc 100644 (file)
--- a/ata.ml
+++ b/ata.ml
@@ -13,9 +13,9 @@ sig
 end =
 struct
   type t = int
-  let make = 
-    let id = ref (-1) in
-      fun () -> incr id;!id
+  let make = let id = ref ~-1 in
+  fun () -> incr id; !id
+
   let compare = (-)
   let equal = (==)
   external hash : t -> int =  "%identity"
@@ -58,8 +58,8 @@ struct
       match f.pos with
        | False -> 0
        | True -> 1
-       | Or (f1,f2) -> HASHINT3(PRIME2,f1.Node.id, f2.Node.id)
-       | And (f1,f2) -> HASHINT3(PRIME3,f1.Node.id,f2.Node.id)
+       | Or (f1,f2) -> HASHINT3(PRIME2,Uid.to_int f1.Node.id, Uid.to_int f2.Node.id)
+       | And (f1,f2) -> HASHINT3(PRIME3,Uid.to_int f1.Node.id, Uid.to_int f2.Node.id)
        | Atom(d,p,s) -> HASHINT4(PRIME4,hash_const_variant d,vb p,s)       
     end
 
@@ -197,7 +197,9 @@ module Transition = struct
   type node = State.t*TagSet.t*bool*Formula.t*bool
   include Hcons.Make(struct
                       type t = node
-                      let hash (s,ts,m,f,b) = HASHINT5(s,TagSet.uid ts,Formula.uid f,vb m,vb b)
+                      let hash (s,ts,m,f,b) = HASHINT5(s,Uid.to_int (TagSet.uid ts),
+                                                       Uid.to_int (Formula.uid f),
+                                                       vb m,vb b)
                       let equal (s,ts,b,f,m) (s',ts',b',f',m') = 
                         s == s' && ts == ts' && b==b' && m==m' && f == f'
                     end)
@@ -284,7 +286,9 @@ module FormTable = Hashtbl.Make(struct
                                  let equal (f1,s1,t1) (f2,s2,t2) =
                                    f1 == f2 && s1 == s2 && t1 == t2
                                  let hash (f,s,t) = 
-                                   HASHINT3(Formula.uid f ,StateSet.uid s,StateSet.uid t)
+                                   HASHINT3(Uid.to_int (Formula.uid f),
+                                            Uid.to_int (StateSet.uid s),
+                                            Uid.to_int (StateSet.uid t))
                                end)
 module F = Formula
 
@@ -332,7 +336,10 @@ module FTable = Hashtbl.Make(struct
                               type t = Tag.t*Formlist.t*StateSet.t*StateSet.t
                               let equal (tg1,f1,s1,t1) (tg2,f2,s2,t2) =
                                 tg1 == tg2 && f1 == f2 &&  s1 == s2 && t1 == t2;;
-                              let hash (tg,f,s,t) =  HASHINT4(tg,Formlist.uid f ,StateSet.uid s,StateSet.uid t);;
+                              let hash (tg,f,s,t) =  
+                                HASHINT4(tg, Uid.to_int (Formlist.uid f),
+                                         Uid.to_int (StateSet.uid s),
+                                         Uid.to_int (StateSet.uid t))
                             end)
 
 
@@ -447,12 +454,12 @@ let tags_of_state a q =
        else 0
       let merge conf t res1 res2 = 
        match conf with
-           NO -> 0                         
-         | MARK -> 1
-         | MARK1 -> res1+1         
+          NO -> 0                         
          | ONLY1 -> res1                
          | ONLY2 -> res2           
          | ONLY12 -> res1+res2     
+         | MARK -> 1
+         | MARK1 -> res1+1         
          | MARK2 -> res2+1         
          | MARK12 -> res1+res2+1   
 
@@ -658,8 +665,22 @@ let tags_of_state a q =
     module Run (RS : ResultSet) =
     struct
 
-      module SList = Hlist.Make (StateSet)
-
+      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
@@ -671,8 +692,10 @@ 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 mk_app_fun f arg _ = f arg 
       let mk_app_fun2 f arg1 arg2 s = let g = f arg1 arg2 in 
        D_IGNORE_(register_funname g ((get_funname f) ^ " " ^ s), g) 
+(*      let mk_app_fun2 f arg1 arg2 s = Printf.eprintf "Building f2 %s\n%!"  s; f arg1 arg2 *)
 
       let string_of_ts tags = (Ptset.Int.fold (fun t a -> a ^ " " ^ (Tag.to_string t) ) tags "{")^ " }"
 
@@ -815,82 +838,40 @@ END
          (mk_fun (Tree.next_sibling_below 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 TransCacheOld = 
+      module CodeCache = 
       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 get = Array.unsafe_get
+       let set = Array.set
 
-       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
-
-      module TransCache = 
-      struct 
-       external get : 'a array -> int ->'a = "%array_unsafe_get"
-       external set : 'a array -> int -> 'a -> unit = "%array_unsafe_set"
-       type fun_tree = [`Tree] Tree.node -> [`Tree] Tree.node -> SList.t*RS.t array
+       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_cell = [||] 
-       let create n = Array.create n dummy_cell
-       let dummy = fun _ _-> assert false
-       let find h tag slist =
-         let tab = get h slist.SList.Node.id in
-         if tab == dummy_cell then raise Not_found
-         else
-         let res = get tab tag in
-         if res == dummy then raise Not_found else res
-
-       let add (h : t) tag slist (data : fun_tree) =
-         let tab = get h slist.SList.Node.id in
-         let tab = if tab == dummy_cell then
-           let x = Array.create 10000 dummy in
-           (set h slist.SList.Node.id  x;x)
+
+       let dummy = fun _ _ _ _ _ -> failwith "Uninitializd CodeCache"
+       let default_line = Array.create 256 dummy (* 256 = 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 tab tag data        
-      end
-       
-      module TransCache2 = struct
-       include Hashtbl.Make (struct
-                       type t = Tag.t*SList.t
-                       let equal (a,b) (c,d) = a==c && b==d
-                       let hash (a,b) = HASHINT2((Obj.magic a), b.SList.Node.id)
-                     end)
-
-       let add h t s d = add h (t,s) d
-       let find h t s = find h (t,s)
+         set line tag data       
+
       end
-       
-      let td_trans = TransCache.create 10000 (* should be number of tags *number of states^2
+
+      let td_trans = CodeCache.create 10000 (* should be number of tags *number of states^2
                                                in the document *)
 
       let empty_size n =
@@ -898,82 +879,42 @@ END
          | n -> loop (SList.cons StateSet.empty acc) (n-1)
        in loop SList.nil n
             
-      module FllTable = Hashtbl.Make (struct type t = Formlistlist.t
-                                            let equal = (==)
-                                            let hash t = t.Formlistlist.Node.id
-                                     end)
-       
+     
       module Fold2Res = struct
-       external get : 'a array -> int ->'a = "%array_unsafe_get"
-       external set : 'a array -> int -> 'a -> unit = "%array_unsafe_set"
-       external field1 : 'a -> 'b = "%field1"
-       type 'a t = 'a array array array array
-       let dummy = [||]
-       let dummy_val : 'a =
-         let v = Obj.repr ((),2,()) in
-         Obj.magic v
-
-       let create n = Array.create n dummy
-
-       let find h tag fl s1 s2 = 
-         let af = get h tag in
-         if af == dummy then raise Not_found
-         else 
-         let as1 = get af fl.Formlistlist.Node.id in
-         if as1 == dummy then raise Not_found
-         else 
-         let as2 = get as1 s1.SList.Node.id in
-         if as2 == dummy then raise Not_found 
-         else let v = get as2 s2.SList.Node.id in
-         if field1 v == 2 then raise Not_found 
-         else v
-       
-       let add h tag fl s1 s2 data = 
-         let af =
-           let x = get h tag in
-           if x == dummy then 
-           begin
-             let y = Array.make 10000 dummy in
-             set h tag y;y
-           end
-           else x
-         in
-         let as1 = 
-           let x = get af fl.Formlistlist.Node.id in 
-           if x == dummy then
-           begin
-             let y = Array.make 10000 dummy in
-             set af fl.Formlistlist.Node.id y;y
-           end
-           else x
-         in
-         let as2 = 
-           let x = get as1 s1.SList.Node.id in 
-           if x == dummy then 
-           begin
-             let y = Array.make 10000 dummy_val in
-             set as1 s1.SList.Node.id y;y
-           end
-           else x
-         in
-         set as2 s2.SList.Node.id data    
-      end
+       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 10000 dummy_val
+       let default_line2 = Array.create 10000 default_line3
+       let default_line1 = Array.create 10000 default_line2
+
+       let create n = Array.create n default_line1
        
-      module Fold2Res2 = struct
-       include Hashtbl.Make(struct 
-                              type t = Tag.t*Formlistlist.t*SList.t*SList.t
-                              let equal (a,b,c,d) (x,y,z,t) =
-                                a == x && b == y && c == z && d == t
-                              let hash (a,b,c,d) = HASHINT4 (a,b.Formlistlist.Node.id,
-                                                             c.SList.Node.id,d.SList.Node.id)
-                            end)
-       let add h t f s1 s2 d =
-         add h (t,f,s1,s2) d
-       let find h t f s1 s2 =
-         find h (t,f,s1,s2)
+       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 h_fold2 = Fold2Res.create 10000
+            
+      let h_fold2 = Fold2Res.create 256
       
       let top_down ?(noright=false) a tree t slist ctx slot_size =     
        let pempty = empty_size slot_size in    
@@ -981,187 +922,222 @@ END
        (* 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 -> 
-              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
-                      in
-                        fold ll1 ll2 fll (i+1) (SList.cons r' aq) ((conf!=NO)||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;
-              end
+         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
+                   in
+                   fold ll1 ll2 fll (i+1) (SList.cons r' aq) ((conf!=NO)||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;
+         end
        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,_ = t.Transition.node 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 f_kind,first = `ANY, Tree.first_child tree
-                 and n_kind,next = `ANY, Tree.next_sibling_below tree 
-                 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') ->                          
-                               let default = fun t _ -> eval_fold2_slist fl_list t (Tree.tag tree t) empty_res
-                                  (loop_tag tag' (first t) llist t )
-                               in default (*
-                               let cf = SList.hd llist in
-                               if (slot_size == 1) && StateSet.is_singleton cf
-                               then
-                               let s = StateSet.choose cf in
-                               if (Algebra.is_rec a s fst) && (Algebra.is_rec a s snd)
-                               && (Algebra.is_final_marking a s)
-                               then 
-                               RS.mk_quick_tag_loop default llist 1 tree tag' 
-                               else default
-                               else default *) *)
-                            | _ ->
-                                (fun t _ -> eval_fold2_slist fl_list t (Tree.tag tree t) empty_res
-                                  (loop (first t) llist t ))
-                        )
-                      | `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)
-                                                                                            
-                            | _ ->
-                                (fun t ctx -> eval_fold2_slist fl_list t (Tree.tag tree t)
-                                   (loop (next t ctx) rlist ctx ) empty_res)
-                       )
+       let empty_res = null_result in
+
+       let rec loop t ctx slist _  =
+         if t == Tree.nil then null_result else
+         let tag = Tree.tag tree t in
+         (CodeCache.get_fun td_trans slist tag) t ctx slist tag false
+           (* get_trans t ctx slist tag false
+           (CodeCache.get_opcode td_trans slist tag)
+           *)
+       and loop_tag t ctx slist tag  =
+         if t == Tree.nil then null_result else 
+         (CodeCache.get_fun td_trans slist tag) t ctx slist tag false
+           (* get_trans t ctx slist tag false 
+           (CodeCache.get_opcode td_trans slist tag) *)
+         
+       and loop_no_right t ctx slist _  = 
+         if t == Tree.nil then null_result else 
+         let tag = Tree.tag tree t in
+         (CodeCache.get_fun td_trans slist tag) t ctx slist tag true
+           (* get_trans t ctx slist tag true 
+              (CodeCache.get_opcode td_trans slist tag) *)
+           (*
+       and get_trans t ctx slist tag noright opcode = 
+         match opcode with
+           | OpCode.K0 fll -> 
+               eval_fold2_slist fll t tag empty_res empty_res
+
+           | OpCode.K1 (fll,first,llist,tag1) -> 
+               eval_fold2_slist fll t tag empty_res
+                 (loop_tag (first t) t llist tag1)
+
+           | OpCode.K2 (fll,first,llist) ->
+               eval_fold2_slist fll t tag empty_res
+                 (loop (first t) t llist)
+                 
+           | OpCode.K3 (fll,next,rlist,tag2) ->
+                eval_fold2_slist fll t tag 
+                 (loop_tag (next t ctx) ctx rlist tag2)
+                 empty_res
+           | OpCode.K4 (fll,next,rlist) ->
+               eval_fold2_slist fll t tag 
+                 (loop (next t ctx) ctx rlist)           
+                 empty_res
+
+           | OpCode.K5 (fll,next,rlist,tag2,first,llist,tag1) ->
+               eval_fold2_slist fll t tag
+                 (loop_tag (next t ctx) ctx rlist tag2)                  
+                 (loop_tag (first t) t llist tag1)
+
+           | OpCode.K6 (fll,next,rlist,first,llist,tag1) ->
+               eval_fold2_slist fll t tag
+                 (loop (next t ctx) ctx rlist)           
+                 (loop_tag (first t) t llist tag1)
+
+           | OpCode.K7 (fll,next,rlist,tag2,first,llist) ->
+               eval_fold2_slist fll t tag
+                 (loop_tag (next t ctx) ctx rlist tag2)                  
+                 (loop (first t) t llist)
+
+           | OpCode.K8 (fll,next,rlist,first,llist) ->
+               eval_fold2_slist fll t tag
+                 (loop (next t ctx) ctx rlist)           
+                 (loop (first t) t llist)
+
+           | OpCode.KDefault _ -> 
+               mk_trans t ctx tag slist noright
+           *)
+       and mk_trans t ctx slist tag noright = 
+         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,_ = t.Transition.node 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;[]
+                         )
                          
-                      | `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 ))
+                    ) 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 fll = fl_list in
+          let cont =
+            match f_kind,n_kind with
+              | `NIL,`NIL -> (*OpCode.K0(fl_list) *)
+                 fun t _ _ tag _ -> eval_fold2_slist fll t tag empty_res empty_res
+               
+             |  _,`NIL -> (
+                   match f_kind with
+                     |`TAG(tag1) -> (*OpCode.K1(fl_list,first,llist,tag1) *)
+                       fun t _ _ tag _ -> eval_fold2_slist fll t tag empty_res
+                         (loop_tag (first t) t llist tag1)
+                    | _ -> (* OpCode.K2(fl_list,first,llist) *)
+                        fun t _ _ tag _  -> eval_fold2_slist fll t tag empty_res
+                          (loop (first t) t llist tag)
+                )
+              | `NIL,_ -> (
+                  match n_kind with
+                    |`TAG(tag2) -> (*OpCode.K3(fl_list,next,rlist,tag2) *)
+                      fun t ctx _ tag _ ->
+                        eval_fold2_slist fll t tag 
+                          (loop_tag (next t ctx) ctx rlist tag2)
+                          empty_res
+
+                    | _ -> (*OpCode.K4(fl_list,next,rlist) *)
+                       fun t ctx _ tag _ ->
+                         eval_fold2_slist fll t tag 
+                           (loop (next t ctx) ctx rlist tag)
+                           empty_res
+                        
+               )
+                 
+              | `TAG(tag1),`TAG(tag2) -> (*OpCode.K5(fl_list,next,rlist,tag2,first,llist,tag1) *)
+                 fun t ctx _ tag _ -> 
+                   eval_fold2_slist fll t tag
+                     (loop_tag (next t ctx) ctx rlist tag2)              
+                     (loop_tag (first t) t llist tag1)
  
-                      | `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 ))
+              | `TAG(tag1),`ANY -> (* OpCode.K6(fl_list,next,rlist,first,llist,tag1) *)
+                 fun t ctx _ tag _ -> 
+                   eval_fold2_slist fll t tag
+                     (loop (next t ctx) ctx rlist tag)
+                     (loop_tag (first t) t llist tag1)
+
+              | `ANY,`TAG(tag2) -> (* OpCode.K7(fl_list,next,rlist,tag2,first,llist) *)
+                 fun t ctx _ tag _ -> 
+                   eval_fold2_slist fll t tag
+                     (loop_tag (next t ctx) ctx rlist tag2)              
+                     (loop (first t) t llist tag)
+                         
                                                                   
-                      | `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 ))
-                 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 cont  ;   cont)
-         in cont t ctx
-              
+              | _,_ -> (*OpCode.K8(fl_list,next,rlist,first,llist) *)
+                 (*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 _ tag _ -> 
+                   eval_fold2_slist fll t tag
+                     (loop (next t ctx) ctx rlist tag)           
+                     (loop (first t) t llist tag)
+
+             
+
+         in
+         CodeCache.set_fun td_trans slist tag cont; 
+         cont t ctx slist tag noright
        in 
-         (if noright then loop_no_right else loop) t slist ctx
+       let _ = CodeCache.init mk_trans in
+       (if noright then loop_no_right else loop) t ctx slist Tag.dummy
 
        let run_top_down a tree =
          let init = SList.cons a.init SList.nil in
@@ -1189,7 +1165,7 @@ END
            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);
+             { hash = HASHINT2(c.hash,Uid.to_int (Ptset.Int.uid s));
                sets = Ptss.add s c.sets;
                results = IMap.add s r c.results
              }
@@ -1223,7 +1199,7 @@ END
            in
            let h,s =
              Ptss.fold 
-               (fun s (ah,ass) -> (HASHINT2(ah,Ptset.Int.uid s),
+               (fun s (ah,ass) -> (HASHINT2(ah, Uid.to_int (Ptset.Int.uid s)),
                                    Ptss.add s ass))
                (Ptss.union c1.sets c2.sets) (0,Ptss.empty)
            in
@@ -1270,7 +1246,7 @@ END
        let h_trans = Hashtbl.create 4096
 
        let get_up_trans slist ptag a tree =      
-         let key = (HASHINT2(SList.uid slist,ptag)) in
+         let key = (HASHINT2(Uid.to_int slist.SList.Node.id ,ptag)) in
            try
          Hashtbl.find h_trans key              
          with
@@ -1395,8 +1371,9 @@ END
 
     end
           
-    let top_down_count a t = let module RI = Run(Integer) in Integer.length (RI.run_top_down a t)
-    let top_down a t = let module RI = Run(IdSet) in (RI.run_top_down a t)
+    let top_down_count a t = let module RI = Run(Integer) in let r = Integer.length (RI.run_top_down a t)
+    in (*RI.TransCache.dump RI.td_trans; *)r
+     let top_down a t = let module RI = Run(IdSet) in (RI.run_top_down a t)
     let bottom_up_count a t k = let module RI = Run(Integer) in Integer.length (RI.run_bottom_up a t k)
     let bottom_up a t k = let module RI = Run(IdSet) in (RI.run_bottom_up a t k)