(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
open Pp open CErrors open Util open Names open Termops open Environ open Constr open Context open EConstr open Vars open Namegen open Evd open Printer open Reductionops open Inductiveops open Tacmach open Tacticals open Tactics open Context.Named.Declaration
module NamedDecl = Context.Named.Declaration
let no_inductive_inconstr env sigma constr =
(str "Cannot recognize an inductive predicate in " ++
pr_leconstr_env env sigma constr ++
str "." ++ spc () ++ str "If there is one, may be the structure of the arity" ++
spc () ++ str "or of the type of constructors" ++ spc () ++
str "is hidden by constant definitions.")
(* returns the sub_signature of sign corresponding to those identifiers that
* are not global. *) (* letget_local_signsign= letlid=ids_of_signsignin letglobsign=Global.named_context()in letadd_localidres_sign= ifnot(mem_signglobsignid)then add_sign(lookup_signidsign)res_sign else res_sign in List.fold_rightadd_locallidnil_sign
*) (* returns the identifier of lid that was the latest declared in sign. *(i.e.istheidentifieridoflidsuchthat *sign_length(sign_prefixidsign)>sign_length(sign_prefixid'sign)> *foranyid'<>idinlid).
* it returns both the pair (id,(sign_prefix id sign)) *) (* letmax_prefix_signlidsign= letrecmax_rec(resid,prefix)=function |[]->(resid,prefix) |(id::l)-> letpre=sign_prefixidsignin ifsign_lengthpre>sign_lengthprefixthen max_rec(id,pre)l else max_rec(resid,prefix)l in matchlidwith |[]->nil_sign |id::l->snd(max_rec(id,sign_prefixidsign)l)
*) let rec add_prods_sign env sigma t = match EConstr.kind sigma (whd_all env sigma t) with
| Prod (na,c1,b) -> let id = id_of_name_using_hdchar env sigma t na.binder_name in let b'= subst1 (mkVar id) b in
add_prods_sign (push_named (LocalAssum ({na with binder_name=id},c1)) env) sigma b'
| LetIn (na,c1,t1,b) -> let id = id_of_name_using_hdchar env sigma t na.binder_name in let b'= subst1 (mkVar id) b in
add_prods_sign (push_named (LocalDef ({na with binder_name=id},c1,t1)) env) sigma b'
| _ -> (env,t)
(* [dep_option] indicates whether the inversion lemma is dependent or not. IfitisdependentandIisoftheform(x_bar:T_bar)(It_bar)then thestatedgoalwillbe(x_bar:T_bar)(H:(It_bar))(Pt_barH) whereP:(x_bar:T_bar)(H:(Ix_bar))[sort]. Thegeneralisationofsuchagoalatthemomentofthedependentcaseshould beeasy.
let compute_first_inversion_scheme env sigma ind sort dep_option = let indf,realargs = dest_ind_type ind in let allvars = vars_of_env env in let p = next_ident_away (Id.of_string "P") allvars in let pty,goal = if dep_option then let pty = make_arity env sigma true indf sort in let r = relevance_of_inductive_type env ind in let goal =
mkProd
(make_annot Anonymous r, mkAppliedInd ind, applist(mkVar p,realargs@[mkRel 1])) in
pty,goal else let i = mkAppliedInd ind in let ivars = Termops.global_vars_set env sigma i in let revargs,ownsign =
fold_named_context
(fun env d (revargs,hyps) -> let d = EConstr.of_named_decl d in let id = NamedDecl.get_id d in if Id.Set.mem id ivars then
((mkVar id)::revargs, Context.Named.add d hyps) else
(revargs,hyps))
env ~init:([],[]) in let pty = it_mkNamedProd_or_LetIn sigma (mkSort sort) ownsign in let goal = mkArrow i ERelevance.relevant (applist(mkVar p, List.rev revargs)) in
(pty,goal) in let npty = nf_all env sigma pty in let extenv = push_named (LocalAssum (make_annot p ERelevance.relevant,npty)) env in
extenv, goal
(* [inversion_scheme sign I]
Givenalocalsignature,[sign],andaninstanceofaninductive relation,[I],inversion_schemewillprovetheassociatedinversion schemeonsort[sort].Dependingonthevalueof[dep_option]itwill
build a dependent lemma or a non-dependent one *)
let inversion_scheme ~name ~poly env sigma t sort dep_option inv_op = let (env,i) = add_prods_sign env sigma t in let ind = try find_rectype env sigma i with Not_found ->
user_err (no_inductive_inconstr env sigma i) in let (invEnv,invGoal) =
compute_first_inversion_scheme env sigma ind sort dep_option in
assert
(Id.Set.subset
(Termops.global_vars_set env sigma invGoal)
(ids_of_named_context_val (named_context_val invEnv))); (* user_err (str"Computedinversiongoalwasnotclosedininitialsignature.");
*) let pf = Proof.start ~name ~poly (Evd.from_ctx (ustate sigma)) [invEnv,invGoal] in let pf, _, () = Proof.run_tactic env (tclTHEN intro (onLastHypId inv_op)) pf in let pfterm = List.hd (Proof.partial_proof pf) in let global_named_context = Global.named_context_val () in let ownSign = refbegin
fold_named_context
(fun env d sign -> let d = EConstr.of_named_decl d in if mem_named_context_val (NamedDecl.get_id d) global_named_context then sign else Context.Named.add d sign)
invEnv ~init:Context.Named.empty endin let avoid = ref Id.Set.empty in let Proof.{sigma} = Proof.data pf in let sigma = Evd.minimize_universes sigma in let rec fill_holes c = match EConstr.kind sigma c with
| Evar (e,args) -> let h = next_ident_away (Id.of_string "H") !avoid in let ty,inst = Evarutil.generalize_evar_over_rels sigma (e,args) in
avoid := Id.Set.add h !avoid;
ownSign := Context.Named.add (LocalAssum (make_annot h ERelevance.relevant,ty)) !ownSign;
applist (mkVar h, inst)
| _ -> EConstr.map sigma fill_holes c in let c = fill_holes pfterm in (* warning: side-effect on ownSign *) let invProof = it_mkNamedLambda_or_LetIn sigma c !ownSign in
invProof, sigma
let add_inversion_lemma ~poly (name:lident) env sigma t sort dep inv_op = let invProof, sigma = inversion_scheme ~name:name.v ~poly env sigma t sort dep inv_op in let cinfo = Declare.CInfo.make ?loc:name.loc ~name:name.v ~typ:None () in let info = Declare.Info.make ~poly ~kind:Decls.(IsProof Lemma) () in let _ : Names.GlobRef.t =
Declare.declare_definition ~cinfo ~info ~opaque:false ~body:invProof sigma in
()
(* inv_op = Inv (derives de complete inv. lemma)
* inv_op = InvNoThining (derives de semi inversion lemma) *)
let add_inversion_lemma_exn ~poly na com comsort bool tac = let env = Global.env () in let sigma = Evd.from_env env in let c, uctx = Constrintern.interp_type env sigma com in let sigma = Evd.from_ctx uctx in let sigma, sort = Evd.fresh_sort_in_quality ~rigid:univ_rigid sigma comsort in
add_inversion_lemma ~poly na env sigma c sort bool tac
(* ================================= *) (* Applying a given inversion lemma *) (* ================================= *)
let lemInv id c =
Proofview.Goal.enter beginfun gls -> let env = Proofview.Goal.env gls in let clause = Clenv.mk_clenv_from env (project gls) (c, pf_get_type_of gls c) in let mv = let mvs = Clenv.clenv_arguments clause in ifList.is_empty mvs then
CErrors.user_err
Pp.(hov 0 (pr_econstr_env (pf_env gls) (project gls) c ++ spc ()
++ str "does not refer to an inversion lemma.")) elseList.last mvs in try let clause = Clenv.clenv_instantiate mv clause (EConstr.mkVar id, Typing.type_of_variable env id) in
Clenv.res_pf clause ~flags:(Unification.elim_flags ()) ~with_evars:false with
| Failure _ | UserError _ ->
user_err
(str "Cannot refine current goal with the lemma " ++
pr_leconstr_env (pf_env gls) (project gls) c ++ str ".") end
let lemInv_gen id c = try_intros_until (fun id -> lemInv id c) id
let lemInvIn id c ids =
Proofview.Goal.enter beginfun gl -> let hyps = List.map (fun id -> pf_get_hyp id gl) ids in let intros_replace_ids = let concl = Proofview.Goal.concl gl in let sigma = project gl in let nb_of_new_hyp = nb_prod sigma concl - List.length ids in if nb_of_new_hyp < 1then
intros_replacing ids else
(tclTHEN (tclDO nb_of_new_hyp intro) (intros_replacing ids)) in
((tclTHEN (tclTHEN (Generalize.bring_hyps hyps) (lemInv id c))
(intros_replace_ids))) end
let lemInvIn_gen id c l = try_intros_until (fun id -> lemInvIn id c l) id
let lemInv_clause id c = function
| [] -> lemInv_gen id c
| l -> lemInvIn_gen id c l
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.