Skip to content

Commit 1888de1

Browse files
committed
A minimal working example modifying the -vok option of coqc/rocqc such that
compilation does not fail on the first error inside proof, but discards all commands to the end of that proof, which is admitted. Subsequent lemmas can then be proved, and they can raise more errors. This makes it possible to have several errors in the same file, but not in the same proof. At the end of compilation, a report is generated, indicating how many proofs failed, the name of each proof, and the error message. In the current version, no location information is provided. This version is a request for comments. One big unsatisfaction is the need to change a line in stm.ml, because we need to use a command that is usually reserved for interactive mode, while the compiler is a batch process. An alternative choice would be to execute all commands, so that there could be more than one error for each lemma and focusing information could be used to guide the recovery process, but this would require more heavyweight programming. The example file on which this has been tested is: Lemma L1 : False. Proof. exact I. fail "any failure". Qed. Lemma L2 : True. Proof. exact I. Qed. Lemma L3 : True /\ False. Proof. split. exact L2. exact L1. Qed. Lemma L4 : True /\ False. Proof. split. exact L2. exact L2. Qed. Lemma L5 : False. Proof. Admitted. Lemma L6 : False. Proof. exact L5. Qed. ==== For this file, compilation with -vok reports 2 errors. Error: proofs failed in file ./trials/toto.v, number of failures: 2 L1 The term "I" has type "True" while it is expected to have type "False". L4 The term "L2" has type "True" while it is expected to have type "False".
1 parent 215a647 commit 1888de1

File tree

5 files changed

+67
-9
lines changed

5 files changed

+67
-9
lines changed

stm/stm.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2670,7 +2670,7 @@ let query ~doc ~at ~route s =
26702670
s
26712671

26722672
let edit_at ~doc id =
2673-
assert (VCS.is_interactive());
2673+
(* assert (VCS.is_interactive()); Needed for recovery mode in coqc -vok *)
26742674
!Hooks.document_edit id;
26752675
if Stateid.equal id Stateid.dummy then anomaly(str"edit_at dummy.") else
26762676
let vcs = VCS.backup () in

toplevel/ccompile.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,13 @@ let compile opts stm_options injections copts ~echo ~f_in ~f_out =
4848
create_empty_file long_f_dot_vok in
4949
match mode with
5050
| BuildVo | BuildVok ->
51+
let recovery_mode = match mode with BuildVok -> true | _ -> false in
5152
let doc, sid = Topfmt.(in_phase ~phase:LoadingPrelude)
5253
Stm.new_doc
5354
Stm.{ doc_type = VoDoc long_f_dot_out; injections; } in
54-
let state = { doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time } in
55+
let state = { doc; sid; proof = None;
56+
time = Option.map Vernac.make_time_output opts.config.time;
57+
failed_proofs = []; in_recovery = false; recovery_mode} in
5558
let state = Load.load_init_vernaculars opts ~state in
5659
let ldir = Stm.get_ldir ~doc:state.doc in
5760
Aux_file.(start_aux_file
@@ -91,7 +94,9 @@ let compile opts stm_options injections copts ~echo ~f_in ~f_out =
9194
Stm.{ doc_type = VosDoc long_f_dot_out; injections;
9295
} in
9396

94-
let state = { doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time } in
97+
let state = { doc; sid; proof = None;
98+
time = Option.map Vernac.make_time_output opts.config.time;
99+
failed_proofs = []; in_recovery = false; recovery_mode = false } in
95100
let state = Load.load_init_vernaculars opts ~state in
96101
let ldir = Stm.get_ldir ~doc:state.doc in
97102
let source = source ldir long_f_dot_in in

toplevel/coqtop.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ let init_document opts stm_options injections =
128128
{ doc_type = Interactive opts.config.logic.toplevel_name;
129129
injections;
130130
}) in
131-
{ doc; sid; proof = None; time = Option.map Vernac.make_time_output opts.config.time }
131+
{ doc; sid; proof = None;
132+
time = Option.map Vernac.make_time_output opts.config.time;
133+
failed_proofs = [];
134+
in_recovery = false;
135+
recovery_mode = false}
132136

133137
let init_toploop opts stm_opts injections =
134138
let state = init_document opts stm_opts injections in

toplevel/vernac.ml

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ module State = struct
5757
sid : Stateid.t;
5858
proof : Proof.t option;
5959
time : time_output option;
60+
failed_proofs : (Names.Id.t * Pp.t) list;
61+
in_recovery : bool;
62+
recovery_mode : bool;
6063
}
6164

