]> matita.cs.unibo.it Git - helm.git/blob - components/content_pres/acic2Procedural.ml
- tactics:
[helm.git] / 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 : (Cic.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    let n = pred (List.length l1) in
55    let before1, after1 = P.list_split n l1 in
56    let before2, after2 = P.list_split n l2 in
57    before1, before2, List.hd after1, List.hd after2
58
59 let string_of_head = function
60    | C.ASort _         -> "sort"
61    | C.AConst _        -> "const"
62    | C.AMutInd _       -> "mutind"
63    | C.AMutConstruct _ -> "mutconstruct"
64    | C.AVar _          -> "var"
65    | C.ARel _          -> "rel"
66    | C.AProd _         -> "prod"
67    | C.ALambda _       -> "lambda"
68    | C.ALetIn _        -> "letin"
69    | C.AFix _          -> "fix"
70    | C.ACoFix _        -> "cofix"
71    | C.AAppl _         -> "appl"
72    | C.ACast _         -> "cast"
73    | C.AMutCase _      -> "mutcase"
74    | C.AMeta _         -> "meta"
75    | C.AImplicit _     -> "implict"
76
77 let next st = {st with depth = succ st.depth; intros = []}
78
79 let add st entry intro = 
80    {st with entries = entry :: st.entries; intros = intro :: st.intros}
81
82 let test_depth st =
83    let msg = Printf.sprintf "Depth %u: " st.depth in
84    match st.max_depth with
85       | None   -> true, "" 
86       | Some d -> 
87          if st.depth < d then true, msg else false, "DEPTH EXCEDED"
88
89 let get_itype st v =
90    let id = T.id_of_annterm v in
91    try Some ((Hashtbl.find st.types id).A.annsynthesized)
92    with Not_found -> None
93
94 (* proof construction *******************************************************)
95
96 let unused_premise = "UNUSED"
97
98 let get_intro name t = match name with 
99    | C.Anonymous -> unused_premise
100    | C.Name s    -> 
101       if DTI.does_not_occur 1 (cic t) then unused_premise else s
102
103 let mk_intros st script =
104    if st.intros = [] then script else
105    let count = List.length st.intros in
106    P.Intros (Some count, List.rev st.intros, "") :: script
107
108 let is_rewrite_right = function
109    | C.AConst (_, uri, []) ->
110       UM.eq uri HObj.Logic.eq_ind_r_URI || Obj.is_eq_ind_r_URI uri
111    | _                     -> false
112
113 let is_rewrite_left = function
114    | C.AConst (_, uri, []) ->
115       UM.eq uri HObj.Logic.eq_ind_URI || Obj.is_eq_ind_URI uri
116    | _                     -> false
117
118 let mk_premise = function
119    | C.ARel (_, _, _, binder) -> binder
120    | _                        -> assert false
121
122 let rec mk_fwd_proof st dtext name = function
123    | C.AAppl (_, hd :: tl) as v -> 
124       if is_rewrite_right hd then
125          let what, where = List.nth tl 5, List.nth tl 3 in
126          let premise = mk_premise where in
127          [P.Rewrite (true, what, Some (premise, name), dtext)] 
128       else if is_rewrite_left hd then
129          let what, where = List.nth tl 5, List.nth tl 3 in
130          let premise = mk_premise where in
131          [P.Rewrite (false, what, Some (premise, name), dtext)]
132       else begin match get_itype st v with
133          | Some ty ->
134             let qs = [[P.Id ""]; mk_proof (next st) v] in
135             [P.Branch (qs, ""); P.Cut (name, ty, dtext)]
136          | None    ->         
137             let ty, _ = TC.type_of_aux' [] st.entries (cic hd) U.empty_ugraph in
138             let (classes, rc) as h = L.classify ty in
139             let text = Printf.sprintf "%u %s" (List.length classes) (L.to_string h) in
140             [P.LetIn (name, v, dtext ^ text)]
141       end
142    | v                          -> 
143       [P.LetIn (name, v, dtext)] 
144
145 and mk_proof st = function
146    | C.ALambda (_, name, v, t) -> 
147       let entry = Some (name, C.Decl (cic v)) in
148       let intro = get_intro name t in
149       mk_proof (add st entry intro) t
150    | C.ALetIn (_, name, v, t) as what ->
151       let proceed, dtext = test_depth st in
152       let script = if proceed then 
153          let intro = get_intro name t in
154          let q = mk_proof (next st) t in
155          List.rev_append (mk_fwd_proof st dtext intro v) q
156       else
157          [P.Apply (what, dtext)]
158       in
159       mk_intros st script
160    | C.ARel _ as what           ->
161       let _, dtext = test_depth st in
162       let script = [P.Apply (what, dtext)] in 
163       mk_intros st script
164    | C.AAppl (_, hd :: tl) as t  ->
165       let proceed, dtext = test_depth st in
166       let script = if proceed then
167          let ty, _ = TC.type_of_aux' [] st.entries (cic hd) U.empty_ugraph in
168          let (classes, rc) as h = L.classify ty in
169          let synth = L.S.singleton 0 in
170          let text = Printf.sprintf "%u %s" (List.length classes) (L.to_string h) in
171          match rc with
172             | Some (i, j) when i > 1 ->
173                let classes, tl, _, what = split2_last classes tl in
174                let synth = L.S.add 1 synth in
175                let qs = mk_bkd_proofs (next st) synth classes tl in
176                if is_rewrite_right hd then 
177                   [P.Rewrite (false, what, None, dtext); P.Branch (qs, "")]
178                else if is_rewrite_left hd then 
179                   [P.Rewrite (true, what, None, dtext); P.Branch (qs, "")]
180                else   
181                   let using = Some hd in
182                   [P.Elim (what, using, dtext ^ text); P.Branch (qs, "")]
183             | _                                             ->
184                let qs = mk_bkd_proofs (next st) synth classes tl in
185                [P.Apply (hd, dtext ^ text); P.Branch (qs, "")]
186       else
187          [P.Apply (t, dtext)]
188       in
189       mk_intros st script
190    | t ->
191       let text = Printf.sprintf "%s: %s" "UNEXPANDED" (string_of_head t) in
192       let script = [P.Note text] in
193       mk_intros st script
194
195 and mk_bkd_proofs st synth classes ts =
196    let _, dtext = test_depth st in   
197    let aux inv v =
198       if L.overlaps synth inv then None else
199       if L.S.is_empty inv then Some (mk_proof st v) else
200       Some [P.Apply (v, dtext ^ "dependent")]
201    in
202    P.list_map2_filter aux classes ts
203
204 (* object costruction *******************************************************)
205
206 let mk_obj st = function
207    | C.AConstant (_, _, s, Some v, t, [], _) ->
208       let ast = mk_proof st v in
209       let count = P.count_steps 0 ast in
210       let text = Printf.sprintf "tactics: %u" count in
211       P.Theorem (s, t, text) :: ast @ [P.Qed ""]
212    | _                                       -> assert false
213
214 (* interface functions ******************************************************)
215
216 let acic2procedural ~ids_to_inner_sorts ~ids_to_inner_types prefix aobj = 
217    let st = {
218       sorts     = ids_to_inner_sorts;
219       types     = ids_to_inner_types;
220       prefix    = prefix;
221       max_depth = None;
222       depth     = 0;
223       entries   = [];
224       intros    = []
225    } in
226    prerr_endline "Level 2 transformation";
227    let steps = mk_obj st aobj in
228    prerr_endline "grafite rendering";
229    List.rev (P.render_steps [] steps)