]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/mathql_interpreter/mQueryInterpreter.ml
- New interface for the MathQL interpreter (1.3 version)
[helm.git] / helm / ocaml / mathql_interpreter / mQueryInterpreter.ml
diff --git a/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml b/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml
new file mode 100644 (file)
index 0000000..f320ebb
--- /dev/null
@@ -0,0 +1,264 @@
+(* Copyright (C) 2000, HELM Team.
+ * 
+ * This file is part of HELM, an Hypertextual, Electronic
+ * Library of Mathematics, developed at the Computer Science
+ * Department, University of Bologna, Italy.
+ * 
+ * HELM is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * HELM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HELM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA  02111-1307, USA.
+ * 
+ * For details, see the HELM World-Wide-Web page,
+ * 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 InvalidConnection
+exception ConnectionFailed of string
+
+exception BooleExpTrue
+  
+(* valuta una MathQL.set_exp e ritorna un MathQL.resource_set *)
+
+let galax_char = 'G'
+let stat_char = 'S'
+
+let execute_aux log m 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 (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 String.contains m stat_char then
+        log ("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 String.contains m stat_char then log ("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 String.contains m stat_char then begin
+          log ("LETIN " ^ svar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+          log (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 String.contains m stat_char then begin
+          log ("LETIN " ^ vvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+           log (X.stop_time before ^ "\n");
+        end;
+       res
+   | M.Relation (inv, rop, path, sexp, assl) -> 
+        let before = X.start_time() in
+       if String.contains m galax_char then begin
+           let res = relation_galax_ex inv rop path (exec_set_exp c sexp) assl in
+           if String.contains m stat_char then begin
+              log  ("RELATION-GALAX " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
+              log (X.stop_time before ^ "\n")
+          end;
+          res
+        end else begin 
+           let res = relation_ex inv rop path (exec_set_exp c sexp) assl in
+          if String.contains m stat_char then begin 
+             log ("RELATION " ^ (fst path) ^ " = " ^ string_of_int(List.length res) ^ ": ");
+              log (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 String.contains m stat_char then begin
+          log ("SELECT " ^ rvar ^ " = " ^ string_of_int (List.length res) ^ ": ");
+          log (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 *)
+
+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
+
+(* valuta una MathQL.val_exp e ritorna un MathQL.value *)
+
+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 s (exec_val_exp c vexp)
+   | M.Property (inv, rop, path, vexp) -> property_ex rop path inv (exec_val_exp c vexp) 
+
+(* valuta una MathQL.set_exp nel contesto vuoto e ritorna un MathQL.resource_set *)
+in
+   exec_set_exp {svars = []; rvars = []; groups = []; vvars = []} x 
+
+(* new interface  ***********************************************************)
+
+module type Callbacks = 
+   sig
+      val log : string -> unit (* logging function *)
+   end
+
+module Make (C: Callbacks) =
+   struct
+      
+      let postgres = "P"
+      let galax = "G"
+      let stat = "S"
+      let quiet = "Q"
+      let warn = "W"
+
+      let execute m x = execute_aux C.log m x
+
+      let init m =
+        let default_connection_string =
+            "host=mowgli.cs.unibo.it dbname=helm_mowgli_new_schema user=helm"
+       in
+       let connection_string =
+            try Sys.getenv "POSTGRESQL_CONNECTION_STRING"
+            with Not_found -> default_connection_string 
+        in
+       if String.contains m galax_char then true else
+          try Dbconn.init connection_string; true
+          with ConnectionFailed s -> false
+
+      let close m =
+         if String.contains m galax_char then () else Dbconn.close ()
+   
+      let check m =
+         if String.contains m galax_char then false else
+        try ignore (Dbconn.pgc ()); true with InvalidConnection -> false 
+        
+   end