X-Git-Url: http://matita.cs.unibo.it/gitweb/?p=helm.git;a=blobdiff_plain;f=helm%2Focaml%2Ftactics%2FprimitiveTactics.ml;fp=helm%2Focaml%2Ftactics%2FprimitiveTactics.ml;h=0000000000000000000000000000000000000000;hp=91cd6198ef8bb28d6d60f7a42a8450fdfa62bcc8;hb=3ef089a4c58fbe429dd539af6215991ecbe11ee2;hpb=1c7fb836e2af4f2f3d18afd0396701f2094265ff diff --git a/helm/ocaml/tactics/primitiveTactics.ml b/helm/ocaml/tactics/primitiveTactics.ml deleted file mode 100644 index 91cd6198e..000000000 --- a/helm/ocaml/tactics/primitiveTactics.ml +++ /dev/null @@ -1,565 +0,0 @@ -(* Copyright (C) 2002, HELM Team. - * - * This file is part of HELM, an Hypertextual, Electronic - * Library of Mathematics, developed at the Computer Science - * Department, University of Bologna, Italy. - * - * HELM is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * HELM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with HELM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * For details, see the HELM World-Wide-Web page, - * http://cs.unibo.it/helm/. - *) - -open ProofEngineHelpers -open ProofEngineTypes - -exception NotAnInductiveTypeToEliminate -exception NotTheRightEliminatorShape -exception NoHypothesesFound -exception WrongUriToVariable of string - -(* lambda_abstract newmeta ty *) -(* returns a triple [bo],[context],[ty'] where *) -(* [ty] = Pi/LetIn [context].[ty'] ([context] is a vector!) *) -(* and [bo] = Lambda/LetIn [context].(Meta [newmeta]) *) -(* So, lambda_abstract is the core of the implementation of *) -(* the Intros tactic. *) -let lambda_abstract context newmeta ty mk_fresh_name = - let module C = Cic in - let rec collect_context context = - function - C.Cast (te,_) -> collect_context context te - | C.Prod (n,s,t) -> - let n' = mk_fresh_name context n ~typ:s in - let (context',ty,bo) = - collect_context ((Some (n',(C.Decl s)))::context) t - in - (context',ty,C.Lambda(n',s,bo)) - | C.LetIn (n,s,t) -> - let (context',ty,bo) = - collect_context ((Some (n,(C.Def s)))::context) t - in - (context',ty,C.LetIn(n,s,bo)) - | _ as t -> - let irl = identity_relocation_list_for_metavariable context in - context, t, (C.Meta (newmeta,irl)) - in - collect_context context ty - -let eta_expand metasenv context t arg = - let module T = CicTypeChecker in - let module S = CicSubstitution in - let module C = Cic in - let rec aux n = - function - t' when t' = S.lift n arg -> C.Rel (1 + n) - | C.Rel m -> if m <= n then C.Rel m else C.Rel (m+1) - | C.Var (uri,exp_named_subst) -> - let exp_named_subst' = aux_exp_named_subst n exp_named_subst in - C.Var (uri,exp_named_subst') - | C.Meta _ - | C.Sort _ - | C.Implicit as t -> t - | C.Cast (te,ty) -> C.Cast (aux n te, aux n ty) - | C.Prod (nn,s,t) -> C.Prod (nn, aux n s, aux (n+1) t) - | C.Lambda (nn,s,t) -> C.Lambda (nn, aux n s, aux (n+1) t) - | C.LetIn (nn,s,t) -> C.LetIn (nn, aux n s, aux (n+1) t) - | C.Appl l -> C.Appl (List.map (aux n) l) - | C.Const (uri,exp_named_subst) -> - let exp_named_subst' = aux_exp_named_subst n exp_named_subst in - C.Const (uri,exp_named_subst') - | C.MutInd (uri,i,exp_named_subst) -> - let exp_named_subst' = aux_exp_named_subst n exp_named_subst in - C.MutInd (uri,i,exp_named_subst') - | C.MutConstruct (uri,i,j,exp_named_subst) -> - let exp_named_subst' = aux_exp_named_subst n exp_named_subst in - C.MutConstruct (uri,i,j,exp_named_subst') - | C.MutCase (sp,i,outt,t,pl) -> - C.MutCase (sp,i,aux n outt, aux n t, - List.map (aux n) pl) - | C.Fix (i,fl) -> - let tylen = List.length fl in - let substitutedfl = - List.map - (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo)) - fl - in - C.Fix (i, substitutedfl) - | C.CoFix (i,fl) -> - let tylen = List.length fl in - let substitutedfl = - List.map - (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo)) - fl - in - C.CoFix (i, substitutedfl) - and aux_exp_named_subst n = - List.map (function uri,t -> uri,aux n t) - in - let argty = - T.type_of_aux' metasenv context arg - in - let fresh_name = - ProofEngineHelpers.mk_fresh_name context (Cic.Name "Heta") ~typ:argty - in - (C.Appl [C.Lambda (fresh_name,argty,aux 0 t) ; arg]) - -(*CSC: ma serve solamente la prima delle new_uninst e l'unione delle due!!! *) -let classify_metas newmeta in_subst_domain subst_in metasenv = - List.fold_right - (fun (i,canonical_context,ty) (old_uninst,new_uninst) -> - if in_subst_domain i then - old_uninst,new_uninst - else - let ty' = subst_in canonical_context ty in - let canonical_context' = - List.fold_right - (fun entry canonical_context' -> - let entry' = - match entry with - Some (n,Cic.Decl s) -> - Some (n,Cic.Decl (subst_in canonical_context' s)) - | Some (n,Cic.Def s) -> - Some (n,Cic.Def (subst_in canonical_context' s)) - | None -> None - in - entry'::canonical_context' - ) canonical_context [] - in - if i < newmeta then - ((i,canonical_context',ty')::old_uninst),new_uninst - else - old_uninst,((i,canonical_context',ty')::new_uninst) - ) metasenv ([],[]) - -(* Auxiliary function for apply: given a type (a backbone), it returns its *) -(* head, a META environment in which there is new a META for each hypothesis,*) -(* a list of arguments for the new applications and the indexes of the first *) -(* and last new METAs introduced. The nth argument in the list of arguments *) -(* is just the nth new META. *) -let new_metasenv_for_apply newmeta proof context ty = - let module C = Cic in - let module S = CicSubstitution in - let rec aux newmeta = - function - C.Cast (he,_) -> aux newmeta he - | C.Prod (name,s,t) -> - let irl = identity_relocation_list_for_metavariable context in - let newargument = C.Meta (newmeta,irl) in - let (res,newmetasenv,arguments,lastmeta) = - aux (newmeta + 1) (S.subst newargument t) - in - res,(newmeta,context,s)::newmetasenv,newargument::arguments,lastmeta - | t -> t,[],[],newmeta - in - (* WARNING: here we are using the invariant that above the most *) - (* recente new_meta() there are no used metas. *) - let (res,newmetasenv,arguments,lastmeta) = aux newmeta ty in - res,newmetasenv,arguments,lastmeta - -(* Useful only inside apply_tac *) -let - generalize_exp_named_subst_with_fresh_metas context newmeta uri exp_named_subst -= - let module C = Cic in - let params = - match CicEnvironment.get_obj uri with - C.Constant (_,_,_,params) - | C.CurrentProof (_,_,_,_,params) - | C.Variable (_,_,_,params) - | C.InductiveDefinition (_,params,_) -> params - in - let exp_named_subst_diff,new_fresh_meta,newmetasenvfragment,exp_named_subst'= - let next_fresh_meta = ref newmeta in - let newmetasenvfragment = ref [] in - let exp_named_subst_diff = ref [] in - let rec aux = - function - [],[] -> [] - | uri::tl,[] -> - let ty = - match CicEnvironment.get_obj uri with - C.Variable (_,_,ty,_) -> - CicSubstitution.subst_vars !exp_named_subst_diff ty - | _ -> raise (WrongUriToVariable (UriManager.string_of_uri uri)) - in - let irl = identity_relocation_list_for_metavariable context in - let subst_item = uri,C.Meta (!next_fresh_meta,irl) in - newmetasenvfragment := - (!next_fresh_meta,context,ty)::!newmetasenvfragment ; - exp_named_subst_diff := !exp_named_subst_diff @ [subst_item] ; - incr next_fresh_meta ; - subst_item::(aux (tl,[])) - | uri::tl1,((uri',_) as s)::tl2 -> - assert (UriManager.eq uri uri') ; - s::(aux (tl1,tl2)) - | [],_ -> assert false - in - let exp_named_subst' = aux (params,exp_named_subst) in - !exp_named_subst_diff,!next_fresh_meta, - List.rev !newmetasenvfragment, exp_named_subst' - in -prerr_endline ("@@@ " ^ CicPp.ppterm (Cic.Var (uri,exp_named_subst)) ^ " |--> " ^ CicPp.ppterm (Cic.Var (uri,exp_named_subst'))) ; - new_fresh_meta,newmetasenvfragment,exp_named_subst',exp_named_subst_diff -;; - -let apply_tac ~term ~status:(proof, goal) = - (* Assumption: The term "term" must be closed in the current context *) - let module T = CicTypeChecker in - let module R = CicReduction in - let module C = Cic in - let (_,metasenv,_,_) = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let newmeta = new_meta ~proof in - let exp_named_subst_diff,newmeta',newmetasenvfragment,term' = - match term with - C.Var (uri,exp_named_subst) -> - let newmeta',newmetasenvfragment,exp_named_subst',exp_named_subst_diff = - generalize_exp_named_subst_with_fresh_metas context newmeta uri - exp_named_subst - in - exp_named_subst_diff,newmeta',newmetasenvfragment, - C.Var (uri,exp_named_subst') - | C.Const (uri,exp_named_subst) -> - let newmeta',newmetasenvfragment,exp_named_subst',exp_named_subst_diff = - generalize_exp_named_subst_with_fresh_metas context newmeta uri - exp_named_subst - in - exp_named_subst_diff,newmeta',newmetasenvfragment, - C.Const (uri,exp_named_subst') - | C.MutInd (uri,tyno,exp_named_subst) -> - let newmeta',newmetasenvfragment,exp_named_subst',exp_named_subst_diff = - generalize_exp_named_subst_with_fresh_metas context newmeta uri - exp_named_subst - in - exp_named_subst_diff,newmeta',newmetasenvfragment, - C.MutInd (uri,tyno,exp_named_subst') - | C.MutConstruct (uri,tyno,consno,exp_named_subst) -> - let newmeta',newmetasenvfragment,exp_named_subst',exp_named_subst_diff = - generalize_exp_named_subst_with_fresh_metas context newmeta uri - exp_named_subst - in - exp_named_subst_diff,newmeta',newmetasenvfragment, - C.MutConstruct (uri,tyno,consno,exp_named_subst') - | _ -> [],newmeta,[],term - in - let metasenv' = metasenv@newmetasenvfragment in -prerr_endline ("^^^^^TERM': " ^ CicPp.ppterm term') ; - let termty = - CicSubstitution.subst_vars exp_named_subst_diff - (CicTypeChecker.type_of_aux' metasenv' context term) - in -prerr_endline ("^^^^^TERMTY: " ^ CicPp.ppterm termty) ; - (* newmeta is the lowest index of the new metas introduced *) - let (consthead,newmetas,arguments,_) = - new_metasenv_for_apply newmeta' proof context termty - in - let newmetasenv = metasenv'@newmetas in - let subst,newmetasenv' = - CicUnification.fo_unif newmetasenv context consthead ty - in - let in_subst_domain i = List.exists (function (j,_) -> i=j) subst in - let apply_subst = CicUnification.apply_subst subst in - let old_uninstantiatedmetas,new_uninstantiatedmetas = - (* subst_in doesn't need the context. Hence the underscore. *) - let subst_in _ = CicUnification.apply_subst subst in - classify_metas newmeta in_subst_domain subst_in newmetasenv' - in - let bo' = - apply_subst - (if List.length newmetas = 0 then - term' - else - Cic.Appl (term'::arguments) - ) - in -prerr_endline ("XXXX " ^ CicPp.ppterm (if List.length newmetas = 0 then term' else Cic.Appl (term'::arguments)) ^ " |>>> " ^ CicPp.ppterm bo') ; - let newmetasenv'' = new_uninstantiatedmetas@old_uninstantiatedmetas in - let (newproof, newmetasenv''') = - let subst_in = CicUnification.apply_subst ((metano,bo')::subst) in - subst_meta_and_metasenv_in_proof - proof metano subst_in newmetasenv'' - in - (newproof, List.map (function (i,_,_) -> i) new_uninstantiatedmetas) - - (* TODO per implementare i tatticali e' necessario che tutte le tattiche - sollevino _solamente_ Fail *) -let apply_tac ~term ~status = - try - apply_tac ~term ~status - (* TODO cacciare anche altre eccezioni? *) - with CicUnification.UnificationFailed as e -> - raise (Fail (Printexc.to_string e)) - -let intros_tac - ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name) () - ~status:(proof, goal) -= - let module C = Cic in - let module R = CicReduction in - let (_,metasenv,_,_) = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let newmeta = new_meta ~proof in - let (context',ty',bo') = - lambda_abstract context newmeta ty mk_fresh_name_callback - in - let (newproof, _) = - subst_meta_in_proof proof metano bo' [newmeta,context',ty'] - in - (newproof, [newmeta]) - -let cut_tac - ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name) - term ~status:(proof, goal) -= - let module C = Cic in - let curi,metasenv,pbo,pty = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let newmeta1 = new_meta ~proof in - let newmeta2 = newmeta1 + 1 in - let fresh_name = - mk_fresh_name_callback context (Cic.Name "Hcut") ~typ:term in - let context_for_newmeta1 = - (Some (fresh_name,C.Decl term))::context in - let irl1 = - identity_relocation_list_for_metavariable context_for_newmeta1 in - let irl2 = identity_relocation_list_for_metavariable context in - let newmeta1ty = CicSubstitution.lift 1 ty in - let bo' = - C.Appl - [C.Lambda (fresh_name,term,C.Meta (newmeta1,irl1)) ; - C.Meta (newmeta2,irl2)] - in - let (newproof, _) = - subst_meta_in_proof proof metano bo' - [newmeta2,context,term; newmeta1,context_for_newmeta1,newmeta1ty]; - in - (newproof, [newmeta1 ; newmeta2]) - -let letin_tac - ?(mk_fresh_name_callback = ProofEngineHelpers.mk_fresh_name) - term ~status:(proof, goal) -= - let module C = Cic in - let curi,metasenv,pbo,pty = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let _ = CicTypeChecker.type_of_aux' metasenv context term in - let newmeta = new_meta ~proof in - let fresh_name = - mk_fresh_name_callback context (Cic.Name "Hletin") ~typ:term in - let context_for_newmeta = - (Some (fresh_name,C.Def term))::context in - let irl = - identity_relocation_list_for_metavariable context_for_newmeta in - let newmetaty = CicSubstitution.lift 1 ty in - let bo' = C.LetIn (fresh_name,term,C.Meta (newmeta,irl)) in - let (newproof, _) = - subst_meta_in_proof - proof metano bo'[newmeta,context_for_newmeta,newmetaty] - in - (newproof, [newmeta]) - - (** functional part of the "exact" tactic *) -let exact_tac ~term ~status:(proof, goal) = - (* Assumption: the term bo must be closed in the current context *) - let (_,metasenv,_,_) = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let module T = CicTypeChecker in - let module R = CicReduction in - if R.are_convertible context (T.type_of_aux' metasenv context term) ty then - begin - let (newproof, metasenv') = - subst_meta_in_proof proof metano term [] in - (newproof, []) - end - else - raise (Fail "The type of the provided term is not the one expected.") - - -(* not really "primitive" tactics .... *) - -let elim_tac ~term ~status:(proof, goal) = - let module T = CicTypeChecker in - let module U = UriManager in - let module R = CicReduction in - let module C = Cic in - let (curi,metasenv,_,_) = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - let termty = T.type_of_aux' metasenv context term in - let uri,exp_named_subst,typeno,args = - match termty with - C.MutInd (uri,typeno,exp_named_subst) -> (uri,exp_named_subst,typeno,[]) - | C.Appl ((C.MutInd (uri,typeno,exp_named_subst))::args) -> - (uri,exp_named_subst,typeno,args) - | _ -> raise NotAnInductiveTypeToEliminate - in - let eliminator_uri = - let buri = U.buri_of_uri uri in - let name = - match CicEnvironment.get_obj uri with - C.InductiveDefinition (tys,_,_) -> - let (name,_,_,_) = List.nth tys typeno in - name - | _ -> assert false - in - let ext = - match T.type_of_aux' metasenv context ty with - C.Sort C.Prop -> "_ind" - | C.Sort C.Set -> "_rec" - | C.Sort C.Type -> "_rect" - | _ -> assert false - in - U.uri_of_string (buri ^ "/" ^ name ^ ext ^ ".con") - in - let eliminator_ref = C.Const (eliminator_uri,exp_named_subst) in - let ety = T.type_of_aux' metasenv context eliminator_ref in - let newmeta = new_meta ~proof in - let (econclusion,newmetas,arguments,lastmeta) = - new_metasenv_for_apply newmeta proof context ety - in - (* Here we assume that we have only one inductive hypothesis to *) - (* eliminate and that it is the last hypothesis of the theorem. *) - (* A better approach would be fingering the hypotheses in some *) - (* way. *) - let meta_of_corpse = - let (_,canonical_context,_) = - List.find (function (m,_,_) -> m=(lastmeta - 1)) newmetas - in - let irl = - identity_relocation_list_for_metavariable canonical_context - in - Cic.Meta (lastmeta - 1, irl) - in - let newmetasenv = newmetas @ metasenv in - let subst1,newmetasenv' = - CicUnification.fo_unif newmetasenv context term meta_of_corpse - in - let ueconclusion = CicUnification.apply_subst subst1 econclusion in - (* The conclusion of our elimination principle is *) - (* (?i farg1 ... fargn) *) - (* The conclusion of our goal is ty. So, we can *) - (* eta-expand ty w.r.t. farg1 .... fargn to get *) - (* a new ty equal to (P farg1 ... fargn). Now *) - (* ?i can be instantiated with P and we are ready *) - (* to refine the term. *) - let emeta, fargs = - match ueconclusion with - C.Appl ((C.Meta (emeta,_))::fargs) -> emeta,fargs - | C.Meta (emeta,_) -> emeta,[] - | _ -> raise NotTheRightEliminatorShape - in - let ty' = CicUnification.apply_subst subst1 ty in - let eta_expanded_ty = -(*CSC: newmetasenv' era metasenv ??????????? *) - List.fold_left (eta_expand newmetasenv' context) ty' fargs - in - let subst2,newmetasenv'' = -(*CSC: passo newmetasenv', ma alcune variabili sono gia' state sostituite -da subst1!!!! Dovrei rimuoverle o sono innocue?*) - CicUnification.fo_unif - newmetasenv' context ueconclusion eta_expanded_ty - in - let in_subst_domain i = - let eq_to_i = function (j,_) -> i=j in - List.exists eq_to_i subst1 || - List.exists eq_to_i subst2 - in - (* When unwinding the META that corresponds to the elimination *) - (* predicate (which is emeta), we must also perform one-step *) - (* beta-reduction. apply_subst doesn't need the context. Hence *) - (* the underscore. *) - let apply_subst _ t = - let t' = CicUnification.apply_subst subst1 t in - CicUnification.apply_subst_reducing - subst2 (Some (emeta,List.length fargs)) t' - in - let old_uninstantiatedmetas,new_uninstantiatedmetas = - classify_metas newmeta in_subst_domain apply_subst - newmetasenv'' - in - let arguments' = List.map (apply_subst context) arguments in - let bo' = Cic.Appl (eliminator_ref::arguments') in - let newmetasenv''' = - new_uninstantiatedmetas@old_uninstantiatedmetas - in - let (newproof, newmetasenv'''') = - (* When unwinding the META that corresponds to the *) - (* elimination predicate (which is emeta), we must *) - (* also perform one-step beta-reduction. *) - (* The only difference w.r.t. apply_subst is that *) - (* we also substitute metano with bo'. *) - (*CSC: Nota: sostituire nuovamente subst1 e' superfluo, *) - (*CSC: no? *) - let apply_subst' t = - let t' = CicUnification.apply_subst subst1 t in - CicUnification.apply_subst_reducing - ((metano,bo')::subst2) - (Some (emeta,List.length fargs)) t' - in - subst_meta_and_metasenv_in_proof - proof metano apply_subst' newmetasenv''' - in - (newproof, - List.map (function (i,_,_) -> i) new_uninstantiatedmetas) -;; - -(* The simplification is performed only on the conclusion *) -let elim_intros_simpl_tac ~term = - Tacticals.then_ ~start:(elim_tac ~term) - ~continuation: - (Tacticals.thens - ~start:(intros_tac ()) - ~continuations: - [ReductionTactics.simpl_tac ~also_in_hypotheses:false ~terms:None]) -;; - -exception NotConvertible - -(*CSC: Bug (or feature?). [with_what] is parsed in the context of the goal, *) -(*CSC: while [what] can have a richer context (because of binders) *) -(*CSC: So it is _NOT_ possible to use those binders in the [with_what] term. *) -(*CSC: Is that evident? Is that right? Or should it be changed? *) -let change_tac ~what ~with_what ~status:(proof, goal) = - let curi,metasenv,pbo,pty = proof in - let metano,context,ty = List.find (function (m,_,_) -> m=goal) metasenv in - (* are_convertible works only on well-typed terms *) - ignore (CicTypeChecker.type_of_aux' metasenv context with_what) ; - if CicReduction.are_convertible context what with_what then - begin - let replace = - ProofEngineReduction.replace - ~equality:(==) ~what:[what] ~with_what:[with_what] - in - let ty' = replace ty in - let context' = - List.map - (function - Some (name,Cic.Def t) -> Some (name,Cic.Def (replace t)) - | Some (name,Cic.Decl t) -> Some (name,Cic.Decl (replace t)) - | None -> None - ) context - in - let metasenv' = - List.map - (function - (n,_,_) when n = metano -> (metano,context',ty') - | _ as t -> t - ) metasenv - in - (curi,metasenv',pbo,pty), [metano] - end - else - raise (ProofEngineTypes.Fail "Not convertible")