6265
end
@@ -70,28 +73,62 @@ let emit_time state com tstart tend =
7073
| ToFeedback -> Feedback.msg_notice pp
7174
| ToChannel ch -> Pp.pp_with ch (pp ++ fnl())
7275

76+
77+
let admitted_com =
78+
CAst.make { control = []; attrs = []; expr =
79+
VernacSynPure (VernacEndProof Admitted)}
80+
81+
let noop_com =
82+
CAst.make {control = []; attrs = []; expr =
83+
VernacSynPure (VernacProof (None, None))}
84+
7385
let interp_vernac ~check ~state ({CAst.loc;_} as com) =
7486
let open State in
87+
7588
try
89+
let new_recovery_status, com =
90+
if state.in_recovery then
91+
(match Vernac_classifier.classify_vernac com with
92+
Vernacextend.VtQed _ -> false, admitted_com
93+
| _ -> true, noop_com)
94+
else false, com in
95+
7696
let doc, nsid, ntip = Stm.add ~doc:state.doc ~ontop:state.sid (not !Flags.quiet) com in
7797

7898
(* Main STM interaction *)
7999
if ntip <> Stm.NewAddTip then
80100
anomaly (str "vernac.ml: We got an unfocus operation on the toplevel!");
81101

82102
(* Force the command *)
83-
let () = if check then Stm.observe ~doc nsid in
84-
let new_proof = Vernacstate.Declare.give_me_the_proof_opt () [@ocaml.warning "-3"] in
85-
{ state with doc; sid = nsid; proof = new_proof; }
103+
(try
104+
let () = if check && not new_recovery_status then
105+
Stm.observe ~doc nsid in
106+
let new_proof = Vernacstate.Declare.give_me_the_proof_opt () [@ocaml.warning "-3"] in
107+
{ state with doc; sid = nsid; proof = new_proof;
108+
in_recovery = new_recovery_status}
109+
with potentially_catched when
110+
state.recovery_mode && noncritical potentially_catched ->
111+
match state.proof with
112+
| Some prf ->
113+
(* If we want the compilation to proceed, we need the faulty error
114+
to be removed from the STM, otherwise "Admitted" will dig it
115+
out later. *)
116+
let _, _ = Stm.edit_at ~doc state.sid in
117+
let doc, nsid, ntip =
118+
Stm.add ~doc:state.doc ~ontop:state.sid
119+
(not !Flags.quiet) noop_com in
120+
{state with doc; sid = nsid; in_recovery = true;
121+
failed_proofs = ((Proof.data prf).name, print potentially_catched) ::
122+
state.failed_proofs}
123+
| None -> raise potentially_catched)
86124
with reraise ->
87125
let (reraise, info) = Exninfo.capture reraise in
88126
let info =
89127
(* Set the loc to the whole command if no loc *)
90128
match Loc.get_loc info, loc with
91129
| None, Some loc -> Loc.add_loc info loc
92130
| Some _, _ | _, None -> info
93-
in
94-
Exninfo.iraise (reraise, info)
131+
in Exninfo.iraise (reraise, info)
95132

96133
(* Load a vernac file. CErrors are annotated with file and location *)
97134
let load_vernac_core ~echo ~check ~state ?source file =
@@ -225,6 +262,15 @@ let beautify_pass ~doc ~comments ~ids ~filename =
225262
pass. *)
226263
let load_vernac ~echo ~check ~state ?source filename =
227264
let ostate, ids, comments = load_vernac_core ~echo ~check ~state ?source filename in
265+
if 1 <= List.length ostate.failed_proofs then
266+
user_err (Pp.str "proofs failed in file " ++ Pp.str filename
267+
++ str ", number of failures: "
268+
++ int (List.length ostate.failed_proofs) ++ fnl()
269+
++ (ostate.failed_proofs
270+
|> List.rev
271+
|> prlist_with_sep fnl
272+
(fun (x, y) -> Names.Id.print x ++ Pp.fnl() ++
273+
y)));
228274
(* Pass for beautify *)
229275
if !Flags.beautify then beautify_pass ~doc:ostate.State.doc ~comments ~ids:(List.rev ids) ~filename;
230276
(* End pass *)

toplevel/vernac.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ module State : sig
2020
sid : Stateid.t;
2121
proof : Proof.t option;
2222
time : time_output option;
23+
failed_proofs : (Names.Id.t * Pp.t) list;
24+
in_recovery : bool;
25+
recovery_mode : bool
2326
}
2427

2528
end

0 commit comments

Comments
 (0)