123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147(*************************************************************************)(* Copyright 2015-2019 MINES ParisTech -- Dual License LGPL 2.1+ / GPL3+ *)(* Copyright 2019-2024 Inria -- Dual License LGPL 2.1+ / GPL3+ *)(* Copyright 2024-2025 Emilio J. Gallego Arias -- LGPL 2.1+ / GPL3+ *)(* Copyright 2025 CNRS -- LGPL 2.1+ / GPL3+ *)(* Written by: Emilio J. Gallego Arias & coq-lsp contributors *)(*************************************************************************)(* Rocq Language Server Protocol: Rocq Goals API *)(*************************************************************************)letequal_option=Option.equalmoduleReified_goal=structtype'ahyp={names:String.tList.t;def:'aoption;ty:'a}[@@derivingequal]letmap_hyp~f{names;def;ty}=letdef=Option.mapfdefinletty=ftyin{names;def;ty}typeinfo={evar:Evar.t;name:Names.Id.toption}[@@derivingequal]type'at={info:info;hyps:'ahypList.t;ty:'a}[@@derivingequal]letmap~f{info;ty;hyps}=letty=ftyinlethyps=List.map(map_hyp~f)hypsin{info;ty;hyps}endtype('a,'pp)t={goals:'aList.t;stack:('aList.t*'aList.t)List.t;bullet:'ppoption;shelf:'aList.t;given_up:'aList.t}[@@derivingequal]letmap~f~g{goals;stack;bullet;shelf;given_up}=letgoals=List.mapfgoalsinletstack=List.map(fun(s,r)->(List.mapfs,List.mapfr))stackinletbullet=Option.mapgbulletinletshelf=List.mapfshelfinletgiven_up=List.mapfgiven_upin{goals;stack;bullet;shelf;given_up}type('goals,'pp)reified=('goalsReified_goal.t,'pp)t(** XXX: Do we need to perform evar normalization? *)moduleCDC=Context.Compacted.Declarationtypecdcl=EConstr.compacted_declarationletbinder_namen=Context.binder_namen|>Names.Id.to_stringletto_tupleppx:cdcl->'pcReified_goal.hyp=letopenCDCinfunction|LocalAssum(idl,tm)->letnames=List.mapbinder_nameidlin{Reified_goal.names;def=None;ty=ppxtm}|LocalDef(idl,tdef,tm)->letnames=List.mapbinder_nameidlin{names;def=Some(ppxtdef);ty=ppxtm}(** gets a hypothesis *)letget_hyp(ppx:EConstr.t->'pc)(_sigma:Evd.evar_map)(hdecl:cdcl):'pcReified_goal.hyp=to_tupleppxhdecl(** gets the constr associated to the type of the current goal *)letget_goal_type(ppx:EConstr.t->'pc)(env:Environ.env)(sigma:Evd.evar_map)(g:Evar.t):_=let(EvarInfoevi)=Evd.findsigmaginletconcl=matchEvd.evar_bodyeviwith|Evd.Evar_empty->Evd.evar_conclevi|Evd.Evar_definedbody->Retyping.get_type_ofenvsigmabodyinppxconclletbuild_infosigmag={Reified_goal.evar=g;name=Evd.evar_identgsigma}(** Generic processor *)letprocess_goal_genppxsigmag:'aReified_goal.t=(* XXX This looks cumbersome *)letenv=Global.env()inlet(EvarInfoevi)=Evd.findsigmaginletenv=Evd.evar_filtered_envenveviin(* why is compaction neccesary... ? [eg for better display] *)letctx=Termops.compact_named_contextsigma(EConstr.named_contextenv)inletppx=ppxenvsigmainlethyps=List.map(get_hypppxsigma)ctx|>List.revinletinfo=build_infosigmagin{info;ty=get_goal_typeppxenvsigmag;hyps}letif_not_empty(pp:Pp.t)=ifPp.(reprpp=Ppcmd_empty)thenNoneelseSomeppletreify~ppxlemmas=letlemmas=State.Proof.to_coqlemmasinletproof=Vernacstate.LemmaStack.with_toplemmas~f:(funpstate->Declare.Proof.getpstate)inlet{Proof.goals;stack;sigma;_}=Proof.dataproofinletppx=List.map(process_goal_genppxsigma)in{goals=ppxgoals;stack=List.map(fun(g1,g2)->(ppxg1,ppxg2))stack;bullet=if_not_empty@@Proof_bullet.suggestproof;shelf=Evd.shelfsigma|>ppx;given_up=Evd.given_upsigma|>Evar.Set.elements|>ppx}moduleEquality=structleteq_constr(_env1,evd1,c1)(_env2,evd2,c2)=(* XXX Fixme, can be much faster using the advance compare functions *)letc1=EConstr.to_constrevd1c1inletc2=EConstr.to_constrevd2c2inConstr.equalc1c2leteq_pppp1pp2=pp1=pp2leteq_rgoal=Reified_goal.equaleq_constrletequal_goalsst1st2=letppxenvevdc=(env,evd,c)inletg1=reify~ppxst1inletg2=reify~ppxst2inequaleq_rgoaleq_ppg1g2end