123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214(************************************************************************)(* * 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) *)(************************************************************************)openUnifyopenRulesopenCErrorsopenUtilopenEConstropenVarsopenTacmach.NewopenTacticsopenTacticals.NewopenProofview.NotationsopenReductionopsopenFormulaopenSequentopenNamesopenContext.Rel.Declarationletcompare_instanceinst1inst2=letcmpc1c2=Constr.compare(EConstr.Unsafe.to_constrc1)(EConstr.Unsafe.to_constrc2)inmatchinst1,inst2withPhantom(d1),Phantom(d2)->(cmpd1d2)|Real((m1,c1),n1),Real((m2,c2),n2)->((-)=?(-)==?cmp)m2m1n1n2c1c2|Phantom(_),Real((m,_),_)->ifInt.equalm0then-1else1|Real((m,_),_),Phantom(_)->ifInt.equalm0then1else-1letcompare_grid1id2=ifid1==id2then0elseifid1==dummy_idthen1elseifid2==dummy_idthen-1elseGlobRef.CanOrd.compareid1id2moduleOrderedInstance=structtypet=instance*GlobRef.tletcompare(inst1,id1)(inst2,id2)=(compare_instance=?compare_gr)inst2inst1id2id1(* we want a __decreasing__ total order *)endmoduleIS=Set.Make(OrderedInstance)letmake_simple_atomsseq=letratoms=matchseq.glatomwithSomet->[t]|None->[]in{negative=seq.latoms;positive=ratoms}letdo_sequentenvsigmasetreftrividseqidomatoms=letflag=reftrueinletphref=reftrivinletdo_atomsa1a2=letdo_pairt1t2=matchunif_atomsenvsigmaidomt1t2withNone->()|Some(Phantom_)->phref:=true|Somec->flag:=false;setref:=IS.add(c,id)!setrefinList.iter(funt->List.iter(do_pairt)a2.negative)a1.positive;List.iter(funt->List.iter(do_pairt)a2.positive)a1.negativeinHP.iter(funlf->do_atomsatomslf.atoms)seq.redexes;do_atomsatoms(make_simple_atomsseq);!flag&&!phrefletmatch_one_quantified_hypenvsigmasetrefseqlf=matchlf.patwithLeft(Lforall(i,dom,triv))|Right(Rexists(i,dom,triv))->ifdo_sequentenvsigmasetreftrivlf.idseqidomlf.atomsthensetref:=IS.add((Phantomdom),lf.id)!setref|_->anomaly(Pp.str"can't happen.")letgive_instancesenvsigmalfseq=letsetref=refIS.emptyinList.iter(match_one_quantified_hypenvsigmasetrefseq)lf;IS.elements!setref(* collector for the engine *)letreccollect_quantifiedsigmaseq=trylethd,seq1=take_formulasigmaseqin(matchhd.patwithLeft(Lforall(_,_,_))|Right(Rexists(_,_,_))->let(q,seq2)=collect_quantifiedsigmaseq1in((hd::q),seq2)|_->[],seq)withHeap.EmptyHeap->[],seq(* open instances processor *)letdummy_bvid=Id.of_string"x"letmk_open_instanceenvsigmaididcmt=letvar_id=(* XXX why physical equality? *)ifid==dummy_idthendummy_bvidelselettyp=Retyping.get_type_ofenvsigmaidcin(* since we know we will get a product,
reduction is not too expensive *)let(nam,_,_)=destProdsigma(whd_allenvsigmatyp)inmatchnam.Context.binder_namewith|Nameid->id|Anonymous->dummy_bvidinletrevt=substl(List.initm(funi->mkRel(m-i)))tinletrecauxnavoidenvsigmadecls=ifInt.equaln0thensigma,declselseletnid=fresh_id_in_envavoidvar_idenvinlet(sigma,(c,_))=Evarutil.new_type_evarenvsigmaEvd.univ_flexibleinletdecl=LocalAssum(Context.make_annot(Namenid)Sorts.Relevant,c)inaux(n-1)(Id.Set.addnidavoid)(EConstr.push_reldeclenv)sigma(decl::decls)inletsigma,decls=auxmId.Set.emptyenvsigma[]in(sigma,decls,revt)(* tactics *)letleft_instance_tac(inst,id)continueseq=letopenEConstrinProofview.Goal.enterbeginfungl->letsigma=projectglinletenv=Proofview.Goal.envglinmatchinstwithPhantomdom->iflookupenvsigma(id,None)seqthentclFAIL0(Pp.str"already done")elsetclTHENS(cutdom)[tclTHENLIST[introf;(pf_constr_of_globalid>>=funidc->Proofview.Goal.enterbeginfungl->letid0=List.nth(pf_ids_of_hypsgl)0ingeneralize[mkApp(idc,[|mkVarid0|])]end);introf;tclSOLVE[wrap1falsecontinue(deepen(record(id,None)seq))]];tclTRYassumption]|Real((m,t),_)->letc=(m,EConstr.to_constr~abort_on_undefined_evars:falsesigmat)iniflookupenvsigma(id,Somec)seqthentclFAIL0(Pp.str"already done")elseletspecial_generalize=ifm>0then(pf_constr_of_globalid>>=funidc->Proofview.Goal.enterbeginfungl->let(evmap,rc,ot)=mk_open_instance(pf_envgl)(projectgl)ididcmtinletgt=it_mkLambda_or_LetIn(mkApp(idc,[|ot|]))rcinletevmap,_=tryTyping.type_of(pf_envgl)evmapgtwithewhenCErrors.noncriticale->user_errPp.(str"Untypable instance, maybe higher-order non-prenex quantification")inProofview.tclTHEN(Proofview.Unsafe.tclEVARSevmap)(generalize[gt])end)elsepf_constr_of_globalid>>=funidc->generalize[mkApp(idc,[|t|])]intclTHENLIST[special_generalize;introf;tclSOLVE[wrap1falsecontinue(deepen(record(id,Somec)seq))]]endletright_instance_tacinstcontinueseq=letopenEConstrinProofview.Goal.enterbeginfungl->matchinstwithPhantomdom->tclTHENS(cutdom)[tclTHENLIST[introf;Proofview.Goal.enterbeginfungl->letid0=List.nth(pf_ids_of_hypsgl)0insplit(Tactypes.ImplicitBindings[mkVarid0])end;tclSOLVE[wrap0truecontinue(deepenseq)]];tclTRYassumption]|Real((0,t),_)->(tclTHEN(split(Tactypes.ImplicitBindings[t]))(tclSOLVE[wrap0truecontinue(deepenseq)]))|Real((m,t),_)->tclFAIL0(Pp.str"not implemented ... yet")endletinstance_tacinst=if(sndinst)==dummy_idthenright_instance_tac(fstinst)elseleft_instance_tacinstletquantified_taclfbacktrackcontinueseq=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletinsts=give_instancesenv(projectgl)lfseqintclORELSE(tclFIRST(List.map(funinst->instance_tacinstcontinueseq)insts))backtrackend