123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298(**************************************************************************)(* *)(* VSCoq *)(* *)(* Copyright INRIA and contributors *)(* (see version control and README file for authors & dates) *)(* *)(**************************************************************************)(* *)(* This file is distributed under the terms of the MIT License. *)(* See LICENSE file. *)(* *)(**************************************************************************)openNamesopenPrinteropenPpletmd_code_blocks=Format.sprintf"```coq\n%s\n```"s(* Format a Coq type to be pretty and compact (e.g. replace forall with ∀) *)letcompactifys=letreplacements=[Str.regexp{|\bfun\b|},"λ";Str.regexp{|\bforall\b|},"∀";Str.regexp{|\bexists\b|},"∃";Str.regexp{| \\/ |}," ∨ ";Str.regexp{| /\\ |}," ∧ ";Str.regexp{| <-> |}," ↔ ";Str.regexp{| -> |}," → ";Str.regexp{| <= )|}," ≤ ";Str.regexp{| >= )|}," ≥ ";Str.regexp{| => )|}," ⇒ ";Str.regexp{| <> )|}," ≠ ";Str.regexp{| ~ )|}," ¬ "]inList.fold_left(funs(reg,repl)->Str.global_replaceregrepls)sreplacements(* TODO this should be exposed by Coq and removed from here *)[%%ifcoq="8.18"]letpr_s=prlist(funCAst.{v=s}->str"%"++strs)leteq_realarg=List.equal(funab->String.equala.CAst.vb.CAst.v)letnargs_maximal_of_pos((na,_,_),_,(maximal,_))=na,maximalletmake_scope=CAst.make[%%else]letpr_delimiter_depth=function|Constrexpr.DelimOnlyTmpScope->str"%_"|Constrexpr.DelimUnboundedScope->str"%"letpr_scope_delimiter(d,sc)=pr_delimiter_depthd++strscletpr_s=prlist(funCAst.{v=s}->pr_scope_delimiters)leteq_realarg=List.equal(funab->letda,a=a.CAst.vinletdb,b=b.CAst.vinda=db&&String.equalab)letnargs_maximal_of_posimp=let(na,_,_)=imp.Impargs.impl_posinna,imp.Impargs.impl_maxletmake_scope=(funs->CAst.make(Constrexpr.DelimUnboundedScope,s))[%%endif]letpr_argsargsmore_implicitsmods=letopenVernacexprinletpr_ifbx=ifbthenxelsestr""inletpr_one_arg(x,k)=pr_ifk(str"!")++Name.printxinletpr_brimpforcex=letleft,right=matchimpwith|Glob_term.NonMaxImplicit->str"[",str"]"|Glob_term.MaxImplicit->str"{",str"}"|Glob_term.Explicit->ifforcethenstr"(",str")"elsemt(),mt()inleft++x++rightinletget_arguments_likesimptl=ifs=[]&&imp=Glob_term.Explicitthen[],tlelseletrecfoldextra=function|RealArgarg::tlwheneq_realargarg.notation_scopes&&arg.implicit_status=imp->fold((arg.name,arg.recarg_like)::extra)tl|args->List.revextra,argsinfold[]tlinletrecprint_arguments=function|[]->mt()|VolatileArg::l->spc()++str"/"++print_argumentsl|BidiArg::l->spc()++str"&"++print_argumentsl|RealArg{name=id;recarg_like=k;notation_scope=s;implicit_status=imp}::tl->letextra,tl=get_arguments_likesimptlinspc()++hov1(pr_brimp(extra<>[])(prlist_with_sepspcpr_one_arg((id,k)::extra))++pr_ss)++print_argumentstlinletrecprint_implicits=function|[]->mt()|(name,impl)::rest->spc()++pr_brimplfalse(Name.printname)++print_implicitsrestinprint_argumentsargs++ifnot(CList.is_emptymore_implicits)thenprlist(funl->str","++print_implicitsl)more_implicitselse(mt())++(ifnot(CList.is_emptymods)thenstr" : "elsestr"")++prlist_with_sep(fun()->str", "++spc())(function|`ReductionDontExposeCase->str"simpl nomatch"|`ReductionNeverUnfold->str"simpl never"|`DefaultImplicits->str"default implicits"|`Rename->str"rename"|`Assert->str"assert"|`ExtraScopes->str"extra scopes"|`ClearImplicits->str"clear implicits"|`ClearScopes->str"clear scopes"|`ClearBidiHint->str"clear bidirectionality hint")modsletimplicit_kind_of_status=function|None->Anonymous,Glob_term.Explicit|Someimp->letna,maximal=nargs_maximal_of_posimpinna,ifmaximalthenGlob_term.MaxImplicitelseGlob_term.NonMaxImplicitletextra_implicit_kind_of_statusimp=let_,imp=implicit_kind_of_statusimpin(Anonymous,imp)letneeds_extra_scopesrefscopes=letopenConstrinletrecauxenvt=function|[]->false|_::scopes->matchkind(Reduction.whd_allenvt)with|Prod(na,dom,codom)->aux(Environ.push_rel(Context.Rel.Declaration.LocalAssum(na,dom))env)codomscopes|_->trueinletenv=Global.env()inletty,_ctx=Typeops.type_of_global_in_contextenvrefinauxenvtyscopesletrecmain_implicitsirenamesrecargsscopesimpls=ifrenames=[]&&recargs=[]&&scopes=[]&&impls=[]then[]elseletrecarg_like,recargs=matchrecargswith|j::recargswheni=j->true,recargs|_->false,recargsinlet(name,implicit_status)=matchrenames,implswith|_,(Some_asi)::_->implicit_kind_of_statusi|name::_,_->(name,Glob_term.Explicit)|[],(None::_|[])->(Anonymous,Glob_term.Explicit)inletnotation_scope=matchscopeswith|scope::_->List.mapmake_scopescope|[]->[]inletstatus={Vernacexpr.implicit_status;name;recarg_like;notation_scope}inlettl=function[]->[]|_::tl->tlin(* recargs is special -> tl handled above *)letrest=main_implicits(i+1)(tlrenames)recargs(tlscopes)(tlimpls)instatus::restletdummy={Vernacexpr.implicit_status=Glob_term.Explicit;name=Anonymous;recarg_like=false;notation_scope=[];}letis_dummy=function|Vernacexpr.(RealArg{implicit_status;name;recarg_like;notation_scope})->name=Anonymous&¬recarg_like&¬ation_scope=[]&&implicit_status=Glob_term.Explicit|_->falseletrecinsert_fake_argsvolatilebidiimpls=letopenVernacexprinmatchvolatile,bidiwith|Some0,_->VolatileArg::insert_fake_argsNonebidiimpls|_,Some0->BidiArg::insert_fake_argsvolatileNoneimpls|None,None->List.map(funa->RealArga)impls|_,_->lethd,tl=matchimplswith|impl::impls->impl,impls|[]->dummy,[]inletf=Option.mappredinRealArghd::insert_fake_args(fvolatile)(fbidi)tl[%%ifcoq="8.18"]letref_of_constx=Somex[%%else]letref_of_const=function|GlobRef.ConstRefref->Someref|_->None[%%endif]letprint_argumentsref=letflags,recargs,nargs_for_red=letopenReductionops.ReductionBehaviourinmatchref_of_constrefwith|Someref->beginmatchgetrefwith|None->[],[],None|SomeNeverUnfold->[`ReductionNeverUnfold],[],None|Some(UnfoldWhen{nargs;recargs})->[],recargs,nargs|Some(UnfoldWhenNoMatch{nargs;recargs})->[`ReductionDontExposeCase],recargs,nargsend|None->[],[],Noneinletnames,not_renamed=tryArguments_renaming.arguments_namesref,falsewithNot_found->letenv=Global.env()inletty,_=Typeops.type_of_global_in_contextenvrefinList.mapUtil.pi1(Impargs.compute_implicits_namesenv(Evd.from_envenv)(EConstr.of_constrty)),trueinletscopes=Notation.find_arguments_scoperefinletflags=ifneeds_extra_scopesrefscopesthen`ExtraScopes::flagselseflagsinletimpls=Impargs.extract_impargs_data(Impargs.implicits_of_globalref)inletimpls,moreimpls=matchimplswith|(_,impls)::rest->impls,rest|[]->assertfalseinletimpls=main_implicits0namesrecargsscopesimplsinletmoreimpls=List.map(fun(_,i)->List.mapextra_implicit_kind_of_statusi)moreimplsinletbidi=Pretyping.get_bidirectionality_hintrefinletimpls=insert_fake_argsnargs_for_redbidiimplsinifList.for_allis_dummyimpls&&moreimpls=[]&&flags=[]thenmt()elsepr_argsimplsmoreimplsflags++(ifnot_renamedthenmt()elsefnl()++str" (where some original arguments have been renamed)")letcanonical_name_inforef=letcref=Globnames.canonical_grrefinifGlobRef.UserOrd.equalrefcrefthenmt()elsematchNametab.path_of_globalcrefwith|path->spc()++str"(syntactically equal to"++spc()++Libnames.pr_pathpath++str")"|exceptionNot_found->spc()++str"(missing canonical, bug?)"(* End of imported Coq code *)letpr_globref_kind=letopenGlobRefinfunction|ConstRef_->"Constant"|IndRef_->"Inductive"|ConstructRef_->"Constructor"|VarRef_->"Variable"letref_infoenv_sigmarefudecl=lettyp,_univs=Typeops.type_of_global_in_contextenvrefinletbl=Printer.universe_binders_with_opt_names(Environ.universes_of_globalenvref)udeclinletsigma=Evd.from_ctx(UState.of_namesbl)inlettyp=Arguments_renaming.rename_typetyprefinletimpargs=Impargs.select_stronger_impargs(Impargs.implicits_of_globalref)inletimpargs=List.mapImpargs.binding_kind_of_statusimpargsinlettyp=pr_ltype_envenvsigma~impargstypinletpath=Libnames.pr_path(Nametab.path_of_globalref)++canonical_name_inforefinletargs=print_argumentsrefinletargs=ifPp.ismtargsthen[]else["**Args:** "^(Pp.string_of_ppcmds(print_argumentsref))]inString.concat"\n\n---\n\n"@@[md_code_block@@compactify@@Pp.string_of_ppcmdstyp]@args@[Format.sprintf"**%s** %s"(pr_globref_kindref)(Pp.string_of_ppcmdspath)]letmod_infomp=md_code_block@@Format.sprintf"Module %s"(DirPath.to_string(Nametab.dirpath_of_modulemp))letmodtype_infomp=md_code_block@@Format.sprintf"Module Type %s"(Libnames.string_of_path(Nametab.path_of_modtypemp))letsyndef_infokn=md_code_block@@Format.sprintf"Notation %s"(Libnames.string_of_path(Nametab.path_of_abbreviationkn))letget_hover_contentsenvsigmaref_or_by_not=matchref_or_by_not.CAst.vwith|Constrexpr.ANqid->letr=begintryletudecl=Noneinletref=Nametab.locateqidinSome(ref_infoenvsigmarefudecl)withNot_found->tryletkn=Nametab.locate_abbreviationqidinSome(syndef_infokn)withNot_found->tryletmp=Nametab.locate_moduleqidinSome(mod_infomp)withNot_found->tryletmp=Nametab.locate_modtypeqidinSome(modtype_infomp)withNot_found->NoneendinOption.mapLsp.Types.(funvalue->MarkupContent.create~kind:MarkupKind.Markdown~value)r|Constrexpr.ByNotation(_ntn,_sc)->assertfalse