123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206(** [('a,'b,'x) runner] means that any function taking ['a] and
returning ['b] and some additional data can be interpreted as a
function on a state ['x].
The additional return data ['d] is useful when combining runners.
We don't need an additional input data as it can just go in the closure.
*)type('a,'b,'x)runner={run:'d.'x->('a->'b*'d)->'x*'d}moduleProg=structtypestate=Declare.OblState.ttypestack=stateNeList.ttype(_,_)t=|Ignore:(unit,unit)t|Modify:(state,state)t|Read:(state,unit)t|Push:(unit,unit)t|Pop:(state,unit)tletrunner(typeab)(ty:(a,b)t):(a,b,stack)runner={run=funpmf->matchtywith|Ignore->let(),v=f()inpm,v|Modify->letst,pm=NeList.reprpminletst,v=fstinNeList.of_repr(st,pm),v|Read->let(),v=f(NeList.headpm)inpm,v|Push->let(),v=f()inNeList.pushDeclare.OblState.empty(Somepm),v|Pop->letst,pm=NeList.reprpminassert(not(CList.is_emptypm));let(),v=fstinNeList.of_listpm,v}endmoduleProof=structmoduleLStack=Vernacstate.LemmaStacktypestate=Declare.Proof.ttypestack=LStack.toptiontype(_,_)t=|Ignore:(unit,unit)t|Modify:(state,state)t|Read:(state,unit)t|ReadOpt:(stateoption,unit)t|Reject:(unit,unit)t|Close:(state,unit)t|Open:(unit,state)tletuse=function|None->CErrors.user_err(Pp.str"Command not supported (No proof-editing in progress).")|Somestack->LStack.popstackletrunner(typeab)(ty:(a,b)t):(a,b,stack)runner={run=funstackf->matchtywith|Ignore->let(),v=f()instack,v|Modify->letp,rest=usestackinletp,v=fpinSome(LStack.pushrestp),v|Read->letp,_=usestackinlet(),v=fpinstack,v|ReadOpt->letp=Option.mapLStack.get_topstackinlet(),v=fpinstack,v|Reject->let()=ifOption.has_somestackthenCErrors.user_err(Pp.str"Command not supported (Open proofs remain).")inlet(),v=f()instack,v|Close->letp,rest=usestackinlet(),v=fpinrest,v|Open->letp,v=f()inSome(LStack.pushstackp),v}endmoduleOpaqueAccess=struct(* Modification of opaque tables (by Require registering foreign
tables and Qed/abstract/etc adding entries to the local table)
is currently not tracked by vernactypes.
*)type_t=|Ignore:unitt|Access:Global.indirect_accessortletaccess=Library.indirect_accessor[@@warning"-3"]letrunner(typea)(ty:at):(a,unit,unit)runner={run=fun()f->matchtywith|Ignore->let(),v=f()in(),v|Access->let(),v=faccessin(),v}end(* lots of messing with tuples in there, can we do better? *)letcombine_runners(typeabxcdy)(r1:(a,b,x)runner)(r2:(c,d,y)runner):(a*c,b*d,x*y)runner={run=fun(x,y)f->matchr1.runx@@funx->matchr2.runy@@funy->matchf(x,y)with((b,d),o)->(d,(b,o))with(y,(b,o))->(b,(y,o))with(x,(y,o))->((x,y),o)}type('prog,'proof,'opaque_access)state_gen={prog:'prog;proof:'proof;opaque_access:'opaque_access;}lettuple{prog;proof;opaque_access}=(prog,proof),opaque_accessletuntuple((prog,proof),opaque_access)={prog;proof;opaque_access}typeno_state=(unit,unit,unit)state_genletno_state={prog=();proof=();opaque_access=();}letignore_state={prog=Prog.Ignore;proof=Proof.Ignore;opaque_access=OpaqueAccess.Ignore}type'rtyped_vernac_gen=TypedVernac:{spec:(('inprog,'outprog)Prog.t,('inproof,'outproof)Proof.t,'inaccessOpaqueAccess.t)state_gen;run:('inprog,'inproof,'inaccess)state_gen->('outprog,'outproof,unit)state_gen*'r;}->'rtyped_vernac_genletmap_typed_vernacf(TypedVernac{spec;run})=TypedVernac{spec;run=(funst->Util.on_sndf(runst))}typetyped_vernac=unittyped_vernac_gentypefull_state=(Prog.stack,Vernacstate.LemmaStack.toption,unit)state_genletrun(TypedVernac{spec={prog;proof;opaque_access};run})(st:full_state):full_state*_=let(*)=combine_runnersinletrunner=Prog.runnerprog*Proof.runnerproof*OpaqueAccess.runneropaque_accessinletst,v=runner.run(tuplest)@@funst->letst,v=run@@untuplestintuplest,vinuntuplest,vlettyped_vernac_genspecrun=TypedVernac{spec;run}lettyped_vernacspecrun=TypedVernac{spec;run=(funst->runst,())}letvtdefaultf=typed_vernacignore_state(fun(_:no_state)->let()=f()inno_state)letvtnoprooff=typed_vernac{ignore_statewithproof=Reject}(fun(_:no_state)->let()=f()inno_state)letvtcloseprooff=typed_vernac{ignore_statewithprog=Modify;proof=Close}(fun{prog;proof}->letprog=f~lemma:proof~pm:progin{no_statewithprog})letvtopenprooff=typed_vernac{ignore_statewithproof=Open}(fun(_:no_state)->letproof=f()in{no_statewithproof})letvtmodifyprooff=typed_vernac{ignore_statewithproof=Modify}(fun{proof}->letproof=f~pstate:proofin{no_statewithproof})letvtreadproofoptf=typed_vernac{ignore_statewithproof=ReadOpt}(fun{proof}->let()=f~pstate:proofinno_state)letvtreadprooff=typed_vernac{ignore_statewithproof=Read}(fun{proof}->let()=f~pstate:proofinno_state)letvtreadprogramf=typed_vernac{ignore_statewithprog=Read}(fun{prog}->let()=f~pm:proginno_state)letvtmodifyprogramf=typed_vernac{ignore_statewithprog=Modify}(fun{prog}->letprog=f~pm:progin{no_statewithprog})letvtdeclareprogramf=typed_vernac{ignore_statewithprog=Read;proof=Open}(fun{prog}->letproof=f~pm:progin{no_statewithproof})letvtopenproofprogramf=typed_vernac{ignore_statewithprog=Modify;proof=Open}(fun{prog}->letprog,proof=f~pm:progin{no_statewithprog;proof;})letvtopaqueaccessf=typed_vernac{ignore_statewithopaque_access=Access}(fun{opaque_access}->let()=f~opaque_accessinno_state)