Skip to content

Commit

Permalink
[vernac] [stm] Tweak with_fail and hopefully fix the semantics.
Browse files Browse the repository at this point in the history
We try to do a bit of cleanup for the `with_fail` function, this still
is delicate code.
  • Loading branch information
ejgallego committed Mar 27, 2019
1 parent b42b707 commit 1786725
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 35 deletions.
8 changes: 7 additions & 1 deletion stm/stm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2064,6 +2064,12 @@ end = struct (* {{{ *)

module TaskQueue = AsyncTaskQueue.MakeQueue(TacTask) ()

let stm_fail ~st fail f =
if fail then
Vernacentries.with_fail ~st f
else
f ()

let vernac_interp ~solve ~abstract ~cancel_switch nworkers safe_id id
{ indentation; verbose; loc; expr = e; strlen } : unit
=
Expand All @@ -2075,7 +2081,7 @@ end = struct (* {{{ *)
| e -> e, time, batch, fail in
find ~time:false ~batch:false ~fail:false e in
let st = Vernacstate.freeze_interp_state ~marshallable:false in
Vernacstate.Proof_global.with_fail ~st (fun () ->
stm_fail ~st fail (fun () ->
(if time then System.with_time ~batch ~header:(Pp.mt ()) else (fun x -> x)) (fun () ->
ignore(TaskQueue.with_n_workers nworkers (fun queue ->
Vernacstate.Proof_global.with_current_proof (fun _ p ->
Expand Down
51 changes: 24 additions & 27 deletions vernac/vernacentries.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2589,41 +2589,38 @@ let test_mode = ref false

(* XXX STATE: this type hints that restoring the state should be the
caller's responsibility *)
let with_fail ~st b f =
if not b
then f ()
else begin try
(* If the command actually works, ignore its effects on the state.
let with_fail ~st f =
try
(* If the command actually works, ignore its effects on the state.
* Note that error has to be printed in the right state, hence
* within the purified function *)
try ignore (f ()); raise HasNotFailed
with
| HasNotFailed as e -> raise e
| e ->
let e = CErrors.push e in
raise (HasFailed (CErrors.iprint
(ExplainErr.process_vernac_interp_error ~allow_uncaught:false e)))
with e when CErrors.noncritical e ->
(* Restore the previous state XXX Careful here with the cache! *)
Vernacstate.invalidate_cache ();
Vernacstate.unfreeze_interp_state st;
let (e, _) = CErrors.push e in
match e with
| HasNotFailed ->
user_err ~hdr:"Fail" (str "The command has not failed!")
| HasFailed msg ->
if not !Flags.quiet || !test_mode then Feedback.msg_info
(str "The command has indeed failed with message:" ++ fnl () ++ msg);
st.Vernacstate.proof
| _ -> assert false
end
try let _ = f () in raise HasNotFailed
with
| HasNotFailed as e -> raise e
| e ->
let e = CErrors.push e in
raise (HasFailed (CErrors.iprint
(ExplainErr.process_vernac_interp_error ~allow_uncaught:false e)))
with e when CErrors.noncritical e ->
(* Restore the previous state XXX Careful here with the cache! *)
Vernacstate.invalidate_cache ();
Vernacstate.unfreeze_interp_state st;
let (e, _) = CErrors.push e in
match e with
| HasNotFailed ->
user_err ~hdr:"Fail" (str "The command has not failed!")
| HasFailed msg ->
if not !Flags.quiet || !test_mode then Feedback.msg_info
(str "The command has indeed failed with message:" ++ fnl () ++ msg)
| _ -> assert false

let interp ?(verbosely=true) ?proof ~st {CAst.loc;v=c} : Proof_global.t option =
let rec control ~st = function
| VernacExpr (atts, v) ->
aux ~atts ~st v
| VernacFail v ->
with_fail ~st true (fun () -> control ~st v)
with_fail ~st (fun () -> ignore(control ~st v));
st.Vernacstate.proof
| VernacTimeout (n,v) ->
current_timeout := Some n;
control ~st v
Expand Down
5 changes: 2 additions & 3 deletions vernac/vernacentries.mli
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ val interp :

val make_cases : string -> string list list

(* XXX STATE: this type hints that restoring the state should be the
caller's responsibility *)
val with_fail : st:Vernacstate.t -> bool -> (unit -> Proof_global.t option) -> Proof_global.t option
(** [with_fail ~st f] runs [f ()] and expects it to fail, otherwise it fails. *)
val with_fail : st:Vernacstate.t -> (unit -> 'a) -> unit

val command_focus : unit Proof.focus_kind

Expand Down
2 changes: 0 additions & 2 deletions vernac/vernacstate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ let make_shallow st =
(* Compatibility module *)
module Proof_global = struct

let with_fail ~st f = f ()

let get () = !s_proof
let set x = s_proof := x

Expand Down
2 changes: 0 additions & 2 deletions vernac/vernacstate.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ val invalidate_cache : unit -> unit
(* Compatibility module: Do Not Use *)
module Proof_global : sig

val with_fail : st:t -> (unit -> unit) -> unit

open Proof_global

(* Low-level stuff *)
Expand Down

0 comments on commit 1786725

Please sign in to comment.