123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384(************************************************************************)(* * 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) *)(************************************************************************)openCErrors(** The type of parsing attribute data *)typevernac_flag_type=|FlagIdentofstring|FlagStringofstringtypevernac_flags=vernac_flaglistandvernac_flag=string*vernac_flag_valueandvernac_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(s,arguments)=letopenPpinstrs++(pr_vernac_flag_valuearguments)letwarn_unsupported_attributes=CWarnings.create~name:"unsupported-attributes"~category:"parsing"~default:CWarnings.AsError(funatts->letkeys=List.mapfstattsinletkeys=List.sort_uniqString.comparekeysinletconj=matchkeyswith[_]->"this attribute: "|_->"these attributes: "inPp.(str"This command does not support "++strconj++prliststrkeys++str"."))letunsupported_attributes=function|[]->()|atts->warn_unsupported_attributesattstype'akey_parser='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_emptykv=ifv<>VernacFlagEmptythenuser_errPp.(str"Attribute "++strk++str" does not accept arguments")leterror_twice~name:'a=user_errPp.(str"Attribute for "++strname++str" specified twice.")letassert_once~nameprev=ifOption.has_someprevthenerror_twice~nameletattribute_of_list(l:(string*'akey_parser)list):'aoptionattribute=letrecpextrav=function|[]->List.revextra,v|(key,attvasatt)::rem->(matchCList.assoc_fString.equalkeylwith|exceptionNot_found->p(att::extra)vrem|parser->letv=Some(parservattv)inpextravrem)inp[]Noneletsingle_key_parser~name~keyvprevargs=assert_emptykeyargs;assert_once~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=function|Somev->CErrors.user_errPp.(str"key '"++strkey++str"' has been already set.")|None->beginfunction|VernacFlagLeaf(FlagIdentb)->beginmatchCList.assoc_fString.equalbvalueswith|exceptionNot_found->CErrors.user_errPp.(str"Invalid value '"++strb++str"' for key "++strkey++fnl()++str"use one of "++pr_possible_values~values)|value->valueend|VernacFlagEmpty->default|err->CErrors.user_errPp.(str"Invalid syntax "++pr_vernac_flag(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~valuesletlegacy_bool_attribute~name~on~off:booloptionattribute=attribute_of_list[(on,single_key_parser~name~key:ontrue);(off,single_key_parser~name~key:offfalse)](* important note: we use on as the default for the new bool_attribute ! *)letdeprecated_bool_attribute_warning=CWarnings.create~name:"deprecated-attribute-syntax"~category:"parsing"~default:CWarnings.Enabled(funname->Pp.(str"Syntax for switching off boolean attributes has been updated, use "++strname++str"=no instead."))letdeprecated_bool_attribute~name~on~off:booloptionattribute=bool_attribute~name:on++legacy_bool_attribute~name~on~off|>map(function|None,None->None|None,Somev->deprecated_bool_attribute_warningname;Somev|Somev,None->Somev|Somev1,Somev2->CErrors.user_errPp.(str"attribute "++strname++str": cannot specify legacy and modern syntax at the same time."))(* Variant of the [bool] attribute with only two values (bool has three). *)letget_bool_value~key~default=function|VernacFlagEmpty->default|VernacFlagList["true",VernacFlagEmpty]->deprecated_bool_attribute_warningkey;true|VernacFlagList["false",VernacFlagEmpty]->deprecated_bool_attribute_warningkey;false|VernacFlagLeaf(FlagIdent"yes")->true|VernacFlagLeaf(FlagIdent"no")->false|_->user_errPp.(str"Attribute "++strkey++str" only accepts boolean values.")letenable_attribute~key~default:boolattribute=funatts->letdefault=default()inletthis,extra=List.partition(fun(k,_)->String.equalkeyk)attsinextra,matchthiswith|[]->default|[_,value]->get_bool_value~key~default:truevalue|_->error_twice~name:keyletqualify_attributequal(parser:'aattribute):'aattribute=funatts->letrecextractextraqualified=function|[]->List.revextra,List.flatten(List.revqualified)|(key,attv)::remwhenString.equalkeyqual->(matchattvwith|VernacFlagEmpty|VernacFlagLeaf_->CErrors.user_err~hdr:"qualified_attribute"Pp.(str"Malformed attribute "++strqual++str": attribute list expected.")|VernacFlagListatts->extractextra(atts::qualified)rem)|att::rem->extract(att::extra)qualifiedreminletextra,qualified=extract[][]attsinletrem,v=parserqualifiedinletextra=ifrem=[]thenextraelse(qual,VernacFlagListrem)::extrainextra,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{optdepr=false;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->returnl(* locality is supposed to be true when local, false when global *)letlocality=letlocality_to_bool=function|Goptions.OptLocal->true|Goptions.OptGlobal->false|Goptions.OptExport->CErrors.user_errPp.(str"export attribute not supported here")|Goptions.OptDefault->CErrors.user_errPp.(str"default attribute not supported here")inoption_locality_parser>>=functionl->return(Option.maplocality_to_booll)letukey="universes"letuniverse_polymorphism_option_name=["Universe";"Polymorphism"]letis_universe_polymorphism=letb=reffalseinlet()=letopenGoptionsindeclare_bool_option{optdepr=false;optkey=universe_polymorphism_option_name;optread=(fun()->!b);optwrite=((:=)b)}infun()->!bletpolymorphic_base=deprecated_bool_attribute~name:"Polymorphism"~on:"polymorphic"~off:"monomorphic">>=function|Someb->returnb|None->return(is_universe_polymorphism())lettemplate=qualify_attributeukey(deprecated_bool_attribute~name:"Template"~on:"template"~off:"notemplate")letpolymorphic=qualify_attributeukeypolymorphic_baseletdeprecation_parser:Deprecation.tkey_parser=funorigargs->assert_once~name:"deprecation"orig;matchargswith|VernacFlagList["since",VernacFlagLeaf(FlagStringsince);"note",VernacFlagLeaf(FlagStringnote)]|VernacFlagList["note",VernacFlagLeaf(FlagStringnote);"since",VernacFlagLeaf(FlagStringsince)]->Deprecation.make~since~note()|VernacFlagList["since",VernacFlagLeaf(FlagStringsince)]->Deprecation.make~since()|VernacFlagList["note",VernacFlagLeaf(FlagStringnote)]->Deprecation.make~note()|_->CErrors.user_err(Pp.str"Ill formed “deprecated” attribute")letdeprecation=attribute_of_list["deprecated",deprecation_parser]letonly_localityatts=parselocalityattsletonly_polymorphismatts=parsepolymorphicattsletvernac_polymorphic_flag=ukey,VernacFlagList["polymorphic",VernacFlagEmpty]letvernac_monomorphic_flag=ukey,VernacFlagList["polymorphic",VernacFlagLeaf(FlagIdent"no")]letcanonical_field=enable_attribute~key:"canonical"~default:(fun()->true)letcanonical_instance=enable_attribute~key:"canonical"~default:(fun()->false)letuses_parser:stringkey_parser=funorigargs->assert_once~name:"using"orig;matchargswith|VernacFlagLeaf(FlagStringstr)->str|_->CErrors.user_err(Pp.str"Ill formed \"using\" attribute")letusing=attribute_of_list["using",uses_parser]letprocess_typing_att~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_errPp.(str"Unknown “typing” attribute: "++stratt)letprocess_typing_disable~key=function|VernacFlagEmpty|VernacFlagLeaf(FlagIdent"yes")->true|VernacFlagLeaf(FlagIdent"no")->false|_->CErrors.user_errPp.(str"Ill-formed attribute value, must be "++strkey++str"={yes, no}")lettyping_flags_parser:Declarations.typing_flagskey_parser=funorigargs->letrecflag_parsertyping_flags=function|[]->typing_flags|(typing_att,enable)::rest->letdisable=process_typing_disable~key:typing_attenableinlettyping_flags=process_typing_att~typing_flagstyping_attdisableinflag_parsertyping_flagsrestinmatchargswith|VernacFlagListatts->lettyping_flags=Global.typing_flags()inflag_parsertyping_flagsatts|att->CErrors.user_errPp.(str"Ill-formed “typing” attribute: "++pr_vernac_flag_valueatt)lettyping_flags=attribute_of_list["bypass_check",typing_flags_parser]