]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/content_pres/acic2Procedural.ml
9b8dbf06383143c7759c9b7f06bb1c95df6ec83a
[helm.git] / helm / software / components / content_pres / acic2Procedural.ml
1 (* Copyright (C) 2003-2005, 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 module C    = Cic
27 module L    = CicClassify
28 module P    = ProceduralTypes
29 module D    = Deannotate
30 module DTI  = DoubleTypeInference
31 module TC   = CicTypeChecker 
32 module U    = CicUniv
33 module UM   = UriManager
34 module Obj  = LibraryObjects
35 module HObj = HelmLibraryObjects
36 module A    = Cic2acic
37 module T    = CicUtil
38
39 type status = {
40    sorts : (C.id, Cic2acic.sort_kind) Hashtbl.t;
41    types : (C.id, A.anntypes) Hashtbl.t;
42    prefix: string;
43    max_depth: int option;
44    depth: int;
45    entries: C.context;
46    intros: string list
47 }
48
49 (* helpers ******************************************************************)
50
51 let cic = D.deannotate_term
52
53 let split2_last l1 l2 =
54 try
55    let n = pred (List.length l1) in
56    let before1, after1 = P.list_split n l1 in
57    let before2, after2 = P.list_split n l2 in
58    before1, before2, List.hd after1, List.hd after2
59 with Invalid_argument _ -> failwith "A2P.split2_last"
60
61 let string_of_head = function
62    | C.ASort _         -> "sort"
63    | C.AConst _        -> "const"
64    | C.AMutInd _       -> "mutind"
65    | C.AMutConstruct _ -> "mutconstruct"
66    | C.AVar _          -> "var"
67    | C.ARel _          -> "rel"
68    | C.AProd _         -> "prod"
69    | C.ALambda _       -> "lambda"
70    | C.ALetIn _        -> "letin"
71    | C.AFix _          -> "fix"
72    | C.ACoFix _        -> "cofix"
73    | C.AAppl _         -> "appl"
74    | C.ACast _         -> "cast"
75    | C.AMutCase _      -> "mutcase"
76    | C.AMeta _         -> "meta"
77    | C.AImplicit _     -> "implict"
78
79 let next st = {st with depth = succ st.depth; intros = []}
80
81 let add st entry intro = 
82    {st with entries = entry :: st.entries; intros = intro :: st.intros}
83
84 let test_depth st =
85 try   
86    let msg = Printf.sprintf "Depth %u: " st.depth in
87    match st.max_depth with
88       | None   -> true, "" 
89       | Some d -> 
90          if st.depth < d then true, msg else false, "DEPTH EXCEDED"
91 with Invalid_argument _ -> failwith "A2P.test_depth"
92
93 let get_itype st v =
94 try
95    let id = T.id_of_annterm v in
96    try Some ((Hashtbl.find st.types id).A.annsynthesized)
97    with Not_found -> None
98 with Invalid_argument _ -> failwith "A2P.get_itype"
99
100 (* proof construction *******************************************************)
101
102 let unused_premise = "UNUSED"
103
104 let get_intro name t = 
105 try
106 match name with 
107    | C.Anonymous -> unused_premise
108    | C.Name s    -> 
109       if DTI.does_not_occur 1 (cic t) then unused_premise else s
110 with Invalid_argument _ -> failwith "A2P.get_intro"
111
112 let mk_intros st script =
113 try
114    if st.intros = [] then script else
115    let count = List.length st.intros in
116    P.Intros (Some count, List.rev st.intros, "") :: script
117 with Invalid_argument _ -> failwith "A2P.mk_intros"
118
119 let is_rewrite_right = function
120    | C.AConst (_, uri, []) ->
121       UM.eq uri HObj.Logic.eq_ind_r_URI || Obj.is_eq_ind_r_URI uri
122    | _                     -> false
123
124 let is_rewrite_left = function
125    | C.AConst (_, uri, []) ->
126       UM.eq uri HObj.Logic.eq_ind_URI || Obj.is_eq_ind_URI uri
127    | _                     -> false
128
129 let mk_premise = function
130    | C.ARel (_, _, _, binder) -> binder
131    | C.AVar (_, uri, _)
132    | C.AConst (_, uri, _)                  -> UM.name_of_uri uri
133    | C.ASort (_, sort)                     -> assert false
134    | C.AMutInd (_, uri, tno, _)            -> assert false
135    | C.AMutConstruct (_, uri, tno, cno, _) -> assert false
136    | _                                     -> assert false
137
138 let rec mk_fwd_proof st dtext name = function
139    | C.AAppl (_, hd :: tl) as v -> 
140       if is_rewrite_right hd then
141          let what, where = List.nth tl 5, List.nth tl 3 in
142          let premise = mk_premise where in
143          [P.Rewrite (true, what, Some (premise, name), dtext)] 
144       else if is_rewrite_left hd then
145          let what, where = List.nth tl 5, List.nth tl 3 in
146          let premise = mk_premise where in
147          [P.Rewrite (false, what, Some (premise, name), dtext)]
148       else begin match get_itype st v with
149          | Some ty ->
150             let qs = [[P.Id ""]; mk_proof (next st) v] in
151             [P.Branch (qs, ""); P.Cut (name, ty, dtext)]
152          | None    ->         
153             let ty, _ = TC.type_of_aux' [] st.entries (cic hd) U.empty_ugraph in
154             let (classes, rc) as h = L.classify ty in
155             let text = Printf.sprintf "%u %s" (List.length classes) (L.to_string h) in
156             [P.LetIn (name, v, dtext ^ text)]
157       end
158    | v                          -> 
159       [P.LetIn (name, v, dtext)] 
160
161 and mk_proof st = function
162    | C.ALambda (_, name, v, t) -> 
163       let entry = Some (name, C.Decl (cic v)) in
164       let intro = get_intro name t in
165       mk_proof (add st entry intro) t
166    | C.ALetIn (_, name, v, t) as what ->
167       let proceed, dtext = test_depth st in
168       let script = if proceed then 
169          let entry = Some (name, C.Def (cic v, None)) in
170          let intro = get_intro name t in
171          let q = mk_proof (next (add st entry intro)) t in
172          List.rev_append (mk_fwd_proof st dtext intro v) q
173       else
174          [P.Apply (what, dtext)]
175       in
176       mk_intros st script
177    | C.ARel _ as what           ->
178       let _, dtext = test_depth st in
179       let script = [P.Apply (what, dtext)] in 
180       mk_intros st script
181    | C.AAppl (_, hd :: tl) as t  ->
182       let proceed, dtext = test_depth st in
183       let script = if proceed then
184          let ty, _ = TC.type_of_aux' [] st.entries (cic hd) U.empty_ugraph in
185          let (classes, rc) as h = L.classify ty in
186          let synth = L.S.singleton 0 in
187          let text = Printf.sprintf "%u %s" (List.length classes) (L.to_string h) in
188          match rc with
189             | Some (i, j) when i > 1 ->
190                let classes, tl, _, what = split2_last classes tl in
191                let synth = L.S.add 1 synth in
192                let qs = mk_bkd_proofs (next st) synth classes tl in
193                if is_rewrite_right hd then 
194                   [P.Rewrite (false, what, None, dtext); P.Branch (qs, "")]
195                else if is_rewrite_left hd then 
196                   [P.Rewrite (true, what, None, dtext); P.Branch (qs, "")]
197                else   
198                   let using = Some hd in
199                   [P.Elim (what, using, dtext ^ text); P.Branch (qs, "")]
200             | _                                             ->
201                let qs = mk_bkd_proofs (next st) synth classes tl in
202                [P.Apply (hd, dtext ^ text); P.Branch (qs, "")]
203       else
204          [P.Apply (t, dtext)]
205       in
206       mk_intros st script
207    | t ->
208       let text = Printf.sprintf "%s: %s" "UNEXPANDED" (string_of_head t) in
209       let script = [P.Note text] in
210       mk_intros st script
211
212 and mk_bkd_proofs st synth classes ts =
213 try 
214    let _, dtext = test_depth st in   
215    let aux inv v =
216       if L.overlaps synth inv then None else
217       if L.S.is_empty inv then Some (mk_proof st v) else
218       Some [P.Apply (v, dtext ^ "dependent")]
219    in
220    let l1, l2 = List.length classes, List.length ts in
221    if l1 > l2 then failwith "partial application" else
222    if l1 < l2 then failwith "too many arguments" else
223    P.list_map2_filter aux classes ts
224 with Invalid_argument _ -> failwith "A2P.mk_bkd_proofs"
225
226 (* object costruction *******************************************************)
227
228 let is_theorem pars =   
229    List.mem (`Flavour `Theorem) pars || List.mem (`Flavour `Fact) pars || 
230    List.mem (`Flavour `Remark) pars || List.mem (`Flavour `Lemma) pars
231
232 let mk_obj st = function
233    | C.AConstant (_, _, s, Some v, t, [], pars) when is_theorem pars ->
234       let ast = mk_proof st v in
235       let count = P.count_steps 0 ast in
236       let text = Printf.sprintf "tactics: %u" count in
237       P.Theorem (s, t, text) :: ast @ [P.Qed ""]
238    | _                                                               ->
239       failwith "not a theorem"
240
241 (* interface functions ******************************************************)
242
243 let acic2procedural ~ids_to_inner_sorts ~ids_to_inner_types prefix aobj = 
244    let st = {
245       sorts     = ids_to_inner_sorts;
246       types     = ids_to_inner_types;
247       prefix    = prefix;
248       max_depth = None;
249       depth     = 0;
250       entries   = [];
251       intros    = []
252    } in
253    prerr_endline "Level 2 transformation";
254    let steps = mk_obj st aobj in
255    prerr_endline "grafite rendering";
256    List.rev (P.render_steps [] steps)