]> matita.cs.unibo.it Git - helm.git/blob - helm/gTopLevel/mQueryGenerator.ml
b91261c07769a32d09de650dfa460bb87f6ec518
[helm.git] / helm / gTopLevel / mQueryGenerator.ml
1 (* Copyright (C) 2000, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (******************************************************************************)
27 (*                                                                            *)
28 (*                               PROJECT HELM                                 *)
29 (*                                                                            *)
30 (*                     Ferruccio Guidi <fguidi@cs.unibo.it>                   *)
31 (*                                 30/04/2002                                 *)
32 (*                                                                            *)
33 (*                                                                            *)
34 (******************************************************************************)
35
36 (* level managing functions *************************************************)
37
38 type levels_spec = (string * bool * int) list
39
40 let levels_of_term metasenv context term =
41    let module TC = CicTypeChecker in
42    let module Red = CicReduction in
43    let module Util = MQueryUtil in
44    let degree t =
45       let rec degree_aux = function
46          | Cic.Sort _         -> 1 
47          | Cic.Cast (u, _)    -> degree_aux u
48          | Cic.Prod (_, _, t) -> degree_aux t
49          | _                  -> 2
50       in 
51       let u = TC.type_of_aux' metasenv context t in
52       degree_aux (Red.whd context u)
53    in
54    let entry_eq (s1, b1, v1) (s2, b2, v2) =
55       s1 = s2 && b1 = b2 
56    in
57    let rec entry_in e = function
58       | []           -> [e]
59       | head :: tail -> 
60          head :: if entry_eq head e then tail else entry_in e tail
61    in
62    let inspect_uri main l uri tc v term =
63       let d = degree term in 
64       entry_in (Util.string_of_uriref (uri, tc), main, 2 * v + d - 1) l 
65    in
66    let rec inspect_term main l v term = match term with
67         Cic.Rel _                        -> l
68       | Cic.Meta _                       -> l
69       | Cic.Sort _                       -> l 
70       | Cic.Implicit                     -> l 
71       | Cic.Var (u,exp_named_subst)      ->
72          let l' = inspect_uri main l u [] v term in
73           inspect_exp_named_subst l' (v+1) exp_named_subst
74       | Cic.Const (u,exp_named_subst)    ->
75          let l' = inspect_uri main l u [] v term in
76           inspect_exp_named_subst l' (v+1) exp_named_subst
77       | Cic.MutInd (u, t, exp_named_subst) ->
78          let l' = inspect_uri main l u [t] v term in
79           inspect_exp_named_subst l' (v+1) exp_named_subst
80       | Cic.MutConstruct (u, t, c, exp_named_subst)    ->
81          let l' = inspect_uri main l u [t; c] v term in
82           inspect_exp_named_subst l' (v+1) exp_named_subst
83       | Cic.Cast (uu, _)                 -> 
84          inspect_term main l v uu
85       | Cic.Prod (_, uu, tt)             ->
86          let luu = inspect_term false l (v + 1) uu in
87          inspect_term main luu (v + 1) tt         
88       | Cic.Lambda (_, uu, tt)           ->
89          let luu = inspect_term false l (v + 1) uu in
90          inspect_term false luu (v + 1) tt 
91       | Cic.LetIn (_, uu, tt)            ->
92          let luu = inspect_term false l (v + 1) uu in
93          inspect_term false luu (v + 1) tt
94       | Cic.Appl m                       -> inspect_list main l true v m 
95       | Cic.MutCase (u, t, tt, uu, m) -> 
96          let lu = inspect_uri main l u [t] (v + 1) term in
97          let ltt = inspect_term false lu (v + 1) tt in
98          let luu = inspect_term false ltt (v + 1) uu in
99          inspect_list main luu false (v + 1) m
100       | Cic.Fix (_, m)                   -> inspect_ind l (v + 1) m 
101       | Cic.CoFix (_, m)                 -> inspect_coind l (v + 1) m 
102    and inspect_list main l head v = function
103       | []      -> l
104       | tt :: m -> 
105          let ltt = inspect_term main l (if head then v else v + 1) tt in
106          inspect_list false ltt false v m
107    and inspect_exp_named_subst l v = function
108         []      -> l
109       | (_,t) :: tl -> 
110          let l' = inspect_term false l v t in
111           inspect_exp_named_subst l' v tl
112    and inspect_ind l v = function
113       | []                  -> l
114       | (_, _, tt, uu) :: m ->  
115          let ltt = inspect_term false l v tt in
116          let luu = inspect_term false ltt v uu in
117          inspect_ind luu v m
118    and inspect_coind l v = function
119       | []               -> l
120       | (_, tt, uu) :: m ->
121          let ltt = inspect_term false l v tt in
122          let luu = inspect_term false ltt v uu in
123          inspect_coind luu v m
124    in
125    let rec inspect_backbone = function
126       | Cic.Cast (uu, _)      -> inspect_backbone uu
127       | Cic.Prod (_, _, tt)   -> inspect_backbone tt                
128       | Cic.LetIn (_, uu, tt) -> inspect_backbone tt
129       | t                     -> inspect_term true [] 0 t
130    in 
131    inspect_backbone term  
132
133 let string_of_levels l sep =
134    let entry_out (s, b, v) =
135       let pos = if b then " HEAD: " else " TAIL: " in
136       string_of_int v ^ pos ^ s ^ sep 
137    in
138    let rec levels_out = function
139       | []           -> ""
140       | head :: tail -> entry_out head ^ levels_out tail
141    in
142    levels_out l
143
144 (* Query issuing functions **************************************************)
145
146 exception Discard  
147
148 let nl = " <p>\n"
149
150 let query_num = ref 1
151
152 let log_file = ref ""
153
154 let confirm_query = ref (fun _ -> true)
155
156 let info = ref []
157
158 let set_log_file f = 
159    log_file := f
160
161 let set_confirm_query f =
162    confirm_query := f
163
164 let get_query_info () = ! info
165
166 let execute_query query =
167    let module Util = MQueryUtil in
168    let mode = [Open_wronly; Open_append; Open_creat; Open_text] in
169    let perm = 64 * 6 + 8 * 6 + 4 in
170    let time () =
171       let lt = Unix.localtime (Unix.time ()) in
172       "NEW LOG: " ^
173       string_of_int (lt.Unix.tm_mon + 1) ^ "-" ^
174       string_of_int (lt.Unix.tm_mday + 1) ^ "-" ^
175       string_of_int (lt.Unix.tm_year + 1900) ^ " " ^
176       string_of_int (lt.Unix.tm_hour) ^ ":" ^
177       string_of_int (lt.Unix.tm_min) ^ ":" ^
178       string_of_int (lt.Unix.tm_sec) 
179    in
180    let log q r = 
181       let och = open_out_gen mode perm ! log_file in
182       if ! query_num = 1 then output_string och (time () ^ nl);
183       let str =
184        "Query: " ^ string_of_int ! query_num ^ nl ^ Util.text_of_query q ^ nl ^ 
185        "Result:" ^ nl ^ Util.text_of_result r nl in
186       output_string och str; 
187       flush och 
188    in
189    let execute q =
190       let r = Mqint.execute q in    
191       if ! log_file <> "" then log q r; 
192       info := string_of_int ! query_num :: ! info;
193       incr query_num;
194       r
195    in 
196    if ! confirm_query query then execute query else raise Discard
197                           
198 (* Query building functions  ************************************************)   
199
200 let locate s =
201    let module M = MathQL in
202    let q =
203     M.Ref (M.Attribute true M.RefineExact ("objectName", []) (M.Const [s]))
204    in
205     execute_query q
206
207 let searchPattern e c t level =
208    let module M = MathQL in
209    let v_pos = M.Const ["MainConclusion"; "InConclusion"] in
210    let q_where =
211     M.Sub
212      (M.RefOf
213        (M.Select
214          ("uri", 
215            M.Relation
216             (false, M.RefineExact, ("refObj", []), M.RVar "uri0", ["pos"]),
217            M.Ex ["uri"]
218             (M.Meet (M.VVar "positions", M.Record ("uri", ("pos", []))))
219           )
220        ),
221        M.VVar "universe"
222      ) in
223    let uri_of_entry (r, b, v) = r in
224    let rec restrict level = function
225       | []                -> []
226       | (u, b, v) :: tail ->
227          if v <= level then (u, b, v) :: restrict level tail
228          else restrict level tail
229    in
230    let build_select (r, b, v) =
231     let pos = if b then "MainConclusion" else "InConclusion" in
232       M.Select
233        ("uri", 
234         M.Relation
235          (false,
236           M.RefineExact,
237           ("backPointer", []),
238           M.Ref (M.Const [r]),
239           ["pos"]),
240         M.Ex ["uri"] (M.Sub (M.Const [pos], M.Record ("uri", ("pos", []))))) in 
241    let rec build_intersect = function
242       | []       -> M.Pattern (M.Const [".*"])
243       | [hd]     -> build_select hd
244       | hd :: tl -> M.Intersect (build_select hd, build_intersect tl)
245    in
246    let levels = levels_of_term e c t in
247    let rest = restrict level levels in
248    info := [string_of_int (List.length rest)];
249    let q_in = build_intersect rest in
250    let q_select = M.Select ("uri0", q_in, q_where) in
251    let universe = M.Const (List.map uri_of_entry levels) in
252    let q_let_u = M.LetVVar ("universe", universe, q_select) in
253    let q_let_p = M.LetVVar ("positions", v_pos, q_let_u) in
254    execute_query q_let_p