]> matita.cs.unibo.it Git - helm.git/blob - components/tactics/inversion.ml
74117f7109dd596602e0d1ee26a23c7a1cd132da
[helm.git] / components / tactics / inversion.ml
1 (* Copyright (C) 2002, 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 (* $Id$ *)
27
28 exception TheTypeOfTheCurrentGoalIsAMetaICannotChooseTheRightElimiantionPrinciple
29 exception NotAnInductiveTypeToEliminate
30
31 let debug = false;; 
32 let debug_print =
33  fun msg -> if debug then prerr_endline (Lazy.force msg) else ()
34
35
36 let inside_obj = function
37  | Cic.InductiveDefinition (type_list,params, nleft, _) ->
38   (type_list,params,nleft)
39  | _ -> raise (Invalid_argument "Errore in inside_obj")
40
41 let term_to_list = function
42  | Cic.Appl l -> l
43  | _ -> raise (Invalid_argument "Errore in term_to_list")
44
45
46 let rec baseuri_of_term = function
47  | Cic.Appl l -> baseuri_of_term (List.hd l)  
48  | Cic.MutInd (baseuri, tyno, []) -> baseuri
49  | _ -> raise (Invalid_argument "baseuri_of_term")
50
51 (* returns DX1 = DX1 -> ... DXn=DXn -> GOALTY *)
52 let rec foo_cut nleft parameters parameters_ty body uri_of_eq = 
53  if nleft > 0 
54  then 
55   foo_cut (nleft-1) (List.tl parameters)  (List.tl parameters_ty) body 
56    uri_of_eq
57  else
58   match parameters with
59    | hd::tl -> 
60     Cic.Prod (
61      Cic.Anonymous, 
62      Cic.Appl[Cic.MutInd (uri_of_eq  ,0,[]);
63       (List.hd parameters_ty) ; hd; hd], 
64      foo_cut nleft (List.map (CicSubstitution.lift 1) tl) 
65       (List.map (CicSubstitution.lift 1) (List.tl parameters_ty)) 
66       (CicSubstitution.lift 1 body) uri_of_eq )
67    | [] -> body
68 ;;
69
70 (* from a complex Cic.Prod term, return the list of its components *)
71 let rec get_sort_type term =
72  match term with 
73   | Cic.Prod (_,src,tgt) -> (get_sort_type tgt)
74   | _ -> term
75 ;;
76
77
78 let rec cut_first n l =
79  if n>0 then  
80   match l with
81    | hd::tl -> cut_first (n-1) tl
82    | [] -> []
83  else l
84 ;;
85
86
87 let rec cut_last l =
88  match l with
89   | hd::tl when tl != [] -> hd:: (cut_last tl)
90   | _ -> []
91 ;;
92
93 (* returns the term to apply*)
94 let foo_appl nleft nright_consno term uri =
95  let l = [] in
96  let a = ref l in
97  for n = 1 to nleft do
98         a := !a @ [(Cic.Implicit None)]
99  done;
100  a:= !a @ [term];
101  for n = 1 to nright_consno do
102         a := !a @ [(Cic.Implicit None)] 
103  done;
104  (*  apply     i_ind           ? ... ?    H *)
105  Cic.Appl ([Cic.Const(uri,[])] @ !a @ [Cic.Rel 1])
106 ;;
107
108
109 let rec foo_prod nright right_param_tys rightparameters l2 base_rel goalty 
110  uri_of_eq rightparameters_ termty isSetType term =
111   match right_param_tys with
112    | hd::tl -> Cic.Prod (
113     Cic.Anonymous, 
114     Cic.Appl
115      [Cic.MutInd(uri_of_eq,0,[]); hd; (List.hd rightparameters); 
116      Cic.Rel base_rel],
117     foo_prod (nright-1) 
118      (List.map (CicSubstitution.lift 1) tl) 
119      (List.map (CicSubstitution.lift 1) (List.tl rightparameters)) 
120      (List.map (CicSubstitution.lift 1) l2) 
121      base_rel (CicSubstitution.lift 1 goalty) uri_of_eq
122      (List.map (CicSubstitution.lift 1) rightparameters_) 
123      (CicSubstitution.lift 1 termty)
124      isSetType (CicSubstitution.lift 1 term))
125    | [] -> ProofEngineReduction.replace_lifting 
126     ~equality:(ProofEngineReduction.alpha_equivalence)
127     ~what: (if isSetType
128      then (rightparameters_ @ [term] ) 
129      else (rightparameters_ ) )
130     ~with_what: (List.map (CicSubstitution.lift (-1)) l2)
131     ~where:goalty 
132 (* the same subterm of goalty could be simultaneously sx and dx!*)
133 ;;
134
135 let rec foo_lambda nright right_param_tys nright_ right_param_tys_ 
136  rightparameters created_vars base_rel goalty uri_of_eq rightparameters_ 
137  termty isSetType term =
138   match right_param_tys with
139    | hd::tl -> Cic.Lambda (
140     (Cic.Name ("lambda" ^ (string_of_int nright))),
141     hd, (* type *)
142     foo_lambda (nright-1) 
143      (List.map (CicSubstitution.lift 1) tl) nright_ 
144      (List.map (CicSubstitution.lift 1) right_param_tys_)
145      (List.map (CicSubstitution.lift 1) rightparameters) 
146      (List.map (CicSubstitution.lift 1) (created_vars @ [Cic.Rel 1])) 
147      base_rel (CicSubstitution.lift 1 goalty) uri_of_eq
148      (List.map (CicSubstitution.lift 1) rightparameters_) 
149      (CicSubstitution.lift 1 termty) isSetType
150      (CicSubstitution.lift 1 term)) 
151    | [] when isSetType -> Cic.Lambda (
152     (Cic.Name ("lambda" ^ (string_of_int nright))),
153     (ProofEngineReduction.replace_lifting
154      ~equality:(ProofEngineReduction.alpha_equivalence)
155      ~what: (rightparameters_ ) 
156      ~with_what: (List.map (CicSubstitution.lift (-1)) created_vars)
157      ~where:termty), (* type of H with replaced right parameters *)
158     foo_prod nright_ (List.map (CicSubstitution.lift 1) right_param_tys_) 
159      (List.map (CicSubstitution.lift 1) rightparameters)  
160      (List.map (CicSubstitution.lift 1) (created_vars @ [Cic.Rel 1])) 
161      (base_rel+1) (CicSubstitution.lift 1 goalty) uri_of_eq
162      (List.map (CicSubstitution.lift 1) rightparameters_) 
163      (CicSubstitution.lift 1 termty) isSetType
164      (CicSubstitution.lift 1 term))
165    | [] -> foo_prod nright_ right_param_tys_ rightparameters created_vars 
166    base_rel goalty uri_of_eq rightparameters_ 
167     termty isSetType term
168 ;;
169
170 let isSetType paramty = ((Pervasives.compare 
171   (get_sort_type paramty)
172   (Cic.Sort Cic.Prop)) != 0) 
173
174 exception EqualityNotDefinedYet
175 let private_inversion_tac ~term =
176  let module T = CicTypeChecker in
177  let module R = CicReduction in
178  let module C = Cic in
179  let module P = PrimitiveTactics in
180  let module PET = ProofEngineTypes in
181  let private_inversion_tac ~term (proof, goal) =
182  
183  (*DEBUG*) debug_print (lazy  ("private inversion begins"));
184  let (_,metasenv,_,_) = proof in
185  let uri_of_eq =
186   match LibraryObjects.eq_URI () with
187      None -> raise EqualityNotDefinedYet
188   | Some uri -> uri
189  in
190  let (_,context,goalty) = CicUtil.lookup_meta goal metasenv in
191  let termty,_ = T.type_of_aux' metasenv context term CicUniv.empty_ugraph in
192  let uri = baseuri_of_term termty in  
193  let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
194  let (_,_,typeno,_) =
195   match termty with
196    C.MutInd (uri,typeno,exp_named_subst) -> (uri,exp_named_subst,typeno,[])
197    | C.Appl ((C.MutInd (uri,typeno,exp_named_subst))::args) ->
198     (uri,exp_named_subst,typeno,args)
199    | _ -> raise NotAnInductiveTypeToEliminate
200  in
201  let buri = UriManager.buri_of_uri uri in
202  let name,nleft,paramty,cons_list =
203   match o with
204    C.InductiveDefinition (tys,_,nleft,_) ->
205     let (name,_,paramty,cons_list) = List.nth tys typeno in
206     (name,nleft,paramty,cons_list)
207    |_ -> assert false
208  in
209  let eliminator_uri = 
210   UriManager.uri_of_string (buri ^ "/" ^ name ^ "_ind" ^ ".con") 
211  in
212  let parameters = (List.tl (term_to_list termty)) in
213  let parameters_tys =  
214   (List.map 
215    (fun t -> (
216     match (T.type_of_aux' metasenv context t CicUniv.empty_ugraph) with
217      (term,graph) -> term))
218    parameters) 
219  in
220  let consno = List.length cons_list in
221  let nright= ((List.length parameters)- nleft) in 
222  let isSetType = isSetType paramty in
223  let cut_term = foo_cut nleft parameters 
224   parameters_tys goalty uri_of_eq in
225  (*DEBUG*)  debug_print (lazy ("cut term " ^ CicPp.ppterm cut_term));
226   debug_print (lazy ("CONTEXT before apply HCUT: " ^ 
227    (CicMetaSubst.ppcontext [] context )));
228   debug_print (lazy ("termty " ^ CicPp.ppterm termty));
229  (* cut DXn=DXn \to GOAL *)
230  let proof1,gl1 = PET.apply_tactic (P.cut_tac cut_term) (proof,goal) in
231  (* apply Hcut ; reflexivity  *)
232  let proof2, gl2 = PET.apply_tactic
233   (Tacticals.then_
234    ~start: (P.apply_tac (C.Rel 1)) (* apply Hcut *)
235    ~continuation: (EqualityTactics.reflexivity_tac)
236   ) (proof1, (List.hd gl1))
237  in      
238  (*DEBUG*) debug_print (lazy  ("after apply HCUT;reflexivity 
239   in private inversion"));
240  (* apply (ledx_ind( lambda x. lambda y, ...)) *)
241  let (t1,metasenv,t3,t4) = proof2 in
242  let goal2 = List.hd (List.tl gl1) in
243  let (_,context,_) = CicUtil.lookup_meta goal2 metasenv in
244  (* rightparameters type list *)
245  let rightparam_ty_l = (cut_first nleft parameters_tys) in
246  (* rightparameters list *)
247  let rightparameters= cut_first nleft parameters in
248  let lambda_t = foo_lambda nright rightparam_ty_l nright rightparam_ty_l 
249  rightparameters [] nright goalty uri_of_eq rightparameters termty isSetType
250  term in 
251  let t = foo_appl nleft (nright+consno) lambda_t eliminator_uri in
252  debug_print (lazy ("Lambda_t: " ^ (CicPp.ppterm t)));
253  debug_print (lazy ("Term: " ^ (CicPp.ppterm termty)));
254  debug_print (lazy ("Body: " ^ (CicPp.ppterm goalty)));
255  debug_print 
256   (lazy ("Right param: " ^ (CicPp.ppterm (Cic.Appl rightparameters))));
257  debug_print (lazy ("CONTEXT before refinement: " ^ 
258   (CicMetaSubst.ppcontext [] context )));
259   (*DEBUG*) debug_print (lazy  ("private inversion: term before refinement: " ^ 
260    CicPp.ppterm t));
261  let (ref_t,_,metasenv'',_) = CicRefine.type_of_aux' metasenv context t 
262   CicUniv.empty_ugraph 
263  in
264  (*DEBUG*) debug_print (lazy  ("private inversion: termine after refinement: "
265   ^ CicPp.ppterm ref_t));
266  let proof2 = (t1,metasenv'',t3,t4) in
267  let my_apply_tac =
268   let my_apply_tac status =
269    let proof,goals = 
270     ProofEngineTypes.apply_tactic (P.apply_tac ref_t) status in
271    let patched_new_goals =
272     let (_,metasenv''',_,_) = proof in
273     let new_goals = ProofEngineHelpers.compare_metasenvs
274      ~oldmetasenv:metasenv ~newmetasenv:metasenv''
275     in
276     List.filter (function i -> List.exists (function (j,_,_) -> j=i) 
277      metasenv''') new_goals @ goals
278    in
279    proof,patched_new_goals
280   in
281  ProofEngineTypes.mk_tactic my_apply_tac
282  in
283  let proof3,gl3 = 
284  PET.apply_tactic
285   (Tacticals.then_
286    ~start:my_apply_tac   
287    ~continuation: 
288     (ReductionTactics.simpl_tac (ProofEngineTypes.conclusion_pattern(None)))) 
289     (proof2,goal2) 
290  in
291
292  (proof3, gl3)
293 in      
294 ProofEngineTypes.mk_tactic (private_inversion_tac ~term)
295 ;;
296
297
298 let inversion_tac ~term =
299  let module T = CicTypeChecker in
300  let module R = CicReduction in
301  let module C = Cic in
302  let module P = PrimitiveTactics in
303  let module PET = ProofEngineTypes in
304  let inversion_tac ~term (proof, goal) =
305  (*DEBUG*) debug_print (lazy ("inversion begins"));
306   let (_,metasenv,_,_) = proof in
307   let (_,context,goalty) = CicUtil.lookup_meta goal metasenv in
308   let termty,_ = T.type_of_aux' metasenv context term CicUniv.empty_ugraph in
309   let uri = baseuri_of_term termty in  
310   let obj,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
311   let name,nleft,arity,cons_list =
312    match obj with
313     Cic.InductiveDefinition (tys,_,nleft,_) ->
314      (*we suppose there is only one inductiveType in the definition, 
315      so typeno=0 identically *)
316      let typeno = 0 in
317      let (name,_,arity,cons_list) = List.nth tys typeno in 
318         (name,nleft,arity,cons_list)
319    |_ -> assert false
320   in
321   let buri = UriManager.buri_of_uri uri in
322   let inversor_uri = 
323    UriManager.uri_of_string (buri ^ "/" ^ name ^ "_inv" ^ ".con") in
324   (* arity length = number  of parameters plus 1 *)
325   let arity_length = (List.length (term_to_list termty)) in
326   (* Check the existence of any right parameter. *)
327   assert (arity_length > (nleft + 1));
328   let appl_term arity_consno uri =
329    let l = [] in
330    let a = ref l in
331    for n = 1 to arity_consno do
332     a := (Cic.Implicit None)::(!a)
333    done;
334   (* apply    i_inv             ? ...?      H).     *)
335   Cic.Appl ([Cic.Const(uri,[])] @ !a @ [Cic.Rel 1])
336   in
337   let t = appl_term (arity_length + (List.length cons_list)) inversor_uri in
338   let (t1,metasenv,t3,t4) = proof in
339   let (ref_t,_,metasenv'',_) = CicRefine.type_of_aux' metasenv context t
340   CicUniv.empty_ugraph 
341   in
342   let proof = (t1,metasenv'',t3,t4) in
343   let proof3,gl3 = 
344      ProofEngineTypes.apply_tactic (P.apply_tac ref_t) (proof,goal) in
345   let patched_new_goals =
346      let (_,metasenv''',_,_) = proof3 in
347      let new_goals = ProofEngineHelpers.compare_metasenvs
348       ~oldmetasenv:metasenv ~newmetasenv:metasenv''
349      in
350      List.filter (function i -> List.exists (function (j,_,_) -> j=i) 
351       metasenv''') new_goals @ gl3
352     in
353   (proof3, patched_new_goals)
354  in     
355 ProofEngineTypes.mk_tactic (inversion_tac ~term)
356 ;;