123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608(************************************************************************)(* * 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenConstropenEConstropenGenredexpropenPatternopenReductionopsopenTacredopenRedFlagsopenLibobjectletwarn_vm_disabled=CWarnings.create~name:"vm-compute-disabled"~category:CWarnings.CoreCategories.bytecode_compiler(fun()->strbrk"vm_compute disabled at configure time; falling back to cbv.")(* call by value normalisation function using the virtual machine *)letcbv_vmenvsigmac=if(Environ.typing_flagsenv).enable_VMthenletctyp=Retyping.get_type_ofenvsigmacinVnorm.cbv_vmenvsigmacctypelsebeginwarn_vm_disabled();computeenvsigmacendletwarn_native_compute_disabled=CWarnings.create_inNativeconv.w_native_disabled(fun()->strbrk"native_compute disabled at configure time; falling back to vm_compute.")letcbv_nativeenvsigmac=if(Environ.typing_flagsenv).enable_native_compilerthenletctyp=Retyping.get_type_ofenvsigmacinNativenorm.native_normenvsigmacctypelse(warn_native_compute_disabled();cbv_vmenvsigmac)let{Goptions.get=simplIsCbn}=Goptions.declare_bool_option_and_ref~key:["SimplIsCbn"]~value:false()letset_strategy_onerefl=Global.set_strategy(Evaluable.to_kevaluableref)l;matchref,lwith|Evaluable.EvalConstRefsp,Conv_oracle.Opaque->()|Evaluable.EvalConstRefsp,_->ifDeclareops.is_opaque(Global.lookup_constantsp)thenuser_err(str"Cannot make"++spc()++Nametab.pr_global_envId.Set.empty(GlobRef.ConstRefsp)++spc()++str"transparent because it was declared opaque.")|_->()letcache_strategy(_,str)=List.iter(fun(lev,ql)->List.iter(funq->set_strategy_oneqlev)ql)strletsubst_strategy(subs,(local,obj))=local,List.Smart.map(fun(k,qlasentry)->letql'=List.Smart.map(Tacred.subst_evaluable_referencesubs)qlinifql==ql'thenentryelse(k,ql'))objletmap_strategyfl=letl'=List.fold_right(fun(lev,ql)str->letql'=List.fold_right(funqql->matchfqwithSomeq'->q'::ql|None->ql)ql[]inifList.is_emptyql'thenstrelse(lev,ql')::str)l[]inifList.is_emptyl'thenNoneelseSome(false,l')letclassify_strategy(local,_)=iflocalthenDisposeelseSubstituteletdisch_refref=matchrefwith|Evaluable.EvalConstRefc->Someref|Evaluable.EvalProjectionRefp->letp=Lib.discharge_proj_reprpinSome(Evaluable.EvalProjectionRefp)|Evaluable.EvalVarRefid->ifLib.is_in_section(GlobRef.VarRefid)thenNoneelseSomerefletdischarge_strategy(local,obj)=iflocalthenNoneelsemap_strategydisch_refobjtypestrategy_obj=bool*(Conv_oracle.level*Evaluable.tlist)listletinStrategy:strategy_obj->obj=declare_object{(default_object"STRATEGY")withcache_function=cache_strategy;load_function=(fun_obj->cache_strategyobj);subst_function=subst_strategy;discharge_function=discharge_strategy;classify_function=classify_strategy;}letset_strategylocalstr=Lib.add_leaf(inStrategy(local,str))(* Generic reduction: reduction functions used in reduction tactics *)typered_expr=(constr,Evaluable.t,constr_pattern,int)red_expr_gentypered_expr_val=(constr,Evaluable.t,constr_pattern,int,strength*RedFlags.reds)red_expr_gen0letmake_flag_constant=function|Evaluable.EvalVarRefid->[fVARid]|Evaluable.EvalConstRefsp->beginmatchStructures.PrimitiveProjections.find_optspwith|None->[fCONSTsp]|Somep->[fCONSTsp;fPROJp]end|Evaluable.EvalProjectionRefp->[fPROJp;fCONST(Projection.Repr.constantp)]letmake_flagenvf=letred=no_redinletred=iff.rBetathenred_addredfBETAelseredinletred=iff.rMatchthenred_addredfMATCHelseredinletred=iff.rFixthenred_addredfFIXelseredinletred=iff.rCofixthenred_addredfCOFIXelseredinletred=iff.rZetathenred_addredfZETAelseredinletred=iff.rDeltathen(* All but rConst *)letred=red_addredfDELTAinletred=red_add_transparentred(Conv_oracle.get_transp_state(Environ.oracleenv))inList.fold_right(funvred->red_sub_listred(make_flag_constantv))f.rConstredelse(* Only rConst *)letred=red_addredfDELTAinList.fold_right(funvred->red_add_listred(make_flag_constantv))f.rConstredinf.rStrength,red(* table of custom reductino fonctions, not synchronized,
filled via ML calls to [declare_reduction] *)letreduction_tab=refString.Map.empty(* table of custom reduction expressions, synchronized,
filled by command Declare Reduction *)letred_expr_tab=Summary.refString.Map.empty~name:"Declare Reduction"letdeclare_reductionsf=ifString.Map.mems!reduction_tab||String.Map.mems!red_expr_tabthenuser_err(str"There is already a reduction expression of name "++strs++str".")elsereduction_tab:=String.Map.addsf!reduction_tabletcheck_custom=function|ExtraRedExprs->ifnot(String.Map.mems!reduction_tab||String.Map.mems!red_expr_tab)thenuser_err(str"Reference to undefined reduction expression "++strs++str".")|_->()letdecl_red_exprse=ifString.Map.mems!reduction_tab||String.Map.mems!red_expr_tabthenuser_err(str"There is already a reduction expression of name "++strs++str".")elsebegincheck_custome;red_expr_tab:=String.Map.addse!red_expr_tabendletout_arg=function|Locus.ArgVar_->anomaly(Pp.str"Unevaluated or_var variable.")|Locus.ArgArgx->xletcheck_occurrencesoccs=matchoccswith|Locus.OnlyOccurrences(n::_asnl)whenn<0->Locus.AllOccurrencesBut(List.mapabsnl)|Locus.OnlyOccurrencesnlwhenList.exists(funn->n<0)nl->CErrors.user_errPp.(str"Illegal negative occurrence number.")|Locus.OnlyOccurrences_|Locus.AllOccurrencesBut_|Locus.NoOccurrences|Locus.AllOccurrences|Locus.AtLeastOneOccurrence->occsletout_occurrencesoccs=letoccs=Locusops.occurrences_map(List.mapout_arg)occsincheck_occurrencesoccsletout_with_occurrences(occs,c)=(out_occurrencesoccs,c)lete_redfenvevmc=evm,fenvevmcletcontextualizef=function|Some(occs,c)->letl=check_occurrencesoccsinletb,c=matchcwith|Inlr->true,PRef(global_of_evaluable_referencer)|Inrc->false,cine_red(contextuallyb(l,c)(fun_->f))|None->e_redfletwarn_simpl_unfolding_modifiers=CWarnings.create~name:"simpl-unfolding-modifiers"~category:CWarnings.CoreCategories.tactics(fun()->Pp.strbrk"The legacy simpl ignores constant unfolding modifiers.")letreceval_red_exprenv=function|Simpl(f,o)->let()=ifnot(simplIsCbn()||List.is_emptyf.rConst)thenwarn_simpl_unfolding_modifiers()inletf=ifsimplIsCbn()thenmake_flagenvfelsef.rStrength,RedFlags.all(* dummy *)inSimpl(f,o)|Cbvf->Cbv(make_flagenvf)|Cbnf->Cbn(make_flagenvf)|Lazyf->Lazy(make_flagenvf)|ExtraRedExprs->beginmatchString.Map.finds!red_expr_tabwith|e->eval_red_exprenve|exceptionNot_found->ExtraRedExprs(* delay to runtime interpretation *)end|(Red|Hnf|Unfold_|Fold_|Pattern_|CbvVm_|CbvNative_)ase->eletred_product_exnenvsigmac=matchred_productenvsigmacwith|None->user_errPp.(str"No head constant to reduce.")|Somec->cletreduction_of_red_expr_val=function|Red->(e_redred_product_exn,DEFAULTcast)|Hnf->(e_redhnf_constr,DEFAULTcast)|Simpl((w,f),o)->letam=matchw,simplIsCbn()with|Norm,true->Cbn.norm_cbnf|Norm,false->simpl|Head,true->Cbn.whd_cbnf|Head,false->whd_simplin(contextualizeamo,DEFAULTcast)|Cbv(Norm,f)->(e_red(cbv_norm_flags~strong:truef),DEFAULTcast)|Cbv(Head,f)->(e_red(cbv_norm_flags~strong:falsef),DEFAULTcast)|Cbn(w,f)->letcbn=matchwwithNorm->Cbn.norm_cbn|Head->Cbn.whd_cbnin(e_red(cbnf),DEFAULTcast)|Lazy(w,f)->letredf=matchwwithNorm->clos_norm_flags|Head->clos_whd_flagsin(e_red(redff),DEFAULTcast)|Unfoldubinds->(e_red(unfoldn(List.map(on_fstcheck_occurrences)ubinds)),DEFAULTcast)|Foldcl->(e_red(fold_commandscl),DEFAULTcast)|Patternlp->(pattern_occs(List.map(on_fstcheck_occurrences)lp),DEFAULTcast)|ExtraRedExprs->(try(e_red(String.Map.finds!reduction_tab),DEFAULTcast)withNot_found->user_err(str"Unknown user-defined reduction \""++strs++str"\"."))|CbvVmo->(contextualizecbv_vmo,VMcast)|CbvNativeo->(contextualizecbv_nativeo,NATIVEcast)letreduction_of_red_exprenvr=reduction_of_red_expr_val(eval_red_exprenvr)(* Possibly equip a reduction with the occurrences mentioned in an
occurrence clause *)leterror_illegal_clause()=CErrors.user_errPp.(str"\"at\" clause not supported in presence of an occurrence clause.")leterror_multiple_patterns()=CErrors.user_errPp.(str"\"at\" clause in occurences not supported with multiple patterns or references.")leterror_illegal_non_atomic_clause()=CErrors.user_errPp.(str"\"at\" clause not supported in presence of a non atomic \"in\" clause.")leterror_at_in_occurrences_not_supported()=CErrors.user_errPp.(str"\"at\" clause not supported for this reduction tactic.")letbind_red_expr_occurrencesoccsnbclredexp=letopenLocusinlethas_at_clause=function|Unfoldl->List.exists(fun(occl,_)->occl!=AllOccurrences)l|Patternl->List.exists(fun(occl,_)->occl!=AllOccurrences)l|Simpl(_,Some(occl,_))->occl!=AllOccurrences|_->falseinifoccs==AllOccurrencesthenifnbcl>1&&has_at_clauseredexpthenerror_illegal_non_atomic_clause()elseredexpelsematchredexpwith|Unfold(_::_::_)->error_multiple_patterns()|Unfold[(occl,c)]->ifoccl!=AllOccurrencesthenerror_illegal_clause()elseUnfold[(occs,c)]|Pattern(_::_::_)->error_multiple_patterns()|Pattern[(occl,c)]->ifoccl!=AllOccurrencesthenerror_illegal_clause()elsePattern[(occs,c)]|Simpl(f,Some(occl,c))->ifoccl!=AllOccurrencesthenerror_illegal_clause()elseSimpl(f,Some(occs,c))|CbvVm(Some(occl,c))->ifoccl!=AllOccurrencesthenerror_illegal_clause()elseCbvVm(Some(occs,c))|CbvNative(Some(occl,c))->ifoccl!=AllOccurrencesthenerror_illegal_clause()elseCbvNative(Some(occs,c))|Red|Hnf|Cbv_|Lazy_|Cbn_|ExtraRedExpr_|Fold_|Simpl(_,None)|CbvVmNone|CbvNativeNone->error_at_in_occurrences_not_supported()|Unfold[]|Pattern[]->assertfalseletreduction_of_red_expr_val?occsr=letr=matchoccswith|None->r|Some(occs,nbcl)->bind_red_expr_occurrencesoccsnbclrinreduction_of_red_expr_valrletsubst_mpssubstc=EConstr.of_constr(Mod_subst.subst_mpssubst(EConstr.Unsafe.to_constrc))letsubst_red_exprsubs=letenv=Global.env()inletsigma=Evd.from_envenvinRedops.map_red_expr_gen(subst_mpssubs)(Tacred.subst_evaluable_referencesubs)(Patternops.subst_patternenvsigmasubs)letinReduction:bool*string*red_expr->obj=declare_object{(default_object"REDUCTION")withcache_function=(fun(_,s,e)->decl_red_exprse);load_function=(fun_(_,s,e)->decl_red_exprse);subst_function=(fun(subs,(b,s,e))->b,s,subst_red_exprsubse);classify_function=(fun((b,_,_))->ifbthenDisposeelseSubstitute)}letdeclare_red_exprlocalitysexpr=Lib.add_leaf(inReduction(locality,s,expr))letmake0?dynname=letwit=Genarg.make0nameinlet()=Geninterp.register_val0witdyninwitletwit_red_expr=make0"redexpr"moduleIntern=structopenCAstopenConstrexpropenLibnamesletevalref_of_globref?locr=let()=(* only dump section variables not proof context variables
(broken if variables got renamed) *)letis_proof_variable=matchrwith|GlobRef.VarRefx->(tryignore(Global.lookup_namedx);falsewithNot_found->true)|_->falseinifnotis_proof_variablethenDumpglob.add_glob?locrinTacred.soft_evaluable_of_global_reference?locrtype('constr,'ref,'pat)intern_env={strict_check:bool;local_ref:qualid->'refoption;global_ref:?short:lident->Evaluable.t->'ref;intern_constr:constr_expr->'constr;ltac_sign:Constrintern.ltac_sign;intern_pattern:constr_expr->'pat;pattern_of_glob:Glob_term.glob_constr->'pat;}letintern_global_referenceistqid=matchist.local_refqidwith|Somev->v|None->letr=trySmartlocate.locate_global_with_alias~head:trueqidwith|Not_foundasexn->ifnotist.strict_check&&qualid_is_identqidthenletid=qualid_basenameqidinGlobRef.VarRefidelselet_,info=Exninfo.captureexninNametab.error_global_not_found~infoqidinletshort=ifqualid_is_identqid&¬ist.strict_checkthenSome(make?loc:qid.CAst.loc@@qualid_basenameqid)elseNoneinletr=evalref_of_globref?loc:qid.locrinist.global_ref?shortrletintern_evaluableist=function|{v=ANqid}->intern_global_referenceistqid|{v=ByNotation(ntn,sc);loc}->letcheck=GlobRef.(functionConstRef_|VarRef_->true|_->false)inletr=Notation.interp_notation_as_global_reference?loc~head:truecheckntnscinletr=evalref_of_globref?locrinist.global_refrletintern_typed_pattern_or_ref_with_occurrencesist(l,p)=letinterp_refr=tryInl(intern_evaluableistr)withewhenCErrors.noncriticale->(* Compatibility. In practice, this means that the code above
is useless. Still the idea of having either an evaluable
ref or a pattern seems interesting, with "head" reduction
in case of an evaluable ref, and "strong" reduction in the
subterm matched when a pattern *)letr=matchrwith|{CAst.v=ANr}->r|{loc}->(qualid_of_path?loc(Nametab.path_of_global(Smartlocate.smart_globalr)))inletloc=r.locinletc=Constrintern.interp_referenceist.ltac_signrinmatchDAst.getcwith|GRef(r,None)->letr=evalref_of_globref?locrinInl(ist.global_refr)|GVarid->letr=evalref_of_globref(GlobRef.VarRefid)inInl(ist.global_refr)|_->Inr(ist.pattern_of_globc)inletp=matchpwith|Inlr->interp_refr|Inr{v=CAppExpl((r,None),[])}->(* We interpret similarly @ref and ref *)interp_ref(make@@ANr)|Inrc->Inr(ist.intern_patternc)in(l,p)letintern_constr_with_occurrencesist(l,c)=(l,ist.intern_constrc)letintern_flagistred={redwithrConst=List.map(intern_evaluableist)red.rConst}letintern_unfoldist(l,qid)=(l,intern_evaluableistqid)letintern_red_exprist=function|Unfoldl->Unfold(List.map(intern_unfoldist)l)|Foldl->Fold(List.mapist.intern_constrl)|Cbvf->Cbv(intern_flagistf)|Cbnf->Cbn(intern_flagistf)|Lazyf->Lazy(intern_flagistf)|Patternl->Pattern(List.map(intern_constr_with_occurrencesist)l)|Simpl(f,o)->Simpl(intern_flagistf,Option.map(intern_typed_pattern_or_ref_with_occurrencesist)o)|CbvVmo->CbvVm(Option.map(intern_typed_pattern_or_ref_with_occurrencesist)o)|CbvNativeo->CbvNative(Option.map(intern_typed_pattern_or_ref_with_occurrencesist)o)|(Red|Hnf|ExtraRedExpr_asr)->rletintern_constrenvc=Constrintern.intern_genWithoutTypeConstraint~strict_check:trueenv(Evd.from_envenv)cletintern_patternenvc=Constrintern.intern_genWithoutTypeConstraint~strict_check:true~pattern_mode:trueenv(Evd.from_envenv)cletfrom_envenv={strict_check=true;local_ref=(fun_->None);global_ref=(fun?short:_r->r);intern_constr=intern_constrenv;ltac_sign=Constrintern.empty_ltac_sign;pattern_of_glob=(func->c);intern_pattern=intern_patternenv;}endmoduleInterp=structtype('constr,'evref,'pat)interp_env={interp_occurrence_var:lident->intlist;interp_constr:Environ.env->Evd.evar_map->'constr->Evd.evar_map*EConstr.constr;interp_constr_list:Environ.env->Evd.evar_map->'constr->Evd.evar_map*EConstr.constrlist;interp_evaluable:Environ.env->Evd.evar_map->'evref->Evaluable.t;interp_pattern:Environ.env->Evd.evar_map->'pat->constr_pattern;interp_evaluable_or_pattern:Environ.env->Evd.evar_map->'evref->(Evaluable.t,constr_pattern)Util.union}letinterp_occurrencesistoccs=letopenLocusinletmap=function|ArgArgx->[x]|ArgVarlid->ist.interp_occurrence_varlidinLocusops.occurrences_map(List.concat_mapmap)occsletinterp_constr_with_occurrencesistenvsigma(occs,c)=let(sigma,c_interp)=ist.interp_constrenvsigmacinsigma,(interp_occurrencesistoccs,c_interp)letinterp_evaluableistenvsigmar=ist.interp_evaluableenvsigmarletinterp_closed_typed_pattern_with_occurrencesistenvsigma(occs,p)=letp=matchpwith|Inrp->Inr(ist.interp_patternenvsigmap)|Inlr->ist.interp_evaluable_or_patternenvsigmarininterp_occurrencesistoccs,pletinterp_unfoldistenvsigma(occs,qid)=(interp_occurrencesistoccs,interp_evaluableistenvsigmaqid)letinterp_flagistenvsigmared={redwithrConst=List.map(interp_evaluableistenvsigma)red.rConst}letinterp_red_expristenvsigma=function|Unfoldl->sigma,Unfold(List.map(interp_unfoldistenvsigma)l)|Foldl->let(sigma,l_interp)=List.fold_left_map(ist.interp_constr_listenv)sigmalinsigma,Fold(List.flattenl_interp)|Cbvf->sigma,Cbv(interp_flagistenvsigmaf)|Cbnf->sigma,Cbn(interp_flagistenvsigmaf)|Lazyf->sigma,Lazy(interp_flagistenvsigmaf)|Patternl->let(sigma,l_interp)=Evd.MonadR.List.map_right(funcsigma->interp_constr_with_occurrencesistenvsigmac)lsigmainsigma,Patternl_interp|Simpl(f,o)->sigma,Simpl(interp_flagistenvsigmaf,Option.map(interp_closed_typed_pattern_with_occurrencesistenvsigma)o)|CbvVmo->sigma,CbvVm(Option.map(interp_closed_typed_pattern_with_occurrencesistenvsigma)o)|CbvNativeo->sigma,CbvNative(Option.map(interp_closed_typed_pattern_with_occurrencesistenvsigma)o)|(Red|Hnf|ExtraRedExpr_asr)->sigma,rletinterp_constrenvsigmac=letflags=Pretyping.all_and_fail_flagsinPretyping.understand_ltacflagsenvsigmaGlob_ops.empty_lvarWithoutTypeConstraintcletinterp_constr_listenvsigmac=letsigma,c=interp_constrenvsigmacinsigma,[c]letinterp_patternenvsigmac=letflags={Pretyping.no_classes_no_fail_inference_flagswithexpand_evars=false}inletsigma,c=Pretyping.understand_ltacflagsenvsigmaGlob_ops.empty_lvarWithoutTypeConstraintcinPatternops.legacy_bad_pattern_of_constrenvsigmacletwithout_ltac={interp_occurrence_var=(funlid->user_err?loc:lid.loc(str"Unbound variable "++Id.printlid.v++str"."));interp_constr;interp_constr_list;interp_evaluable=(fun__x->x);interp_pattern;interp_evaluable_or_pattern=(fun__r->Inlr);}endletinterp_redexp_no_ltacenvsigmar=letr=Intern.(intern_red_expr(from_envenv)r)inInterp.(interp_red_exprwithout_ltac)envsigmar