1 (* Copyright (C) 2002, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
28 exception TheTypeOfTheCurrentGoalIsAMetaICannotChooseTheRightElimiantionPrinciple
29 exception NotAnInductiveTypeToEliminate
33 fun msg -> if debug then prerr_endline (Lazy.force msg) else ()
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")
41 let term_to_list = function
43 | _ -> raise (Invalid_argument "Errore in term_to_list")
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")
51 (* returns DX1 = DX1 -> ... DXn=DXn -> GOALTY *)
52 let rec foo_cut nleft parameters parameters_ty body uri_of_eq selections =
55 foo_cut (nleft-1) (List.tl parameters) (List.tl parameters_ty) body
58 match parameters,selections with
59 | hd::tl, x::xs when x ->
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 xs)
68 foo_cut nleft tl (List.tl parameters_ty) body uri_of_eq xs
70 | _ -> raise (Invalid_argument "inverter: the selection doesn't match the arity of the specified inductive type")
73 (* from a complex Cic.Prod term, return the list of its components *)
74 let rec get_sort_type term =
76 | Cic.Prod (_,src,tgt) -> (get_sort_type tgt)
81 let rec cut_first n l =
84 | hd::tl -> cut_first (n-1) tl
92 | hd::tl when tl != [] -> hd:: (cut_last tl)
96 (* returns the term to apply*)
97 let foo_appl nleft nright_consno term uri =
100 for n = 1 to nleft do
101 a := !a @ [(Cic.Implicit None)]
104 for n = 1 to nright_consno do
105 a := !a @ [(Cic.Implicit None)]
107 (* apply i_ind ? ... ? H *)
108 Cic.Appl ([Cic.Const(uri,[])] @ !a @ [Cic.Rel 1])
112 (* induction/inversion, abbastanza semplicemente, consiste nel generare i prod
113 * delle uguaglianze corrispondenti ai soli parametri destri appartenenti all'insieme S.
114 * Attenzione al caso base: cos'e` replace_lifting?
115 * S = {} e` il principio di induzione
116 * S = insieme_dei_destri e` il principio di inversione *)
117 let rec foo_prod nright right_param_tys rightparameters l2 base_rel goalty
118 uri_of_eq rightparameters_ termty isSetType term selections selections_ =
119 match right_param_tys, selections with
120 | hd::tl, x::xs when x -> Cic.Prod (
123 [Cic.MutInd(uri_of_eq,0,[]); hd; (List.hd rightparameters);
126 (List.map (CicSubstitution.lift 1) tl)
127 (List.map (CicSubstitution.lift 1) (List.tl rightparameters))
128 (List.map (CicSubstitution.lift 1) l2)
129 base_rel (CicSubstitution.lift 1 goalty) uri_of_eq
130 (List.map (CicSubstitution.lift 1) rightparameters_)
131 (CicSubstitution.lift 1 termty)
132 isSetType (CicSubstitution.lift 1 term)) xs selections_
134 foo_prod (nright-1) tl (List.tl rightparameters) l2
135 (base_rel-1) goalty uri_of_eq rightparameters_ termty
136 isSetType term xs selections_
138 ProofEngineReduction.replace_lifting
139 ~equality:(fun _ -> CicUtil.alpha_equivalence)
142 then rightparameters_ @ [term]
143 else rightparameters_ )
144 ~with_what: (List.map (CicSubstitution.lift (-1)) l2)
146 | _ -> raise (Invalid_argument "inverter: the selection doesn't match the arity of the specified inductive type")
147 (* the same subterm of goalty could be simultaneously sx and dx!*)
150 (* induction/inversion, abbastanza semplicemente, consiste nel generare i lambda
151 * soltanto per i parametri destri appartenenti all'insieme S.
152 * Warning: non ne sono piu` cosi` sicuro...
153 * S = {} e` il principio di induzione
154 * S = insieme_dei_destri e` il principio di inversione *)
155 let rec foo_lambda nright right_param_tys nright_ right_param_tys_
156 rightparameters created_vars base_rel goalty uri_of_eq rightparameters_
157 termty isSetType term selections =
158 match right_param_tys with
159 | hd::tl -> Cic.Lambda (
160 (Cic.Name ("lambda" ^ (string_of_int nright))),
162 foo_lambda (nright-1)
163 (List.map (CicSubstitution.lift 1) tl) nright_
164 (List.map (CicSubstitution.lift 1) right_param_tys_)
165 (List.map (CicSubstitution.lift 1) rightparameters)
166 (List.map (CicSubstitution.lift 1) (created_vars @ [Cic.Rel 1]))
167 base_rel (CicSubstitution.lift 1 goalty) uri_of_eq
168 (List.map (CicSubstitution.lift 1) rightparameters_)
169 (CicSubstitution.lift 1 termty) isSetType
170 (CicSubstitution.lift 1 term)) selections
171 | [] when isSetType -> Cic.Lambda (
172 (Cic.Name ("lambda" ^ (string_of_int nright))),
173 (ProofEngineReduction.replace_lifting
174 ~equality:(fun _ -> CicUtil.alpha_equivalence)
176 ~what: (rightparameters_ )
177 ~with_what: (List.map (CicSubstitution.lift (-1)) created_vars)
178 ~where:termty), (* type of H with replaced right parameters *)
179 foo_prod nright_ (List.map (CicSubstitution.lift 1) right_param_tys_)
180 (List.map (CicSubstitution.lift 1) rightparameters)
181 (List.map (CicSubstitution.lift 1) (created_vars @ [Cic.Rel 1]))
182 (base_rel+1) (CicSubstitution.lift 1 goalty) uri_of_eq
183 (List.map (CicSubstitution.lift 1) rightparameters_)
184 (CicSubstitution.lift 1 termty) isSetType
185 (CicSubstitution.lift 1 term)) selections selections
186 | [] -> foo_prod nright_ right_param_tys_ rightparameters created_vars
187 base_rel goalty uri_of_eq rightparameters_
188 termty isSetType term selections selections
191 let isSetType paramty = ((Pervasives.compare
192 (get_sort_type paramty)
193 (Cic.Sort Cic.Prop)) != 0)
195 exception EqualityNotDefinedYet
196 let private_inversion_tac ~term selections =
197 let module T = CicTypeChecker in
198 let module R = CicReduction in
199 let module C = Cic in
200 let module P = PrimitiveTactics in
201 let module PET = ProofEngineTypes in
202 let private_inversion_tac ~term (proof, goal) =
204 (*DEBUG*) debug_print (lazy ("private inversion begins"));
205 let _,metasenv,_subst,_,_, _ = proof in
207 match LibraryObjects.eq_URI () with
208 None -> raise EqualityNotDefinedYet
211 let (_,context,goalty) = CicUtil.lookup_meta goal metasenv in
212 let termty,_ = T.type_of_aux' metasenv context term CicUniv.oblivion_ugraph in
213 let uri = baseuri_of_term termty in
214 let o,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
217 C.MutInd (uri,typeno,exp_named_subst) -> (uri,exp_named_subst,typeno,[])
218 | C.Appl ((C.MutInd (uri,typeno,exp_named_subst))::args) ->
219 (uri,exp_named_subst,typeno,args)
220 | _ -> raise NotAnInductiveTypeToEliminate
222 let buri = UriManager.buri_of_uri uri in
223 let name,nleft,paramty,cons_list =
225 C.InductiveDefinition (tys,_,nleft,_) ->
226 let (name,_,paramty,cons_list) = List.nth tys typeno in
227 (name,nleft,paramty,cons_list)
231 UriManager.uri_of_string (buri ^ "/" ^ name ^ "_ind" ^ ".con")
233 let parameters = (List.tl (term_to_list termty)) in
237 match (T.type_of_aux' metasenv context t CicUniv.oblivion_ugraph) with
238 (term,graph) -> term))
241 let consno = List.length cons_list in
242 let nright= ((List.length parameters)- nleft) in
243 let isSetType = isSetType paramty in
244 let cut_term = foo_cut nleft parameters
245 parameters_tys goalty uri_of_eq selections in
246 (*DEBUG*) debug_print (lazy ("cut term " ^ CicPp.ppterm cut_term));
247 debug_print (lazy ("CONTEXT before apply HCUT: " ^
248 (CicMetaSubst.ppcontext ~metasenv [] context )));
249 debug_print (lazy ("termty " ^ CicPp.ppterm termty));
250 (* cut DXn=DXn \to GOAL *)
251 let proof1,gl1 = PET.apply_tactic (P.cut_tac cut_term) (proof,goal) in
252 (* apply Hcut ; reflexivity *)
253 let proof2, gl2 = PET.apply_tactic
255 ~start: (P.apply_tac (C.Rel 1)) (* apply Hcut *)
256 ~continuation: (EqualityTactics.reflexivity_tac)
257 ) (proof1, (List.hd gl1))
259 (*DEBUG*) debug_print (lazy ("after apply HCUT;reflexivity
260 in private inversion"));
261 (* apply (ledx_ind( lambda x. lambda y, ...)) *)
262 let t1,metasenv,_subst,t3,t4, attrs = proof2 in
263 let goal2 = List.hd (List.tl gl1) in
264 let (_,context,g2ty) = CicUtil.lookup_meta goal2 metasenv in
265 (* rightparameters type list *)
266 let rightparam_ty_l = (cut_first nleft parameters_tys) in
267 (* rightparameters list *)
268 let rightparameters= cut_first nleft parameters in
270 (lazy ("Right param: " ^ (CicPp.ppterm (Cic.Appl rightparameters))));
271 let lambda_t = foo_lambda nright rightparam_ty_l nright rightparam_ty_l
272 rightparameters [] nright goalty uri_of_eq rightparameters termty isSetType
274 let t = foo_appl nleft (nright+consno) lambda_t eliminator_uri in
275 debug_print (lazy ("Lambda_t: " ^ (CicPp.ppterm t)));
276 debug_print (lazy ("Term: " ^ (CicPp.ppterm termty)));
277 debug_print (lazy ("Body: " ^ (CicPp.ppterm goalty)));
279 (lazy ("Right param: " ^ (CicPp.ppterm (Cic.Appl rightparameters))));
280 debug_print (lazy ("CONTEXT before refinement: " ^
281 (CicMetaSubst.ppcontext ~metasenv [] context )));
282 (*DEBUG*) debug_print (lazy ("private inversion: term before refinement: " ^
284 let (ref_t,_,metasenv'',_) = CicRefine.type_of_aux' metasenv context t
285 CicUniv.oblivion_ugraph
287 (*DEBUG*) debug_print (lazy ("private inversion: termine after refinement: "
288 ^ CicPp.ppterm ref_t));
289 let proof2 = (t1,metasenv'',_subst,t3,t4, attrs) in
291 let my_apply_tac status =
293 ProofEngineTypes.apply_tactic (P.apply_tac ref_t) status in
294 let patched_new_goals =
295 let (_,metasenv''',_subst,_,_, _) = proof in
296 let new_goals = ProofEngineHelpers.compare_metasenvs
297 ~oldmetasenv:metasenv ~newmetasenv:metasenv''
299 List.filter (function i -> List.exists (function (j,_,_) -> j=i)
300 metasenv''') new_goals @ goals
302 proof,patched_new_goals
304 ProofEngineTypes.mk_tactic my_apply_tac
311 (ReductionTactics.simpl_tac (ProofEngineTypes.conclusion_pattern(None))))
317 ProofEngineTypes.mk_tactic (private_inversion_tac ~term)
321 let inversion_tac ~term =
322 let module T = CicTypeChecker in
323 let module R = CicReduction in
324 let module C = Cic in
325 let module P = PrimitiveTactics in
326 let module PET = ProofEngineTypes in
327 let inversion_tac ~term (proof, goal) =
328 (*DEBUG*) debug_print (lazy ("inversion begins"));
329 let _,metasenv,_subst,_,_, _ = proof in
330 let (_,context,goalty) = CicUtil.lookup_meta goal metasenv in
331 let termty,_ = T.type_of_aux' metasenv context term CicUniv.oblivion_ugraph in
334 | Cic.MutInd (uri,typeno,_)
335 | Cic.Appl(Cic.MutInd (uri,typeno,_)::_) -> uri,typeno
338 (* let uri = baseuri_of_term termty in *)
339 let obj,_ = CicEnvironment.get_obj CicUniv.oblivion_ugraph uri in
340 let name,nleft,arity,cons_list =
342 Cic.InductiveDefinition (tys,_,nleft,_) ->
343 let (name,_,arity,cons_list) = List.nth tys typeno in
344 (name,nleft,arity,cons_list)
347 let buri = UriManager.buri_of_uri uri in
349 UriManager.uri_of_string (buri ^ "/" ^ name ^ "_inv" ^ ".con") in
350 (* arity length = number of parameters plus 1 *)
351 let arity_length = (List.length (term_to_list termty)) in
352 (* Check the existence of any right parameter. *)
353 assert (arity_length > (nleft + 1));
354 let appl_term arity_consno uri =
357 for n = 1 to arity_consno do
358 a := (Cic.Implicit None)::(!a)
360 (* apply i_inv ? ...? H). *)
361 Cic.Appl ([Cic.Const(uri,[])] @ !a @ [term])
363 let t = appl_term (arity_length + (List.length cons_list)) inversor_uri in
364 let (t1,metasenv,_subst,t3,t4, attrs) = proof in
365 let (ref_t,_,metasenv'',_) = CicRefine.type_of_aux' metasenv context t
366 CicUniv.oblivion_ugraph
368 let proof = (t1,metasenv'',_subst,t3,t4, attrs) in
370 ProofEngineTypes.apply_tactic (P.apply_tac ref_t) (proof,goal) in
371 let patched_new_goals =
372 let (_,metasenv''',_subst,_,_, _) = proof3 in
373 let new_goals = ProofEngineHelpers.compare_metasenvs
374 ~oldmetasenv:metasenv ~newmetasenv:metasenv''
376 List.filter (function i -> List.exists (function (j,_,_) -> j=i)
377 metasenv''') new_goals @ gl3
379 (proof3, patched_new_goals)
381 ProofEngineTypes.mk_tactic (inversion_tac ~term)