1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003(************************************************************************)(* * The Rocq Prover / The Rocq 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) *)(************************************************************************)openUtilopenPpopenNamesopenTac2expropenTac2envopenPputilsletpr_tacrefavoidkn=tryLibnames.pr_qualid(Tac2env.shortest_qualid_of_ltacavoid(TacConstantkn))withNot_foundwhen!Flags.in_debugger||KNmap.memkn(Tac2env.globals())->str(ModPath.to_string(KerName.modpathkn))++str"."++Label.print(KerName.labelkn)++if!Flags.in_debuggerthenmt()elsestr" (* local *)"(** Utils *)letchange_kn_labelknid=letmp=KerName.modpathkninKerName.makemp(Label.of_idid)letparenp=hov2(str"("++p++str")")lett_list=KerName.makeTac2env.rocq_prefix(Label.of_id(Id.of_string"list"))letc_nil=change_kn_labelt_list(Id.of_string_soft"[]")letc_cons=change_kn_labelt_list(Id.of_string_soft"::")(** Type printing *)typetyp_level=|T5_l|T5_r|T2|T1|T0lett_unit=KerName.makeTac2env.rocq_prefix(Label.of_id(Id.of_string"unit"))letpr_typrefkn=Libnames.pr_qualid(Tac2env.shortest_qualid_of_typekn)letpr_glbtype_genprlvlc=letrecpr_glbtypelvl=function|GTypVarn->str"'"++str(prn)|GTypRef(Otherkn,[])->pr_typrefkn|GTypRef(Otherkn,[t])->letparen=matchlvlwith|T5_r|T5_l|T2|T1->funx->x|T0->pareninparen(pr_glbtypeT1t++spc()++pr_typrefkn)|GTypRef(Otherkn,tl)->letparen=matchlvlwith|T5_r|T5_l|T2|T1->funx->x|T0->pareninparen(str"("++prlist_with_seppr_comma(pr_glbtypelvl)tl++str")"++spc()++pr_typrefkn)|GTypArrow(t1,t2)->letparen=matchlvlwith|T5_r->funx->x|T5_l|T2|T1|T0->pareninparen(pr_glbtypeT5_lt1++spc()++str"->"++spc()++pr_glbtypeT5_rt2)|GTypRef(Tuple0,[])->Libnames.pr_qualid(Tac2env.shortest_qualid_of_typet_unit)|GTypRef(Tuple_,tl)->letparen=matchlvlwith|T5_r|T5_l->funx->x|T2|T1|T0->pareninparen(prlist_with_sep(fun()->str" * ")(pr_glbtypeT2)tl)inhov0(pr_glbtypelvlc)letpr_glbtypeprc=pr_glbtype_genprT5_rcletint_name()=letvars=refInt.Map.emptyinfunn->ifInt.Map.memn!varsthenInt.Map.findn!varselseletnum=Int.Map.cardinal!varsinletbase=nummod26inletrem=num/26inletname=String.make1(Char.chr(97+base))inletsuff=ifInt.equalrem0then""elsestring_of_intreminletname=name^suffinlet()=vars:=Int.Map.addnname!varsinname(** Term printing *)letpr_constructorkn=Libnames.pr_qualid(Tac2env.shortest_qualid_of_constructorkn)letpr_projectionkn=Libnames.pr_qualid(Tac2env.shortest_qualid_of_projectionkn)typeexp_level=Tac2expr.exp_level=|E5|E4|E3|E2|E1|E0letpr_atom=function|AtmIntn->Pp.intn|AtmStrs->qstringsletpr_name=function|Nameid->Id.printid|Anonymous->str"_"letfind_constructornemptydef=letrecfindn=function|[]->assertfalse|(_,id,[])asans::rem->ifemptythenifInt.equaln0thenanselsefind(predn)remelsefindnrem|(_,id,_::_)asans::rem->ifnotemptythenifInt.equaln0thenanselsefind(predn)remelsefindnreminfindndefletpr_internal_constructortpenis_const=letdata=matchTac2env.interp_typetpewith|(_,GTydAlgdata)->data|_->assertfalseinlet(_,id,_)=find_constructornis_constdata.galg_constructorsinletkn=change_kn_labeltpeidinpr_constructorknletorder_branchescbrnbrdef=letrecordercidxnidxdef=matchdefwith|[]->[]|(_,id,[])::rem->letans=order(succcidx)nidxremin(id,[],cbr.(cidx))::ans|(_,id,_::_)::rem->letans=ordercidx(succnidx)reminlet(vars,e)=nbr.(nidx)in(id,Array.to_listvars,e)::ansinorder00deftype('a,'b)factorization=|FullListof'alist|ListPrefixof'alist*'a|Otherof'bletpr_factorized_constructorpr_reclvltpe=function|FullListl->letpre=pr_recE4einhov2(str"["++prlist_with_seppr_semicolonpr(List.revl)++str"]")|ListPrefix(l,e)->letparen=matchlvlwith|E0|E1|E2->paren|E3|E4|E5->funx->xinletpre=pr_recE1einletpr_cons()=spc()++str"::"++spc()inparen(hov2(prlist_with_seppr_conspr(List.rev(e::l))))|Other(n,cl)->let_,data=Tac2env.interp_typetpeinmatchdatawith|GTydDefNone->str"<abstr>"|GTydAlgdef->letparen=matchlvlwith|E0->ifList.is_emptyclthenfunx->xelseparen|E1|E2|E3|E4|E5->funx->xinletcstr=pr_internal_constructortpen(List.is_emptycl)inletcl=matchclwith|[]->mt()|_->spc()++pr_sequence(pr_recE0)clinparen(hov2(cstr++cl))|GTydRecdef->letargs=List.combinedefclinletpr_arg((id,_,_),arg)=letkn=change_kn_labeltpeidinpr_projectionkn++spc()++str":="++spc()++pr_recE1arginletargs=prlist_with_seppr_semicolonpr_argargsinhv0(str"{"++spc()++args++spc()++str"}")|(GTydDef_|GTydOpn)->assertfalseletpr_partial_pat_gen=letopenPartialPatinletrecpr_patlvlpat=matchpat.CAst.vwith|Varx->pr_namex|Atoma->pr_atoma|As(p,x)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hv0(pr_patE1p++spc()++str"as"++spc()++Id.printx))|Ref({ctyp=None;cnargs=0},_)->str"()"|Ref({ctyp=None},args)->letparen=matchlvlwith|E0|E1->paren|E2|E3|E4|E5->funx->xinparen(prlist_with_seppr_comma(pr_patE1)args)|Ref({cindx=Openkn},args)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinletc=pr_constructorkninparen(hov0(c++spc()++(pr_sequence(pr_patE0)args)))|Ref({ctyp=Somectyp;cindx=Closedi},args)->(* TODO when we have patterns for records this will need an update *)letfactorized=ifKerName.equalctypt_listthenletrecfactorizeaccupat=matchpat.CAst.vwith|Ref(_,[])->accu,None|Ref(_,[e;l])->factorize(e::accu)l|_->accu,Somepatinletl,e=factorize[]patinmatchewith|None->FullListl|Somee->ListPrefix(l,e)elseOther(i,args)inpr_factorized_constructorpr_patlvlctypfactorized|Extension{example=None}->str"*extension*"|Extension{example=Somea}->pr_atoma|Orpats->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hv0(prlist_with_sep(fun()->spc()++str"|"++spc())(pr_patE1)pats))infunlvlpat->hov0(pr_patlvlpat)letpr_partial_patpat=pr_partial_pat_genE5pat(* Lets us share the pattern printing code *)letrecpartial_pat_of_glb_patpat=letopenPartialPatinletpat=matchpatwith|GPatVarx->Varx|GPatAtmx->Atomx|GPatRef(ctor,pats)->Ref(ctor,List.mappartial_pat_of_glb_patpats)|GPatOrpats->Or(List.mappartial_pat_of_glb_patpats)|GPatAs(p,x)->As(partial_pat_of_glb_patp,x)inCAst.makepatletpr_glb_patpat=pr_partial_pat(partial_pat_of_glb_patpat)letrecavoid_glb_patavoid=function|GPatVarx->Termops.add_vnameavoidx|GPatAtm_->avoid|GPatRef(_,pats)->List.fold_leftavoid_glb_patavoidpats|GPatOr[]->assertfalse|GPatOr(p::_)->avoid_glb_patavoidp|GPatAs(p,x)->avoid_glb_pat(Id.Set.addxavoid)pletpr_glbexpr_genlvl~avoidc=letrecpr_glbexprlvlavoid=function|GTacAtmatm->pr_atomatm|GTacVarid->Id.printid|GTacRefgr->pr_tacrefavoidgr|GTacFun(nas,c)->letavoid=List.fold_leftTermops.add_vnameavoidnasinletnas=pr_sequencepr_namenasinletparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinparen(hov0(hov2(str"fun"++spc()++nas)++spc()++str"=>"++spc()++pr_glbexprE5avoidc))|GTacApp(c,cl)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hov2(pr_glbexprE1avoidc++spc()++(pr_sequence(pr_glbexprE0avoid)cl)))|GTacLet(isrec,bnd,e)->letparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinletpprec=ifisrecthenstr"rec "elsemt()inletavoidbnd=List.fold_left(funavoid(na,_)->Termops.add_vnameavoidna)avoidbndinletpr_bnd(na,e)=letavoid=ifisrecthenavoidbndelseavoidin(* negative offset: the box starts at the | in "let |x := ..."
but we want to print with offset 2 from the start of "let" *)hov(-2-ifisrecthen4else0)(pr_namena++str" :="++spc()++pr_glbexprE5avoide)inletbnd=prlist_with_sep(fun()->spc()++str"with ")pr_bndbndinparen(v0(hov0(v0(str"let "++pprec++bnd)++spc()++str"in")++spc())++pr_glbexprE5avoidbnde)|GTacCst(Tuple0,_,_)->str"()"|GTacCst(Tuple_,_,cl)->paren(prlist_with_sep(fun()->str","++spc())(pr_glbexprE1avoid)cl)|GTacCst(Othertpe,n,cl)->pr_applied_constructorlvlavoidtpencl|GTacCse(e,info,cst_br,ncst_br)->lete=pr_glbexprE5avoideinletbr=matchinfowith|Otherkn->beginmatchTac2env.interp_typeknwith|_,GTydDefNone->str"<abstr>"|_,GTydDef_|_,GTydRec_|_,GTydOpn->assertfalse|_,GTydAlg{galg_constructors=def}->letbr=order_branchescst_brncst_brdefinletpr_branch(cstr,vars,p)=letcstr=change_kn_labelkncstrinletcstr=pr_constructorcstrinletavoid=List.fold_leftTermops.add_vnameavoidvarsinletvars=matchvarswith|[]->mt()|_->spc()++pr_sequencepr_namevarsinhov4(str"|"++spc()++hov0(cstr++vars++spc()++str"=>")++spc()++hov2(pr_glbexprE5avoidp))inprlist_with_sepspcpr_branchbrend|Tuplen->let(vars,p)=ifInt.equaln0then([||],cst_br.(0))elsencst_br.(0)inletavoid=Array.fold_leftTermops.add_vnameavoidvarsinletp=pr_glbexprE5avoidpinletvars=prvect_with_sep(fun()->str","++spc())pr_namevarsinhov4(str"|"++spc()++hov0(parenvars++spc()++str"=>")++spc()++p)inv0(hv0(str"match"++spc()++e++spc()++str"with")++spc()++br++spc()++str"end")|GTacWthwth->lete=pr_glbexprE5avoidwth.opn_matchinletpr_patterncselfvarsavoidp=letavoid=Termops.add_vnameavoidselfinletself=matchselfwith|Anonymous->mt()|Nameid->spc()++str"as"++spc()++Id.printidinhov4(str"|"++spc()++hov0(c++vars++self++spc()++str"=>")++spc()++hov2(pr_glbexprE5avoidp))++spc()inletpr_branch(cstr,(self,vars,p))=letcstr=pr_constructorcstrinletavoid=Array.fold_leftTermops.add_vnameavoidvarsinletvars=matchArray.to_listvarswith|[]->mt()|vars->spc()++pr_sequencepr_namevarsinpr_patterncstrselfvarsavoidpinletbr=prlistpr_branch(KNmap.bindingswth.opn_branch)inlet(def_as,def_p)=wth.opn_defaultinletdef=pr_pattern(str"_")def_as(mt())avoiddef_pinletbr=br++definv0(hv0(str"match"++spc()++e++spc()++str"with")++spc()++br++str"end")|GTacFullMatch(e,brs)->lete=pr_glbexprE5avoideinletpr_one_branch(pat,br)=letavoid=avoid_glb_patavoidpatinhov4(str"|"++spc()++hov0(pr_glb_patpat++spc()++str"=>")++spc()++hov2(pr_glbexprE5avoidbr))inletbrs=prlist_with_sepspcpr_one_branchbrsinv0(hv0(str"match"++spc()++e++spc()++str"with")++spc()++brs++spc()++str"end")|GTacPrj(kn,e,n)->beginmatchTac2env.interp_typeknwith|_,GTydDefNone->str"<abstr>"|_,GTydDef_|_,GTydAlg_|_,GTydOpn->assertfalse|_,GTydRecdef->let(proj,_,_)=List.nthdefninletproj=change_kn_labelknprojinletproj=pr_projectionprojinlete=pr_glbexprE0avoideinhov0(e++str"."++parenproj)end|GTacSet(kn,e,n,r)->beginmatchTac2env.interp_typeknwith|_,GTydDefNone->str"<abstr>"|_,GTydDef_|_,GTydAlg_|_,GTydOpn->assertfalse|_,GTydRecdef->let(proj,_,_)=List.nthdefninletproj=change_kn_labelknprojinletproj=pr_projectionprojinlete=pr_glbexprE0avoideinletr=pr_glbexprE1avoidrinhov0(e++str"."++parenproj++spc()++str":="++spc()++r)end|GTacOpn(kn,[])->pr_constructorkn|GTacOpn(kn,cl)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinletc=pr_constructorkninparen(hov0(c++spc()++(pr_sequence(pr_glbexprE0avoid)cl)))|GTacExt(tag,arg)->lettpe=interp_ml_objecttaginletenv=Global.env()inletsigma=Evd.from_envenvinhov0(tpe.ml_printenvsigmaarg)|GTacPrmprm->hov0(str"@external"++spc()++qstringprm.mltac_plugin++spc()++qstringprm.mltac_tactic)andpr_applied_constructorlvlavoidtpencl=letfactorized=ifKerName.equaltpet_listthenletrecfactorizeaccu=function|GTacCst(_,0,[])->accu,None|GTacCst(_,0,[e;l])->factorize(e::accu)l|e->accu,Someeinletl,e=factorize[](GTacCst(Othertpe,n,cl))inmatchewith|None->FullListl|Somee->ListPrefix(l,e)elseOther(n,cl)inpr_factorized_constructor(funlvl->pr_glbexprlvlavoid)lvltpefactorizedinhov0(pr_glbexprlvlavoidc)letpr_glbexpr~avoidc=pr_glbexpr_genE5~avoidc(** Raw datas *)letpr_relidpr=function|AbsKnx->prx|RelIdqid->Libnames.pr_qualidqidletswap_tuple_relid:_or_tupleor_relid->_or_relidor_tuple=function|RelId_asx->Otherx|AbsKn(Tuple_asx)->x|AbsKn(Otherx)->Other(AbsKnx)letrecpr_rawtype_genlvlt=matcht.CAst.vwith|CTypVarAnonymous->str"_"|CTypVar(Nameid)->str"'"++Id.printid|CTypArrow(t1,t2)->letparen=matchlvlwith|T5_r->funx->x|T5_l|T2|T1|T0->pareninparen(pr_rawtype_genT5_lt1++spc()++str"->"++spc()++pr_rawtype_genT5_rt2)|CTypRef(kn,args)->matchswap_tuple_relidknwith|Tuplen->let()=ifnot(Int.equaln(List.lengthargs))thenCErrors.anomaly?loc:t.locPp.(str"Incorrect tuple.")inifInt.equaln0thenLibnames.pr_qualid(Tac2env.shortest_qualid_of_typet_unit)elseletparen=matchlvlwith|T5_r|T5_l->funx->x|T2|T1|T0->pareninparen(prlist_with_sep(fun()->str" * ")(pr_rawtype_genT2)args)|Otherkn->letppkn=pr_relidpr_typrefkninmatchargswith|[]->ppkn|[arg]->letparen=matchlvlwith|T5_r|T5_l|T2|T1->funx->x|T0->pareninparen(pr_rawtype_genT1arg++spc()++ppkn)|_->letparen=matchlvlwith|T5_r|T5_l|T2|T1->funx->x|T0->pareninparen(surround(prlist_with_seppr_comma(pr_rawtype_genlvl)args)++spc()++ppkn)letrecids_of_patternaccu{CAst.v=pat}=matchpatwith|CPatVarAnonymous|CPatAtm_->accu|CPatVar(Nameid)->Id.Set.addidaccu|CPatAs(p,id)->ids_of_pattern(Id.Set.addid.vaccu)p|CPatRef(_,pl)|CPatOrpl->List.fold_leftids_of_patternaccupl|CPatCnv(pat,_)->ids_of_patternaccupat|CPatRecordpats->List.fold_left(funaccu(_,pat)->ids_of_patternaccupat)accupatsletrecpr_rawpat_genlvlp=matchp.CAst.vwith|CPatVarx->pr_namex|CPatAtma->pr_atoma|CPatRef(AbsKn(Tuplen),pats)->let()=ifnot(Int.equaln(List.lengthpats))thenCErrors.anomaly?loc:p.locPp.(str"Incorrect tuple.")instr"("++prlist_with_seppr_comma(pr_rawpat_genE1)pats++str")"|CPatRef(RelIdr,pats)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hov0(Libnames.pr_qualidr++spc()++pr_sequence(pr_rawpat_genE0)pats))|CPatRef(AbsKn(Otherkn),pats)->letrecfactorizeaccupat=matchpat.CAst.vwith|CPatRef(AbsKn(Otherkn),pats)whenKerName.equalknc_nil->let()=ifnot(CList.is_emptypats)thenCErrors.anomaly?loc:p.loc(str"Incorrect list pattern.")inaccu,None|CPatRef(AbsKn(Otherkn),pats)whenKerName.equalknc_cons->lethd,tl=matchpatswith|[hd;tl]->hd,tl|_->CErrors.anomaly?loc:p.loc(str"Incorrect list pattern.")infactorize(hd::accu)tl|_->accu,Somepatinbeginmatchfactorize[]pwith|pats,None->hov2(str"["++prlist_with_seppr_semicolon(pr_rawpat_genE4)(List.revpats)++str"]")|(_::_)aspats,Somerest->letparen=matchlvlwith|E0|E1|E2->paren|E3|E4|E5->funx->xinletpr_cons()=spc()++str"::"++spc()inparen(hov2(prlist_with_seppr_cons(pr_rawpat_genE1)(List.rev(rest::pats))))|[],Somep'->assert(p==p');ifCList.is_emptypatsthenpr_constructorknelseletparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hov0(pr_constructorkn++spc()++pr_sequence(pr_rawpat_genE0)pats))end|CPatRecordpats->letpr_field(proj,p)=pr_relidpr_projectionproj++spc()++str":="++spc()++pr_rawpat_genE1pinhov0(str"{"++spc()++prlist_with_seppr_semicolonpr_fieldpats++spc()++str"}")|CPatCnv(pat,t)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(pr_rawpat_genE5pat++spc()++str":"++spc()++pr_rawtype_genT5_lt)|CPatOrpats->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hv0(prlist_with_sep(fun()->spc()++str"|"++spc())(pr_rawpat_genE1)pats))|CPatAs(p,x)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hv0(pr_rawpat_genE1p++spc()++str"as"++spc()++Id.printx.v))(* XXX in principle we could have collisions with user names *)letbase_internal_ty_ident=Id.of_string"__α"letpr_rawexpr_genlvl~avoidc=letrecpr_rawexprlvlavoidc=letloc=c.CAst.locinmatchc.CAst.vwith|CTacAtma->pr_atoma|CTacRef(RelIdqid)->Libnames.pr_qualidqid|CTacRef(AbsKn(TacConstantr))->pr_tacrefavoidr|CTacRef(AbsKn(TacAlias_asr))->Libnames.pr_qualid(Tac2env.shortest_qualid_of_ltacavoidr)|CTacCst(RelIdqid)->Libnames.pr_qualidqid|CTacCst(AbsKn(Tuple0))->str"()"|CTacCst(AbsKn(Tuplen))->CErrors.anomaly?locPp.(str"Incorrect tuple.")|CTacCst(AbsKn(Otherkn))whenKerName.equalc_nilkn->str"[]"|CTacCst(AbsKn(Otherkn))->pr_constructorkn|CTacFun(pats,c)->letavoid=List.fold_leftids_of_patternavoidpatsinletpats=pr_sequence(pr_rawpat_genE0)patsinletparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinparen(hov0(hov2(str"fun"++spc()++pats)++spc()++str"=>"++spc()++pr_rawexprE5avoidc))|CTacApp({v=CTacCst(AbsKn(Tuple0))},args)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hov0(str"()"++spc()++pr_sequence(pr_rawexprE0avoid)args))|CTacApp({v=CTacCst(AbsKn(Tuplen))},args)->let()=ifnot(Int.equaln(List.lengthargs))thenCErrors.anomaly?locPp.(str"Incorrect tuple.")insurround(prlist_with_seppr_comma(pr_rawexprE1avoid)args)|CTacApp({v=CTacCst(AbsKn(Otherkn))},_)whenKerName.equalknc_cons->letrecfactorizeaccuc=matchc.CAst.vwith|CTacCst(AbsKn(Otherkn))whenKerName.equalc_nilkn->accu,None|CTacApp({v=CTacCst(AbsKn(Otherkn))},args)whenKerName.equalknc_cons->lethd,tl=matchargswith|[hd;tl]->hd,tl|_->CErrors.anomaly?loc(str"Incorrect list.")infactorize(hd::accu)tl|_->accu,Somecinbeginmatchfactorize[]cwith|l,None->hov2(str"["++prlist_with_seppr_semicolon(pr_rawexprE4avoid)(List.revl)++str"]")|l,Somerest->letparen=matchlvlwith|E0|E1|E2->paren|E3|E4|E5->funx->xinletpr_cons()=spc()++str"::"++spc()inparen(hov2(prlist_with_seppr_cons(pr_rawexprE1avoid)(List.rev(rest::l))))end|CTacApp(hd,args)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinparen(hov0(pr_rawexprE0avoidhd++spc()++pr_sequence(pr_rawexprE0avoid)args))|CTacSyn(_,kn)->fmt"<notation %t>"(fun()->KerName.printkn)|CTacLet(isrec,bnd,e)->letparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinletpprec=ifisrecthenstr"rec"++spc()elsemt()inletavoidbnd=List.fold_left(funavoid(pat,_)->ids_of_patternavoidpat)avoidbndinletpr_bnd(pat,e)=letavoid=ifisrecthenavoidbndelseavoidinhov(-2-ifisrecthen4else0)(pr_rawpat_genE0pat++str" :="++spc()++hov2(pr_rawexprE5avoide))inletbnd=prlist_with_sep(fun()->spc()++str"with ")pr_bndbndinparen(v0(hov0(v0(str"let "++pprec++bnd)++spc()++str"in")++spc())++pr_rawexprE5avoidbnde)|CTacCnv(e,t)->paren(pr_rawexprE5avoide++spc()++str":"++spc()++pr_rawtype_genT5_lt)|CTacSeq(e1,e2)->letparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinparen(pr_rawexprE4avoide1++str";"++spc()++pr_rawexprE4avoide2)|CTacIft(b,e1,e2)->letparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinparen(str"if"++spc()++pr_rawexprE5avoidb++spc()++str"then"++spc()++pr_rawexprE5avoide1++spc()++str"else"++spc()++pr_rawexprE5avoide2)|CTacCse(e,brs)->letpr_one_branch(pat,br)=letavoid=ids_of_patternavoidpatinhov4(str"|"++spc()++hov0(pr_rawpat_genE5pat++spc()++str"=>")++spc()++hov2(pr_rawexprE5avoidbr))inletbrs=prlist_with_sepspcpr_one_branchbrsinv0(hv0(str"match"++spc()++pr_rawexprE5avoide++spc()++str"with")++spc()++brs++spc()++str"end")|CTacRec(def,fields)->letdef=matchdefwith|None->mt()|Somedef->pr_rawexprE0avoiddef++spc()++str"with"++spc()inletpr_field(proj,e)=pr_relidpr_projectionproj++spc()++str":="++spc()++pr_rawexprE1avoideinhov2(str"{"++spc()++def++prlist_with_seppr_semicolonpr_fieldfields++str"}")|CTacPrj(e,p)->hov0(pr_rawexprE0avoide++str"."++paren(pr_relidpr_projectionp))|CTacSet(e1,p,e2)->hov0(pr_rawexprE0avoide1++str"."++paren(pr_relidpr_projectionp)++spc()++str":="++spc()++pr_rawexprE1avoide2)|CTacExt(tag,arg)->letobj=interp_ml_objecttaginletenv=Global.env()inletsigma=Evd.from_envenvinobj.ml_raw_printenvsigmaarg|CTacGlb(prms,args,body,ty)->letavoid,tynames=Array.fold_left_map(funavoid()->letna=Namegen.next_ident_awaybase_internal_ty_identavoidinletavoid=Id.Set.addnaavoidinavoid,Id.to_stringna)avoid(Array.makeprms())inlettynamesi=tynames.(i)inletpr_arg(pat,arg,ty)=letbnd=matchtywith|Somety->paren(pr_namepat.CAst.v++spc()++str":"++spc()++pr_glbtype_gentynamesT5_lty)|None->pr_namepat.CAst.vinhov(-2)(bnd++str" :="++spc()++hov2(pr_rawexprE5avoidarg))inletparen=matchlvlwith|E0|E1|E2|E3|E4->paren|E5->funx->xinletbnd=prlist_with_sep(fun()->spc()++str"with ")pr_argargsinparen(v0(hov0(v0(str"let "++bnd)++spc()++str"in")++spc())++pr_glbexpr_gen~avoidE5body++spc()++str":"++pr_glbtype_gentynamesT5_lty)inhov0(pr_rawexprlvlavoidc)letpr_mutflagismut=ifismutthenstr"mutable "elsemt()letpr_isrecisrec=ifisrecthenstr"rec "elsemt()letpr_one_strval~isrec(na,e)=letavoid=matchna.CAst.vwith|Anonymous->Id.Set.empty|Nameid->ifisrecthenId.Set.singletonidelseId.Set.emptyinpr_lnamena++str" :="++spc()++pr_rawexpr_genE5~avoide(* XXX boxing can probably be improved, current output is not great
(try -beautify on Ltac2.Std to see) *)letpr_one_strtyp(qid,redef,(params,v))=letppparams=matchparamswith|[]->mt()|[x]->pr_lidentx++spc()|_->surround(prlist_with_seppr_commapr_lidentparams)++spc()inletppredef=ifredefthenstr" ::="++spc()elsestr" :="++spc()inletppv=matchvwith|CTydDefNone->mt()|CTydDef(Sometyp)->ppredef++pr_rawtype_genT5_rtyp|CTydAlg[]->ppredef++str"[ ]"|CTydAlgctors->letpr_one_ctor(atts,na,typs)=letpptyps=ifCList.is_emptytypsthenmt()elsespc()++surround(prlist_with_seppr_comma(pr_rawtype_genT5_r)typs)inhov2(Ppvernac.pr_vernac_attributesatts++Id.printna++pptyps)inletppctors=matchctorswith|[]->str"[ ]"|[c]->str"["++spc()++pr_one_ctorc++spc()++str"]"|_->hv0(str"["++spc()++prlist_with_sepspc(func->str"| "++pr_one_ctorc)ctors++spc()++str"]")inppredef++ppctors|CTydRecfields->ppredef++letpr_one_field(id,ismut,typ)=hov2(pr_mutflagismut++Id.printid++str" :"++spc()++pr_rawtype_genT5_rtyp++str";")++spc()inhv2(str"{"++spc()++prlist_with_sepmtpr_one_fieldfields++str"}")|CTydOpn->ppredef++str"[ .. ]"inhov0(ppparams++Libnames.pr_qualidqid++ppv)letpr_strexpr=function|StrVal(ismut,isrec,vals)->pr_mutflagismut++pr_isrecisrec++prlist_with_sep(fun()->spc()++str"with ")(pr_one_strval~isrec)vals|StrTyp(isrec,typs)->str"Type "++pr_isrecisrec++hv0(prlist_with_sep(fun()->spc()++str"with ")pr_one_strtyptyps)|StrPrm(id,typ,v)->str"@external "++pr_lidentid++spc()++str": "++hov0(pr_rawtype_genT5_rtyp)++spc()++hov2(str":= "++qstringv.mltac_plugin++spc()++qstringv.mltac_tactic)|StrMut(qid,asna,e)->letavoid=matchasnawith|None->Id.Set.empty|Someasid->Id.Set.singletonasid.vinstr"Set "++Libnames.pr_qualidqid++pr_opt(funasid->str"as "++pr_lidentasid)asna++spc()++hov2(str":= "++pr_rawexpr_genE5~avoide)letrecpr_syntax_class=letopenCAstinfunction|SexprStr{v=s}->qstrings|SexprInt{v=n}->Pp.intn|SexprRec(_,{v=na},args)->letna=matchnawith|None->str"_"|Someid->Id.printidinletppargs=ifCList.is_emptyargsthenmt()elsestr"("++prlist_with_sep(fun()->str", ")pr_syntax_classargs++str")"inna++ppargs(** Toplevel printers *)letrecsubst_typesubst(t:'aglb_typexpr)=matchtwith|GTypVarid->subst.(id)|GTypArrow(t1,t2)->GTypArrow(subst_typesubstt1,subst_typesubstt2)|GTypRef(qid,args)->GTypRef(qid,List.map(funt->subst_typesubstt)args)letunfoldknargs=let(nparams,def)=Tac2env.interp_typekninmatchdefwith|GTydDef(Somedef)->letargs=Array.of_listargsinSome(subst_typeargsdef)|_->Noneletreckindt=matchtwith|GTypVarid->GTypVarid|GTypRef(Otherkn,tl)->beginmatchunfoldkntlwith|None->t|Somet->kindtend|GTypArrow_|GTypRef(Tuple_,_)->ttypeval_printer={val_printer:'a.Environ.env->Evd.evar_map->Tac2val.valexpr->'aglb_typexprlist->Pp.t}letprinters=refKNmap.emptyletregister_val_printerknpr=printers:=KNmap.addknpr!printersopenTac2ffiletrecpr_valexpr_genenvsigmalvlvt=matchkindtwith|GTypVar_->str"<poly>"|GTypRef(Otherkn,params)->letpr=trySome(KNmap.findkn!printers)withNot_found->Noneinbeginmatchprwith|Somepr->(* for now assume all printers produce atomic expressions so no need to pass [lvl] *)pr.val_printerenvsigmavparams|None->letn,repr=Tac2env.interp_typekninifKerName.equalknt_listthenpr_val_listenvsigma(to_list(funv->repr_tovalexprv)v)(List.hdparams)elsematchreprwith|GTydDefNone->str"<abstr>"|GTydDef(Some_)->(* Shouldn't happen thanks to kind *)assertfalse|GTydAlgalg->ifTac2val.Valexpr.is_intvthenpr_internal_constructorkn(Tac2ffi.to_intv)trueelseletparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinlet(n,args)=Tac2ffi.to_blockvinlet(_,id,tpe)=find_constructornfalsealg.galg_constructorsinletknc=change_kn_labelknidinletargs=pr_constrargsenvsigmaparamsargstpeinparen(pr_constructorknc++spc()++args)|GTydRecrcd->let(_,args)=Tac2ffi.to_blockvinpr_recordenvsigmaparamsargsrcd|GTydOpn->beginmatchTac2ffi.to_openvwith|(knc,[||])->pr_constructorknc|(knc,args)->letparen=matchlvlwith|E0->paren|E1|E2|E3|E4|E5->funx->xinletdata=Tac2env.interp_constructorkncinletargs=pr_constrargsenvsigmaparamsargsdata.Tac2env.cdata_argsinparen(pr_constructorknc++spc()++args)endend|GTypArrow_->str"<fun>"|GTypRef(Tuple0,[])->str"()"|GTypRef(Tuple_,tl)->letblk=Array.to_list(snd(to_blockv))inifList.lengthblk==List.lengthtlthenletprs=List.map2(funvt->pr_valexpr_genenvsigmaE1vt)blktlinhv2(str"("++prlist_with_seppr_comma(funp->p)prs++str")")elsestr"<unknown>"andpr_constrargsenvsigmaparamsargstpe=letsubst=Array.of_listparamsinlettpe=List.map(funt->subst_typesubstt)tpeinletargs=Array.to_listargsinletargs=List.combineargstpeinpr_sequence(fun(v,t)->pr_valexpr_genenvsigmaE0vt)argsandpr_recordenvsigmaparamsargsrcd=letsubst=Array.of_listparamsinletmap(id,_,tpe)=(id,subst_typesubsttpe)inletrcd=List.mapmaprcdinletargs=Array.to_listargsinletfields=List.combinercdargsinletpr_field((id,t),arg)=Id.printid++spc()++str":="++spc()++pr_valexpr_genenvsigmaE1argtinstr"{"++spc()++prlist_with_seppr_semicolonpr_fieldfields++spc()++str"}"andpr_val_listenvsigmaargstpe=letprv=pr_valexpr_genenvsigmaE4vtpeinhov1(str"["++prlist_with_seppr_semicolonprargs++str"]")letpr_valexprenvsigmavt=pr_valexpr_genenvsigmaE5vtletregister_initnf=letkn=KerName.makeTac2env.rocq_prefix(Label.maken)inregister_val_printerkn{val_printer=funenvsigmav_->fenvsigmav}let()=register_init"int"beginfun__n->letn=to_intninPp.intnendlet()=register_init"string"beginfun__s->lets=to_stringsinPp.quote(strs)endlet()=register_init"ident"beginfun__id->letid=to_identidinstr"@"++Id.printidendlet()=register_init"constr"beginfunenvsigmac->letc=to_constrcinletc=tryPrinter.pr_leconstr_envenvsigmacwith_->str"..."inhov2(str"constr:("++c++str")")endlet()=register_init"preterm"beginfunenvsigmac->letc=to_pretermcin(* XXX should we get the ltac2 env out of the closure and print it too? Maybe with a debug flag? *)letc=tryPrinter.pr_closed_glob_envenvsigmacwith_->str"..."inhov2(str"preterm:("++c++str")")endlet()=register_init"pattern"beginfunenvsigmac->letc=to_patterncinletc=tryPrinter.pr_lconstr_pattern_envenvsigmacwith_->str"..."inhov2(str"pat:("++c++str")")endlet()=register_init"message"beginfun__pp->hov2(str"message:("++to_pppp++str")")endlet()=register_init"err"beginfun__e->lete=to_erreinhov2(str"err:("++CErrors.iprint_no_reporte++str")")endlet()=letkn=KerName.makeTac2env.rocq_prefix(Label.make"array")inletval_printerenvsigmavarg=matchargwith|[arg]->let(_,v)=to_blockvinstr"[|"++spc()++prvect_with_seppr_semicolon(funa->pr_valexprenvsigmaaarg)v++spc()++str"|]"|_->assertfalseinregister_val_printerkn{val_printer}letpr_profile_frame=letopenPpinfunction|FrAnone->str"<fun "++pr_glbexpr~avoid:Id.Set.emptye++str">"|FrLtackn->pr_tacrefId.Set.emptykn|FrPrimml->str"<"++strml.mltac_plugin++str":"++strml.mltac_tactic++str">"|FrExtn(tag,_)->str"<extn:"++str(Tac2dyn.Arg.reprtag)++str">"let()=Hook.setTac2bt.pr_frame_hookpr_profile_frame