1 (* Copyright (C) 2000, 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/.
27 ref (None : (UriManager.uri * Cic.metasenv * Cic.term * Cic.term) option)
29 let goal = ref (None : int option);;
31 (*CSC: commento vecchio *)
32 (* refine_meta_with_brand_new_metasenv meta term subst_in newmetasenv *)
33 (* This (heavy) function must be called when a tactic can instantiate old *)
34 (* metavariables (i.e. existential variables). It substitues the metasenv *)
35 (* of the proof with the result of removing [meta] from the domain of *)
36 (* [newmetasenv]. Then it replaces Cic.Meta [meta] with [term] everywhere *)
37 (* in the current proof. Finally it applies [apply_subst_replacing] to *)
39 (*CSC: A questo punto perche' passare un bo' gia' istantiato, se tanto poi *)
40 (*CSC: ci ripasso sopra apply_subst!!! *)
41 (*CSC: Attenzione! Ora questa funzione applica anche [subst_in] a *)
42 (*CSC: [newmetasenv]. *)
43 let subst_meta_and_metasenv_in_current_proof meta subst_in newmetasenv =
47 | Some (uri,_,bo,ty) -> uri,bo,ty
49 let bo' = subst_in bo in
52 (fun metasenv_entry i ->
53 match metasenv_entry with
54 (m,canonical_context,ty) when m <> meta ->
55 let canonical_context' =
59 | Some (i,Cic.Decl t) -> Some (i,Cic.Decl (subst_in t))
60 | Some (i,Cic.Def t) -> Some (i,Cic.Def (subst_in t))
63 (m,canonical_context',subst_in ty)::i
67 proof := Some (uri,metasenv',bo',ty) ;
71 let subst_meta_in_current_proof meta term newmetasenv =
72 let (uri,metasenv,bo,ty) =
75 | Some (uri,metasenv,bo,ty) -> uri,metasenv,bo,ty
77 let subst_in = CicUnification.apply_subst [meta,term] in
79 newmetasenv @ (List.filter (function (m,_,_) -> m <> meta) metasenv)
83 (function i,canonical_context,ty ->
84 let canonical_context' =
87 Some (n,Cic.Decl s) -> Some (n,Cic.Decl (subst_in s))
88 | Some (n,Cic.Def s) -> Some (n,Cic.Def (subst_in s))
92 i,canonical_context',(subst_in ty)
95 let bo' = subst_in bo in
96 proof := Some (uri,metasenv'',bo',ty) ;
100 (* Returns the first meta whose number is above the *)
101 (* number of the higher meta. *)
106 | Some (_,metasenv,_,_) -> metasenv
112 | None,(n,_,_)::tl -> aux (Some n,tl)
113 | Some m,(n,_,_)::tl -> if n > m then aux (Some n,tl) else aux (Some m,tl)
115 1 + aux (None,metasenv)
118 (* metas_in_term term *)
119 (* Returns the ordered list of the metas that occur in [term]. *)
120 (* Duplicates are removed. The implementation is not very efficient. *)
121 let metas_in_term term =
122 let module C = Cic in
127 | C.Meta (n,_) -> [n]
130 | C.Cast (te,ty) -> (aux te) @ (aux ty)
131 | C.Prod (_,s,t) -> (aux s) @ (aux t)
132 | C.Lambda (_,s,t) -> (aux s) @ (aux t)
133 | C.LetIn (_,s,t) -> (aux s) @ (aux t)
134 | C.Appl l -> List.fold_left (fun i t -> i @ (aux t)) [] l
137 | C.MutConstruct _ -> []
138 | C.MutCase (sp,cookingsno,i,outt,t,pl) ->
139 (aux outt) @ (aux t) @
140 (List.fold_left (fun i t -> i @ (aux t)) [] pl)
142 List.fold_left (fun i (_,_,ty,bo) -> i @ (aux bo) @ (aux ty)) [] fl
144 List.fold_left (fun i (_,ty,bo) -> i @ (aux bo) @ (aux ty)) [] fl
146 let metas = aux term in
147 let rec elim_duplicates =
151 he::(elim_duplicates (List.filter (function el -> he <> el) tl))
153 elim_duplicates metas
156 (* identity_relocation_list_for_metavariable i canonical_context *)
157 (* returns the identity relocation list, which is the list [1 ; ... ; n] *)
158 (* where n = List.length [canonical_context] *)
159 (*CSC: ma mi basta la lunghezza del contesto canonico!!!*)
160 let identity_relocation_list_for_metavariable canonical_context =
161 let canonical_context_length = List.length canonical_context in
165 | (n,None::tl) -> None::(aux ((n+1),tl))
166 | (n,_::tl) -> (Some (Cic.Rel n))::(aux ((n+1),tl))
168 aux (1,canonical_context)
171 (* perforate context term ty *)
172 (* replaces the term [term] in the proof with a new metavariable whose type *)
173 (* is [ty]. [context] must be the context of [term] in the whole proof. This *)
174 (* could be easily computed; so the only reasons to have it as an argument *)
175 (* are efficiency reasons. *)
176 let perforate context term ty =
177 let module C = Cic in
178 let newmeta = new_meta () in
181 | Some (uri,metasenv,bo,gty) ->
182 (* We push the new meta at the end of the list for pretty-printing *)
183 (* purposes: in this way metas are ordered. *)
184 let metasenv' = metasenv@[newmeta,context,ty] in
185 let irl = identity_relocation_list_for_metavariable context in
186 (*CSC: Bug: se ci sono due term uguali nella prova dovrei bucarne uno solo!!!*)
188 ProofEngineReduction.replace (==) term (C.Meta (newmeta,irl)) bo
190 (* It may be possible that some metavariables occurred only in *)
191 (* the term we are perforating and they now occurs no more. We *)
192 (* get rid of them, collecting the really useful metavariables *)
194 (*CSC: Bug: una meta potrebbe non comparire in bo', ma comparire nel tipo *)
195 (*CSC: di una metavariabile che compare in bo'!!!!!!! *)
196 let newmetas = metas_in_term bo' in
198 List.filter (function (n,_,_) -> List.mem n newmetas) metasenv'
200 proof := Some (uri,metasenv'',bo',gty) ;
204 (************************************************************)
205 (* Some easy tactics. *)
206 (************************************************************)
208 exception Fail of string;;
210 (*CSC: generatore di nomi? Chiedere il nome? *)
212 let next_fresh_index = ref 0
215 incr next_fresh_index ;
216 "fresh_name" ^ string_of_int !next_fresh_index
219 (* lambda_abstract newmeta ty *)
220 (* returns a triple [bo],[context],[ty'] where *)
221 (* [ty] = Pi/LetIn [context].[ty'] ([context] is a vector!) *)
222 (* and [bo] = Lambda/LetIn [context].(Meta [newmeta]) *)
223 (* So, lambda_abstract is the core of the implementation of *)
224 (* the Intros tactic. *)
225 let lambda_abstract context newmeta ty =
226 let module C = Cic in
227 let rec collect_context context =
229 C.Cast (te,_) -> collect_context context te
234 (*CSC: generatore di nomi? Chiedere il nome? *)
235 | C.Anonimous -> C.Name (fresh_name ())
237 let (context',ty,bo) =
238 collect_context ((Some (n',(C.Decl s)))::context) t
240 (context',ty,C.Lambda(n',s,bo))
242 let (context',ty,bo) =
243 collect_context ((Some (n,(C.Def s)))::context) t
245 (context',ty,C.LetIn(n,s,bo))
247 let irl = identity_relocation_list_for_metavariable context in
248 context, t, (C.Meta (newmeta,irl))
250 collect_context context ty
254 let module C = Cic in
255 let module R = CicReduction in
259 | Some (_,metasenv,_,_) -> metasenv
261 let metano,context,ty =
264 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
266 let newmeta = new_meta () in
267 let (context',ty',bo') = lambda_abstract context newmeta ty in
268 let _ = subst_meta_in_current_proof metano bo' [newmeta,context',ty'] in
272 (* The term bo must be closed in the current context *)
274 let module T = CicTypeChecker in
275 let module R = CicReduction in
279 | Some (_,metasenv,_,_) -> metasenv
281 let metano,context,ty =
284 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
286 if R.are_convertible context (T.type_of_aux' metasenv context bo) ty then
288 let metasenv' = subst_meta_in_current_proof metano bo [] in
292 | (n,_,_)::_ -> Some n
295 raise (Fail "The type of the provided term is not the one expected.")
298 (*CSC: The call to the Intros tactic is embedded inside the code of the *)
299 (*CSC: Elim tactic. Do we already need tacticals? *)
300 (* Auxiliary function for apply: given a type (a backbone), it returns its *)
301 (* head, a META environment in which there is new a META for each hypothesis,*)
302 (* a list of arguments for the new applications and the indexes of the first *)
303 (* and last new METAs introduced. The nth argument in the list of arguments *)
304 (* is the nth new META lambda-abstracted as much as possible. Hence, this *)
305 (* functions already provides the behaviour of Intros on the new goals. *)
306 let new_metasenv_for_apply_intros context ty =
307 let module C = Cic in
308 let module S = CicSubstitution in
309 let rec aux newmeta =
311 C.Cast (he,_) -> aux newmeta he
312 | C.Prod (name,s,t) ->
313 let newcontext,ty',newargument = lambda_abstract context newmeta s in
314 let (res,newmetasenv,arguments,lastmeta) =
315 aux (newmeta + 1) (S.subst newargument t)
317 res,(newmeta,newcontext,ty')::newmetasenv,newargument::arguments,lastmeta
318 | t -> t,[],[],newmeta
320 let newmeta = new_meta () in
321 (* WARNING: here we are using the invariant that above the most *)
322 (* recente new_meta() there are no used metas. *)
323 let (res,newmetasenv,arguments,lastmeta) = aux newmeta ty in
324 res,newmetasenv,arguments,newmeta,lastmeta
327 (* Auxiliary function for apply: given a type (a backbone), it returns its *)
328 (* head, a META environment in which there is new a META for each hypothesis,*)
329 (* a list of arguments for the new applications and the indexes of the first *)
330 (* and last new METAs introduced. The nth argument in the list of arguments *)
331 (* is just the nth new META. *)
332 let new_metasenv_for_apply context ty =
333 let module C = Cic in
334 let module S = CicSubstitution in
335 let rec aux newmeta =
337 C.Cast (he,_) -> aux newmeta he
338 | C.Prod (name,s,t) ->
339 let irl = identity_relocation_list_for_metavariable context in
340 let newargument = C.Meta (newmeta,irl) in
341 let (res,newmetasenv,arguments,lastmeta) =
342 aux (newmeta + 1) (S.subst newargument t)
344 res,(newmeta,context,s)::newmetasenv,newargument::arguments,lastmeta
345 | t -> t,[],[],newmeta
347 let newmeta = new_meta () in
348 (* WARNING: here we are using the invariant that above the most *)
349 (* recente new_meta() there are no used metas. *)
350 let (res,newmetasenv,arguments,lastmeta) = aux newmeta ty in
351 res,newmetasenv,arguments,newmeta,lastmeta
355 (*CSC: ma serve solamente la prima delle new_uninst e l'unione delle due!!! *)
356 let classify_metas newmeta in_subst_domain subst_in metasenv =
358 (fun (i,canonical_context,ty) (old_uninst,new_uninst) ->
359 if in_subst_domain i then
360 old_uninst,new_uninst
362 let ty' = subst_in canonical_context ty in
363 let canonical_context' =
365 (fun entry canonical_context' ->
368 Some (n,Cic.Decl s) ->
369 Some (n,Cic.Decl (subst_in canonical_context' s))
370 | Some (n,Cic.Def s) ->
371 Some (n,Cic.Def (subst_in canonical_context' s))
374 entry'::canonical_context'
375 ) canonical_context []
378 ((i,canonical_context',ty')::old_uninst),new_uninst
380 old_uninst,((i,canonical_context',ty')::new_uninst)
384 (* The term bo must be closed in the current context *)
386 let module T = CicTypeChecker in
387 let module R = CicReduction in
388 let module C = Cic in
392 | Some (_,metasenv,_,_) -> metasenv
394 let metano,context,ty =
398 List.find (function (m,_,_) -> m=metano) metasenv
400 let termty = CicTypeChecker.type_of_aux' metasenv context term in
401 (* newmeta is the lowest index of the new metas introduced *)
402 let (consthead,newmetas,arguments,newmeta,_) =
403 new_metasenv_for_apply context termty
405 let newmetasenv = newmetas@metasenv in
406 let subst,newmetasenv' =
407 CicUnification.fo_unif newmetasenv context consthead ty
409 let in_subst_domain i = List.exists (function (j,_) -> i=j) subst in
410 let apply_subst = CicUnification.apply_subst subst in
411 let old_uninstantiatedmetas,new_uninstantiatedmetas =
412 (* subst_in doesn't need the context. Hence the underscore. *)
413 let subst_in _ = CicUnification.apply_subst subst in
414 classify_metas newmeta in_subst_domain subst_in newmetasenv'
417 if List.length newmetas = 0 then
420 let arguments' = List.map apply_subst arguments in
421 Cic.Appl (term::arguments')
423 let newmetasenv'' = new_uninstantiatedmetas@old_uninstantiatedmetas in
425 let subst_in = CicUnification.apply_subst ((metano,bo')::subst) in
426 subst_meta_and_metasenv_in_current_proof metano subst_in
429 match newmetasenv''' with
431 | (i,_,_)::_ -> goal := Some i
434 let eta_expand metasenv context t arg =
435 let module T = CicTypeChecker in
436 let module S = CicSubstitution in
437 let module C = Cic in
440 t' when t' = S.lift n arg -> C.Rel (1 + n)
441 | C.Rel m -> if m <= n then C.Rel m else C.Rel (m+1)
445 | C.Implicit as t -> t
446 | C.Cast (te,ty) -> C.Cast (aux n te, aux n ty)
447 | C.Prod (nn,s,t) -> C.Prod (nn, aux n s, aux (n+1) t)
448 | C.Lambda (nn,s,t) -> C.Lambda (nn, aux n s, aux (n+1) t)
449 | C.LetIn (nn,s,t) -> C.LetIn (nn, aux n s, aux (n+1) t)
450 | C.Appl l -> C.Appl (List.map (aux n) l)
451 | C.Const _ as t -> t
453 | C.MutConstruct _ as t -> t
454 | C.MutCase (sp,cookingsno,i,outt,t,pl) ->
455 C.MutCase (sp,cookingsno,i,aux n outt, aux n t,
458 let tylen = List.length fl in
461 (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo))
464 C.Fix (i, substitutedfl)
466 let tylen = List.length fl in
469 (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo))
472 C.CoFix (i, substitutedfl)
475 T.type_of_aux' metasenv context arg
477 (C.Appl [C.Lambda ((C.Name "dummy"),argty,aux 0 t) ; arg])
480 exception NotAnInductiveTypeToEliminate;;
481 exception NotTheRightEliminatorShape;;
482 exception NoHypothesesFound;;
484 let elim_intros_simpl term =
485 let module T = CicTypeChecker in
486 let module U = UriManager in
487 let module R = CicReduction in
488 let module C = Cic in
492 | Some (curi,metasenv,_,_) -> curi,metasenv
494 let metano,context,ty =
498 List.find (function (m,_,_) -> m=metano) metasenv
500 let termty = T.type_of_aux' metasenv context term in
501 let uri,cookingno,typeno,args =
503 C.MutInd (uri,cookingno,typeno) -> (uri,cookingno,typeno,[])
504 | C.Appl ((C.MutInd (uri,cookingno,typeno))::args) ->
505 (uri,cookingno,typeno,args)
506 | _ -> raise NotAnInductiveTypeToEliminate
509 let buri = U.buri_of_uri uri in
511 match CicEnvironment.get_cooked_obj uri cookingno with
512 C.InductiveDefinition (tys,_,_) ->
513 let (name,_,_,_) = List.nth tys typeno in
518 match T.type_of_aux' metasenv context ty with
519 C.Sort C.Prop -> "_ind"
520 | C.Sort C.Set -> "_rec"
521 | C.Sort C.Type -> "_rect"
524 U.uri_of_string (buri ^ "/" ^ name ^ ext ^ ".con")
526 let eliminator_cookingno =
527 UriManager.relative_depth curi eliminator_uri 0
529 let eliminator_ref = C.Const (eliminator_uri,eliminator_cookingno) in
531 T.type_of_aux' [] [] eliminator_ref
533 let (econclusion,newmetas,arguments,newmeta,lastmeta) =
535 new_metasenv_for_apply context ety
537 new_metasenv_for_apply_intros context ety
539 (* Here we assume that we have only one inductive hypothesis to *)
540 (* eliminate and that it is the last hypothesis of the theorem. *)
541 (* A better approach would be fingering the hypotheses in some *)
544 let (_,canonical_context,_) =
545 List.find (function (m,_,_) -> m=(lastmeta - 1)) newmetas
548 identity_relocation_list_for_metavariable canonical_context
550 Cic.Meta (lastmeta - 1, irl)
552 let newmetasenv = newmetas @ metasenv in
553 let subst1,newmetasenv' =
554 CicUnification.fo_unif newmetasenv context term meta_of_corpse
556 let ueconclusion = CicUnification.apply_subst subst1 econclusion in
557 (* The conclusion of our elimination principle is *)
558 (* (?i farg1 ... fargn) *)
559 (* The conclusion of our goal is ty. So, we can *)
560 (* eta-expand ty w.r.t. farg1 .... fargn to get *)
561 (* a new ty equal to (P farg1 ... fargn). Now *)
562 (* ?i can be instantiated with P and we are ready *)
563 (* to refine the term. *)
565 match ueconclusion with
566 (*CSC: Code to be used for Apply
567 C.Appl ((C.Meta (emeta,_))::fargs) -> emeta,fargs
568 | C.Meta (emeta,_) -> emeta,[]
570 (*CSC: Code to be used for ApplyIntros *)
571 C.Appl (he::fargs) ->
574 C.Meta (emeta,_) -> emeta
575 | C.Lambda (_,_,t) -> find_head t
576 | C.LetIn (_,_,t) -> find_head t
577 | _ ->raise NotTheRightEliminatorShape
580 | C.Meta (emeta,_) -> emeta,[]
582 | _ -> raise NotTheRightEliminatorShape
584 let ty' = CicUnification.apply_subst subst1 ty in
585 let eta_expanded_ty =
586 (*CSC: newmetasenv' era metasenv ??????????? *)
587 List.fold_left (eta_expand newmetasenv' context) ty' fargs
589 let subst2,newmetasenv'' =
590 (*CSC: passo newmetasenv', ma alcune variabili sono gia' state sostituite
591 da subst1!!!! Dovrei rimuoverle o sono innocue?*)
592 CicUnification.fo_unif
593 newmetasenv' context ueconclusion eta_expanded_ty
595 let in_subst_domain i =
596 let eq_to_i = function (j,_) -> i=j in
597 List.exists eq_to_i subst1 ||
598 List.exists eq_to_i subst2
600 (*CSC: codice per l'elim
601 (* When unwinding the META that corresponds to the elimination *)
602 (* predicate (which is emeta), we must also perform one-step *)
603 (* beta-reduction. apply_subst doesn't need the context. Hence *)
604 (* the underscore. *)
605 let apply_subst _ t =
606 let t' = CicUnification.apply_subst subst1 t in
607 CicUnification.apply_subst_reducing
608 subst2 (Some (emeta,List.length fargs)) t'
611 (*CSC: codice per l'elim_intros_simpl. Non effettua semplificazione. *)
612 let apply_subst context t =
613 let t' = CicUnification.apply_subst (subst1@subst2) t in
614 ProofEngineReduction.simpl context t'
617 let old_uninstantiatedmetas,new_uninstantiatedmetas =
618 classify_metas newmeta in_subst_domain apply_subst
621 let arguments' = List.map (apply_subst context) arguments in
622 let bo' = Cic.Appl (eliminator_ref::arguments') in
624 new_uninstantiatedmetas@old_uninstantiatedmetas
626 let newmetasenv'''' =
627 (* When unwinding the META that corresponds to the *)
628 (* elimination predicate (which is emeta), we must *)
629 (* also perform one-step beta-reduction. *)
630 (* The only difference w.r.t. apply_subst is that *)
631 (* we also substitute metano with bo'. *)
632 (*CSC: Nota: sostituire nuovamente subst1 e' superfluo, *)
634 (*CSC: codice per l'elim
636 let t' = CicUnification.apply_subst subst1 t in
637 CicUnification.apply_subst_reducing
638 ((metano,bo')::subst2)
639 (Some (emeta,List.length fargs)) t'
642 (*CSC: codice per l'elim_intros_simpl *)
644 CicUnification.apply_subst
645 ((metano,bo')::(subst1@subst2)) t
648 subst_meta_and_metasenv_in_current_proof metano
649 apply_subst' newmetasenv'''
651 match newmetasenv'''' with
653 | (i,_,_)::_ -> goal := Some i
656 let reduction_tactic reduction_function term =
657 let curi,metasenv,pbo,pty =
660 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
662 let metano,context,ty =
665 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
667 (* We don't know if [term] is a subterm of [ty] or a subterm of *)
668 (* the type of one metavariable. So we replace it everywhere. *)
669 (*CSC: Il vero problema e' che non sapendo dove sia il term non *)
670 (*CSC: sappiamo neppure quale sia il suo contesto!!!! Insomma, *)
671 (*CSC: e' meglio prima cercare il termine e scoprirne il *)
672 (*CSC: contesto, poi ridurre e infine rimpiazzare. *)
673 let replace context where=
674 (*CSC: Per il momento se la riduzione fallisce significa solamente che *)
675 (*CSC: siamo nel contesto errato. Metto il try, ma che schifo!!!! *)
676 (*CSC: Anche perche' cosi' catturo anche quelle del replace che non dovrei *)
678 let term' = reduction_function context term in
679 ProofEngineReduction.replace ~equality:(==) ~what:term ~with_what:term'
684 let ty' = replace context ty in
687 (fun entry context ->
689 Some (name,Cic.Def t) ->
690 (Some (name,Cic.Def (replace context t)))::context
691 | Some (name,Cic.Decl t) ->
692 (Some (name,Cic.Decl (replace context t)))::context
693 | None -> None::context
699 (n,_,_) when n = metano -> (metano,context',ty')
703 proof := Some (curi,metasenv',pbo,pty) ;
707 (* Reduces [term] using [reduction_function] in the current scratch goal [ty] *)
708 let reduction_tactic_in_scratch reduction_function term ty =
712 | Some (_,metasenv,_,_) -> metasenv
714 let metano,context,_ =
717 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
719 let term' = reduction_function context term in
720 ProofEngineReduction.replace
721 ~equality:(==) ~what:term ~with_what:term' ~where:ty
724 let whd = reduction_tactic CicReduction.whd;;
725 let reduce = reduction_tactic ProofEngineReduction.reduce;;
726 let simpl = reduction_tactic ProofEngineReduction.simpl;;
728 let whd_in_scratch = reduction_tactic_in_scratch CicReduction.whd;;
729 let reduce_in_scratch =
730 reduction_tactic_in_scratch ProofEngineReduction.reduce;;
731 let simpl_in_scratch =
732 reduction_tactic_in_scratch ProofEngineReduction.simpl;;
734 (* It is just the opposite of whd. The code should probably be merged. *)
736 let curi,metasenv,pbo,pty =
739 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
741 let metano,context,ty =
744 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
746 let term' = CicReduction.whd context term in
747 (* We don't know if [term] is a subterm of [ty] or a subterm of *)
748 (* the type of one metavariable. So we replace it everywhere. *)
749 (*CSC: ma si potrebbe ovviare al problema. Ma non credo *)
750 (*CSC: che si guadagni nulla in fatto di efficienza. *)
752 ProofEngineReduction.replace
753 ~equality:(ProofEngineReduction.syntactic_equality)
754 ~what:term' ~with_what:term
756 let ty' = replace ty in
760 Some (n,Cic.Decl t) -> Some (n,Cic.Decl (replace t))
761 | Some (n,Cic.Def t) -> Some (n,Cic.Def (replace t))
768 (n,_,_) when n = metano -> (metano,context',ty')
772 proof := Some (curi,metasenv',pbo,pty) ;
777 let module C = Cic in
778 let curi,metasenv,pbo,pty =
781 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
783 let metano,context,ty =
786 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
788 let newmeta1 = new_meta () in
789 let newmeta2 = newmeta1 + 1 in
790 let context_for_newmeta1 =
791 (Some (C.Name "dummy_for_cut",C.Decl term))::context in
793 identity_relocation_list_for_metavariable context_for_newmeta1 in
794 let irl2 = identity_relocation_list_for_metavariable context in
795 let newmeta1ty = CicSubstitution.lift 1 ty in
798 [C.Lambda (C.Name "dummy_for_cut",term,C.Meta (newmeta1,irl1)) ;
799 C.Meta (newmeta2,irl2)]
802 subst_meta_in_current_proof metano bo'
803 [newmeta2,context,term; newmeta1,context_for_newmeta1,newmeta1ty];
805 goal := Some newmeta1
809 let module C = Cic in
810 let curi,metasenv,pbo,pty =
813 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
815 let metano,context,ty =
818 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
820 let _ = CicTypeChecker.type_of_aux' metasenv context term in
821 let newmeta = new_meta () in
822 let context_for_newmeta =
823 (Some (C.Name "dummy_for_letin",C.Def term))::context in
825 identity_relocation_list_for_metavariable context_for_newmeta in
826 let newmetaty = CicSubstitution.lift 1 ty in
827 let bo' = C.LetIn (C.Name "dummy_for_letin",term,C.Meta (newmeta,irl)) in
828 let _ = subst_meta_in_current_proof metano bo' [newmeta,context_for_newmeta,newmetaty] in
832 exception NotConvertible;;
834 (*CSC: Bug (or feature?). [input] is parsed in the context of the goal, *)
835 (*CSC: while [goal_input] can have a richer context (because of binders) *)
836 (*CSC: So it is _NOT_ possible to use those binders in the [input] term. *)
837 (*CSC: Is that evident? Is that right? Or should it be changed? *)
838 let change ~goal_input ~input =
839 let curi,metasenv,pbo,pty =
842 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
844 let metano,context,ty =
847 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
849 (* are_convertible works only on well-typed terms *)
850 ignore (CicTypeChecker.type_of_aux' metasenv context input) ;
851 if CicReduction.are_convertible context goal_input input then
854 ProofEngineReduction.replace
855 ~equality:(==) ~what:goal_input ~with_what:input
857 let ty' = replace ty in
861 Some (name,Cic.Def t) -> Some (name,Cic.Def (replace t))
862 | Some (name,Cic.Decl t) -> Some (name,Cic.Decl (replace t))
869 (n,_,_) when n = metano -> (metano,context',ty')
873 proof := Some (curi,metasenv',pbo,pty) ;
881 let module C = Cic in
884 | Some (_, C.Decl _) -> raise (Fail "No Body To Clear")
885 | Some (n_to_clear_body, C.Def term) as hyp_to_clear_body ->
886 let curi,metasenv,pbo,pty =
889 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
894 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
904 (m,canonical_context,ty) when m = metano ->
905 let canonical_context' =
907 (fun entry context ->
909 t when t == hyp_to_clear_body ->
912 CicTypeChecker.type_of_aux' metasenv context term
914 Some (n_to_clear_body, Cic.Decl ty)
916 cleared_entry::context
917 | None -> None::context
919 | Some (n,C.Def t) ->
922 CicTypeChecker.type_of_aux' metasenv context t
927 ("The correctness of hypothesis " ^
929 " relies on the body of " ^
930 string_of_name n_to_clear_body)
934 ) canonical_context []
938 CicTypeChecker.type_of_aux' metasenv canonical_context' ty
943 ("The correctness of the goal relies on the body of " ^
944 string_of_name n_to_clear_body))
946 m,canonical_context',ty
950 proof := Some (curi,metasenv',pbo,pty)
953 let clear hyp_to_clear =
954 let module C = Cic in
955 match hyp_to_clear with
957 | Some (n_to_clear, _) ->
958 let curi,metasenv,pbo,pty =
961 | Some (curi,metasenv,bo,ty) -> curi,metasenv,bo,ty
963 let metano,context,ty =
966 | Some metano -> List.find (function (m,_,_) -> m=metano) metasenv
976 (m,canonical_context,ty) when m = metano ->
977 let canonical_context' =
979 (fun entry context ->
981 t when t == hyp_to_clear -> None::context
982 | None -> None::context
984 | Some (n,C.Def t) ->
987 CicTypeChecker.type_of_aux' metasenv context t
994 " uses hypothesis " ^
995 string_of_name n_to_clear)
999 ) canonical_context []
1003 CicTypeChecker.type_of_aux' metasenv canonical_context' ty
1008 ("Hypothesis " ^ string_of_name n_to_clear ^
1009 " occurs in the goal"))
1011 m,canonical_context',ty
1015 proof := Some (curi,metasenv',pbo,pty)