123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405(************************************************************************)(* * 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) *)(************************************************************************)(** The type of parsing attribute data *)typevernac_flag_type=|FlagIdentofstring|FlagStringofstringtypevernac_flags=vernac_flaglistandvernac_flag=(string*vernac_flag_value)CAst.tandvernac_flag_value=|VernacFlagEmpty|VernacFlagLeafofvernac_flag_type|VernacFlagListofvernac_flagsletpr_vernac_flag_leaf=function|FlagIdentb->Pp.strb|FlagStrings->Pp.(quote(strs))letrecpr_vernac_flag_value=letopenPpinfunction|VernacFlagEmpty->mt()|VernacFlagLeafl->str"="++pr_vernac_flag_leafl|VernacFlagLists->surround(prlist_with_seppr_commapr_vernac_flags)andpr_vernac_flag_r(s,arguments)=letopenPpinstrs++(pr_vernac_flag_valuearguments)andpr_vernac_flag{CAst.v}=pr_vernac_flag_rvletwarn_unsupported_attributes=CWarnings.create~name:"unsupported-attributes"~category:CWarnings.CoreCategories.parsing~default:CWarnings.AsError(funatts->letkeys=List.map(funx->fstx.CAst.v)attsinletkeys=List.sort_uniqString.comparekeysinletconj=matchkeyswith[_]->"this attribute: "|_->"these attributes: "inPp.(str"This command does not support "++strconj++prlist_with_sep(fun()->strbrk", ")strkeys++str"."))letunsupported_attributes=function|[]->()|atts->letloc=List.fold_left(funlocatt->Loc.merge_optlocatt.CAst.loc)Noneattsinwarn_unsupported_attributes?locattstype'akey_parser=?loc:Loc.t->'aoption->vernac_flag_value->'atype'aattribute=vernac_flags->vernac_flags*'aletparse_with_extra(p:'aattribute)(atts:vernac_flags):vernac_flags*'a=pattsletparse_drop_extraattatts=snd(parse_with_extraattatts)letparse(p:'aattribute)atts:'a=letextra,v=parse_with_extrapattsinunsupported_attributesextra;vletmake_attributex=xmoduleNotations=structtype'at='aattributeletreturnx=funatts->atts,xlet(>>=)attf=funatts->letatts,v=attattsinfvattslet(>>)p1p2=funatts->letatts,()=p1attsinp2attsletmapfatt=funatts->letatts,v=attattsinatts,fvlet(++)(p1:'aattribute)(p2:'battribute):('a*'b)attribute=funatts->letatts,v1=p1attsinletatts,v2=p2attsinatts,(v1,v2)endopenNotationsletassert_empty?lockv=ifv<>VernacFlagEmptythenCErrors.user_err?locPp.(str"Attribute "++strk++str" does not accept arguments")leterror_twice?loc~name:'a=CErrors.user_err?locPp.(str"Attribute for "++strname++str" specified twice.")letassert_once?loc~nameprev=ifOption.has_someprevthenerror_twice?loc~nameletattribute_of_list(l:(string*'akey_parser)list):'aoptionattribute=letrecpextrav=function|[]->List.revextra,v|({CAst.v=key,attv;loc}asatt)::rem->(matchCList.assoc_fString.equalkeylwith|exceptionNot_found->p(att::extra)vrem|parser->letv=Some(parser?locvattv)inpextravrem)inp[]Noneletsingle_key_parser~name~keyv?locprevargs=assert_empty?lockeyargs;assert_once?loc~nameprev;vletpr_possible_values~values=Pp.(str"{"++prlist_with_seppr_commastr(List.mapfstvalues)++str"}")(** [key_value_attribute ~key ~default ~values] parses a attribute [key=value]
with possible [key] [value] in [values], [default] is for compatibility for users
doing [qualif(key)] which is parsed as [qualif(key=default)] *)letkey_value_attribute~key~default~(values:(string*'a)list):'aoptionattribute=letparser?loc=function|Somev->CErrors.user_err?locPp.(str"key '"++strkey++str"' has been already set.")|None->beginfunction|VernacFlagLeaf(FlagIdentb)->beginmatchCList.assoc_fString.equalbvalueswith|exceptionNot_found->CErrors.user_err?locPp.(str"Invalid value '"++strb++str"' for key "++strkey++fnl()++str"use one of "++pr_possible_values~values)|value->valueend|VernacFlagEmpty->default|err->CErrors.user_err?locPp.(str"Invalid syntax "++pr_vernac_flag_r(key,err)++str", try "++strkey++str"="++pr_possible_values~values++str" instead.")endinattribute_of_list[key,parser]letbool_attribute~name:booloptionattribute=letvalues=["yes",true;"no",false]inkey_value_attribute~key:name~default:true~values(* Variant of the [bool] attribute with only two values (bool has three). *)letget_bool_value?loc~key~default=function|VernacFlagEmpty->default|VernacFlagLeaf(FlagIdent"yes")->true|VernacFlagLeaf(FlagIdent"no")->false|_->CErrors.user_err?locPp.(str"Attribute "++strkey++str" only accepts boolean values.")letenable_attribute~key~default:boolattribute=funatts->letthis,extra=List.partition(fun{CAst.v=k,_}->String.equalkeyk)attsinextra,matchthiswith|[]->default()|[{CAst.v=_,value;loc}]->get_bool_value?loc~key~default:truevalue|_::{CAst.loc}::_->(* We report the location of the 2nd item *)error_twice?loc~name:keyletqualify_attributequal(parser:'aattribute):'aattribute=funatts->letrecextractextraqualified=function|[]->List.revextra,List.flatten(List.revqualified)|{CAst.v=key,attv;loc}::remwhenString.equalkeyqual->(matchattvwith|VernacFlagEmpty|VernacFlagLeaf_->CErrors.user_err?locPp.(str"Malformed attribute "++strqual++str": attribute list expected.")|VernacFlagListatts->extractextra(atts::qualified)rem)|att::rem->extract(att::extra)qualifiedreminletextra,qualified=extract[][]attsinletrem,v=parserqualifiedinletrem=List.rev_map(funrem->CAst.make?loc:rem.CAst.loc(qual,VernacFlagList[rem]))reminletextra=List.rev_appendremextrainextra,v(** [program_mode] tells that Program mode has been activated, either
globally via [Set Program] or locally via the Program command prefix. *)letprogram_mode_option_name=["Program";"Mode"]letprogram_mode=reffalselet()=letopenGoptionsindeclare_bool_option{optstage=Summary.Stage.Interp;optdepr=None;optkey=program_mode_option_name;optread=(fun()->!program_mode);optwrite=(funb->program_mode:=b)}letprogram=enable_attribute~key:"program"~default:(fun()->!program_mode)(* This is a bit complex as the grammar in g_vernac.mlg doesn't
distingish between the boolean and ternary case.*)letoption_locality_parser=letname="Locality"inattribute_of_list[("local",single_key_parser~name~key:"local"Goptions.OptLocal);("global",single_key_parser~name~key:"global"Goptions.OptGlobal);("export",single_key_parser~name~key:"export"Goptions.OptExport);]letoption_locality=option_locality_parser>>=function|None->returnGoptions.OptDefault|Somel->returnlletexplicit_hint_locality=letopenHintsinletname="Locality"inattribute_of_list[("local",single_key_parser~name~key:"local"Local);("global",single_key_parser~name~key:"global"SuperGlobal);("export",single_key_parser~name~key:"export"Export);]letdefault_hint_locality()=ifLib.sections_are_opened()thenHints.LocalelseHints.Exportlethint_locality=explicit_hint_locality>>=function|Somev->returnv|None->return(default_hint_locality())(* locality is supposed to be true when local, false when global *)letlocality=letname="Locality"inattribute_of_list[("local",single_key_parser~name~key:"local"true);("global",single_key_parser~name~key:"global"false);]letukey="universes"letuniverse_polymorphism_option_name=["Universe";"Polymorphism"]letis_universe_polymorphism=letb=reffalseinlet()=letopenGoptionsindeclare_bool_option{optstage=Summary.Stage.Interp;optdepr=None;optkey=universe_polymorphism_option_name;optread=(fun()->!b);optwrite=((:=)b)}infun()->!bletpolymorphic=qualify_attributeukey(bool_attribute~name:"polymorphic")>>=function|Someb->returnb|None->return(is_universe_polymorphism())lettemplate=qualify_attributeukey(bool_attribute~name:"template")letunfold_fix=enable_attribute~key:"unfold_fix"~default:(fun()->false)letdeprecation_parser:Deprecation.tkey_parser=fun?locorigargs->assert_once?loc~name:"deprecation"orig;matchargswith|VernacFlagList[{CAst.v="since",VernacFlagLeaf(FlagStringsince)};{CAst.v="note",VernacFlagLeaf(FlagStringnote)}]|VernacFlagList[{CAst.v="note",VernacFlagLeaf(FlagStringnote)};{CAst.v="since",VernacFlagLeaf(FlagStringsince)}]->Deprecation.make~since~note()|VernacFlagList[{CAst.v="since",VernacFlagLeaf(FlagStringsince)}]->Deprecation.make~since()|VernacFlagList[{CAst.v="note",VernacFlagLeaf(FlagStringnote)}]->Deprecation.make~note()|_->CErrors.user_err?loc(Pp.str"Ill formed “deprecated” attribute.")letdeprecation=attribute_of_list["deprecated",deprecation_parser]letuser_warn_parser:UserWarn.warnlistkey_parser=fun?locorigargs->letorig=Option.default[]originmatchargswith|VernacFlagList[{CAst.v="note",VernacFlagLeaf(FlagStringnote)};{CAst.v="cats",VernacFlagLeaf(FlagStringcats)}]|VernacFlagList[{CAst.v="cats",VernacFlagLeaf(FlagStringcats)};{CAst.v="note",VernacFlagLeaf(FlagStringnote)}]->UserWarn.make_warn~note~cats()::orig|VernacFlagList[{CAst.v="note",VernacFlagLeaf(FlagStringnote)}]->UserWarn.make_warn~note()::orig|_->CErrors.user_err?loc(Pp.str"Ill formed “warn” attribute.")letuser_warn_warn=attribute_of_list["warn",user_warn_parser]>>=function|None->return[]|Somel->return(List.revl)letuser_warns=(deprecation++user_warn_warn)>>=function|None,[]->returnNone|depr,warn->return(SomeUserWarn.{depr;warn})letonly_localityatts=parselocalityattsletonly_polymorphismatts=parsepolymorphicattsletvernac_polymorphic_flagloc=CAst.make?loc(ukey,VernacFlagList[CAst.make?loc("polymorphic",VernacFlagEmpty)])letvernac_monomorphic_flagloc=CAst.make?loc(ukey,VernacFlagList[CAst.make?loc("polymorphic",VernacFlagLeaf(FlagIdent"no"))])letreversible=bool_attribute~name:"reversible"letcanonical_field=enable_attribute~key:"canonical"~default:(fun()->true)letcanonical_instance=enable_attribute~key:"canonical"~default:(fun()->false)letpayload_parser?cat~name:stringkey_parser=fun?locorigargs->matchargswith|VernacFlagLeaf(FlagStringstr)->beginmatchorig,catwith|None,_->str|Someorig,Somecat->catorigstr|Some_,None->error_twice?loc~nameend|_->CErrors.user_err?locPp.(str"Ill formed \""++strname++str"\" attribute")letpayload_attribute?cat~name=attribute_of_list[name,payload_parser?cat~name]letusing=payload_attribute?cat:None~name:"using"letprocess_typing_att?loc~typing_flagsattdisable=letenable=notdisableinmatchattwith|"universes"->{typing_flagswithDeclarations.check_universes=enable}|"guard"->{typing_flagswithDeclarations.check_guarded=enable}|"positivity"->{typing_flagswithDeclarations.check_positive=enable}|att->CErrors.user_err?locPp.(str"Unknown “typing” attribute: "++stratt)letprocess_typing_disable?loc~key=function|VernacFlagEmpty|VernacFlagLeaf(FlagIdent"yes")->true|VernacFlagLeaf(FlagIdent"no")->false|_->CErrors.user_err?locPp.(str"Ill-formed attribute value, must be "++strkey++str"={yes, no}")lettyping_flags_parser:Declarations.typing_flagskey_parser=fun?locorigargs->letrecflag_parsertyping_flags=function|[]->typing_flags|{CAst.v=typing_att,disable;loc}::rest->letdisable=process_typing_disable?loc~key:typing_attdisableinlettyping_flags=process_typing_att?loc~typing_flagstyping_attdisableinflag_parsertyping_flagsrestinmatchargswith|VernacFlagListatts->lettyping_flags=Global.typing_flags()inflag_parsertyping_flagsatts|att->CErrors.user_err?locPp.(str"Ill-formed “typing” attribute: "++pr_vernac_flag_valueatt)lettyping_flags=attribute_of_list["bypass_check",typing_flags_parser]letbind_scope_where=letname="where to bind scope"inattribute_of_list[("add_top",single_key_parser~name~key:"add_top"Notation.AddScopeTop);("add_bottom",single_key_parser~name~key:"add_bottom"Notation.AddScopeBottom);]letraw_attributes:_attribute=funflags->[],flags