123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269(************************************************************************)(* * 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenNameopsopenTermopsopenEnvironopenReductionopsmoduleNamedDecl=Context.Named.Declarationtyperefiner_error=(* Errors raised by the refiner *)|UnresolvedBindingsofName.tlist|CannotApplyofEConstr.t*EConstr.t|NonLinearProofofEConstr.t(* Errors raised by the tactics *)|IntroNeedsProduct|NoSuchHypofId.texceptionRefinerErrorofEnviron.env*Evd.evar_map*refiner_errorleterror_no_such_hypothesisenvsigmaid=raise(RefinerError(env,sigma,NoSuchHypid))(************************************************************************)(************************************************************************)(* Implementation of the structural rules (moving and deleting
hypotheses around) *)(* The ClearBody tactic *)(* Reordering of the context *)(* faire le minimum d'echanges pour que l'ordre donne soit un *)(* sous-ordre du resultat. Par exemple, 2 hyps non mentionnee ne sont *)(* pas echangees. Choix: les hyps mentionnees ne peuvent qu'etre *)(* reculees par rapport aux autres (faire le contraire!) *)letmt_q=(Id.Map.empty,[])letpush_valy=function(_,[]asq)->q|(m,(x,l)::q)->(m,(x,Id.Set.addyl)::q)letpush_itemxv(m,l)=(Id.Map.addxvm,(x,Id.Set.empty)::l)letmem_qx(m,_)=Id.Map.memxmletfind_qx(m,q)=letv=Id.Map.findxminletm'=Id.Map.removexminletrecfindaccsacc=function[]->raiseNot_found|[(x',l)]->ifId.equalxx'then((v,Id.Set.unionaccsl),(m',List.revacc))elseraiseNot_found|(x',lasi)::((x'',l'')::qasitl)->ifId.equalxx'then((v,Id.Set.unionaccsl),(m',List.revacc@(x'',Id.Set.addx(Id.Set.unionll''))::q))elsefind(Id.Set.unionlaccs)(i::acc)itlinfindId.Set.empty[]qletoccur_vars_in_declenvsigmahypsd=ifId.Set.is_emptyhypsthenfalseelseletohyps=global_vars_set_of_declenvsigmadinId.Set.exists(funh->Id.Set.memhohyps)hypsletreorder_contextenvsigmasignord=letords=List.fold_rightId.Set.addordId.Set.emptyinifnot(Int.equal(List.lengthord)(Id.Set.cardinalords))thenuser_errPp.(str"Order list has duplicates");letrecstepordexpectedctxt_headmoved_hypsctxt_tail=matchordwith|[]->List.revctxt_tail@ctxt_head|top::ord'whenmem_qtopmoved_hyps->let((d,h),mh)=find_qtopmoved_hypsinifoccur_vars_in_declenvsigmahdthenuser_err(str"Cannot move declaration "++Id.printtop++spc()++str"before "++pr_sequenceId.print(Id.Set.elements(Id.Set.interh(global_vars_set_of_declenvsigmad)))++str".");stepord'expectedctxt_headmh(d::ctxt_tail)|_->(matchctxt_headwith|[]->error_no_such_hypothesisenvsigma(List.hdord)|d::ctxt->letx=NamedDecl.get_iddinifId.Set.memxexpectedthenstepord(Id.Set.removexexpected)ctxt(push_itemxdmoved_hyps)ctxt_tailelsestepordexpectedctxt(push_valxmoved_hyps)(d::ctxt_tail))instepordordssignmt_q[]letreorder_val_contextenvsigmasignord=matchordwith|[]|[_]->(* Single variable-free definitions need not be reordered *)sign|_::_::_->letopenEConstrinval_of_named_context(reorder_contextenvsigma(named_context_of_valsign)ord)letcheck_decl_positionenvsigmasignd=letopenEConstrinletx=NamedDecl.get_iddinletneeded=global_vars_set_of_declenvsigmadinletdeps=dependency_closureenvsigma(named_context_of_valsign)neededinifId.List.memxdepsthenuser_err(str"Cannot create self-referring hypothesis "++Id.printx++str".");x::deps(* Auxiliary functions for primitive MOVE tactic
*
* [move_hyp with_dep toleft (left,(hfrom,typfrom),right) hto] moves
* hyp [hfrom] at location [hto] which belongs to the hyps on the
* left side [left] of the full signature if [toleft=true] or to the hyps
* on the right side [right] if [toleft=false].
* If [with_dep] then dependent hypotheses are moved accordingly. *)(** Move destination for hypothesis *)type'idmove_location=|MoveAfterof'id|MoveBeforeof'id|MoveFirst|MoveLast(** can be seen as "no move" when doing intro *)(** Printing of [move_location] *)letpr_move_locationpr_id=function|MoveAfterid->brk(1,1)++str"after "++pr_idid|MoveBeforeid->brk(1,1)++str"before "++pr_idid|MoveFirst->str" at top"|MoveLast->str" at bottom"letmove_location_eqm1m2=matchm1,m2with|MoveAfterid1,MoveAfterid2->Id.equalid1id2|MoveBeforeid1,MoveBeforeid2->Id.equalid1id2|MoveLast,MoveLast->true|MoveFirst,MoveFirst->true|_->falseletmem_id_contextidctx=Id.Map.memidctx.Environ.env_named_mapletsplit_signenvsigmahfroml=let()=ifnot(mem_id_contexthfroml)thenerror_no_such_hypothesisenvsigmahfrominletrecsplitrecleftsign=matchEConstr.match_named_context_valsignwith|None->assertfalse|Some(d,right)->lethyp=NamedDecl.get_iddinifId.equalhyphfromthen(left,right,d)elsesplitrec(d::left)rightinsplitrec[]l(* ocaml/ocaml#10027 triggered if inline record *)typecannot_move_hyp={from:Id.t;hto:Id.tmove_location;hyp:Id.t}exceptionCannotMoveHypofcannot_move_hyplet()=CErrors.register_handler(function|CannotMoveHyp{from;hto;hyp}->SomePp.(str"Cannot move "++Id.printfrom++pr_move_locationId.printhto++str": it occurs in the declaration of "++Id.printhyp++str".")|_->None)letmove_hypenvsigmatoleft(left,declfrom,right)hto=letopenEConstrinletpushprefixsign=List.fold_rightpush_named_context_valprefixsigninletpush_revprefixsign=List.fold_left(funaccud->push_named_context_valdaccu)signprefixinletrecmoverec_toleftansfirstmiddlemidvars=function|[]->pushmiddle@@pushfirstans|d::_asrightwhenmove_location_eqhto(MoveBefore(NamedDecl.get_idd))->push_revright@@pushmiddle@@pushfirstans|d::right->lethyp=NamedDecl.get_iddinlet(first',middle',midvars')=ifoccur_vars_in_declenvsigmamidvarsdthenifnot(move_location_eqhto(MoveAfterhyp))then(first,d::middle,Id.Set.addhypmidvars)elseraise(CannotMoveHyp{from=NamedDecl.get_iddeclfrom;hto;hyp})else(d::first,middle,midvars)inifmove_location_eqhto(MoveAfterhyp)thenpush_revright@@pushmiddle'@@pushfirst'anselsemoverec_toleftansfirst'middle'midvars'rightinletrecmoverec_torightfirstmiddledepvarsright=matchEConstr.match_named_context_valrightwith|None->push_revfirst@@push_revmiddleright|Some(d,_)whenmove_location_eqhto(MoveBefore(NamedDecl.get_idd))->push_revfirst@@push_revmiddle@@right|Some(d,right)->lethyp=NamedDecl.get_iddinlet(first',middle',depvars')=ifId.Set.memhypdepvarsthenifnot(move_location_eqhto(MoveAfterhyp))thenletvars=global_vars_set_of_declenvsigmadinletdepvars=Id.Set.unionvarsdepvarsin(first,d::middle,depvars)elseraise(CannotMoveHyp{from=NamedDecl.get_iddeclfrom;hto;hyp})else(d::first,middle,depvars)inifmove_location_eqhto(MoveAfterhyp)thenpush_revfirst'@@push_revmiddle'@@rightelsemoverec_torightfirst'middle'depvars'rightiniftoleftthenletid=NamedDecl.get_iddeclfrominmoverec_toleftright[][declfrom](Id.Set.singletonid)leftelseletdepvars=global_vars_set_of_declenvsigmadeclfrominletright=moverec_toright[][declfrom]depvarsrightinpush_revleft@@rightletmove_hyp_in_named_contextenvsigmahfromhtosign=let(left,right,declfrom)=split_signenvsigmahfromsigninlettoleft=matchhtowith|MoveLast->true|MoveAfterid|MoveBeforeid->ifmem_id_contextidrightthenfalseelseifmem_id_contextidsignthentrueelseerror_no_such_hypothesisenvsigmaid|MoveFirst->falseinmove_hypenvsigmatoleft(left,declfrom,right)htoletinsert_decl_in_named_contextenvsigmadeclhtosign=move_hypenvsigmafalse([],decl,sign)htoletconvert_hyp~check~reorderenvsigmad=letid=NamedDecl.get_iddinletb=NamedDecl.get_valuedinletsign=Environ.named_context_valenvinmatchlookup_named_ctxtidsignwith|exceptionNot_found->ifcheckthenerror_no_such_hypothesisenvsigmaidelsesign|d'->letc=Option.mapEConstr.of_constr(NamedDecl.get_valued')inifcheck&¬(is_convenvsigma(NamedDecl.get_typed)(EConstr.of_constr(NamedDecl.get_typed')))thenuser_err(str"Incorrect change of the type of "++Id.printid++str".");ifcheck&¬(Option.equal(is_convenvsigma)bc)thenuser_err(str"Incorrect change of the body of "++Id.printid++str".");letsign'=apply_to_hypsignid(fun___->EConstr.Unsafe.to_named_decld)inifreorderthenreorder_val_contextenvsigmasign'(check_decl_positionenvsigmasignd)elsesign'