X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Focaml%2Fmathql_interpreter%2FmQueryInterpreter.ml;h=453b1643ce7fec85eef7483312848fde097f0298;hb=4167cea65ca58897d1a3dbb81ff95de5074700cc;hp=c1422b8ae50c1a6e6b586580da35cd4cb5325a86;hpb=39b9497090ee5cc501de1e3d9044d71fdc5cf1fb;p=helm.git diff --git a/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml b/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml index c1422b8ae..453b1643c 100644 --- a/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml +++ b/helm/ocaml/mathql_interpreter/mQueryInterpreter.ml @@ -23,205 +23,223 @@ * 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);; +(* AUTOR: Ferruccio Guidi + *) -exception BooleExpTrue - -(* valuta una MathQL.set_exp e ritorna un MathQL.resource_set *) +(* contexts *****************************************************************) -let galax_char = 'G' -let stat_char = 'S' +type svar_context = (MathQL.svar * MathQL.resource_set) list -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 *) +type avar_context = (MathQL.avar * MathQL.resource) list -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 +type group_context = (MathQL.avar * MathQL.attribute_group) list -(* valuta una MathQL.val_exp e ritorna un MathQL.value *) +type vvar_context = (MathQL.vvar * MathQL.value) list -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 context = {svars: svar_context; + avars: avar_context; + groups: group_context; (* auxiliary context *) + vvars: vvar_context + } -(* valuta una MathQL.set_exp nel contesto vuoto e ritorna un MathQL.resource_set *) -in - exec_set_exp {svars = []; rvars = []; groups = []; vvars = []} x +(* execute *****************************************************************) -(* new interface ***********************************************************) +exception Found -let execute handle x = execute_aux handle x +module M = MathQL +module P = MQueryUtil +module C = MQIConn +module U = MQIUtil +let execute h x = + let warn q = + if C.set h C.Warn then + begin + C.log h "MQIExecute: waring: reference to undefined variables: "; + P.text_of_query (C.log h) "\n" q + end + in + let rec eval_val c = function + | M.False -> U.mql_false + | M.True -> U.mql_true + | M.Const s -> [s] + | M.Set l -> U.iter (eval_val c) l + | M.Test (k,y1,y2) -> + let cand y1 y2 = + if eval_val c y1 = U.mql_false then U.mql_false else eval_val c y2 + in + let cor y1 y2 = + let v1 = eval_val c y1 in + if v1 = U.mql_false then eval_val c y2 else v1 + in + let h f y1 y2 = f (eval_val c y1) (eval_val c y2) in + let f = match k with + | M.And -> cand + | M.Or -> cor + | M.Xor -> h U.xor + | M.Sub -> h U.set_sub + | M.Meet -> h U.set_meet + | M.Eq -> h U.set_eq + | M.Le -> h U.le + | M.Lt -> h U.lt + in + f y1 y2 + | M.Not y -> + if eval_val c y = U.mql_false then U.mql_true else U.mql_false + | M.VVar i -> begin + try List.assoc i c.vvars + with Not_found -> warn (M.Subj (M.VVar i)); [] end + | M.Dot (i,p) -> begin + try List.assoc p (List.assoc i c.groups) + with Not_found -> warn (M.Subj (M.Dot (i,p))); [] end + | 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 v else [] in + let proj_group a = U.iter proj_group_aux a in + let proj_set (_, g) = U.iter proj_group g in + U.iter proj_set (eval_query c x) + | M.Ex (l,y) -> + let rec ex_aux h = function + | [] -> + let d = {c with groups = h} in + if eval_val 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.StatVal y -> + let t = P.start_time () in + let r = (eval_val c y) in + let s = P.stop_time t in + C.log h (Printf.sprintf "Stat: %s,%i\n" s (List.length r)); + r + | M.Count y -> [string_of_int (List.length (eval_val c y))] + | M.Align (s,y) -> U.iter (U.align s) (eval_val c y) + and eval_query c = function + | M.Empty -> [] + | M.Subj x -> + List.map (fun s -> (s, [])) (eval_val c x) + | M.Log (_,b,x) -> + if b then begin + let t = P.start_time () in + P.text_of_query (C.log h) "\n" x; + let s = P.stop_time t in + if C.set h C.Times 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 + P.text_of_result (C.log h) "\n" s; + let r = P.stop_time t in + if C.set h C.Times then + C.log h (Printf.sprintf "Log: %s\n" r); + s + end + | M.If (y,x1,x2) -> + if (eval_val c y) = U.mql_false + then (eval_query c x2) else (eval_query c x1) + | M.Bin (k,x1,x2) -> + let f = match k with + | M.BinFJoin -> U.mql_union + | M.BinFMeet -> U.mql_intersect + | M.BinFDiff -> U.mql_diff + in + f (eval_query c x1) (eval_query c x2) + | 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.LetSVar (i,x1,x2) -> + let d = {c with svars = U.set (i, eval_query c x1) c.svars} in + eval_query d x2 + | M.LetVVar (i,y,x) -> + let d = {c with vvars = U.set (i, eval_val c y) c.vvars} in + eval_query d x + | 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 = U.set (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_val c y) + else (q2 @ mc), (pat, [], eval_val c y) + in + let eval_cons (pat, p, y) = (pat, q2 @ p, eval_val 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.Times then + C.log h (Printf.sprintf "Property: %s,%i\n" s (List.length r)); + r + | M.StatQuery x -> + let t = P.start_time () in + let r = (eval_query c x) in + let s = P.stop_time t in + C.log h (Printf.sprintf "Stat: %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 = U.set (i, h) c.avars} in + if eval_val d y = U.mql_false + then select_aux t else h :: select_aux t + in + select_aux (eval_query c x) + | 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) + and eval_grp c = function + | M.Attr gs -> + let attr_aux g (p, y) = U.mql_union g [(p, eval_val 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 = []; vvars = []} in + let t = P.start_time () in + if C.set h C.Source then P.text_of_query (C.log h) "\n" x; + let r = eval_query c x in + if C.set h C.Result then P.text_of_result (C.log h) "\n" r; + let s = P.stop_time t in + if C.set h C.Times then + C.log h (Printf.sprintf "MQIExecute: %s,%s\n" s + (C.string_of_flags (C.flags h))); + r