123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenNames(* Utilities *)moduleSubscript=structtypet={ss_zero:int;(** Number of leading zeros of the subscript *)ss_subs:int;(** Digital value of the subscript, zero meaning empty *)}letrecoverflown=Int.equal(nmod10)9&&(Int.equal(n/10)0||overflow(n/10))letzero={ss_subs=0;ss_zero=0}letsuccs=ifInt.equals.ss_subs0thenifInt.equals.ss_zero0then(* [] -> [0] *){ss_zero=1;ss_subs=0}else(* [0...00] -> [0..01] *){ss_zero=s.ss_zero-1;ss_subs=1}elseifoverflows.ss_substhenifInt.equals.ss_zero0then(* [9...9] -> [10...0] *){ss_zero=0;ss_subs=1+s.ss_subs}else(* [0...009...9] -> [0...010...0] *){ss_zero=s.ss_zero-1;ss_subs=1+s.ss_subs}else(* [0...0n] -> [0...0{n+1}] *){ss_zero=s.ss_zero;ss_subs=s.ss_subs+1}letequals1s2=Int.equals1.ss_zeros2.ss_zero&&Int.equals1.ss_subss2.ss_subsletcompares1s2=(* Lexicographic order is reversed in order to ensure that [succ] is strictly
increasing. *)letc=Int.compares1.ss_subss2.ss_subsinifInt.equalc0thenInt.compares1.ss_zeros2.ss_zeroelsecendletcode_of_0=Char.code'0'letcode_of_9=Char.code'9'letcut_identskip_quotes=lets=Id.to_stringsinletslen=String.lengthsin(* [n'] is the position of the first non nullary digit *)letrecnumpartnn'=ifInt.equaln0then(* ident made of _ and digits only [and ' if skip_quote]: don't cut it *)slenelseletc=Char.code(String.gets(n-1))inifInt.equalccode_of_0&¬(Int.equalnslen)thennumpart(n-1)n'elseifcode_of_0<=c&&c<=code_of_9thennumpart(n-1)(n-1)elseifskip_quote&&(Int.equalc(Char.code'\'')||Int.equalc(Char.code'_'))thennumpart(n-1)(n-1)elsen'innumpartslenslenletrepr_idents=letnumstart=cut_identfalsesinlets=Id.to_stringsinletslen=String.lengthsinifInt.equalnumstartslenthen(s,None)else(String.subs0numstart,Some(int_of_string(String.subsnumstart(slen-numstart))))letmake_identsa=function|Somen->letc=Char.code(String.getsa(String.lengthsa-1))inlets=ifc<code_of_0||c>code_of_9thensa^(string_of_intn)elsesa^"_"^(string_of_intn)inId.of_strings|None->Id.of_stringsaletroot_of_idid=letsuffixstart=cut_identtrueidinId.of_string(String.sub(Id.to_stringid)0suffixstart)(* Return the same identifier as the original one but whose {i subscript} is incremented.
If the original identifier does not have a suffix, [0] is appended to it.
Example mappings:
[bar] ↦ [bar0]
[bar0] ↦ [bar1]
[bar00] ↦ [bar01]
[bar1] ↦ [bar2]
[bar01] ↦ [bar02]
[bar9] ↦ [bar10]
[bar09] ↦ [bar10]
[bar99] ↦ [bar100]
*)letincrement_subscriptid=letid=Id.to_stringidinletlen=String.lengthidinletrecaddcarrypos=letc=id.[carrypos]inifis_digitcthenifInt.equal(Char.codec)(Char.code'9')thenbeginassert(carrypos>0);add(carrypos-1)endelsebeginletnewid=Bytes.of_stringidinBytes.fillnewid(carrypos+1)(len-1-carrypos)'0';Bytes.setnewidcarrypos(Char.chr(Char.codec+1));newidendelsebeginletnewid=Bytes.of_string(id^"0")inifcarrypos<len-1thenbeginBytes.fillnewid(carrypos+1)(len-1-carrypos)'0';Bytes.setnewid(carrypos+1)'1'end;newidendinId.of_bytes(add(len-1))lethas_subscriptid=letid=Id.to_stringidinis_digit(id.[String.lengthid-1])letget_subscriptid=letid0=idinletid=Id.to_stringidinletlen=String.lengthidinletrecget_sufaccupos=ifpos<0then(pos,accu)elseletc=id.[pos]inifis_digitcthenget_suf(Char.codec-Char.code'0'::accu)(pos-1)else(pos,accu)inlet(pos,suf)=get_suf[](len-1)inifInt.equalpos(len-1)then(id0,Subscript.zero)elseletid=String.subid0(pos+1)inletreccompute_zerosaccu=function|[]->(accu,[])|0::l->compute_zeros(succaccu)l|_::_asl->(accu,l)inlet(ss_zero,suf)=compute_zeros0sufinletreccompute_sufaccu=function|[]->accu|n::l->compute_suf(10*accu+n)linletss_subs=compute_suf0sufin(Id.of_stringid,{Subscript.ss_subs;ss_zero;})letadd_subscriptidss=ifSubscript.equalSubscript.zerossthenidelseifInt.equalss.Subscript.ss_subs0thenletid=Id.to_stringidinletpad=String.makess.Subscript.ss_zero'0'inId.of_string(Printf.sprintf"%s%s"idpad)elseletid=Id.to_stringidinletpad=String.makess.Subscript.ss_zero'0'inletsuf=ss.Subscript.ss_subsinId.of_string(Printf.sprintf"%s%s%i"idpadsuf)letforget_subscriptid=letnumstart=cut_identfalseidinletnewid=Bytes.make(numstart+1)'0'inString.blit(Id.to_stringid)0newid0numstart;(Id.of_bytesnewid)letadd_suffixids=Id.of_string(Id.to_stringid^s)letadd_prefixsid=Id.of_string(s^Id.to_stringid)letatompart_of_idid=fst(repr_identid)(* Names *)moduletypeExtName=sigincludemoduletypeofstructincludeNames.NameendexceptionIsAnonymousvalfold_left:('a->Id.t->'a)->'a->t->'avalfold_right:(Id.t->'a->'a)->t->'a->'avaliter:(Id.t->unit)->t->unitvalmap:(Id.t->Id.t)->t->tvalfold_left_map:('a->Id.t->'a*Id.t)->'a->t->'a*tvalfold_right_map:(Id.t->'a->Id.t*'a)->Name.t->'a->Name.t*'avalget_id:t->Id.tvalpick:t->t->tvalpick_annot:tContext.binder_annot->tContext.binder_annot->tContext.binder_annotvalcons:t->Id.tlist->Id.tlistvalto_option:Name.t->Id.toptionendmoduleName:ExtName=structincludeNames.NameexceptionIsAnonymousletfold_leftfa=function|Nameid->faid|Anonymous->aletfold_rightfnaa=matchnawith|Nameid->fida|Anonymous->aletiterfna=fold_right(funx()->fx)na()letmapf=function|Nameid->Name(fid)|Anonymous->Anonymousletfold_left_mapfa=function|Nameid->let(a,id)=faidin(a,Nameid)|Anonymous->a,Anonymousletfold_right_mapfnaa=matchnawith|Nameid->let(id,a)=fidain(Nameid,a)|Anonymous->Anonymous,aletget_id=function|Nameid->id|Anonymous->raiseIsAnonymousletpickna1na2=matchna1with|Name_->na1|Anonymous->na2letpick_annotna1na2=letopenContextinmatchna1.binder_namewith|Name_->na1|Anonymous->na2letconsnal=matchnawith|Anonymous->l|Nameid->id::lletto_option=function|Anonymous->None|Nameid->Someidend(* Metavariables *)letpr_meta=Pp.intletstring_of_meta=string_of_int