]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/mathql_interpreter/mQILib.ml
patched and new Gen constructor added
[helm.git] / helm / ocaml / mathql_interpreter / mQILib.ml
index f816590d102b687cf626d05ade27345e0d8954c7..8cfa9deed961b501d721c4576036c91eeb7bc617 100644 (file)
@@ -28,8 +28,8 @@
 
 module M = MathQL
 module P = MQueryUtil 
+module C = MQIConn 
 module U = MQIUtil
-module C = MQIConn
 
 (* external function specification ******************************************)
 
@@ -37,64 +37,112 @@ type arity_t = Const of int
              | Positive
             | Any
 
-type eval_spec = {eval   : M.query -> M.result;
-                  handle : C.handle
+type eval_spec = {eval : M.query -> M.result;
+                  conn : C.handle
                 }
 
-type txt_out_spec = {out    : string -> unit;
-                     path   : M.path -> unit;
-                    query  : M.query -> unit;
-                    result : M.result -> unit
-                   }
+type text_out_spec = {out    : string -> unit;
+                      path   : (string -> unit) -> M.path -> unit;
+                     query  : (string -> unit) -> string -> M.query -> unit;
+                     result : (string -> unit) -> string -> M.result -> unit
+                    }
+
+type text_in_spec = {result_in : Lexing.lexbuf -> M.result}
 
 type fun_spec = {arity_p : arity_t;
                  arity_s : arity_t;
-                 body    : eval_spec -> txt_out_spec ->
+                 body    : eval_spec -> text_out_spec -> text_in_spec ->
                           M.path list -> M.query list -> M.result;
-                txt_out : txt_out_spec -> 
+                txt_out : text_out_spec ->  
                           M.path list -> M.query list -> unit
                }
 
+type gen_spec = {arity : arity_t;
+                 code  : eval_spec -> M.query list -> M.query
+                }
+
 exception ArityError of M.path * arity_t * int
 
 exception NameError of M.path
 
 exception NumberError of M.result
 
+type std_text_out_spec = {s_out    : string -> unit;
+                          s_path   : M.path -> unit;
+                         s_query  : M.query -> unit;
+                         s_result : M.result -> unit
+}
+
+let check_arity p i = function 
+   | Const k when i = k  -> ()
+   | Positive when i > 0 -> ()
+   | Any                 -> ()
+   | a                   -> raise (ArityError (p, a, i))
+
 (* external functions implementation ****************************************)
 
-let int_of_set s =
-   try match s with 
-      | [s, _] -> int_of_string s
+let std o = 
+   {s_out = o.out; s_path = o.path o.out; 
+    s_query = o.query o.out ""; s_result = o.result o.out "\n"
+   }
+
+type t = End
+       | Space
+       | Figure of int
+       | Error
+
+let my_int_of_string s =
+   let l = String.length s in
+   let get_t i =
+      if i = l then End else
+      match s.[i] with
+         | ' ' | '\t' | '\r' | 'n' -> Space
+        | '0' .. '9'              -> Figure (Char.code s.[i] - Char.code '0')
+        | _                       -> Error
+   in
+   let rec aux i xv = match get_t i, xv with
+      | Error, _ 
+      | End, None        -> raise (Failure "int_of_string") 
+      | End, Some v      -> v
+      | Space, xv        -> aux (succ i) xv
+      | Figure f, None   -> aux (succ i) (Some f)
+      | Figure f, Some v -> aux (succ i) (Some (10 * v + f))
+   in
+   aux 0 None
+
+let int_of_set r =
+   try match r with 
+      | [s, _] -> my_int_of_string s
       | _      -> raise (Failure "int_of_string")
-   with Failure "int_of_string" -> raise (NumberError s)
+   with Failure "int_of_string" -> raise (NumberError r)
 
-let out_txt2 out commit n x1 x2 =
-   out "(" ; commit x1; out (" " ^ n ^ " "); commit x2; out ")"
+let out_txt2 o n x1 x2 =
+   o.s_out "(" ; o.s_query x1; o.s_out (" " ^ n ^ " "); o.s_query x2; o.s_out ")"
 
-let out_txt_ out path commit p xl = 
-   path p; out " {"; P.flat_list out commit ", " xl; out "}"    
+let out_txt_ o p xl =
+   if p <> [] then begin o.s_path p; o.s_out " " end;
+   o.s_out "{"; P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"    
 
-let out_txt_full out path commit p pl xl = 
-   path p; out " {"; P.flat_list out path ", " pl; out "} {";
-   P.flat_list out commit ", " xl; out "}"    
+let out_txt_full o p pl xl = 
+   o.s_path p; o.s_out " {"; P.flat_list o.s_out o.s_path ", " pl; o.s_out "} {";
+   P.flat_list o.s_out o.s_query ", " xl; o.s_out "}"    
 
 let arity0 n r =
    let arity_p = Const 0 in
    let arity_s = Const 0 in
-   let body _ _ _ _ = U.mql_true in
-   let txt_out s _ _ = s.out n in
+   let body _ _ _ _ _ = r in
+   let txt_out o _ _ = (std o).s_out n in
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
 let arity1 n f =
    let arity_p = Const 0 in
    let arity_s = Const 1 in
-   let body eval _ _ = function
-      | [x] -> f (eval x)
+   let body e _ _ _ = function
+      | [x] -> f (e.eval x)
       | _   -> assert false
    in
-   let txt_out out _ commit _ = function
-      | [x] -> out (n ^ " "); commit x
+   let txt_out o _ = function
+      | [x] -> let o = std o in o.s_out (n ^ " "); o.s_query x
       | _   -> assert false
    in   
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
@@ -102,28 +150,34 @@ let arity1 n f =
 let arity2 n f =
    let arity_p = Const 0 in
    let arity_s = Const 2 in
-   let body eval _ _ = function
-      | [x1; x2] -> f (eval x1) (eval x2)
+   let body e _ _ _ = function
+      | [x1; x2] -> f (e.eval x1) (e.eval x2)
       | _        -> assert false
    in
-   let txt_out out _ commit _ = function
-      | [x1; x2] -> out_txt2 out commit n x1 x2
+   let txt_out o _ = function
+      | [x1; x2] -> let o = std o in out_txt2 o n x1 x2
       | _        -> assert false
    in   
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
-let false_fun = arity0 "false" U.mql_false
+let false_fun b =
+   let s = if b then "false" else "empty" in 
+   arity0 s U.mql_false
 
 let true_fun = arity0 "true" U.mql_true
 
 let not_fun = 
    let aux r = if r = U.mql_false then U.mql_true else U.mql_false in
-   arity1 "not" aux 
+   arity1 "!" aux 
 
 let count_fun =
    let aux r = [string_of_int (List.length r), []] in
-   arity1 "count" aux
-   
+   arity1 "#" aux
+
+let peek_fun =
+   let aux = function [] -> [] | hd :: _ -> [hd] in
+   arity1 "peek" aux
+
 let diff_fun = arity2 "diff" U.mql_diff
 
 let xor_fun = arity2 "xor" U.xor
@@ -132,34 +186,99 @@ let sub_fun = arity2 "sub" U.set_sub
 
 let meet_fun = arity2 "meet" U.set_meet
 
-let eq_fun = arity2 "eq" U.set_eq
+let eq_fun = arity2 "==" U.set_eq
 
 let le_fun = 
    let le v1 v2 =
       if int_of_set v1 <= int_of_set v2 then U.mql_true else U.mql_false
    in
-   arity2 "le" le
+   arity2 "<=" le
 
 let lt_fun = 
    let lt v1 v2 =
       if int_of_set v1 < int_of_set v2 then U.mql_true else U.mql_false
    in
-   arity2 "lt" lt
+   arity2 "<" lt
 
 let stat_fun =
    let arity_p = Const 0 in
    let arity_s = Const 1 in
-   let body eval h _ = function
+   let body e o _ _ = function
       | [x] -> 
          let t = P.start_time () in
-        let r = (eval x) in
+        let r = (e.eval x) in
         let s = P.stop_time t in
-         C.log h (Printf.sprintf "Stat: %s,%i\n" s (List.length r));
+         o.out (Printf.sprintf "Stat: %s,%i\n" s (List.length r));
         r
       | _   -> assert false
    in
-   let txt_out out _ commit _ = function
-      | [x] -> out "stat "; commit x
+   let txt_out o _ = function
+      | [x] -> let o = std o in o.s_out "stat "; o.s_query x
+      | _   -> assert false
+   in   
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let log_fun xml src =
+   let log_src e o x =
+      let t = P.start_time () in o.s_query x;
+      let s = P.stop_time t in
+      if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log source: %s\n" s);
+      e.eval x 
+   in
+   let log_res e o x =  
+      let s = e.eval x in
+      let t = P.start_time () in o.s_result s;
+      let r = P.stop_time t in
+      if C.set e.conn C.Stat then o.s_out (Printf.sprintf "Log: %s\n" r); s
+   in
+   let txt_log o = 
+      if xml then o.s_out "xml ";
+      if src then o.s_out "source "
+   in
+   let arity_p = Const 0 in
+   let arity_s = Const 1 in
+   let body e o _ _ = function
+      | [x] -> let o = std o in if src then log_src e o x else log_res e o x
+      | _   -> assert false
+   in        
+   let txt_out o _ = function
+      | [x] -> let o = std o in o.s_out "log "; txt_log o; o.s_query x
+      | _   -> assert false
+   in   
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let render_fun = 
+   let arity_p = Const 0 in
+   let arity_s = Const 1 in
+   let body e o _ _ = function
+      | [x] -> 
+         let rs = ref "" in
+        let out s = rs := ! rs ^ s in 
+         o.result out " " (e.eval x);
+        [! rs, []]
+      | _   -> assert false
+   in
+   let txt_out o _ = function
+      | [x] -> let o = std o in o.s_out "render "; o.s_query x
+      | _   -> assert false
+   in   
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let read_fun = 
+   let arity_p = Const 0 in
+   let arity_s = Const 1 in
+   let body e o i _ = function
+      | [x] -> 
+         let aux av = 
+           let ich = open_in (fst av) in
+           let r = i.result_in (Lexing.from_channel ich) in
+           close_in ich; r
+        in
+        U.mql_iter aux (e.eval x)
+      | _   -> assert false
+   in
+   let txt_out o _ = function
+      | [x] -> let o = std o in o.s_out "read "; o.s_query x
       | _   -> assert false
    in   
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
@@ -171,14 +290,16 @@ let align_fun =
    in   
    let arity_p = Const 0 in
    let arity_s = Const 2 in
-   let body eval _ _ = function
+   let body e _ _ _ = function
       | [y; x] ->
-         let l = int_of_set (eval y) in
-         U.mql_iter (aux l) (eval x)      
+         let l = int_of_set (e.eval y) in
+         U.mql_iter (aux l) (e.eval x)      
       | _      -> assert false
    in
-   let txt_out out _ commit _ = function
-      | [y; x] -> out "align "; commit y; out " in "; commit x
+   let txt_out o _ = function
+      | [y; x] -> 
+         let o = std o in
+        o.s_out "align "; o.s_query y; o.s_out " in "; o.s_query x
       | _      -> assert false
    in
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
@@ -186,14 +307,16 @@ let align_fun =
 let if_fun =
    let arity_p = Const 0 in
    let arity_s = Const 3 in
-   let body eval _ _ = function
+   let body e _ _ _ = function
       | [y; x1; x2] ->
-         if (eval y) = U.mql_false then (eval x2) else (eval x1)
+         if (e.eval y) = U.mql_false then (e.eval x2) else (e.eval x1)
       | _           -> assert false
    in
-   let txt_out out _ commit _ = function
+   let txt_out o _ = function
       | [y; x1; x2] ->
-         out "if "; commit y; out " then "; commit x1; out " else "; commit x2
+         let o = std o in
+         o.s_out "if "; o.s_query y; o.s_out " then "; o.s_query x1; 
+        o.s_out " else "; o.s_query x2
       | _           -> assert false
    in
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
@@ -206,21 +329,19 @@ let intersect_fun =
    in
    let arity_p = Const 0 in
    let arity_s = Positive in
-   let body eval _ _ xl = iter eval xl in
-   let txt_out out path commit _ = function
+   let body e _ _ _ xl = iter e.eval xl in
+   let txt_out o _ = function
       | []           -> assert false
-      | [x1; x2]     -> out_txt2 out commit "intersect" x1 x2
-      | xl           -> out_txt_ out path commit ["intersect"] xl  
+      | [x1; x2]     -> let o = std o in out_txt2 o "/\\" x1 x2
+      | xl           -> let o = std o in out_txt_ o ["intersect"] xl  
    in   
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
 let union_fun = 
    let arity_p = Const 0 in
    let arity_s = Any in
-   let body eval _ _ xl = U.mql_iter eval xl in
-   let txt_out out path commit _ = function
-      | [x1; x2]     -> out_txt2 out commit "union" x1 x2
-      | xl           -> out_txt_ out path commit ["union"] xl  
+   let body e _ _ _ xl = U.mql_iter e.eval xl in
+   let txt_out o _ xl = let o = std o in out_txt_ o [] xl  
    in      
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
@@ -233,114 +354,158 @@ let or_fun =
    in
    let arity_p = Const 0 in
    let arity_s = Any in
-   let body eval _ _ xl = iter eval xl in
-   let txt_out out path commit _ = function
-      | [x1; x2]     -> out_txt2 out commit "or" x1 x2
-      | xl           -> out_txt_ out path commit ["or"] xl  
+   let body e _ _ _ xl = iter e.eval xl in
+   let txt_out o _ = function
+      | [x1; x2]     -> let o = std o in out_txt2 o "||" x1 x2
+      | xl           -> let o = std o in out_txt_ o ["or"] xl  
    in
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
 let and_fun = 
    let rec iter f = function
       | []           -> U.mql_true
+      | [head]       -> f head
       | head :: tail -> 
-         if f head = U.mql_false then U.mql_false else (iter f tail)
+         if f head = U.mql_false then U.mql_false else iter f tail
    in
    let arity_p = Const 0 in
    let arity_s = Any in
-   let body eval _ _ xl = iter eval xl in
-   let txt_out out path commit _ = function
-      | [x1; x2]     -> out_txt2 out commit "and" x1 x2
-      | xl           -> out_txt_ out path commit ["and"] xl  
+   let body e _ _ _ xl = iter e.eval xl in
+   let txt_out o _ = function 
+      | [x1; x2]  -> let o = std o in out_txt2 o "&&" x1 x2
+      | xl        -> let o = std o in out_txt_ o ["and"] xl
+   in
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let seq_fun = 
+   let rec iter f = function
+      | []           -> U.mql_true
+      | [head]       -> f head
+      | head :: tail -> ignore (f head); iter f tail
+   in
+   let arity_p = Const 0 in
+   let arity_s = Any in
+   let body e _ _ _ xl = iter e.eval xl in
+   let txt_out o _ = function 
+      | [x1; x2]  -> 
+         let o = std o in o.s_query x1; o.s_out " ;; "; o.s_query x2
+      | xl        -> let o = std o in out_txt_ o ["seq"] xl
+   in
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let proj_fun =
+   let proj_group_aux p (q, v) = if q = p then U.mql_subj v else [] in 
+   let proj_group p a = U.mql_iter (proj_group_aux p) a in
+   let proj_set p (_, g) = U.mql_iter (proj_group p) g in
+   let arity_p = Const 1 in
+   let arity_s = Const 1 in
+   let body e _ _ pl xl =
+      match pl, xl with
+         | [p], [x] -> U.mql_iter (proj_set p) (e.eval x)
+        | _        -> assert false
+   in
+   let txt_out o pl xl =
+      match pl, xl with
+         | [p], [x] -> 
+           let o = std o in
+           o.s_out "proj "; o.s_path p; o.s_out " of "; o.s_query x
+        | _        -> assert false
+   in
+   {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
+
+let keep_fun b =
+   let proj (r, _) = (r, []) in
+   let keep_path l (p, v) t = if List.mem p l = b then t else (p, v) :: t in
+   let keep_grp l a = List.fold_right (keep_path l) a [] in
+   let keep_set l a g = 
+      let kg = keep_grp l a in
+      if kg = [] then g else kg :: g
+   in
+   let keep_av l (s, g) = (s, List.fold_right (keep_set l) g []) in
+   let txt_allbut o = if b then o.s_out "allbut " in
+   let txt_path_list o l = P.flat_list o.s_out o.s_path ", " l in 
+   let arity_p = Any in
+   let arity_s = Const 1 in
+   let body e _ _ pl xl =
+      match b, pl, xl with
+         | true, [], [x]  -> e.eval x
+         | false, [], [x] -> List.map proj (e.eval x)
+         | _, l, [x]      -> List.map (keep_av l) (e.eval x)
+         | _              -> assert false
+  in
+  let txt_out o pl xl =
+      match pl, xl with
+         | [], [x] -> 
+           let o = std o in 
+           o.s_out "keep "; txt_allbut o; o.s_query x
+        | l, [x]  -> 
+           let o = std o in
+           o.s_out "keep "; txt_allbut o; txt_path_list o l; 
+           o.s_out " in "; o.s_query x
+        | _      -> assert false
    in
    {arity_p = arity_p; arity_s = arity_s; body = body; txt_out = txt_out}
 
 (* external functions interface *********************************************)
 
-let get_spec = function
-   | ["false"]     -> false_fun
-   | ["true"]      -> true_fun
-   | ["not"]       -> not_fun
-   | ["count"]     -> count_fun
-   | ["stat"]      -> stat_fun
-   | ["diff"]      -> diff_fun
-   | ["xor"]       -> xor_fun
-   | ["sub"]       -> sub_fun
-   | ["meet"]      -> meet_fun
-   | ["eq"]        -> eq_fun
-   | ["le"]        -> le_fun
-   | ["lt"]        -> lt_fun
-   | ["align"]     -> align_fun
-   | ["if"]        -> if_fun 
-   | ["intersect"] -> intersect_fun
-   | ["union"]     -> union_fun
-   | ["or"]        -> or_fun
-   | ["and"]       -> and_fun
-   | p             -> raise (NameError p) 
+let fun_get_spec = function
+   | ["empty"]                 -> false_fun false
+   | ["false"]                 -> false_fun true
+   | ["true"]                  -> true_fun
+   | ["not"]                   -> not_fun
+   | ["count"]                 -> count_fun
+   | ["stat"]                  -> stat_fun
+   | ["log"; "text"; "result"] -> log_fun false false
+   | ["log"; "text"; "source"] -> log_fun false true
+   | ["render"]                -> render_fun
+   | ["read"]                  -> read_fun
+   | ["peek"]                  -> peek_fun
+   | ["diff"]                  -> diff_fun
+   | ["xor"]                   -> xor_fun
+   | ["sub"]                   -> sub_fun
+   | ["meet"]                  -> meet_fun
+   | ["eq"]                    -> eq_fun
+   | ["le"]                    -> le_fun
+   | ["lt"]                    -> lt_fun
+   | ["align"]                 -> align_fun
+   | ["if"]                    -> if_fun 
+   | ["intersect"]             -> intersect_fun
+   | ["union"]                 -> union_fun
+   | ["or"]                    -> or_fun
+   | ["and"]                   -> and_fun 
+   | ["seq"]                   -> seq_fun
+   | ["proj"]                  -> proj_fun
+   | ["keep"; "these"]         -> keep_fun false
+   | ["keep"; "allbut"]        -> keep_fun true
+   | p                         -> raise (NameError p) 
    
-let check_arity p m n =
-   let aux i = function 
-      | Const k when i = k  -> ()
-      | Positive when i > 0 -> ()
-      | Any                 -> ()
-      | a                     -> raise (ArityError (p, a, i))
-   in   
-   aux m (get_spec p).arity_p; aux n (get_spec p).arity_s 
-
-let exec eval h p pl xl = (get_spec p).body eval h pl xl
-
-let txt_out out path commit p pl xl =
-   try (get_spec p).txt_out out path commit pl xl 
-   with NameError q when q = p -> out_txt_full out path commit p pl xl
-
-(*
-      | M.Proj (Some p) x -> out "proj "; txt_path out p; out "of "; txt_set x
-      | M.Log a b x       -> out "log "; txt_log a b; txt_set x
-      | M.Keep b l x      -> out "keep "; txt_allbut b; txt_path_list l;
-                             txt_set x
-   let txt_path_list l = P.flat_list out (txt_path out) ", " l in 
-   let txt_log a b = 
-      if a then out "xml ";
-      if b then out "source "
+let fun_arity p m n =
+   check_arity p m (fun_get_spec p).arity_p; 
+   check_arity p n (fun_get_spec p).arity_s 
+
+let fun_eval e o i p pl xl = (fun_get_spec p).body e o i pl xl
+
+let fun_txt_out o p pl xl =
+   try (fun_get_spec p).txt_out o pl xl 
+   with NameError q when q = p -> out_txt_full (std o) p pl xl
+
+(* generator functions implementation ***************************************)
+
+let helm_vars_gen =
+   let mk_let v s x = M.Let (v, M.Const [(s, [])], x) in 
+   let arity = Const 1 in
+   let code _ = function
+      | [x] -> mk_let "SET" "Set" x
+      | _   -> assert false
    in
-   let txt_allbut b = if b then out "allbut " in
-
-      | M.Proj None x -> List.map (fun (r, _) -> (r, [])) (eval_query c x)
-      | M.Proj (Some p) x -> 
-         let proj_group_aux (q, v) = if q = p then subj v else [] in 
-         let proj_group a = U.mql_iter proj_group_aux a in
-         let proj_set (_, g) = U.mql_iter proj_group g in
-         U.mql_iter proj_set (eval_query c x)
-
-
-      | M.Log _ b x ->
-         if b then begin
-           let t = P.start_time () in
-           F.text_of_query (C.log h) x "\n";
-           let s = P.stop_time t in
-           if C.set h C.Stat then 
-              C.log h (Printf.sprintf "Log source: %s\n" s);
-           eval_query c x
-        end else begin
-            let s = (eval_query c x) in
-           let t = P.start_time () in
-           F.text_of_result (C.log h) s "\n"; 
-           let r = P.stop_time t in
-           if C.set h C.Stat then 
-              C.log h (Printf.sprintf "Log: %s\n" r);
-           s
-        end
-
-      | M.Keep b l x -> 
-         let keep_path (p, v) t = 
-           if List.mem p l = b then t else (p, v) :: t in
-        let keep_grp a = List.fold_right keep_path a [] in
-         let keep_set a g = 
-           let kg = keep_grp a in
-           if kg = [] then g else kg :: g
-        in
-        let keep_av (s, g) = (s, List.fold_right keep_set g []) in
-        List.map keep_av (eval_query c x)
+   {arity = arity; code = code}
+
+(* generator functions interface ********************************************)
+
+let gen_get_spec = function
+   | ["helm"; "vars"] -> helm_vars_gen
+   | p                -> raise (NameError p) 
 
+let gen_arity p n = check_arity p n (gen_get_spec p).arity 
 
-*)      
+let gen_eval e p xl = (gen_get_spec p).code e xl