123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176(************************************************************************)(* * 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) *)(************************************************************************)openPpopenUtilopenCAstopenCErrorsopenNamesopenLibnamesopenLibobjectopenNametabopenTac2expropenTac2printopenTac2intern(** Grammar entries *)modulePltac=structletltac2_expr=Pcoq.Entry.make"ltac2_expr"lettac2expr_in_env=Pcoq.Entry.make"tac2expr_in_env"letq_ident=Pcoq.Entry.make"q_ident"letq_bindings=Pcoq.Entry.make"q_bindings"letq_with_bindings=Pcoq.Entry.make"q_with_bindings"letq_intropattern=Pcoq.Entry.make"q_intropattern"letq_intropatterns=Pcoq.Entry.make"q_intropatterns"letq_destruction_arg=Pcoq.Entry.make"q_destruction_arg"letq_induction_clause=Pcoq.Entry.make"q_induction_clause"letq_conversion=Pcoq.Entry.make"q_conversion"letq_rewriting=Pcoq.Entry.make"q_rewriting"letq_clause=Pcoq.Entry.make"q_clause"letq_dispatch=Pcoq.Entry.make"q_dispatch"letq_occurrences=Pcoq.Entry.make"q_occurrences"letq_reference=Pcoq.Entry.make"q_reference"letq_strategy_flag=Pcoq.Entry.make"q_strategy_flag"letq_constr_matching=Pcoq.Entry.make"q_constr_matching"letq_goal_matching=Pcoq.Entry.make"q_goal_matching"letq_hintdb=Pcoq.Entry.make"q_hintdb"letq_move_location=Pcoq.Entry.make"q_move_location"letq_pose=Pcoq.Entry.make"q_pose"letq_assert=Pcoq.Entry.make"q_assert"endlet()=letentries=[Pcoq.Entry.AnyPltac.ltac2_expr;]inPcoq.register_grammars_by_name"ltac2"entries(** Tactic definition *)typetacdef={tacdef_local:bool;tacdef_mutable:bool;tacdef_expr:glb_tacexpr;tacdef_type:type_scheme;tacdef_deprecation:Deprecation.toption;}letperform_tacdefvisibility((sp,kn),def)=let()=ifnotdef.tacdef_localthenTac2env.push_ltacvisibilitysp(TacConstantkn)inletdata={Tac2env.gdata_expr=def.tacdef_expr;gdata_type=def.tacdef_type;gdata_mutable=def.tacdef_mutable;gdata_deprecation=def.tacdef_deprecation;}inTac2env.define_globalkndataletload_tacdefiobj=perform_tacdef(Untili)objletopen_tacdefiobj=perform_tacdef(Exactlyi)objletcache_tacdef((sp,kn),def)=let()=Tac2env.push_ltac(Until1)sp(TacConstantkn)inletdata={Tac2env.gdata_expr=def.tacdef_expr;gdata_type=def.tacdef_type;gdata_mutable=def.tacdef_mutable;gdata_deprecation=def.tacdef_deprecation;}inTac2env.define_globalkndataletsubst_tacdef(subst,def)=letexpr'=subst_exprsubstdef.tacdef_exprinlettype'=subst_type_schemesubstdef.tacdef_typeinifexpr'==def.tacdef_expr&&type'==def.tacdef_typethendefelse{defwithtacdef_expr=expr';tacdef_type=type'}letclassify_tacdefo=SubstituteletinTacDef:Id.t->tacdef->obj=declare_named_object{(default_object"TAC2-DEFINITION")withcache_function=cache_tacdef;load_function=load_tacdef;open_function=simple_openopen_tacdef;subst_function=subst_tacdef;classify_function=classify_tacdef}(** Type definition *)typetypdef={typdef_local:bool;typdef_expr:glb_quant_typedef;}letchange_kn_labelknid=letmp=KerName.modpathkninKerName.makemp(Label.of_idid)letchange_sp_labelspid=let(dp,_)=Libnames.repr_pathspinLibnames.make_pathdpidletpush_typedefvisibilityspkn(_,def)=matchdefwith|GTydDef_->Tac2env.push_typevisibilityspkn|GTydAlg{galg_constructors=cstrs}->(* Register constructors *)letiter(c,_)=letspc=change_sp_labelspcinletknc=change_kn_labelkncinTac2env.push_constructorvisibilityspckncinTac2env.push_typevisibilityspkn;List.iteritercstrs|GTydRecfields->(* Register fields *)letiter(c,_,_)=letspc=change_sp_labelspcinletknc=change_kn_labelkncinTac2env.push_projectionvisibilityspckncinTac2env.push_typevisibilityspkn;List.iteriterfields|GTydOpn->Tac2env.push_typevisibilityspknletnexti=letans=!iinlet()=incriinansletdefine_typedefkn(params,defasqdef)=matchdefwith|GTydDef_->Tac2env.define_typeknqdef|GTydAlg{galg_constructors=cstrs}->(* Define constructors *)letconstant=ref0inletnonconstant=ref0inletiter(c,args)=letknc=change_kn_labelkncinlettag=ifList.is_emptyargsthennextconstantelsenextnonconstantinletdata={Tac2env.cdata_prms=params;cdata_type=kn;cdata_args=args;cdata_indx=Sometag;}inTac2env.define_constructorkncdatainTac2env.define_typeknqdef;List.iteritercstrs|GTydRecfs->(* Define projections *)letiteri(id,mut,t)=letknp=change_kn_labelknidinletproj={Tac2env.pdata_prms=params;pdata_type=kn;pdata_ptyp=t;pdata_mutb=mut;pdata_indx=i;}inTac2env.define_projectionknpprojinTac2env.define_typeknqdef;List.iteriiterfs|GTydOpn->Tac2env.define_typeknqdefletperform_typdefvs((sp,kn),def)=let()=ifnotdef.typdef_localthenpush_typedefvsspkndef.typdef_exprindefine_typedefkndef.typdef_exprletload_typdefiobj=perform_typdef(Untili)objletopen_typdefiobj=perform_typdef(Exactlyi)objletcache_typdef((sp,kn),def)=let()=push_typedef(Until1)spkndef.typdef_exprindefine_typedefkndef.typdef_exprletsubst_typdef(subst,def)=letexpr'=subst_quant_typedefsubstdef.typdef_exprinifexpr'==def.typdef_exprthendefelse{defwithtypdef_expr=expr'}letclassify_typdefo=SubstituteletinTypDef:Id.t->typdef->obj=declare_named_object{(default_object"TAC2-TYPE-DEFINITION")withcache_function=cache_typdef;load_function=load_typdef;open_function=simple_openopen_typdef;subst_function=subst_typdef;classify_function=classify_typdef}(** Type extension *)typeextension_data={edata_name:Id.t;edata_args:intglb_typexprlist;}typetypext={typext_local:bool;typext_prms:int;typext_type:type_constant;typext_expr:extension_datalist;}letpush_typextvisprefixdef=letiterdata=letspc=Libnames.make_pathprefix.obj_dirdata.edata_nameinletknc=KerName.makeprefix.obj_mp(Label.of_iddata.edata_name)inTac2env.push_constructorvisspckncinList.iteriterdef.typext_exprletdefine_typextmpdef=letiterdata=letknc=KerName.makemp(Label.of_iddata.edata_name)inletcdata={Tac2env.cdata_prms=def.typext_prms;cdata_type=def.typext_type;cdata_args=data.edata_args;cdata_indx=None;}inTac2env.define_constructorknccdatainList.iteriterdef.typext_exprletcache_typext(prefix,def)=let()=define_typextprefix.obj_mpdefinpush_typext(Until1)prefixdefletperform_typextvs(prefix,def)=let()=ifnotdef.typext_localthenpush_typextvsprefixdefindefine_typextprefix.obj_mpdefletload_typextiobj=perform_typext(Untili)objletopen_typextiobj=perform_typext(Exactlyi)objletsubst_typext(subst,e)=letopenMod_substinletsubst_datadata=letedata_args=List.Smart.map(fune->subst_typesubste)data.edata_argsinifedata_args==data.edata_argsthendataelse{datawithedata_args}inlettypext_type=subst_knsubste.typext_typeinlettypext_expr=List.Smart.mapsubst_datae.typext_expriniftypext_type==e.typext_type&&typext_expr==e.typext_exprtheneelse{ewithtypext_type;typext_expr}letclassify_typexto=SubstituteletinTypExt:typext->obj=declare_named_object_gen{(default_object"TAC2-TYPE-EXTENSION")withcache_function=cache_typext;load_function=load_typext;open_function=simple_openopen_typext;subst_function=subst_typext;classify_function=classify_typext}(** Toplevel entries *)letfresh_varavoidx=letbadid=Id.Set.memidavoid||(tryignore(Tac2env.locate_ltac(qualid_of_identid));truewithNot_found->false)inNamegen.next_ident_away_from(Id.of_stringx)badletextract_pattern_type({loc;v=p}aspat)=matchpwith|CPatCnv(pat,ty)->pat,Somety|CPatAtm_|CPatVar_|CPatRef_|CPatOr_|CPatAs_|CPatRecord_->pat,None(** Mangle recursive tactics *)letinline_rec_tactictactics=letavoid=List.fold_left(funaccu({v=id},_)->Id.Set.addidaccu)Id.Set.emptytacticsinletmap(id,e)=matche.vwith|CTacFun(pat,_)->(id,List.mapextract_pattern_typepat,e)|_->user_err?loc:id.loc(str"Recursive tactic definitions must be functions")inlettactics=List.mapmaptacticsinletmap(id,pat,e)=letfold_var(avoid,ans)(pat,_)=letid=fresh_varavoid"x"inletloc=pat.locin(Id.Set.addidavoid,CAst.make?locid::ans)in(* Fresh variables to abstract over the function patterns *)let_,vars=List.fold_leftfold_var(avoid,[])patinletmap_body({loc;v=id},_,e)=CAst.(make?loc@@CPatVar(Nameid)),einletbnd=List.mapmap_bodytacticsinletpat_of_id{loc;v=id}=CAst.make?loc@@CPatVar(Nameid)inletvar_of_id{loc;v=id}=letqid=qualid_of_ident?locidinCAst.make?loc@@CTacRef(RelIdqid)inletloc0=e.locinletvpat=List.mappat_of_idvarsinletvarg=List.mapvar_of_idvarsinlete=CAst.make?loc:loc0@@CTacLet(true,bnd,CAst.make?loc:loc0@@CTacApp(var_of_idid,varg))in(id,CAst.make?loc:loc0@@CTacFun(vpat,e))inList.mapmaptacticsletcheck_lowercase{loc;v=id}=ifTac2env.is_constructor(Libnames.qualid_of_identid)thenuser_err?loc(str"The identifier "++Id.printid++str" must be lowercase")letcheck_value?loce=ifnot(is_valuee)thenuser_err?loc(str"Tactic definition must be a syntactical value."++spc()++str"Consider using a thunk.")letregister_ltac?deprecation?(local=false)?(mut=false)isrectactics=letmap({loc;v=na},e)=letid=matchnawith|Anonymous->user_err?loc(str"Tactic definition must have a name")|Nameid->idinlet()=check_lowercaseCAst.(make?locid)in(CAst.(make?locid),e)inlettactics=List.mapmaptacticsinlettactics=ifisrectheninline_rec_tactictacticselsetacticsinletmap({loc;v=id},({loc=eloc}ase))=let(e,t)=intern~strict:true[]einlet()=check_value?loc:eloceinletkn=Lib.make_knidinletexists=trylet_=Tac2env.interp_globalknintruewithNot_found->falseinlet()=ifexiststhenuser_err?loc(str"Tactic "++Names.Id.printid++str" already exists")in(id,e,t)inletdefs=List.mapmaptacticsinletiter(id,e,t)=letdef={tacdef_local=local;tacdef_mutable=mut;tacdef_expr=e;tacdef_type=t;tacdef_deprecation=deprecation;}inLib.add_leaf(inTacDefiddef)inList.iteriterdefsletqualid_to_identqid=ifqualid_is_identqidthenCAst.make?loc:qid.CAst.loc@@qualid_basenameqidelseuser_err?loc:qid.CAst.loc(str"Identifier expected")letregister_typedef?(local=false)isrectypes=letsame_name({v=id1},_)({v=id2},_)=Id.equalid1id2inlet()=matchList.duplicatessame_nametypeswith|[]->()|({loc;v=id},_)::_->user_err?loc(str"Multiple definition of the type name "++Id.printid)inlet()=letcheck_existing_type({v=id},_)=let(_,kn)=Lib.make_fonameidintrylet_=Tac2env.interp_typekninuser_err(str"Multiple definition of the type name "++Id.printid)withNot_found->()inList.itercheck_existing_typetypesinletcheck({loc;v=id},(params,def))=letsame_name{v=id1}{v=id2}=Id.equalid1id2inlet()=matchList.duplicatessame_nameparamswith|[]->()|{loc;v=id}::_->user_err?loc(str"The type parameter "++Id.printid++str" occurs several times")inmatchdefwith|CTydDef_->ifisrecthenuser_err?loc(str"The type abbreviation "++Id.printid++str" cannot be recursive")|CTydAlgcs->letsame_name(id1,_)(id2,_)=Id.equalid1id2inlet()=matchList.duplicatessame_namecswith|[]->()|(id,_)::_->user_err(str"Multiple definitions of the constructor "++Id.printid)inlet()=letcheck_uppercase_ident(id,_)=ifnot(Tac2env.is_constructor_idid)thenuser_err(str"Constructor name should start with an uppercase letter "++Id.printid)inList.itercheck_uppercase_identcsinlet()=letcheck_existing_ctor(id,_)=let(_,kn)=Lib.make_fonameidintrylet_=Tac2env.interp_constructorkninuser_err(str"Constructor already defined in this module "++Id.printid)withNot_found->()inList.itercheck_existing_ctorcsin()|CTydRecps->letsame_name(id1,_,_)(id2,_,_)=Id.equalid1id2inlet()=matchList.duplicatessame_namepswith|[]->()|(id,_,_)::_->user_err(str"Multiple definitions of the projection "++Id.printid)in()|CTydOpn->ifisrecthenuser_err?loc(str"The open type declaration "++Id.printid++str" cannot be recursive")inlet()=List.iterchecktypesinletself=ifisrecthenletfoldaccu({v=id},(params,_))=Id.Map.addid(Lib.make_knid,List.lengthparams)accuinList.fold_leftfoldId.Map.emptytypeselseId.Map.emptyinletmap({v=id},def)=lettypdef={typdef_local=local;typdef_expr=intern_typedefselfdef;}in(id,typdef)inlettypes=List.mapmaptypesinletiter(id,def)=Lib.add_leaf(inTypDefiddef)inList.iteritertypesletregister_primitive?deprecation?(local=false){loc;v=id}tml=lett=intern_open_typetinlet()=trylet_=Tac2env.interp_primitivemlin()withNot_found->user_err?loc(str"Unregistered primitive "++quote(strml.mltac_plugin)++spc()++quote(strml.mltac_tactic))inlete=GTacPrmmlinletdef={tacdef_local=local;tacdef_mutable=false;tacdef_expr=e;tacdef_type=t;tacdef_deprecation=deprecation;}inLib.add_leaf(inTacDefiddef)letregister_open?(local=false)qid(params,def)=letkn=tryTac2env.locate_typeqidwithNot_found->user_err?loc:qid.CAst.loc(str"Unbound type "++pr_qualidqid)inlet(tparams,t)=Tac2env.interp_typekninlet()=matchtwith|GTydOpn->()|GTydAlg_|GTydRec_|GTydDef_->user_err?loc:qid.CAst.loc(str"Type "++pr_qualidqid++str" is not an open type")inlet()=ifnot(Int.equal(List.lengthparams)tparams)thenTac2intern.error_nparams_mismatch?loc:qid.CAst.loc(List.lengthparams)tparamsinmatchdefwith|CTydOpn->()|CTydAlgdef->let()=letsame_name(id1,_)(id2,_)=Id.equalid1id2inlet()=matchList.duplicatessame_namedefwith|[]->()|(id,_)::_->user_err(str"Multiple definitions of the constructor "++Id.printid)inletcheck_existing_ctor(id,_)=let(_,kn)=Lib.make_fonameidintrylet_=Tac2env.interp_constructorkninuser_err(str"Constructor already defined in this module "++Id.printid)withNot_found->()inlet()=List.itercheck_existing_ctordefin()inletintern_typet=lettpe=CTydDef(Somet)inlet(_,ans)=intern_typedefId.Map.empty(params,tpe)inmatchanswith|GTydDef(Somet)->t|_->assertfalseinletmap(id,tpe)=ifnot(Tac2env.is_constructor_idid)thenuser_err(str"Constructor name should start with an uppercase letter "++Id.printid);lettpe=List.mapintern_typetpein{edata_name=id;edata_args=tpe}inletdef=List.mapmapdefinletdef={typext_local=local;typext_type=kn;typext_prms=tparams;typext_expr=def;}inLib.add_leaf(inTypExtdef)|CTydRec_|CTydDef_->user_err?loc:qid.CAst.loc(str"Extensions only accept inductive constructors")letregister_type?localisrectypes=matchtypeswith|[qid,true,def]->let()=ifisrecthenuser_err?loc:qid.CAst.loc(str"Extensions cannot be recursive")inregister_open?localqiddef|_->letmap(qid,redef,def)=let()=ifredefthenuser_err?loc:qid.loc(str"Types can only be extended one by one")in(qualid_to_identqid,def)inlettypes=List.mapmaptypesinregister_typedef?localisrectypes(** Parsing *)type'atoken=|TacTermofstring|TacNonTermofName.t*'atypescope_rule=|ScopeRule:(raw_tacexpr,_,'a)Pcoq.Symbol.t*('a->raw_tacexpr)->scope_ruletypescope_interpretation=sexprlist->scope_ruleletscope_table:scope_interpretationId.Map.tref=refId.Map.emptyletregister_scopeids=scope_table:=Id.Map.addids!scope_tablemoduleParseToken=structletloc_of_token=function|SexprStr{loc}->loc|SexprInt{loc}->loc|SexprRec(loc,_,_)->Somelocletparse_scope=function|SexprRec(_,{loc;v=Someid},toks)->ifId.Map.memid!scope_tablethenId.Map.findid!scope_tabletokselseCErrors.user_err?loc(str"Unknown scope"++spc()++Names.Id.printid)|SexprStr{v=str}->letv_unit=CAst.make@@CTacCst(AbsKn(Tuple0))inScopeRule(Pcoq.Symbol.token(Tok.PIDENT(Somestr)),(fun_->v_unit))|tok->letloc=loc_of_tokentokinCErrors.user_err?loc(str"Invalid parsing token")letparse_token=function|SexprStr{v=s}->TacTerms|SexprRec(_,na,[tok])->letna=matchna.CAst.vwith|None->Anonymous|Someid->let()=check_lowercase(CAst.make?loc:na.CAst.locid)inNameidinletscope=parse_scopetokinTacNonTerm(na,scope)|tok->letloc=loc_of_tokentokinCErrors.user_err?loc(str"Invalid parsing token")letrecprint_scope=function|SexprStrs->strs.CAst.v|SexprInti->inti.CAst.v|SexprRec(_,{v=na},[])->Option.cataId.print(str"_")na|SexprRec(_,{v=na},e)->Option.cataId.print(str"_")na++str"("++pr_sequenceprint_scopee++str")"letprint_token=function|SexprStr{v=s}->quote(strs)|SexprRec(_,{v=na},[tok])->print_scopetok|_->assertfalseendletparse_scope=ParseToken.parse_scopetypesynext={synext_kn:KerName.t;synext_tok:sexprlist;synext_lev:int;synext_loc:bool;synext_depr:Deprecation.toption;}typekrule=|KRule:(raw_tacexpr,_,'act,Loc.t->raw_tacexpr)Pcoq.Rule.t*((Loc.t->(Name.t*raw_tacexpr)list->raw_tacexpr)->'act)->kruleletrecget_rule(tok:scope_ruletokenlist):krule=matchtokwith|[]->KRule(Pcoq.Rule.stop,funkloc->kloc[])|TacNonTerm(na,ScopeRule(scope,inj))::tok->letKRule(rule,act)=get_ruletokinletrule=Pcoq.Rule.nextrulescopeinletactke=act(funlocacc->kloc((na,inje)::acc))inKRule(rule,act)|TacTermt::tok->letKRule(rule,act)=get_ruletokinletrule=Pcoq.(Rule.nextrule(Symbol.token(Pcoq.terminalt)))inletactk_=actkinKRule(rule,act)letdeprecated_ltac2_notation=Deprecation.create_warning~object_name:"Ltac2 notation"~warning_name_if_no_since:"deprecated-ltac2-notation"(fun(toks:sexprlist)->pr_sequenceParseToken.print_tokentoks)(* This is a hack to preserve the level 4 entry which is initially empty. The
grammar engine has the great idea to silently delete empty levels on rule
removal, so we have to work around this using the Pcoq API.
FIXME: we should really keep those levels around instead. *)letget_reinit=function|4->Some(Gramlib.Gramext.LeftA,Gramlib.Gramext.After"5")|_->Noneletperform_notationsynst=lettok=List.rev_mapParseToken.parse_tokensyn.synext_tokinletKRule(rule,act)=get_ruletokinletmklocargs=let()=matchsyn.synext_deprwith|None->()|Somedepr->deprecated_ltac2_notation~loc(syn.synext_tok,depr)inletmap(na,e)=((CAst.make?loc:e.loc@@CPatVarna),e)inletbnd=List.mapmapargsinCAst.make~loc@@CTacSyn(bnd,syn.synext_kn)inletrule=Pcoq.Production.makerule(actmk)inletpos=Some(string_of_intsyn.synext_lev)inletrule=Pcoq.Reuse(pos,[rule])inmatchget_reinitsyn.synext_levwith|None->([Pcoq.ExtendRule(Pltac.ltac2_expr,rule)],st)|Somereinit->([Pcoq.ExtendRuleReinit(Pltac.ltac2_expr,reinit,rule)],st)letltac2_notation=Pcoq.create_grammar_command"ltac2-notation"{gext_fun=perform_notation;gext_eq=(==)(* FIXME *)}letcache_synextsyn=Pcoq.extend_grammar_commandltac2_notationsynletopen_synextisyn=ifInt.equali1thenPcoq.extend_grammar_commandltac2_notationsynletsubst_synext(subst,syn)=letkn=Mod_subst.subst_knsubstsyn.synext_kninifkn==syn.synext_knthensynelse{synwithsynext_kn=kn}letclassify_synexto=ifo.synext_locthenDisposeelseSubstituteletltac2_notation_cat=Libobject.create_category"ltac2.notations"letinTac2Notation:synext->obj=declare_object{(default_object"TAC2-NOTATION")withobject_stage=Summary.Stage.Synterp;cache_function=cache_synext;open_function=simple_open~cat:ltac2_notation_catopen_synext;subst_function=subst_synext;classify_function=classify_synext}letcache_synext_interp(local,kn,tac)=Tac2env.define_notationkntacletopen_synext_interpio=ifInt.equali1thencache_synext_interpoletsubst_synext_interp(subst,(local,kn,tacaso))=lettac'=Tac2intern.subst_rawexprsubsttacinletkn'=Mod_subst.subst_knsubstkninifkn'==kn&&tac'==tacthenoelse(local,kn',tac')letclassify_synext_interp(local,_,_)=iflocalthenDisposeelseSubstituteletinTac2NotationInterp:(bool*KerName.t*raw_tacexpr)->obj=declare_object{(default_object"TAC2-NOTATION-INTERP")withcache_function=cache_synext_interp;open_function=simple_open~cat:ltac2_notation_catopen_synext_interp;subst_function=subst_synext_interp;classify_function=classify_synext_interp}typeabbreviation={abbr_body:raw_tacexpr;abbr_depr:Deprecation.toption;}letperform_abbreviationvisibility((sp,kn),abbr)=let()=Tac2env.push_ltacvisibilitysp(TacAliaskn)inTac2env.define_alias?deprecation:abbr.abbr_deprknabbr.abbr_bodyletload_abbreviationiobj=perform_abbreviation(Untili)objletopen_abbreviationiobj=perform_abbreviation(Exactlyi)objletcache_abbreviation((sp,kn),abbr)=let()=Tac2env.push_ltac(Until1)sp(TacAliaskn)inTac2env.define_alias?deprecation:abbr.abbr_deprknabbr.abbr_bodyletsubst_abbreviation(subst,abbr)=letbody'=subst_rawexprsubstabbr.abbr_bodyinifbody'==abbr.abbr_bodythenabbrelse{abbr_body=body';abbr_depr=abbr.abbr_depr}letclassify_abbreviationo=SubstituteletinTac2Abbreviation:Id.t->abbreviation->obj=declare_named_object{(default_object"TAC2-ABBREVIATION")withcache_function=cache_abbreviation;load_function=load_abbreviation;open_function=simple_open~cat:ltac2_notation_catopen_abbreviation;subst_function=subst_abbreviation;classify_function=classify_abbreviation}letrecstring_of_scope=function|SexprStrs->Printf.sprintf"str(%s)"s.CAst.v|SexprInti->Printf.sprintf"int(%i)"i.CAst.v|SexprRec(_,{v=na},[])->Option.cataId.to_string"_"na|SexprRec(_,{v=na},e)->Printf.sprintf"%s(%s)"(Option.cataId.to_string"_"na)(String.concat" "(List.mapstring_of_scopee))letstring_of_token=function|SexprStr{v=s}->Printf.sprintf"str(%s)"s|SexprRec(_,{v=na},[tok])->string_of_scopetok|_->assertfalseletmake_fresh_keytokens=letprods=String.concat"_"(List.mapstring_of_tokentokens)in(* We embed the hash of the kernel name in the label so that the identifier
should be mostly unique. This ensures that including two modules
together won't confuse the corresponding labels. *)lethash=(ModPath.hash(Lib.current_mp()))land0x7FFFFFFFinletlbl=Id.of_string_soft(Printf.sprintf"%s_%08X"prodshash)inLib.make_knlbltypenotation_interpretation_data=|AbbreviationofId.t*Deprecation.toption*raw_tacexpr|Synextofbool*KerName.t*Id.Set.t*raw_tacexprletregister_notationattstknlevbody=letdeprecation,local=Attributes.(parseNotations.(deprecation++locality))attsinletlocal=Option.defaultfalselocalinmatchtkn,levwith|[SexprRec(_,{loc;v=Someid},[])],None->(* Tactic abbreviation *)let()=check_lowercaseCAst.(make?locid)inAbbreviation(id,deprecation,body)|_->(* Check that the tokens make sense *)letentries=List.mapParseToken.parse_tokentkninletfoldaccutok=matchtokwith|TacTerm_->accu|TacNonTerm(Nameid,_)->Id.Set.addidaccu|TacNonTerm(Anonymous,_)->accuinletids=List.fold_leftfoldId.Set.emptyentriesin(* Globalize so that names are absolute *)letlev=matchlevwith|Somen->let()=ifn<0||n>6thenuser_err(str"Notation levels must range between 0 and 6")inn|None->5inletkey=make_fresh_keytkninletext={synext_kn=key;synext_tok=tkn;synext_lev=lev;synext_loc=local;synext_depr=deprecation;}inLib.add_leaf(inTac2Notationext);Synext(local,key,ids,body)letregister_notation_interpretation=function|Abbreviation(id,deprecation,body)->letbody=Tac2intern.globalizeId.Set.emptybodyinletabbr={abbr_body=body;abbr_depr=deprecation}inLib.add_leaf(inTac2Abbreviationidabbr)|Synext(local,kn,ids,body)->letbody=Tac2intern.globalizeidsbodyinLib.add_leaf(inTac2NotationInterp(local,kn,body))typeredefinition={redef_kn:ltac_constant;redef_body:glb_tacexpr;redef_old:Id.toption;}letperform_redefinitionredef=letkn=redef.redef_kninletdata=Tac2env.interp_globalkninletbody=matchredef.redef_oldwith|None->redef.redef_body|Someid->(* Rebind the old value with a let-binding *)GTacLet(false,[Nameid,data.Tac2env.gdata_expr],redef.redef_body)inletdata={datawithTac2env.gdata_expr=body}inTac2env.define_globalkndataletsubst_redefinition(subst,redef)=letkn=Mod_subst.subst_knsubstredef.redef_kninletbody=Tac2intern.subst_exprsubstredef.redef_bodyinifkn==redef.redef_kn&&body==redef.redef_bodythenredefelse{redef_kn=kn;redef_body=body;redef_old=redef.redef_old}letclassify_redefinitiono=SubstituteletinTac2Redefinition:redefinition->obj=declare_object{(default_object"TAC2-REDEFINITION")withcache_function=perform_redefinition;open_function=simple_open(fun_->perform_redefinition);subst_function=subst_redefinition;classify_function=classify_redefinition;}letregister_redefinitionqidold({loc=eloc}ase)=letkn=tryTac2env.locate_ltacqidwithNot_found->user_err?loc:qid.CAst.loc(str"Unknown tactic "++pr_qualidqid)inletkn=matchknwith|TacConstantkn->kn|TacAlias_->user_err?loc:qid.CAst.loc(str"Cannot redefine syntactic abbreviations")inletdata=Tac2env.interp_globalkninlet()=ifnot(data.Tac2env.gdata_mutable)thenuser_err?loc:qid.CAst.loc(str"The tactic "++pr_qualidqid++str" is not declared as mutable")inletctx=matcholdwith|None->[]|Some{CAst.v=id}->[id,data.Tac2env.gdata_type]inlet(e,t)=intern~strict:truectxeinlet()=check_value?loc:eloceinlet()=ifnot(Tac2intern.check_subtypetdata.Tac2env.gdata_type)thenletname=int_name()inuser_err?loc:qid.CAst.loc(str"Type "++pr_glbtypename(sndt)++str" is not a subtype of "++pr_glbtypename(snddata.Tac2env.gdata_type))inletold=Option.map(fun{CAst.v=id}->id)oldinletdef={redef_kn=kn;redef_body=e;redef_old=old;}inLib.add_leaf(inTac2Redefinitiondef)letperform_eval~pstatee=letenv=Global.env()inlet(e,ty)=Tac2intern.intern~strict:false[]einletv=Tac2interp.interpTac2interp.empty_environmenteinletselector,proof=matchpstatewith|None->letsigma=Evd.from_envenvinletname,poly=Id.of_string"ltac2",falseinGoal_select.SelectAll,Proof.start~name~polysigma[]|Somepstate->Goal_select.get_default_goal_selector(),Declare.Proof.getpstateinletnosuchgoal=letinfo=Exninfo.reify()inProofview.tclZERO~info(Proof.SuggestNoSuchGoals(1,proof))inletv=Goal_select.tclSELECT~nosuchgoalselectorvinlet(proof,_,ans)=Proof.run_tactic(Global.env())vproofinlet{Proof.sigma}=Proof.dataproofinletname=int_name()inFeedback.msg_notice(str"- : "++pr_glbtypename(sndty)++spc()++str"="++spc()++Tac2print.pr_valexprenvsigmaans(sndty))(** Toplevel entries *)letwarn_modtype=CWarnings.create~name:"ltac2-in-modtype"~category:CWarnings.CoreCategories.ltac2~default:AsErrorPp.(funwhat->strbrk"Ltac2 "++strwhat++strbrk" should not be defined inside module types: functor application to arguments of this module type will be unchecked")letcheck_modtypewhat=ifLib.is_modtype()thenwarn_modtypewhatletregister_structattsstr=matchstrwith|StrVal(mut,isrec,e)->check_modtype"definitions";letdeprecation,local=Attributes.(parseNotations.(deprecation++locality))attsinregister_ltac?deprecation?local~mutisrece|StrTyp(isrec,t)->check_modtype"types";letlocal=Attributes.(parselocality)attsinregister_type?localisrect|StrPrm(id,t,ml)->check_modtype"externals";letdeprecation,local=Attributes.(parseNotations.(deprecation++locality))attsinregister_primitive?deprecation?localidtml|StrMut(qid,old,e)->let()=Attributes.unsupported_attributesattsinregister_redefinitionqidolde(** Toplevel exception *)let()=Goptions.declare_bool_option{Goptions.optstage=Summary.Stage.Interp;Goptions.optdepr=None;Goptions.optkey=["Ltac2";"Backtrace"];Goptions.optread=(fun()->!Tac2bt.print_ltac2_backtrace);Goptions.optwrite=(funb->Tac2bt.print_ltac2_backtrace:=b);}letpr_frame=function|FrAnone->str"Call {"++pr_glbexpre++str"}"|FrLtackn->str"Call "++pr_tacrefkn|FrPrimml->str"Prim <"++strml.mltac_plugin++str":"++strml.mltac_tactic++str">"|FrExtn(tag,arg)->letobj=Tac2env.interp_ml_objecttaginletenv=Global.env()inletsigma=Evd.from_envenvinstr"Extn "++str(Tac2dyn.Arg.reprtag)++str":"++spc()++obj.Tac2env.ml_printenvsigmaarglet()=register_handlerbeginfunction|Tac2interp.LtacError(kn,args)->lett_exn=KerName.makeTac2env.coq_prefix(Label.make"exn")inletv=Tac2ffi.of_open(kn,args)inlett=GTypRef(Othert_exn,[])inletc=Tac2print.pr_valexpr(Global.env())Evd.emptyvtinSome(hov0(str"Uncaught Ltac2 exception:"++spc()++hov0c))|_->Noneendlet()=CErrors.register_additional_error_infobeginfuninfo->if!Tac2bt.print_ltac2_backtracethenletbt=Exninfo.getinfoTac2bt.backtraceinletbt=matchbtwith|Somebt->List.revbt|None->[]inletbt=str"Backtrace:"++fnl()++prlist_with_sepfnlpr_framebt++fnl()inSomebtelseNoneend(** Printing *)letprint_constant~print_defqid?infodata=lete=data.Tac2env.gdata_exprinlet(_,t)=data.Tac2env.gdata_typeinletname=int_name()inletdef=ifprint_defthenfnl()++hov2(pr_qualidqid++spc()++str":="++spc()++pr_glbexpre)elsemt()inletinfo=matchinfowith|None->mt()|Someinfo->fnl()++fnl()++hov2(str"Compiled as"++spc()++strinfo.Tac2env.source)inhov0(hov2(pr_qualidqid++spc()++str":"++spc()++pr_glbtypenamet)++def++info)letprint_tacref~print_defqid=function|TacConstantkn->letdata=Tac2env.interp_globalkninletinfo=Option.mapfst(Tac2env.get_compiled_globalkn)inprint_constant~print_defqiddata?info|TacAliaskn->str"Alias to ..."letlocatable_ltac2="Ltac2"typeltac2_object=|Constructorofltac_constructor|TacRefoftacrefletlocate_objectqid=tryConstructor(Tac2env.locate_constructorqid)withNot_found->TacRef(Tac2env.locate_ltacqid)letlocate_all_objectqid=letopenTac2envin(List.map(funx->Constructorx)(locate_extended_all_constructorqid))@(List.map(funx->TacRefx)(locate_extended_all_ltacqid))letshortest_qualid_of_object=function|Constructorkn->Tac2env.shortest_qualid_of_constructorkn|TacRefkn->Tac2env.shortest_qualid_of_ltacknletpath_of_object=function|Constructorkn->Tac2env.path_of_constructorkn|TacRefkn->Tac2env.path_of_ltacknletprint_object~print_defqid=function|Constructor_->str"Ltac2 Constructor"++spc()++pr_qualidqid|TacRefkn->str"Ltac2 "++print_tacref~print_defqidknlet()=letopenPrettypinletlocateqid=trySome(qid,locate_objectqid)withNot_found->Noneinletlocate_allqid=List.map(funx->qid,x)(locate_all_objectqid)inletshortest_qualid(_,kn)=shortest_qualid_of_objectkninletname(_,kn)=lethdr=matchknwith|TacRef(TacConstant_)->str"Ltac2"|TacRef(TacAlias_)->str"Ltac2 Notation"|Constructor_->str"Ltac2 Constructor"inhdr++spc()++pr_path(path_of_objectkn)inletprint(qid,kn)=print_object~print_def:trueqidkninletabout(qid,kn)=print_object~print_def:falseqidkninregister_locatablelocatable_ltac2{locate;locate_all;shortest_qualid;name;print;about;}letprint_located_tacticqid=Feedback.msg_notice(Prettyp.print_located_otherlocatable_ltac2qid)letprint_ltac2qid=ifTac2env.is_constructorqidthenletkn=tryTac2env.locate_constructorqidwithNot_found->user_err?loc:qid.CAst.loc(str"Unknown constructor "++pr_qualidqid)inlet_=Tac2env.interp_constructorkninFeedback.msg_notice(hov2(str"Constructor"++spc()++str":"++spc()++pr_qualidqid))elseletkn=tryTac2env.locate_ltacqidwithNot_found->user_err?loc:qid.CAst.loc(str"Unknown tactic "++pr_qualidqid)inFeedback.msg_notice(print_tacref~print_def:trueqidkn)letprint_signatures()=letentries=KNmap.bindings(Tac2env.globals())inletsort(kn1,_)(kn2,_)=KerName.comparekn1kn2inletentries=List.sortsortentriesinletmap(kn,entry)=letqid=trySome(Tac2env.shortest_qualid_of_ltac(TacConstantkn))withNot_found->Noneinmatchqidwith|None->None|Someqid->Some(qid,entry)inletentries=List.map_filtermapentriesinletpr_entry(qid,data)=hov2(print_constant~print_def:falseqiddata)inFeedback.msg_notice(prlist_with_sepfnlpr_entryentries)(** Calling tactics *)letltac2_interpe=letloc=e.locinlet(e,t)=intern~strict:false[]einlet()=check_unit?loctinlettac=Tac2interp.interpTac2interp.empty_environmenteinProofview.tclIGNOREtacletComTactic.Interpreterltac2_interp=ComTactic.register_tactic_interpreter"coq-core.plugins.ltac2"ltac2_interpletcall~pstateg~with_end_tactac=letg=Option.default(Goal_select.get_default_goal_selector())ginComTactic.solve~pstate~with_end_tacg~info:None(ltac2_interptac)letcall_par~pstate~with_end_tactac=ComTactic.solve_parallel~pstate~info:None(ltac2_interptac)~abstract:false~with_end_tac(** Primitive algebraic types than can't be defined Coq-side *)letregister_prim_algnameparamsdef=letid=Id.of_stringnameinletdef=List.map(fun(cstr,tpe)->(Id.of_string_softcstr,tpe))definletgetn(const,nonconst)(c,args)=matchargswith|[]->(succconst,nonconst)|_::_->(const,succnonconst)inletnconst,nnonconst=List.fold_leftgetn(0,0)definletalg={galg_constructors=def;galg_nconst=nconst;galg_nnonconst=nnonconst;}inletdef=(params,GTydAlgalg)inletdef={typdef_local=false;typdef_expr=def}inLib.add_leaf(inTypDefiddef)letcoq_defn=KerName.makeTac2env.coq_prefix(Label.maken)letdef_unit={typdef_local=false;typdef_expr=0,GTydDef(Some(GTypRef(Tuple0,[])));}lett_list=coq_def"list"let()=Mltop.declare_cache_objbeginfun()->letunit=Id.of_string"unit"inLib.add_leaf(inTypDefunitdef_unit);register_prim_alg"list"1[("[]",[]);("::",[GTypVar0;GTypRef(Othert_list,[GTypVar0])]);];end"coq-core.plugins.ltac2"