]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/content_pres/content2Procedural.ml
Procedural: "ByInduction" method ok
[helm.git] / helm / software / components / content_pres / content2Procedural.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 H = HExtlib
27 module U = UriManager
28 module C = Content
29 module G = GrafiteAst
30 module N = CicNotationPt
31
32 (* functions to be moved ****************************************************)
33
34 let rec list_split n l =
35    if n = 0 then [],l else 
36    let l1, l2 = list_split (pred n) (List.tl l) in
37    List.hd l :: l1, l2
38
39 let cont sep a = match sep with 
40    | None     -> a
41    | Some sep -> sep :: a
42
43 let list_rev_map_concat map sep a l =
44    let rec aux a = function
45       | []          -> a
46       | [x]         -> map a x
47       | x :: y :: l -> aux (sep :: map a x) (y :: l)  
48    in
49    aux a l
50
51 (****************************************************************************)
52
53 type name  = string
54 type what  = Cic.annterm
55 type using = Cic.annterm
56 type count = int
57 type note  = string
58
59 type step = Note of note 
60           | Theorem of name * what * note
61           | Qed of note
62           | Intros of count option * name list * note
63           | Elim of what * using option * note
64           | LetIn of name * what * note
65           | Exact of what * note
66           | Branch of step list list * note
67
68 (* annterm constructors *****************************************************)
69
70 let mk_arel i b = Cic.ARel ("", "", i, b)
71
72 (* level 2 transformation ***************************************************)
73
74 let mk_name = function
75    | Some name -> name
76    | None      -> "UNUSED" (**)
77
78 let mk_intros_arg = function
79    | `Declaration {C.dec_name = name}
80    | `Hypothesis {C.dec_name = name}
81    | `Definition {C.def_name = name}  -> mk_name name 
82    | `Joint _                         -> assert false
83    | `Proof _                         -> assert false
84
85 let mk_intros_args pc = List.map mk_intros_arg pc
86
87 let split_inductive n tl =
88    let l1, l2 = list_split (int_of_string n) tl in
89    List.hd (List.rev l2), l1
90
91 let rec mk_apply_term aref ac ds cargs =
92    let step0 = mk_arg true (ac, [], ds) (List.hd cargs) in
93    let _, row, ds = List.fold_left (mk_arg false) step0 (List.tl cargs) in
94    Cic.AAppl (aref, List.rev row), ds 
95
96 and mk_delta p ds =
97    let cmethod = p.C.proof_conclude.C.conclude_method in
98    let cargs = p.C.proof_conclude.C.conclude_args in
99    let capply = p.C.proof_apply_context in
100    let ccont = p.C.proof_context in
101    let caref = p.C.proof_conclude.C.conclude_aref in
102    match cmethod with
103       | "Exact"
104       | "Apply" when ccont = [] ->
105          let what, ds = mk_apply_term caref capply ds cargs in
106          let name = "PREVIOUS" in
107          mk_arel 1 name, LetIn (name, what, "") :: ds
108       | _ -> mk_arel 1 "COMPOUND", ds
109
110 and mk_arg first (ac, row, ds) = function
111    | C.Lemma {C.lemma_id = aref; C.lemma_uri = uri} ->
112       ac, Cic.AConst (aref, U.uri_of_string uri, []) :: row, ds 
113    | C.Premise {C.premise_n = Some i; C.premise_binder = Some b} -> 
114       ac, mk_arel i b :: row, ds
115    | C.Premise {C.premise_n = None; C.premise_binder = None} -> 
116       begin match first, ac with
117          | _, hd :: tl -> 
118             let arg, ds = mk_delta hd ds in 
119             tl, arg :: row, ds
120          | false, []   -> ac, Cic.AImplicit ("", None) :: row, ds
121          | _           -> assert false
122       end
123    | C.Term t when first -> ac, t :: row, ds
124    | C.Term _            -> ac, Cic.AImplicit ("", None) :: row, ds
125    | C.Premise _         -> assert false
126    | C.ArgMethod _       -> assert false
127    | C.ArgProof _        -> assert false
128    | C.Aux _             -> assert false
129
130 let rec mk_proof p =
131    let names = mk_intros_args p.C.proof_context in
132    let count = List.length names in
133    if count > 0 then Intros (Some count, names, "") :: mk_proof_body p
134    else mk_proof_body p
135    
136 and mk_proof_body p = 
137    let cmethod = p.C.proof_conclude.C.conclude_method in
138    let cargs = p.C.proof_conclude.C.conclude_args in
139    let capply = p.C.proof_apply_context in
140    match cmethod, cargs with
141       | "Intros+LetTac", [C.ArgProof p] -> mk_proof p 
142       | "ByInduction", C.Aux n :: C.Term (Cic.AAppl (_, using :: _)) :: tl ->
143          let whatm, ms = split_inductive n tl in (* actual rx params here *)
144          let _, row, ds = mk_arg true (List.rev capply, [], []) whatm in
145          let what, qs = List.hd row, List.map mk_subproof ms in
146          List.rev ds @ [Elim (what, Some using, ""); Branch (qs, "")] 
147       | _ ->  
148          let text = 
149             Printf.sprintf "UNEXPANDED %s %u" cmethod (List.length cargs)
150          in [Note text] 
151
152 and mk_subproof = function
153    | C.ArgProof ({C.proof_name = Some n} as p) -> Note n :: mk_proof p
154    | C.ArgProof ({C.proof_name = None} as p)   -> Note "" :: mk_proof p
155    | _                                         -> assert false
156
157 let mk_obj ids_to_inner_sorts prefix (_, params, xmenv, obj) =
158    if List.length params > 0 || xmenv <> None then assert false;
159    match obj with
160       | `Def (C.Const, t, `Proof ({C.proof_name = Some name} as p)) ->
161            Theorem (name, t, "") :: mk_proof p @ [Qed ""]
162       | _ -> assert false 
163
164 (* grafite ast constructors *************************************************)
165
166 let floc = H.dummy_floc
167
168 let mk_note str = G.Comment (floc, G.Note (floc, str))
169
170 let mk_theorem name t = 
171    let obj = N.Theorem (`Theorem, name, t, None) in
172    G.Executable (floc, G.Command (floc, G.Obj (floc, obj)))
173
174 let mk_qed =
175    G.Executable (floc, G.Command (floc, G.Qed floc))
176
177 let mk_tactic tactic =
178    G.Executable (floc, G.Tactical (floc, G.Tactic (floc, tactic), None))
179
180 let mk_intros xi ids =
181    let tactic = G.Intros (floc, xi, ids) in
182    mk_tactic tactic
183
184 let mk_elim what using =
185    let tactic = G.Elim (floc, what, using, Some 0, []) in
186    mk_tactic tactic
187
188 let mk_letin name what =
189    let tactic = G.LetIn (floc, what, name) in
190    mk_tactic tactic
191
192 let mk_exact t =
193    let tactic = G.Exact (floc, t) in
194    mk_tactic tactic
195
196 let mk_dot = G.Executable (floc, G.Tactical (floc, G.Dot floc, None))
197
198 let mk_sc = G.Executable (floc, G.Tactical (floc, G.Semicolon floc, None))
199
200 let mk_ob = G.Executable (floc, G.Tactical (floc, G.Branch floc, None))
201
202 let mk_cb = G.Executable (floc, G.Tactical (floc, G.Merge floc, None))
203
204 let mk_vb = G.Executable (floc, G.Tactical (floc, G.Shift floc, None))
205
206 (* rendering ****************************************************************)
207
208 let rec render_step sep a = function
209    | Note s            -> mk_note s :: a
210    | Theorem (n, t, s) -> mk_note s :: mk_theorem n t :: a 
211    | Qed s             -> mk_note s :: mk_qed :: a
212    | Intros (c, ns, s) -> mk_note s :: cont sep (mk_intros c ns :: a)
213    | Elim (t, xu, s)   -> mk_note s :: cont sep (mk_elim t xu :: a)
214    | LetIn (n, t, s)   -> mk_note s :: cont sep (mk_letin n t :: a)
215    | Exact (t, s)      -> mk_note s :: cont sep (mk_exact t :: a)
216    | Branch ([], s)    -> a
217    | Branch ([ps], s)  -> render_steps a ps
218    | Branch (pss, s)   ->
219       let a =  mk_ob :: a in
220       let body = mk_cb :: list_rev_map_concat render_steps mk_vb a pss in
221       mk_note s :: cont sep body
222
223 and render_steps a = function
224    | []                                          -> a
225    | [p]                                         -> render_step None a p
226    | (Note _ | Theorem _ | Qed _ as p) :: ps     ->
227       render_steps (render_step None a p) ps 
228    | p :: ((Branch (_ :: _ :: _, _) :: _) as ps) ->
229       render_steps (render_step (Some mk_sc) a p) ps
230    | p :: ps                                     ->
231       render_steps (render_step (Some mk_dot) a p) ps
232
233 (* interface functions ******************************************************)
234
235 let content2procedural ~ids_to_inner_sorts prefix cobj = 
236    prerr_endline "Level 2 transformation";
237    let steps = mk_obj ids_to_inner_sorts prefix cobj in
238    prerr_endline "grafite rendering";
239    List.rev (render_steps [] steps)
240