Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file scheduler.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291(**************************************************************************)(* *)(* VSCoq *)(* *)(* Copyright INRIA and contributors *)(* (see version control and README file for authors & dates) *)(* *)(**************************************************************************)(* *)(* This file is distributed under the terms of the MIT License. *)(* See LICENSE file. *)(* *)(**************************************************************************)openTypesletLoglog=Log.mk_log"scheduler"moduleSM=CMap.Make(Stateid)typeerror_recovery_strategy=|RSkip|RAdmittedtypeexecutable_sentence={id:sentence_id;ast:Synterp.vernac_control_entry;classif:Vernacextend.vernac_classification;synterp:Vernacstate.Synterp.t;error_recovery:error_recovery_strategy;}typetask=|Skipof{id:sentence_id;error:Pp.toption}|Blockof{id:sentence_id;error:Pp.tLoc.located}|Execofexecutable_sentence|OpaqueProofof{terminator:executable_sentence;opener_id:sentence_id;proof_using:Vernacexpr.section_subset_expr;tasks:executable_sentencelist;(* non empty list *)}|Queryofexecutable_sentence(*
| SubProof of ast list
| ModuleWithSignature of ast list
*)typeproof_block={proof_sentences:executable_sentencelist;opener_id:sentence_id;}typestate={document_scope:sentence_idlist;(* List of sentences whose effect scope is the document that follows them *)proof_blocks:proof_blocklist;(* List of sentences whose effect scope ends with the Qed *)section_depth:int;(* Statically computed section nesting *)}letinitial_state={document_scope=[];proof_blocks=[];section_depth=0;}typeschedule={tasks:(sentence_idoption*task)SM.t;dependencies:Stateid.Set.tSM.t;}letinitial_schedule={tasks=SM.empty;dependencies=SM.empty;}letpush_executable_proof_sentenceex_sentenceblock={blockwithproof_sentences=ex_sentence::block.proof_sentences}letpush_ex_sentenceex_sentencest=matchst.proof_blockswith|[]->{stwithdocument_scope=ex_sentence.id::st.document_scope}|l::q->{stwithproof_blocks=push_executable_proof_sentenceex_sentencel::q}(* Not sure what the base_id for nested lemmas should be, e.g.
Lemma foo : X.
Proof.
Definition x := True.
intros ...
Lemma bar : Y. <- What should the base_id be for this command? -> 83
*)letbase_idst=letrecaux=function|[]->(matchst.document_scopewithhd::_->Somehd|[]->None)|block::l->beginmatchblock.proof_sentenceswith|[]->auxl|ex_sentence::_->Someex_sentence.idendinauxst.proof_blocksletopen_proof_blockex_sentencest=letst=push_ex_sentenceex_sentencestinletblock={proof_sentences=[];opener_id=ex_sentence.id}in{stwithproof_blocks=block::st.proof_blocks}letextrude_side_effectex_sentencest=letdocument_scope=ex_sentence.id::st.document_scopeinletproof_blocks=List.map(push_executable_proof_sentenceex_sentence)st.proof_blocksin{stwithdocument_scope;proof_blocks}letflatten_proof_blockst=matchst.proof_blockswith|[]->st|[block]->letdocument_scope=CList.uniquize@@List.map(funx->x.id)block.proof_sentences@st.document_scopein{stwithdocument_scope;proof_blocks=[]}|block1::block2::tl->(* Nested proofs. TODO check if we want to extrude one level or directly to document scope *)letproof_sentences=CList.uniquize@@block1.proof_sentences@block2.proof_sentencesinletblock2={block2withproof_sentences}in{stwithproof_blocks=block2::tl}(*
[1] Lemma foo : XX.
[2] Proof.
[3] Definition y := True.
[4] Lemma bar : y.
[5] Proof.
[6] exact I.
[7] Qed.
[8] apply bar.
[9] Qed.
-> We don't delegate
8: Exec(127, Qed)
2: Exec(1, Lemma foo : XX)
--> We delegate only pure proofs
*)(* FIXME handle commands with side effects followed by `Abort` *)letfind_proof_using(ast:Synterp.vernac_control_entry)=matchast.CAst.v.exprwith|VernacSynPure(VernacProof(_,Somee))->Somee|_->log(fun()->"no ast for proof using, looking at a default");Proof_using.get_default_proof_using()(* TODO: There is also a #[using] annotation on the proof opener we should
take into account (but it is not on a proof sentence, but rather
on the proof opener). Ask maxime if the attribute is processed during
synterp, and if so where its value is stored. *)letfind_proof_using_annotation{proof_sentences}=matchList.revproof_sentenceswith|ex_sentence::_->find_proof_usingex_sentence.ast|_->Noneletis_opaque_flat_proofterminatorsection_depthblock=letopenVernacextendinlethas_side_effect{classif}=matchclassifwith|VtStartProof_|VtSideff_|VtQed_|VtProofMode_|VtMeta->true|VtProofStep_|VtQuery->falseinifList.existshas_side_effectblock.proof_sentencesthenNoneelsematchterminatorwith|VtDrop->SomeVernacexpr.SsEmpty|VtKeepVtKeepDefined->None|VtKeep(VtKeepAxiom|VtKeepOpaque)->ifsection_depth=0thenSomeVernacexpr.SsEmptyelsefind_proof_using_annotationblockletpush_stateidastsynterpclassifst=letopenVernacextendinletex_sentence={id;ast;classif;synterp;error_recovery=RSkip}inmatchclassifwith|VtStartProof_->base_idst,open_proof_blockex_sentencest,Execex_sentence|VtQedterminator_type->log(fun()->"scheduling a qed");beginmatchst.proof_blockswith|[]->(* can happen on ill-formed documents *)base_idst,push_ex_sentenceex_sentencest,Execex_sentence|block::pop->(* TODO do not delegate if command with side effect inside the proof or nested lemmas *)matchis_opaque_flat_proofterminator_typest.section_depthblockwith|Someproof_using->log(fun()->"opaque proof");letterminator={ex_sentencewitherror_recovery=RAdmitted}inlettasks=List.revblock.proof_sentencesinletst={stwithproof_blocks=pop}inbase_idst,push_ex_sentenceex_sentencest,OpaqueProof{terminator;opener_id=block.opener_id;tasks;proof_using}|None->log(fun()->"not an opaque proof");letst=flatten_proof_blockstinbase_idst,push_ex_sentenceex_sentencest,Execex_sentenceend|VtQuery->(* queries have no impact, we don't push them *)base_idst,push_ex_sentenceex_sentencest,Queryex_sentence|VtProofStep_->base_idst,push_ex_sentenceex_sentencest,Execex_sentence|VtSideff_->base_idst,extrude_side_effectex_sentencest,Execex_sentence|VtMeta->base_idst,push_ex_sentenceex_sentencest,Skip{id;error=Some(Pp.str"Unsupported command")}|VtProofMode_->base_idst,push_ex_sentenceex_sentencest,Skip{id;error=Some(Pp.str"Unsupported command")}letstring_of_task(task_id,(base_id,task))=lets=matchtaskwith|Skip{id}->Format.sprintf"Skip %s"(Stateid.to_stringid)|Exec{id}->Format.sprintf"Exec %s"(Stateid.to_stringid)|OpaqueProof{terminator;tasks}->Format.sprintf"OpaqueProof [%s | %s]"(Stateid.to_stringterminator.id)(String.concat","(List.map(funtask->Stateid.to_stringtask.id)tasks))|Query{id}->Format.sprintf"Query %s"(Stateid.to_stringid)|Block{id}->Format.sprintf"Block %s"(Stateid.to_stringid)inFormat.sprintf"[%s] : [%s] -> %s"(Stateid.to_stringtask_id)(Option.cataStateid.to_string"init"base_id)slet_string_of_statest=letscopes=(List.map(funb->List.map(funx->x.id)b.proof_sentences)st.proof_blocks)@[st.document_scope]inString.concat"|"(List.map(funl->String.concat" "(List.mapStateid.to_stringl))scopes)letschedule_errored_sentenceiderrorschedule=lettask=Block{id;error}inlettasks=SM.addid(None,task)schedule.tasksinletdependencies=SM.addidStateid.Set.emptyschedule.dependenciesin{tasks;dependencies}letschedule_sentence(id,(ast,classif,synterp_st))stschedule=letbase,st,task=letopenVernacexprinlet(base,st,task)=push_stateidastsynterp_stclassifstinbeginmatchast.CAst.v.exprwith|VernacSynterp(EVernacBeginSection_)->(base,{stwithsection_depth=st.section_depth+1},task)|VernacSynterp(EVernacEndSegment_)->(base,{stwithsection_depth=max0(st.section_depth-1)},task)|_->(base,st,task)endin(*
log (fun () -> "Scheduled " ^ (Stateid.to_string id) ^ " based on " ^ (match base with Some id -> Stateid.to_string id | None -> "no state"));
log (fun () -> "New scheduler state: " ^ string_of_state st);
*)lettasks=SM.addid(base,task)schedule.tasksinletadd_depdepsxid=letupd=function|Somedeps->Some(Stateid.Set.addiddeps)|None->Some(Stateid.Set.singletonid)inSM.updatexupddepsinletdependencies=Option.cata(funx->add_depschedule.dependenciesxid)schedule.dependenciesbasein(* This new sentence impacts no sentence (yet) *)letdependencies=SM.addidStateid.Set.emptydependenciesinst,{tasks;dependencies}lettask_for_sentencescheduleid=matchSM.find_optidschedule.taskswith|Somex->x|None->CErrors.anomalyPp.(str"cannot find schedule for sentence "++Stateid.printid)letdependentsscheduleid=matchSM.find_optidschedule.dependencieswith|Somex->x|None->CErrors.anomalyPp.(str"cannot find dependents for sentence "++Stateid.printid)(** Dependency computation algo *)(*
{}
1. Definition y := ...
{{1}}
2. Lemma x : T.
{{},{1,2}}
3. Proof using v.
{{3},{1,2}}
4. tac1.
{{3,4},{1,2}}
5. Definition f := Type.
{{3,4,5},{1,2,5}}
6. Defined. || 6. Qed.
{{1,2,3,4,5,6}} || {{1,2,5,6}}
7. Check x.
*)letstring_of_scheduleschedule="Task\n"^String.concat"\n"@@List.mapstring_of_task@@SM.bindingsschedule.tasks