]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/mathql_interpreter/mQueryInterpreter.ml
patched and some funtions added
[helm.git] / helm / ocaml / mathql_interpreter / mQueryInterpreter.ml
index c1422b8ae50c1a6e6b586580da35cd4cb5325a86..a459fe82954e9eaa02ca09e9c3d07bac31712dad 100644 (file)
  * http://cs.unibo.it/helm/.
  *)
 
-open Dbconn;;
-open Union;;
-open Intersect;;
-open Meet;;
-open Property;;
-open Sub;;
-open Context;;
-open Diff;;
-open Relation;;
-open Func;;
-open Pattern;;
-
-exception SVarUnbound of string;;
-exception RVarUnbound of string;;
-exception VVarUnbound of string;;
-exception PathUnbound of (string * string list);;
-
-exception BooleExpTrue
-  
-(* valuta una MathQL.set_exp e ritorna un MathQL.resource_set *)
-
-let galax_char = 'G'
-let stat_char = 'S'
+(*  AUTOR: Ferruccio Guidi <fguidi@cs.unibo.it>
+ *)
 
-let execute_aux handle x =
-   let module M = MathQL in
-   let module X = MQueryMisc in
-let rec exec_set_exp c = function
-     M.SVar svar ->
-      (try
-        List.assoc svar c.svars
-       with Not_found ->
-        raise (SVarUnbound svar))
-   | M.RVar rvar ->
-      (try
-        [List.assoc rvar c.rvars]  
-       with Not_found ->
-        raise (RVarUnbound rvar))
-   | M.Ref vexp -> List.map (fun s -> (s,[])) (exec_val_exp c vexp)
-   | M.Pattern vexp -> pattern_ex handle (exec_val_exp c vexp)
-   | M.Intersect (sexp1, sexp2) ->    
-        let before = X.start_time() in
-       let rs1 = exec_set_exp c sexp1 in
-       let rs2 = exec_set_exp c sexp2 in
-        let res = intersect_ex rs1 rs2 in
-        let diff = X.stop_time before in
-        let ll1 = string_of_int (List.length rs1) in
-        let ll2 = string_of_int (List.length rs2) in
-       if MQIConn.set handle MQIConn.Stat then
-        MQIConn.log handle ("INTERSECT(" ^ ll1 ^ "," ^ ll2 ^ ") = " ^ string_of_int (List.length res) ^
-         ": " ^ diff ^ "\n");
-        res
-   | M.Union (sexp1, sexp2) -> 
-        let before = X.start_time () in
-       let res = union_ex (exec_set_exp c sexp1) (exec_set_exp c sexp2) in
-       let diff = X.stop_time before in
-        if MQIConn.set handle MQIConn.Stat then MQIConn.log handle ("UNION: " ^ diff ^ "\n");
-        res                    
-   | M.LetSVar (svar, sexp1, sexp2) ->
-        let before = X.start_time() in
-        let c1 = upd_svars c ((svar, exec_set_exp c sexp1) :: c.svars) in 
-       let res = exec_set_exp c1 sexp2 in
-       if MQIConn.set handle MQIConn.Stat then begin
-          MQIConn.log handle ("LETIN " ^ svar ^ " = " ^ string_of_int (List.length res) ^ ": ");
-          MQIConn.log handle (X.stop_time before ^ "\n");
-        end;
-       res                     
-   | M.LetVVar (vvar, vexp, sexp) ->
-        let before = X.start_time() in
-       let c1 = upd_vvars c ((vvar, exec_val_exp c vexp) :: c.vvars) in
-       let res = exec_set_exp c1 sexp in
-       if MQIConn.set handle MQIConn.Stat then begin
-          MQIConn.log handle ("LETIN " ^ vvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
-           MQIConn.log handle (X.stop_time before ^ "\n");
-        end;
-       res
-   | M.Relation (inv, rop, path, sexp, assl) -> 
-        let before = X.start_time() in
-       if MQIConn.set handle MQIConn.Galax  then begin
-           let res = relation_galax_ex handle inv rop path (exec_set_exp c sexp) assl in
-           if MQIConn.set handle MQIConn.Stat then begin
-              MQIConn.log handle  ("RELATION-GALAX " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
-              MQIConn.log handle (X.stop_time before ^ "\n")
-          end;
-          res
-        end else begin 
-           let res = relation_ex handle inv rop path (exec_set_exp c sexp) assl in
-          if MQIConn.set handle MQIConn.Stat then begin 
-             MQIConn.log handle ("RELATION " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
-              MQIConn.log handle (X.stop_time before ^ "\n")
-           end;
-           res
-       end
-   | M.Select (rvar, sexp, bexp) ->
-        let before = X.start_time() in
-        let rset = (exec_set_exp c sexp) in
-        let rec select_ex =
-         function
-           [] -> []
-         | r::tl -> 
-             let c1 = upd_rvars c ((rvar,r)::c.rvars) in                      
-              if (exec_boole_exp c1 bexp) then
-               r::(select_ex tl)
-              else
-               select_ex tl
-        in 
-       let res = select_ex rset in
-       if MQIConn.set handle MQIConn.Stat then begin
-          MQIConn.log handle ("SELECT " ^ rvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
-          MQIConn.log handle (X.stop_time before ^ "\n");
-        end;
-       res
-   | M.Diff (sexp1, sexp2) -> diff_ex (exec_set_exp c sexp1) (exec_set_exp c sexp2)
-   
-(* valuta una MathQL.boole_exp e ritorna un boole *)
+exception Found
 
-and exec_boole_exp c =
- function
-    M.False      -> false
-  | M.True       -> true
-  | M.Not x      -> not (exec_boole_exp c x)
-  | M.And (x, y) -> (exec_boole_exp c x) && (exec_boole_exp c y)
-  | M.Or (x, y)  -> (exec_boole_exp c x) || (exec_boole_exp c y)
-  | M.Sub (vexp1, vexp2) ->
-     sub_ex (exec_val_exp c vexp1) (exec_val_exp c vexp2)
-  | M.Meet (vexp1, vexp2) ->
-     meet_ex (exec_val_exp c vexp1) (exec_val_exp c vexp2)
-  | M.Eq (vexp1, vexp2) -> (exec_val_exp c vexp1) = (exec_val_exp c vexp2)
-  | M.Ex l bexp -> 
-     if l = [] then
-      (exec_boole_exp c bexp)
-     else
-        let latt =
-          List.map
-           (fun uri -> 
-             let (r,attl) =
-              (try
-                List.assoc uri c.rvars
-               with Not_found -> assert false)
-             in
-              (uri,attl)
-           ) l (*latt = l + attributi*)
-        in
-         try
-          let rec prod c =
-            function
-              [] -> if (exec_boole_exp c bexp) then raise BooleExpTrue 
-            | (uri,attl)::tail1 ->
-                 (*per ogni el. di attl devo andare in ric. su tail1*)
-                 let rec sub_prod attl =
-                  match attl with
-                     [] -> () 
-                   | att::tail2 ->
-                      let c1 = upd_groups c ((uri,att)::c.groups) in
-                       prod c1 tail1; sub_prod tail2 
-                 in          
-                  sub_prod attl 
-          in
-           prod c latt;
-            false
-         with BooleExpTrue -> true
+module M = MathQL
+module P = MQueryUtil 
+module C = MQIConn
+module U = MQIUtil
+module L = MQILib
+module F = MQueryIO
 
-(* valuta una MathQL.val_exp e ritorna un MathQL.value *)
+(* contexts *****************************************************************)
 
-and exec_val_exp c = function
-     M.Const x -> let
-        ol = List.sort compare x in 
-                       let rec edup = function
-                       
-                          [] -> [] 
-                        | s::tl -> if tl <> [] then  
-                                                if s = (List.hd tl) then edup tl
-                                                else s::(edup tl)
-                                   else s::[]
-                       in
-                        edup ol
-   | M.Record (rvar, path) ->
-      (try
-        List.assoc path
-         (try
-           List.assoc rvar c.groups
-          with Not_found ->
-           raise (RVarUnbound rvar))
-       with Not_found ->
-        raise (PathUnbound path))
-   | M.VVar s ->
-      (try
-        List.assoc s c.vvars
-       with Not_found ->
-        raise (VVarUnbound s))
-   | M.RefOf sexp -> List.map (fun (s,_) -> s) (exec_set_exp c sexp)
-   | M.Fun (s, vexp) -> fun_ex handle s (exec_val_exp c vexp)
-   | M.Property (inv, rop, path, vexp) -> property_ex handle rop path inv (exec_val_exp c vexp) 
+type svar_context = (M.svar * M.resource_set) list
 
-(* valuta una MathQL.set_exp nel contesto vuoto e ritorna un MathQL.resource_set *)
-in
-   exec_set_exp {svars = []; rvars = []; groups = []; vvars = []} x 
+type avar_context = (M.avar * M.resource) list
 
-(* new interface  ***********************************************************)
+type group_context = (M.avar * M.attribute_group) list
 
-let execute handle x = execute_aux handle x
+type context = {svars: svar_context;   
+                avars: avar_context;   
+                groups: group_context (* auxiliary context *)  
+               }
+              
+(* execute ******************************************************************)
 
+let execute h x =
+   let warn q = 
+     if C.set h C.Warn then 
+     begin
+        C.log h "MQIExecute: waring: reference to undefined variables: ";
+       F.text_of_query (C.log h) "\n" q
+     end
+   in
+   let proj v = List.map fst v in
+   let rec eval_query c = function
+      | M.Const r -> r
+      | M.Dot i p -> begin
+         try U.mql_subj (List.assoc p (List.assoc i c.groups)) 
+        with Not_found -> warn (M.Dot i p); [] end
+      | M.Ex l y -> 
+         let rec ex_aux h = function
+           | []        -> 
+              let d = {c with groups = h} in
+               if eval_query d y = U.mql_false then () else raise Found 
+           | i :: tail -> 
+               begin
+                 try 
+                    let (_, a) = List.assoc i c.avars in 
+                    let rec add_group = function
+                       | []     -> ()
+                       | g :: t -> ex_aux ((i, g) :: h) tail; add_group t 
+                    in
+                    add_group a
+                 with Not_found -> ()
+              end
+         in
+        (try ex_aux [] l; U.mql_false with Found -> U.mql_true)
+      | M.SVar i -> begin
+         try List.assoc i c.svars 
+        with Not_found -> warn (M.SVar i); [] end  
+      | M.AVar i -> begin
+         try [List.assoc i c.avars] 
+        with Not_found -> warn (M.AVar i); [] end
+      | M.Let i x1 x2 ->
+        let d = {c with svars = P.add_assoc (i, eval_query c x1) c.svars} in
+         eval_query d x2
+      | M.For k i x1 x2 ->
+         let f = match k with
+           | M.GenFJoin -> U.mql_union
+           | M.GenFMeet -> U.mql_intersect
+        in
+         let rec for_aux = function
+           | []     -> []
+           | h :: t ->
+              let d = {c with avars = P.add_assoc (i, h) c.avars} in
+              f (eval_query d x2) (for_aux t)
+        in
+        for_aux (eval_query c x1)
+      | M.Add b z x ->
+         let f = if b then U.mql_prod else U.set_union in
+        let g a s = (fst a, f (snd a) (eval_grp c z)) :: s in
+        List.fold_right g (eval_query c x) []
+      | M.Property q0 q1 q2 mc ct cfl el pat y ->
+        let subj, mct = 
+           if q0 then [], (pat, q2 @ mc, eval_query c y)
+                 else (q2 @ mc), (pat, [], eval_query c y)  
+        in
+         let eval_cons (pat, p, y) = (pat, q2 @ p, eval_query c y) in
+        let cons_true = mct :: List.map eval_cons ct in
+        let cons_false = List.map (List.map eval_cons) cfl in
+        let eval_exp (p, po) = (q2 @ p, po) in
+        let exp = List.map eval_exp el in
+        let t = P.start_time () in
+        let r = MQIProperty.exec h q1 subj cons_true cons_false exp in 
+        let s = P.stop_time t in
+         if C.set h C.Stat then 
+           C.log h (Printf.sprintf "Property: %s,%i\n" s (List.length r));
+        r 
+      | M.Select i x y ->
+         let rec select_aux = function
+           | []     -> []
+           | h :: t ->
+              let d = {c with avars = P.add_assoc (i, h) c.avars} in
+              if eval_query d y = U.mql_false 
+                 then select_aux t else h :: select_aux t
+        in
+        select_aux (eval_query c x)
+      | M.Fun p pl xl -> 
+         let e = {L.eval = eval_query c; L.conn = h} in
+         L.eval e (F.text_out_spec (C.log h) "\n") F.text_in_spec 
+            p pl xl
+   and eval_grp c = function
+      | M.Attr gs ->
+         let attr_aux g (p, y) = U.mql_union g [p, proj (eval_query c y)] in
+        let attr_auxs s l = U.set_union s [List.fold_left attr_aux [] l] in
+        List.fold_left attr_auxs [] gs
+      | M.From i ->
+         try snd (List.assoc i c.avars) 
+        with Not_found -> warn (M.AVar i); []
+   in
+   let c = {svars = []; avars = []; groups = []} in
+   let t = P.start_time () in
+   let r = eval_query c x in
+   let s = P.stop_time t in
+   if C.set h C.Stat then 
+      C.log h (Printf.sprintf "MQIExecute: %s,%s\n" s 
+         (C.string_of_flags (C.flags h)));
+   r