(************************************************************************) (* * The Rocq Prover / The Rocq 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) *) (************************************************************************)
open Pp
let stm_pr_err s = Format.eprintf "%s] %s\n%!" (Spawned.process_id ()) s
type response =
| RespBuiltSubProof of (Constr.constr * UState.t)
| RespError ofbool * Pp.t
| RespKilled of int
| RespNoProgress
let name = "tactic" let extra_env () = [||] type competence = unit type worker_status = Fresh | Old of competence
let task_match _ _ = true
(* run by the master, on a thread *) let request_of_task age { t_state; t_ast; t_goalno; t_goal; t_name } =
Some {
r_state = if age <> Fresh then None else Some t_state;
r_ast = t_ast;
r_goalno = t_goalno;
r_goal = t_goal;
r_name = t_name }
let assign r v = let () = assert (Option.is_empty !r) in
r := Some v
let use_response _ { t_assign; t_kill } resp =
assign t_assign resp; let kill = match resp with
| RespNoProgress | RespBuiltSubProof _ -> false
| RespError _ -> true
| RespKilled _ -> assert false in if kill then t_kill ();
`Stay ((),[])
let on_task_cancellation_or_expiration_or_slave_death = function
| Some { t_goalno; t_assign; t_kill } ->
t_kill ();
assert (Option.is_empty !t_assign);
t_assign := Some (RespKilled t_goalno)
| _ -> ()
let command_focus = Proof.new_focus_kind "partac_focus" let focus_cond = Proof.no_cond command_focus
let state = ref None let receive_state = function
| None -> ()
| Some st -> state := Some st
let perform { r_state = st; r_ast = tactic; r_goal; r_goalno } =
receive_state st;
Vernacstate.unfreeze_full_state (Option.get !state); try
Vernacstate.LemmaStack.with_top (Option.get (Option.get !state).Vernacstate.interp.lemmas) ~f:(fun pstate -> let pstate =
Declare.Proof.map pstate ~f:(Proof.focus focus_cond () r_goalno) in let pstate =
ComTactic.solve ~pstate
Goal_select.SelectAll ~info:None tactic ~with_end_tac:falsein let { Proof.sigma } = Declare.Proof.fold pstate ~f:Proof.data in let EvarInfo evi = Evd.find sigma r_goal in match Evd.(evar_body evi) with
| Evd.Evar_empty -> RespNoProgress
| Evd.Evar_defined t -> let t = Evarutil.nf_evar sigma t in let evars = Evarutil.undefined_evars_of_term sigma t in if Evar.Set.is_empty evars then let t = EConstr.Unsafe.to_constr t in
RespBuiltSubProof (t, Evd.ustate sigma) else
CErrors.user_err
Pp.(str"The par: selector requires a tactic that makes no progress or fully" ++
str" solves the goal and leaves no unresolved existential variables. The following" ++
str" existentials remain unsolved: " ++ prlist (Termops.pr_existential_key (Global.env ()) sigma) (Evar.Set.elements evars))
) with e -> let noncrit = CErrors.noncritical e in
RespError (noncrit, CErrors.print e ++ spc() ++ str "(for goal "++int r_goalno ++ str ")")
let assign_tac ~abstract res : unit Proofview.tactic =
Proofview.(Goal.enter beginfun g -> let gid = Goal.goal g in matchList.assoc gid res with
| exception Not_found -> (* No progress *) tclUNIT ()
| (pt, uc) -> letopen Notations in let push_state ctx =
Proofview.tclEVARMAP >>= fun sigma ->
Proofview.Unsafe.tclEVARS (Evd.merge_universe_context sigma ctx) in
(if abstract then Abstract.tclABSTRACT None else (fun x -> x))
(push_state uc <*> Tactics.exact_no_check (EConstr.of_constr pt)) end)
let get_results res = (* If one of the goals failed others may be missing results, so we need to check for RespError before complaining about missing results. Also if there are non-RespKilled errors we prefer to
report them. *) let missing = ref [] in let killed = ref [] in let res = CList.map_filter_i (fun i (g,v) -> match !v with
| None -> missing := (succ i) :: !missing; None
| Some (RespBuiltSubProof v) -> Some (g,v)
| Some RespNoProgress -> None
| Some (RespKilled goalno) -> killed := goalno :: !killed; None
| Some (RespError (noncrt, msg)) -> if noncrt thenraise (AsyncTaskQueue.RemoteException msg) else CErrors.anomaly msg)
res in match !killed, !missing with
| [], [] -> res
| killed :: _, _ -> CErrors.anomaly Pp.(str "Worker failed (for goal " ++ int killed ++ str")")
| [], missing ->
CErrors.anomaly
(str "Missing results (for " ++
str (CString.plural (List.length missing) "goal") ++
spc () ++ prlist_with_sep spc int missing ++ str ")")
let enable_par ~spawn_args ~nworkers = ComTactic.set_par_implementation
(fun ~pstate ~info t_ast ~abstract ~with_end_tac -> let t_state = Vernacstate.freeze_full_state () in let t_state = Vernacstate.Stm.make_shallow t_state in
TaskQueue.with_n_workers ~spawn_args nworkers CoqworkmgrApi.High (fun queue ->
Declare.Proof.map pstate ~f:(fun p -> letopen TacTask in let results = (Proof.data p).Proof.goals |> CList.map_i (fun i g -> let ans = ref None in
TaskQueue.enqueue_task queue
~cancel_switch:(reffalse)
{ t_state; t_assign = ans; t_ast;
t_goalno = i; t_goal = g; t_name = Proof.goal_uid g;
t_kill = (fun () -> TaskQueue.cancel_all queue) };
g, ans) 1 in
TaskQueue.join queue; let results = get_results results in let p,_,() =
NewProfile.profile "partac.assign" (fun () ->
Proof.run_tactic (Global.env())
(assign_tac ~abstract results) p)
() in
p)))
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.