Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file taccoerce.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451(************************************************************************)(* * The Coq Proof Assistant / The Coq 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) *)(************************************************************************)openUtilopenNamesopenConstropenEConstropenNamegenopenTactypesopenGenargopenStdargopenTacargopenGeninterpopenPpexceptionCannotCoerceToofstringletbase_val_typwit=matchval_tag(topwitwit)withVal.Baset->t|_->CErrors.anomaly(Pp.str"Not a base val.")let(wit_constr_context:(Empty.t,Empty.t,Constr_matching.context)Genarg.genarg_type)=letwit=Genarg.create_arg"constr_context"inlet()=register_val0witNoneinletprenvsigmalevc:Pp.t=Printer.pr_econstr_n_envenvsigmalev(Constr_matching.repr_contextc)inlet()=Genprint.register_val_print0(base_val_typwit)(Pptactic.make_constr_printerpr)inwit(* includes idents known to be bound and references *)let(wit_constr_under_binders:(Empty.t,Empty.t,Ltac_pretype.constr_under_binders)Genarg.genarg_type)=letwit=Genarg.create_arg"constr_under_binders"inlet()=register_val0witNoneinlet()=Genprint.register_val_print0(base_val_typwit)(func->Genprint.TopPrinterNeedsContext(funenvsigma->Printer.pr_constr_under_binders_envenvsigmac))inwit(** All the types considered here are base types *)letval_tagwit=matchval_tagwitwith|Val.Baset->t|_->assertfalselethas_type:typea.Val.t->atyped_abstract_argument_type->bool=funvwit->letVal.Dyn(t,_)=vinmatchVal.eqt(val_tagwit)with|None->false|SomeRefl->trueletprj:typea.aVal.typ->Val.t->aoption=funtv->letVal.Dyn(t',x)=vinmatchVal.eqtt'with|None->None|SomeRefl->Somexletin_genwitv=Val.Dyn(val_tagwit,v)letout_genwitv=matchprj(val_tagwit)vwithNone->assertfalse|Somex->xmoduleValue=structtypet=Val.tletof_constrc=in_gen(topwitwit_constr)cletto_constrv=ifhas_typev(topwitwit_constr)thenletc=out_gen(topwitwit_constr)vinSomecelseifhas_typev(topwitwit_constr_under_binders)thenletvars,c=out_gen(topwitwit_constr_under_binders)vinmatchvarswith[]->Somec|_->NoneelseNoneletof_uconstrc=in_gen(topwitwit_uconstr)cletto_uconstrv=ifhas_typev(topwitwit_uconstr)thenSome(out_gen(topwitwit_uconstr)v)elseNoneletof_inti=in_gen(topwitwit_int)iletto_intv=ifhas_typev(topwitwit_int)thenSome(out_gen(topwitwit_int)v)elseNoneletof_identid=in_gen(topwitwit_ident)idletto_identv=ifhas_typev(topwitwit_ident)thenSome(out_gen(topwitwit_ident)v)elseNoneletto_listv=prjVal.typ_listvletto_optionv=prjVal.typ_optvletto_pairv=prjVal.typ_pairvletcast_errorwitv=letpr_v=Pptactic.pr_valuePptactic.ltopvinletVal.Dyn(tag,_)=vinlettag=Val.prtaginCErrors.user_err(str"Type error: value "++pr_v++str" is a "++tag++str" while type "++Val.prwit++str" was expected.")letunboxwitvans=matchanswith|None->cast_errorwitv|Somex->xletrecprj:typea.aVal.tag->Val.t->a=funtagv->matchtagwith|Val.Listtag->List.map(funv->prjtagv)(unboxVal.typ_listv(to_listv))|Val.Opttag->Option.map(funv->prjtagv)(unboxVal.typ_optv(to_optionv))|Val.Pair(tag1,tag2)->let(x,y)=unboxVal.typ_pairv(to_pairv)in(prjtag1x,prjtag2y)|Val.Baset->letVal.Dyn(t',x)=vinmatchVal.eqtt'with|None->cast_errortv|SomeRefl->xletrectag_of_arg:typeabc.(a,b,c)genarg_type->cVal.tag=funwit->matchwitwith|ExtraArg_->Geninterp.val_tag(topwitwit)|ListArgt->Val.List(tag_of_argt)|OptArgt->Val.Opt(tag_of_argt)|PairArg(t1,t2)->Val.Pair(tag_of_argt1,tag_of_argt2)letval_castargv=prj(tag_of_argarg)vletcast(Topwitwit)v=val_castwitvendletis_variableenvid=Id.List.memid(Termops.ids_of_named_context(Environ.named_contextenv))(* Transforms an id into a constr if possible, or fails with Not_found *)letconstr_of_idenvid=EConstr.mkVar(let_=Environ.lookup_namedidenvinid)(* Gives the constr corresponding to a Constr_context tactic_arg *)letcoerce_to_constr_contextv=ifhas_typev(topwitwit_constr_context)thenout_gen(topwitwit_constr_context)velseraise(CannotCoerceTo"a term context")letis_intro_patternv=ifhas_typev(topwitwit_intro_pattern)thenSome(out_gen(topwitwit_intro_pattern)v).CAst.velseNone(* Interprets an identifier which must be fresh *)letcoerce_var_to_identfreshenvsigmav=letfail()=raise(CannotCoerceTo"a fresh identifier")inmatchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))->id|Some_->fail()|None->ifhas_typev(topwitwit_intro_pattern)thenmatchout_gen(topwitwit_intro_pattern)vwith|{CAst.v=IntroNaming(IntroIdentifierid)}->id|_->fail()elseifhas_typev(topwitwit_hyp)thenout_gen(topwitwit_hyp)velsematchValue.to_constrvwith|None->fail()|Somec->(* We need it fresh for intro e.g. in "Tac H = clear H; intro H" *)ifisVarsigmac&¬(fresh&&is_variableenv(destVarsigmac))thendestVarsigmacelsefail()(* Interprets, if possible, a constr to an identifier which may not
be fresh but suitable to be given to the fresh tactic. Works for
vars, constants, inductive, constructors and sorts. *)letcoerce_to_ident_not_freshsigmav=letid_of_name=function|Name.Anonymous->Id.of_string"x"|Name.Namex->xinletfail()=raise(CannotCoerceTo"an identifier")inmatchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))->id|Some_->fail()|None->ifhas_typev(topwitwit_hyp)thenout_gen(topwitwit_hyp)velsematchValue.to_constrvwith|None->fail()|Somec->matchEConstr.kindsigmacwith|Varid->id|Metam->id_of_name(Evd.meta_namesigmam)|Evar(kn,_)->beginmatchEvd.evar_identknsigmawith|None->fail()|Someid->idend|Const(cst,_)->Label.to_id(Constant.labelcst)|Construct(cstr,_)->letref=GlobRef.ConstructRefcstrinletbasename=Nametab.basename_of_globalrefinbasename|Ind(ind,_)->letref=GlobRef.IndRefindinletbasename=Nametab.basename_of_globalrefinbasename|Sorts->beginmatchESorts.kindsigmaswith|Sorts.SProp->Label.to_id(Label.make"SProp")|Sorts.Prop->Label.to_id(Label.make"Prop")|Sorts.Set->Label.to_id(Label.make"Set")|Sorts.Type_->Label.to_id(Label.make"Type")end|_->fail()letcoerce_to_intro_patternsigmav=matchis_intro_patternvwith|Somepat->pat|None->ifhas_typev(topwitwit_hyp)thenletid=out_gen(topwitwit_hyp)vinIntroNaming(IntroIdentifierid)elsematchValue.to_constrvwith|SomecwhenisVarsigmac->(* This happens e.g. in definitions like "Tac H = clear H; intro H" *)(* but also in "destruct H as (H,H')" *)IntroNaming(IntroIdentifier(destVarsigmac))|_->raise(CannotCoerceTo"an introduction pattern")letcoerce_to_intro_pattern_namingsigmav=matchcoerce_to_intro_patternsigmavwith|IntroNamingpat->pat|_->raise(CannotCoerceTo"a naming introduction pattern")letcoerce_to_hint_basev=matchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))->Id.to_stringid|Some_|None->raise(CannotCoerceTo"a hint base name")letcoerce_to_intv=ifhas_typev(topwitwit_int)thenout_gen(topwitwit_int)velseraise(CannotCoerceTo"an integer")letcoerce_to_constrenvv=letfail()=raise(CannotCoerceTo"a term")inmatchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))->(try([],constr_of_idenvid)withNot_found->fail())|Some_->fail()|None->ifhas_typev(topwitwit_constr)thenletc=out_gen(topwitwit_constr)vin([],c)elseifhas_typev(topwitwit_constr_under_binders)thenout_gen(topwitwit_constr_under_binders)velseifhas_typev(topwitwit_hyp)thenletid=out_gen(topwitwit_hyp)vin(try[],constr_of_idenvidwithNot_found->fail())elsefail()letcoerce_to_uconstrv=ifhas_typev(topwitwit_uconstr)thenout_gen(topwitwit_uconstr)velseraise(CannotCoerceTo"an untyped term")letcoerce_to_closed_constrenvv=letids,c=coerce_to_constrenvvinlet()=ifnot(List.is_emptyids)thenraise(CannotCoerceTo"a term")incletcoerce_to_evaluable_refenvsigmav=letopenTacredinletfail()=raise(CannotCoerceTo"an evaluable reference")inletev=matchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))whenis_variableenvid->EvalVarRefid|Some_->fail()|None->ifhas_typev(topwitwit_hyp)thenletid=out_gen(topwitwit_hyp)vinifId.List.memid(Termops.ids_of_contextenv)thenEvalVarRefidelsefail()elseifhas_typev(topwitwit_ref)thenletopenGlobRefinletr=out_gen(topwitwit_ref)vinmatchrwith|VarRefvar->EvalVarRefvar|ConstRefc->EvalConstRefc|IndRef_|ConstructRef_->fail()elseifhas_typev(topwitwit_smart_global)thenletopenGlobRefinletr=out_gen(topwitwit_smart_global)vinmatchrwith|VarRefvar->EvalVarRefvar|ConstRefc->EvalConstRefc|IndRef_|ConstructRef_->fail()elsematchValue.to_constrvwith|SomecwhenisConstsigmac->EvalConstRef(fst(destConstsigmac))|SomecwhenisVarsigmac->EvalVarRef(destVarsigmac)|_->fail()inifTacred.is_evaluableenvevthenevelsefail()letcoerce_to_constr_listenvv=letv=Value.to_listvinmatchvwith|Somel->letmapv=coerce_to_closed_constrenvvinList.mapmapl|None->raise(CannotCoerceTo"a term list")letcoerce_to_intro_pattern_list?locsigmav=matchValue.to_listvwith|None->raise(CannotCoerceTo"an intro pattern list")|Somel->letmapv=CAst.make?loc@@coerce_to_intro_patternsigmavinList.mapmaplletcoerce_to_hypenvsigmav=letfail()=raise(CannotCoerceTo"a variable")inmatchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))whenis_variableenvid->id|Some_->fail()|None->ifhas_typev(topwitwit_hyp)thenletid=out_gen(topwitwit_hyp)vinifis_variableenvidthenidelsefail()elsematchValue.to_constrvwith|SomecwhenisVarsigmac->destVarsigmac|_->fail()letcoerce_to_hyp_listenvsigmav=letv=Value.to_listvinmatchvwith|Somel->letmapn=coerce_to_hypenvsigmaninList.mapmapl|None->raise(CannotCoerceTo"a variable list")(* Interprets a qualified name *)letcoerce_to_referencesigmav=matchValue.to_constrvwith|Somec->begintryfst(EConstr.destRefsigmac)withDestKO->raise(CannotCoerceTo"a reference")end|None->raise(CannotCoerceTo"a reference")(* Quantified named or numbered hypothesis or hypothesis in context *)(* (as in Inversion) *)letcoerce_to_quantified_hypothesissigmav=matchis_intro_patternvwith|Some(IntroNaming(IntroIdentifierid))->NamedHyp(CAst.makeid)|Some_->raise(CannotCoerceTo"a quantified hypothesis")|None->ifhas_typev(topwitwit_hyp)thenletid=out_gen(topwitwit_hyp)vinNamedHyp(CAst.makeid)elseifhas_typev(topwitwit_int)thenAnonHyp(out_gen(topwitwit_int)v)elsematchValue.to_constrvwith|SomecwhenisVarsigmac->NamedHyp(CAst.make@@destVarsigmac)|_->raise(CannotCoerceTo"a quantified hypothesis")(* Quantified named or numbered hypothesis or hypothesis in context *)(* (as in Inversion) *)letcoerce_to_decl_or_quant_hypsigmav=ifhas_typev(topwitwit_int)thenAnonHyp(out_gen(topwitwit_int)v)elsetrycoerce_to_quantified_hypothesissigmavwithCannotCoerceTo_->raise(CannotCoerceTo"a declared or quantified hypothesis")letcoerce_to_int_or_var_listv=matchValue.to_listvwith|None->raise(CannotCoerceTo"an int list")|Somel->letmapn=Locus.ArgArg(coerce_to_intn)inList.mapmapl(** Abstract application, to print ltac functions *)typeappl=|UnnamedAppl(** For generic applications: nothing is printed *)|GlbApplof(Names.KerName.t*Val.tlist)list(** For calls to global constants, some may alias other. *)(* Values for interpretation *)typetacvalue=|VFunofappl*Tacexpr.ltac_trace*Loc.toption*(* when executing a global Ltac function: the location where this function was called *)Val.tId.Map.t*(* closure *)Name.tlist*(* binders *)Tacexpr.glob_tactic_expr(* body *)|VRecofVal.tId.Map.tref*Tacexpr.glob_tactic_exprlet(wit_tacvalue:(Empty.t,tacvalue,tacvalue)Genarg.genarg_type)=letwit=Genarg.create_arg"tacvalue"inlet()=register_val0witNoneinlet()=Genprint.register_val_print0(base_val_typwit)(fun_->Genprint.TopPrinterBasic(fun()->str"<tactic closure>"))inwitletpr_argument_typearg=letVal.Dyn(tag,_)=arginVal.prtag(** TODO: unify printing of generic Ltac values in case of coercion failure. *)(* Displays a value *)letpr_valueenvv=letpr_with_envpr=matchenvwith|Some(env,sigma)->prenvsigma|None->str"a value of type"++spc()++pr_argument_typevinletopenGenprintinmatchgeneric_val_printvwith|TopPrinterBasicpr->pr()|TopPrinterNeedsContextpr->pr_with_envpr|TopPrinterNeedsContextAndLevel{default_already_surrounded;printer}->pr_with_env(funenvsigma->printerenvsigmadefault_already_surrounded)exceptionCoercionErrorofId.t*(Environ.env*Evd.evar_map)option*Val.t*stringlet()=CErrors.register_handlerbeginfunction|CoercionError(id,env,v,s)->Some(str"Ltac variable "++Id.printid++strbrk" is bound to"++spc()++pr_valueenvv++spc()++strbrk"which cannot be coerced to "++strs++str".")|_->Noneendleterror_ltac_variable?locidenvvs=Loc.raise?loc(CoercionError(id,env,v,s))