aboutsummaryrefslogtreecommitdiff
path: root/vernac
diff options
context:
space:
mode:
Diffstat (limited to 'vernac')
-rw-r--r--vernac/classes.ml73
-rw-r--r--vernac/classes.mli10
-rw-r--r--vernac/comAssumption.ml12
-rw-r--r--vernac/comAssumption.mli25
-rw-r--r--vernac/comDefinition.ml4
-rw-r--r--vernac/comDefinition.mli17
-rw-r--r--vernac/comFixpoint.ml47
-rw-r--r--vernac/comFixpoint.mli17
-rw-r--r--vernac/declareDef.ml8
-rw-r--r--vernac/declareDef.mli6
-rw-r--r--vernac/egramcoq.ml85
-rw-r--r--vernac/egramml.ml16
-rw-r--r--vernac/egramml.mli2
-rw-r--r--vernac/lemmas.ml145
-rw-r--r--vernac/lemmas.mli34
-rw-r--r--vernac/metasyntax.ml9
-rw-r--r--vernac/obligations.ml45
-rw-r--r--vernac/obligations.mli15
-rw-r--r--vernac/pvernac.ml2
-rw-r--r--vernac/record.ml2
-rw-r--r--vernac/search.ml33
-rw-r--r--vernac/search.mli12
-rw-r--r--vernac/vernacentries.ml802
-rw-r--r--vernac/vernacentries.mli8
-rw-r--r--vernac/vernacextend.ml2
-rw-r--r--vernac/vernacstate.ml84
-rw-r--r--vernac/vernacstate.mli58
27 files changed, 1023 insertions, 550 deletions
diff --git a/vernac/classes.ml b/vernac/classes.ml
index 6ce2a3f0a5..d61d324941 100644
--- a/vernac/classes.ml
+++ b/vernac/classes.ml
@@ -32,7 +32,7 @@ open Entries
let refine_instance = ref false
let () = Goptions.(declare_bool_option {
- optdepr = false;
+ optdepr = true;
optname = "definition of instances by refining";
optkey = ["Refine";"Instance";"Mode"];
optread = (fun () -> !refine_instance);
@@ -147,7 +147,7 @@ let do_declare_instance env sigma ~global ~poly k u ctx ctx' pri decl imps subst
Declare.declare_univ_binders (ConstRef cst) (Evd.universe_binders sigma);
instance_hook k pri global imps (ConstRef cst)
-let declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl ids term termtype =
+let declare_instance_open ~pstate env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl ids term termtype =
let kind = Decl_kinds.Global, poly, Decl_kinds.DefinitionBody Decl_kinds.Instance in
if program_mode then
let hook _ _ vis gr =
@@ -166,33 +166,44 @@ let declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id
in
let hook = Lemmas.mk_hook hook in
let ctx = Evd.evar_universe_context sigma in
- ignore (Obligations.add_definition id ?term:constr
- ~univdecl:decl typ ctx ~kind:(Global,poly,Instance) ~hook obls)
+ let _progress = Obligations.add_definition id ?term:constr
+ ~univdecl:decl typ ctx ~kind:(Global,poly,Instance) ~hook obls in
+ pstate
else
- Flags.silently (fun () ->
+ Some Flags.(silently (fun () ->
(* spiwack: it is hard to reorder the actions to do
the pretyping after the proof has opened. As a
consequence, we use the low-level primitives to code
the refinement manually.*)
let gls = List.rev (Evd.future_goals sigma) in
let sigma = Evd.reset_future_goals sigma in
- Lemmas.start_proof id ~pl:decl kind sigma (EConstr.of_constr termtype)
+ let pstate = Lemmas.start_proof ~ontop:pstate id ~pl:decl kind sigma (EConstr.of_constr termtype)
~hook:(Lemmas.mk_hook
- (fun _ _ _ -> instance_hook k pri global imps ?hook));
+ (fun _ _ _ -> instance_hook k pri global imps ?hook)) in
(* spiwack: I don't know what to do with the status here. *)
- if not (Option.is_empty term) then
- let init_refine =
- Tacticals.New.tclTHENLIST [
- Refine.refine ~typecheck:false (fun sigma -> (sigma,EConstr.of_constr (Option.get term)));
- Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls);
- Tactics.New.reduce_after_refine;
- ]
- in
- ignore (Pfedit.by init_refine)
- else ignore (Pfedit.by (Tactics.auto_intros_tac ids));
- (match tac with Some tac -> ignore (Pfedit.by tac) | None -> ())) ()
+ let pstate =
+ if not (Option.is_empty term) then
+ let init_refine =
+ Tacticals.New.tclTHENLIST [
+ Refine.refine ~typecheck:false (fun sigma -> (sigma,EConstr.of_constr (Option.get term)));
+ Proofview.Unsafe.tclNEWGOALS (CList.map Proofview.with_empty_state gls);
+ Tactics.New.reduce_after_refine;
+ ]
+ in
+ let pstate, _ = Pfedit.by init_refine pstate in
+ pstate
+ else
+ let pstate, _ = Pfedit.by (Tactics.auto_intros_tac ids) pstate in
+ pstate
+ in
+ match tac with
+ | Some tac ->
+ let pstate, _ = Pfedit.by tac pstate in
+ pstate
+ | None ->
+ pstate) ())
-let do_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode cty k u ctx ctx' pri decl imps subst id props =
+let do_instance ~pstate env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode cty k u ctx ctx' pri decl imps subst id props =
let props =
match props with
| Some (true, { CAst.v = CRecord fs }) ->
@@ -272,12 +283,14 @@ let do_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode ct
Pretyping.check_evars env (Evd.from_env env) sigma termtype;
let termtype = to_constr sigma termtype in
let term = Option.map (to_constr ~abort_on_undefined_evars:false sigma) term in
- if not (Evd.has_undefined sigma) && not (Option.is_empty props) then
- declare_instance_constant k pri global imps ?hook id decl poly sigma (Option.get term) termtype
- else if program_mode || refine || Option.is_empty props then
- declare_instance_open env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl (List.map RelDecl.get_name ctx) term termtype
- else CErrors.user_err Pp.(str "Unsolved obligations remaining.");
- id
+ let pstate =
+ if not (Evd.has_undefined sigma) && not (Option.is_empty props) then
+ (declare_instance_constant k pri global imps ?hook id decl poly sigma (Option.get term) termtype;
+ None)
+ else if program_mode || refine || Option.is_empty props then
+ declare_instance_open ~pstate env sigma ?hook ~tac ~program_mode ~global ~poly k id pri imps decl (List.map RelDecl.get_name ctx) term termtype
+ else CErrors.user_err Pp.(str "Unsolved obligations remaining.") in
+ id, pstate
let interp_instance_context ~program_mode env ctx ?(generalize=false) pl bk cl =
let sigma, decl = Constrexpr_ops.interp_univ_decl_opt env pl in
@@ -321,7 +334,7 @@ let interp_instance_context ~program_mode env ctx ?(generalize=false) pl bk cl =
sigma, cl, u, c', ctx', ctx, imps, args, decl
-let new_instance ?(global=false) ?(refine= !refine_instance) ~program_mode
+let new_instance ~pstate ?(global=false) ?(refine= !refine_instance) ~program_mode
poly ctx (instid, bk, cl) props
?(generalize=true) ?(tac:unit Proofview.tactic option) ?hook pri =
let env = Global.env() in
@@ -337,7 +350,7 @@ let new_instance ?(global=false) ?(refine= !refine_instance) ~program_mode
Namegen.next_global_ident_away i (Termops.vars_of_env env)
in
let env' = push_rel_context ctx env in
- do_instance env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode
+ do_instance ~pstate env env' sigma ?hook ~refine ~tac ~global ~poly ~program_mode
cty k u ctx ctx' pri decl imps subst id props
let declare_new_instance ?(global=false) ~program_mode poly ctx (instid, bk, cl) pri =
@@ -361,7 +374,7 @@ let named_of_rel_context l =
l ([], [])
in ctx
-let context poly l =
+let context ~pstate poly l =
let env = Global.env() in
let sigma = Evd.from_env env in
let sigma, (_, ((env', fullctx), impls)) = interp_context_evars ~program_mode:false env sigma l in
@@ -429,12 +442,12 @@ let context poly l =
let decl = (Discharge, poly, Definitional) in
let nstatus = match b with
| None ->
- pi3 (ComAssumption.declare_assumption false decl (t, univs) UnivNames.empty_binders [] impl
+ pi3 (ComAssumption.declare_assumption ~pstate false decl (t, univs) UnivNames.empty_binders [] impl
Declaremods.NoInline (CAst.make id))
| Some b ->
let decl = (Discharge, poly, Definition) in
let entry = Declare.definition_entry ~univs ~types:t b in
- let _ = DeclareDef.declare_definition id decl entry UnivNames.empty_binders [] in
+ let _gr = DeclareDef.declare_definition ~ontop:pstate id decl entry UnivNames.empty_binders [] in
Lib.sections_are_opened () || Lib.is_modtype_strict ()
in
status && nstatus
diff --git a/vernac/classes.mli b/vernac/classes.mli
index 7e0ec42625..73e4b024ef 100644
--- a/vernac/classes.mli
+++ b/vernac/classes.mli
@@ -40,6 +40,7 @@ val declare_instance_constant :
unit
val new_instance :
+ pstate:Proof_global.t option ->
?global:bool (** Not global by default. *) ->
?refine:bool (** Allow refinement *) ->
program_mode:bool ->
@@ -51,7 +52,8 @@ val new_instance :
?tac:unit Proofview.tactic ->
?hook:(GlobRef.t -> unit) ->
Hints.hint_info_expr ->
- Id.t
+ (* May open a proof *)
+ Id.t * Proof_global.t option
val declare_new_instance :
?global:bool (** Not global by default. *) ->
@@ -74,4 +76,8 @@ val id_of_class : typeclass -> Id.t
(** returns [false] if, for lack of section, it declares an assumption
(unless in a module type). *)
-val context : Decl_kinds.polymorphic -> local_binder_expr list -> bool
+val context
+ : pstate:Proof_global.t option
+ -> Decl_kinds.polymorphic
+ -> local_binder_expr list
+ -> bool
diff --git a/vernac/comAssumption.ml b/vernac/comAssumption.ml
index 37a33daf8f..d7bd64067b 100644
--- a/vernac/comAssumption.ml
+++ b/vernac/comAssumption.ml
@@ -42,7 +42,7 @@ let should_axiom_into_instance = function
true
| Global | Local -> !axiom_into_instance
-let declare_assumption is_coe (local,p,kind) (c,ctx) pl imps impl nl {CAst.v=ident} =
+let declare_assumption ~pstate is_coe (local,p,kind) (c,ctx) pl imps impl nl {CAst.v=ident} =
match local with
| Discharge when Lib.sections_are_opened () ->
let ctx = match ctx with
@@ -53,7 +53,7 @@ match local with
let _ = declare_variable ident decl in
let () = assumption_message ident in
let () =
- if not !Flags.quiet && Proof_global.there_are_pending_proofs () then
+ if not !Flags.quiet && Option.has_some pstate then
Feedback.msg_info Pp.(str"Variable" ++ spc () ++ Id.print ident ++
strbrk " is not visible from current goals")
in
@@ -96,11 +96,11 @@ let next_uctx =
| Polymorphic_entry _ as uctx -> uctx
| Monomorphic_entry _ -> empty_uctx
-let declare_assumptions idl is_coe k (c,uctx) pl imps nl =
+let declare_assumptions ~pstate idl is_coe k (c,uctx) pl imps nl =
let refs, status, _ =
List.fold_left (fun (refs,status,uctx) id ->
let ref',u',status' =
- declare_assumption is_coe k (c,uctx) pl imps false nl id in
+ declare_assumption ~pstate is_coe k (c,uctx) pl imps false nl id in
(ref',u')::refs, status' && status, next_uctx uctx)
([],true,uctx) idl
in
@@ -132,7 +132,7 @@ let process_assumptions_udecls kind l =
in
udecl, List.map (fun (coe, (idl, c)) -> coe, (List.map fst idl, c)) l
-let do_assumptions ~program_mode kind nl l =
+let do_assumptions ~pstate ~program_mode kind nl l =
let open Context.Named.Declaration in
let env = Global.env () in
let udecl, l = process_assumptions_udecls kind l in
@@ -173,7 +173,7 @@ let do_assumptions ~program_mode kind nl l =
let ubinders = Evd.universe_binders sigma in
pi2 (List.fold_left (fun (subst,status,uctx) ((is_coe,idl),t,imps) ->
let t = replace_vars subst t in
- let refs, status' = declare_assumptions idl is_coe kind (t,uctx) ubinders imps nl in
+ let refs, status' = declare_assumptions ~pstate idl is_coe kind (t,uctx) ubinders imps nl in
let subst' = List.map2
(fun {CAst.v=id} (c,u) -> (id, Constr.mkRef (c,u)))
idl refs
diff --git a/vernac/comAssumption.mli b/vernac/comAssumption.mli
index 2b794b001a..32914cc11b 100644
--- a/vernac/comAssumption.mli
+++ b/vernac/comAssumption.mli
@@ -17,8 +17,13 @@ open Decl_kinds
(** {6 Parameters/Assumptions} *)
-val do_assumptions : program_mode:bool -> locality * polymorphic * assumption_object_kind ->
- Declaremods.inline -> (ident_decl list * constr_expr) with_coercion list -> bool
+val do_assumptions
+ : pstate:Proof_global.t option
+ -> program_mode:bool
+ -> locality * polymorphic * assumption_object_kind
+ -> Declaremods.inline
+ -> (ident_decl list * constr_expr) with_coercion list
+ -> bool
(************************************************************************)
(** Internal API *)
@@ -28,10 +33,16 @@ val do_assumptions : program_mode:bool -> locality * polymorphic * assumption_ob
(** returns [false] if the assumption is neither local to a section,
nor in a module type and meant to be instantiated. *)
-val declare_assumption : coercion_flag -> assumption_kind ->
- types in_universes_entry ->
- UnivNames.universe_binders -> Impargs.manual_implicits ->
- bool (** implicit *) -> Declaremods.inline -> variable CAst.t ->
- GlobRef.t * Univ.Instance.t * bool
+val declare_assumption
+ : pstate:Proof_global.t option
+ -> coercion_flag
+ -> assumption_kind
+ -> types in_universes_entry
+ -> UnivNames.universe_binders
+ -> Impargs.manual_implicits
+ -> bool (** implicit *)
+ -> Declaremods.inline
+ -> variable CAst.t
+ -> GlobRef.t * Univ.Instance.t * bool
val do_primitive : lident -> CPrimitives.op_or_type -> constr_expr option -> unit
diff --git a/vernac/comDefinition.ml b/vernac/comDefinition.ml
index 28773a3965..feaf47df18 100644
--- a/vernac/comDefinition.ml
+++ b/vernac/comDefinition.ml
@@ -90,7 +90,7 @@ let check_definition ~program_mode (ce, evd, _, imps) =
check_evars_are_solved ~program_mode env evd;
ce
-let do_definition ~program_mode ?hook ident k univdecl bl red_option c ctypopt =
+let do_definition ~ontop ~program_mode ?hook ident k univdecl bl red_option c ctypopt =
let (ce, evd, univdecl, imps as def) =
interp_definition ~program_mode univdecl bl (pi2 k) red_option c ctypopt
in
@@ -114,4 +114,4 @@ let do_definition ~program_mode ?hook ident k univdecl bl red_option c ctypopt =
let ce = check_definition ~program_mode def in
let uctx = Evd.evar_universe_context evd in
let hook_data = Option.map (fun hook -> hook, uctx, []) hook in
- ignore(DeclareDef.declare_definition ident k ?hook_data ce (Evd.universe_binders evd) imps )
+ ignore(DeclareDef.declare_definition ~ontop ident k ?hook_data ce (Evd.universe_binders evd) imps)
diff --git a/vernac/comDefinition.mli b/vernac/comDefinition.mli
index 9cb6190fcc..12853d83e0 100644
--- a/vernac/comDefinition.mli
+++ b/vernac/comDefinition.mli
@@ -16,11 +16,18 @@ open Constrexpr
(** {6 Definitions/Let} *)
-val do_definition : program_mode:bool ->
- ?hook:Lemmas.declaration_hook ->
- Id.t -> definition_kind -> universe_decl_expr option ->
- local_binder_expr list -> red_expr option -> constr_expr ->
- constr_expr option -> unit
+val do_definition
+ : ontop:Proof_global.t option
+ -> program_mode:bool
+ -> ?hook:Lemmas.declaration_hook
+ -> Id.t
+ -> definition_kind
+ -> universe_decl_expr option
+ -> local_binder_expr list
+ -> red_expr option
+ -> constr_expr
+ -> constr_expr option
+ -> unit
(************************************************************************)
(** Internal API *)
diff --git a/vernac/comFixpoint.ml b/vernac/comFixpoint.ml
index 2f00b41b7c..2aadbd224f 100644
--- a/vernac/comFixpoint.ml
+++ b/vernac/comFixpoint.ml
@@ -255,7 +255,8 @@ let interp_fixpoint ~cofix l ntns =
let uctx,fix = ground_fixpoint env evd fix in
(fix,pl,uctx,info)
-let declare_fixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximps) indexes ntns =
+let declare_fixpoint ~ontop local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximps) indexes ntns =
+ let pstate =
if List.exists Option.is_empty fixdefs then
(* Some bodies to define by proof *)
let thms =
@@ -265,8 +266,9 @@ let declare_fixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximp
Some (List.map (Option.cata (EConstr.of_constr %> Tactics.exact_no_check) Tacticals.New.tclIDTAC)
fixdefs) in
let evd = Evd.from_ctx ctx in
- Lemmas.start_proof_with_initialization (local,poly,DefinitionBody Fixpoint)
- evd pl (Some(false,indexes,init_tac)) thms None
+ Some
+ (Lemmas.start_proof_with_initialization ~ontop (local,poly,DefinitionBody Fixpoint)
+ evd pl (Some(false,indexes,init_tac)) thms None)
else begin
(* We shortcut the proof process *)
let fixdefs = List.map Option.get fixdefs in
@@ -282,15 +284,18 @@ let declare_fixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximp
let ctx = Evd.check_univ_decl ~poly evd pl in
let pl = Evd.universe_binders evd in
let fixdecls = List.map Safe_typing.mk_pure_proof fixdecls in
- ignore (List.map4 (DeclareDef.declare_fix (local, poly, Fixpoint) pl ctx)
+ ignore (List.map4 (DeclareDef.declare_fix ~ontop (local, poly, Fixpoint) pl ctx)
fixnames fixdecls fixtypes fiximps);
(* Declare the recursive definitions *)
fixpoint_message (Some indexes) fixnames;
- end;
+ None
+ end in
(* Declare notations *)
- List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns
+ List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns;
+ pstate
-let declare_cofixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximps) ntns =
+let declare_cofixpoint ~ontop local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fiximps) ntns =
+ let pstate =
if List.exists Option.is_empty fixdefs then
(* Some bodies to define by proof *)
let thms =
@@ -300,8 +305,8 @@ let declare_cofixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fixi
Some (List.map (Option.cata (EConstr.of_constr %> Tactics.exact_no_check) Tacticals.New.tclIDTAC)
fixdefs) in
let evd = Evd.from_ctx ctx in
- Lemmas.start_proof_with_initialization (Global,poly, DefinitionBody CoFixpoint)
- evd pl (Some(true,[],init_tac)) thms None
+ Some (Lemmas.start_proof_with_initialization ~ontop (Global,poly, DefinitionBody CoFixpoint)
+ evd pl (Some(true,[],init_tac)) thms None)
else begin
(* We shortcut the proof process *)
let fixdefs = List.map Option.get fixdefs in
@@ -314,13 +319,15 @@ let declare_cofixpoint local poly ((fixnames,fixrs,fixdefs,fixtypes),pl,ctx,fixi
let evd = Evd.restrict_universe_context evd vars in
let ctx = Evd.check_univ_decl ~poly evd pl in
let pl = Evd.universe_binders evd in
- ignore (List.map4 (DeclareDef.declare_fix (local, poly, CoFixpoint) pl ctx)
+ ignore (List.map4 (DeclareDef.declare_fix ~ontop (local, poly, CoFixpoint) pl ctx)
fixnames fixdecls fixtypes fiximps);
(* Declare the recursive definitions *)
- cofixpoint_message fixnames
- end;
+ cofixpoint_message fixnames;
+ None
+ end in
(* Declare notations *)
- List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns
+ List.iter (Metasyntax.add_notation_interpretation (Global.env())) ntns;
+ pstate
let extract_decreasing_argument limit = function
| (na,CStructRec) -> na
@@ -348,16 +355,18 @@ let check_safe () =
let flags = Environ.typing_flags (Global.env ()) in
flags.check_universes && flags.check_guarded
-let do_fixpoint local poly l =
+let do_fixpoint ~ontop local poly l =
let fixl, ntns = extract_fixpoint_components true l in
let (_, _, _, info as fix) = interp_fixpoint ~cofix:false fixl ntns in
let possible_indexes =
List.map compute_possible_guardness_evidences info in
- declare_fixpoint local poly fix possible_indexes ntns;
- if not (check_safe ()) then Feedback.feedback Feedback.AddedAxiom else ()
+ let pstate = declare_fixpoint ~ontop local poly fix possible_indexes ntns in
+ if not (check_safe ()) then Feedback.feedback Feedback.AddedAxiom else ();
+ pstate
-let do_cofixpoint local poly l =
+let do_cofixpoint ~ontop local poly l =
let fixl,ntns = extract_cofixpoint_components l in
let cofix = interp_fixpoint ~cofix:true fixl ntns in
- declare_cofixpoint local poly cofix ntns;
- if not (check_safe ()) then Feedback.feedback Feedback.AddedAxiom else ()
+ let pstate = declare_cofixpoint ~ontop local poly cofix ntns in
+ if not (check_safe ()) then Feedback.feedback Feedback.AddedAxiom else ();
+ pstate
diff --git a/vernac/comFixpoint.mli b/vernac/comFixpoint.mli
index 9bcb53697b..15ff5f4498 100644
--- a/vernac/comFixpoint.mli
+++ b/vernac/comFixpoint.mli
@@ -19,12 +19,14 @@ open Vernacexpr
(** Entry points for the vernacular commands Fixpoint and CoFixpoint *)
val do_fixpoint :
+ ontop:Proof_global.t option ->
(* When [false], assume guarded. *)
- locality -> polymorphic -> (fixpoint_expr * decl_notation list) list -> unit
+ locality -> polymorphic -> (fixpoint_expr * decl_notation list) list -> Proof_global.t option
val do_cofixpoint :
+ ontop:Proof_global.t option ->
(* When [false], assume guarded. *)
- locality -> polymorphic -> (cofixpoint_expr * decl_notation list) list -> unit
+ locality -> polymorphic -> (cofixpoint_expr * decl_notation list) list -> Proof_global.t option
(************************************************************************)
(** Internal API *)
@@ -81,15 +83,20 @@ val interp_fixpoint :
(** [Not used so far] *)
val declare_fixpoint :
+ ontop:Proof_global.t option ->
locality -> polymorphic ->
recursive_preentry * UState.universe_decl * UState.t *
(Constr.rel_context * Impargs.manual_implicits * int option) list ->
- Proof_global.lemma_possible_guards -> decl_notation list -> unit
+ Proof_global.lemma_possible_guards -> decl_notation list ->
+ Proof_global.t option
-val declare_cofixpoint : locality -> polymorphic ->
+val declare_cofixpoint :
+ ontop:Proof_global.t option ->
+ locality -> polymorphic ->
recursive_preentry * UState.universe_decl * UState.t *
(Constr.rel_context * Impargs.manual_implicits * int option) list ->
- decl_notation list -> unit
+ decl_notation list ->
+ Proof_global.t option
(** Very private function, do not use *)
val compute_possible_guardness_evidences :
diff --git a/vernac/declareDef.ml b/vernac/declareDef.ml
index 7dcd098183..052832244b 100644
--- a/vernac/declareDef.ml
+++ b/vernac/declareDef.ml
@@ -33,12 +33,12 @@ let get_locality id ~kind = function
| Local -> true
| Global -> false
-let declare_definition ident (local, p, k) ?hook_data ce pl imps =
+let declare_definition ~ontop ident (local, p, k) ?hook_data ce pl imps =
let fix_exn = Future.fix_exn_of ce.const_entry_body in
let gr = match local with
| Discharge when Lib.sections_are_opened () ->
let _ = declare_variable ident (Lib.cwd(), SectionLocalDef ce, IsDefinition k) in
- let () = if Proof_global.there_are_pending_proofs () then warn_definition_not_visible ident in
+ let () = if Option.has_some ontop then warn_definition_not_visible ident in
VarRef ident
| Discharge | Local | Global ->
let local = get_locality ident ~kind:"definition" local in
@@ -57,9 +57,9 @@ let declare_definition ident (local, p, k) ?hook_data ce pl imps =
end;
gr
-let declare_fix ?(opaque = false) ?hook_data (_,poly,_ as kind) pl univs f ((def,_),eff) t imps =
+let declare_fix ~ontop ?(opaque = false) ?hook_data (_,poly,_ as kind) pl univs f ((def,_),eff) t imps =
let ce = definition_entry ~opaque ~types:t ~univs ~eff def in
- declare_definition f kind ?hook_data ce pl imps
+ declare_definition ~ontop f kind ?hook_data ce pl imps
let check_definition_evars ~allow_evars sigma =
let env = Global.env () in
diff --git a/vernac/declareDef.mli b/vernac/declareDef.mli
index 3f95ec7107..8e4f4bf7fb 100644
--- a/vernac/declareDef.mli
+++ b/vernac/declareDef.mli
@@ -14,7 +14,8 @@ open Decl_kinds
val get_locality : Id.t -> kind:string -> Decl_kinds.locality -> bool
val declare_definition
- : Id.t
+ : ontop:Proof_global.t option
+ -> Id.t
-> definition_kind
-> ?hook_data:(Lemmas.declaration_hook * UState.t * (Id.t * Constr.t) list)
-> Safe_typing.private_constants Entries.definition_entry
@@ -23,7 +24,8 @@ val declare_definition
-> GlobRef.t
val declare_fix
- : ?opaque:bool
+ : ontop:Proof_global.t option
+ -> ?opaque:bool
-> ?hook_data:(Lemmas.declaration_hook * UState.t * (Id.t * Constr.t) list)
-> definition_kind
-> UnivNames.universe_binders
diff --git a/vernac/egramcoq.ml b/vernac/egramcoq.ml
index 1a07d74a0e..f1a08cc9b3 100644
--- a/vernac/egramcoq.ml
+++ b/vernac/egramcoq.ml
@@ -247,10 +247,10 @@ type (_, _) entry =
| TTReference : ('self, qualid) entry
| TTBigint : ('self, Constrexpr.raw_natural_number) entry
| TTConstr : notation_entry * prod_info * 'r target -> ('r, 'r) entry
-| TTConstrList : prod_info * Tok.t list * 'r target -> ('r, 'r list) entry
+| TTConstrList : prod_info * string Tok.p list * 'r target -> ('r, 'r list) entry
| TTPattern : int -> ('self, cases_pattern_expr) entry
| TTOpenBinderList : ('self, local_binder_expr list) entry
-| TTClosedBinderList : Tok.t list -> ('self, local_binder_expr list list) entry
+| TTClosedBinderList : string Tok.p list -> ('self, local_binder_expr list list) entry
type _ any_entry = TTAny : ('s, 'r) entry -> 's any_entry
@@ -319,41 +319,49 @@ let is_binder_level from e = match e with
let make_sep_rules = function
| [tk] -> Atoken tk
| tkl ->
- let rec mkrule : Tok.t list -> string rules = function
- | [] -> Rules ({ norec_rule = Stop }, fun _ -> (* dropped anyway: *) "")
+ let rec mkrule : 'a Tok.p list -> 'a rules = function
+ | [] -> Rules (Stop, fun _ -> (* dropped anyway: *) "")
| tkn :: rem ->
- let Rules ({ norec_rule = r }, f) = mkrule rem in
- let r = { norec_rule = Next (r, Atoken tkn) } in
+ let Rules (r, f) = mkrule rem in
+ let r = NextNoRec (r, Atoken tkn) in
Rules (r, fun _ -> f)
in
let r = mkrule (List.rev tkl) in
Arules [r]
-let symbol_of_target : type s. _ -> _ -> _ -> _ -> s target -> (s, s) symbol = fun custom p assoc from forpat ->
- if custom = InConstrEntry && is_binder_level from p then Aentryl (target_entry InConstrEntry forpat, "200")
- else if is_self from p then Aself
+type ('s, 'a) mayrec_symbol =
+| MayRecNo : ('s, norec, 'a) symbol -> ('s, 'a) mayrec_symbol
+| MayRecMay : ('s, mayrec, 'a) symbol -> ('s, 'a) mayrec_symbol
+
+let symbol_of_target : type s. _ -> _ -> _ -> _ -> s target -> (s, s) mayrec_symbol = fun custom p assoc from forpat ->
+ if custom = InConstrEntry && is_binder_level from p then MayRecNo (Aentryl (target_entry InConstrEntry forpat, "200"))
+ else if is_self from p then MayRecMay Aself
else
let g = target_entry custom forpat in
let lev = adjust_level assoc from p in
begin match lev with
- | None -> Aentry g
- | Some None -> Anext
- | Some (Some (lev, cur)) -> Aentryl (g, string_of_int lev)
+ | None -> MayRecNo (Aentry g)
+ | Some None -> MayRecMay Anext
+ | Some (Some (lev, cur)) -> MayRecNo (Aentryl (g, string_of_int lev))
end
-let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) symbol = fun assoc from typ -> match typ with
+let symbol_of_entry : type s r. _ -> _ -> (s, r) entry -> (s, r) mayrec_symbol = fun assoc from typ -> match typ with
| TTConstr (s, p, forpat) -> symbol_of_target s p assoc from forpat
| TTConstrList (typ', [], forpat) ->
- Alist1 (symbol_of_target InConstrEntry typ' assoc from forpat)
+ begin match symbol_of_target InConstrEntry typ' assoc from forpat with
+ | MayRecNo s -> MayRecNo (Alist1 s)
+ | MayRecMay s -> MayRecMay (Alist1 s) end
| TTConstrList (typ', tkl, forpat) ->
- Alist1sep (symbol_of_target InConstrEntry typ' assoc from forpat, make_sep_rules tkl)
-| TTPattern p -> Aentryl (Constr.pattern, string_of_int p)
-| TTClosedBinderList [] -> Alist1 (Aentry Constr.binder)
-| TTClosedBinderList tkl -> Alist1sep (Aentry Constr.binder, make_sep_rules tkl)
-| TTName -> Aentry Prim.name
-| TTOpenBinderList -> Aentry Constr.open_binders
-| TTBigint -> Aentry Prim.bigint
-| TTReference -> Aentry Constr.global
+ begin match symbol_of_target InConstrEntry typ' assoc from forpat with
+ | MayRecNo s -> MayRecNo (Alist1sep (s, make_sep_rules tkl))
+ | MayRecMay s -> MayRecMay (Alist1sep (s, make_sep_rules tkl)) end
+| TTPattern p -> MayRecNo (Aentryl (Constr.pattern, string_of_int p))
+| TTClosedBinderList [] -> MayRecNo (Alist1 (Aentry Constr.binder))
+| TTClosedBinderList tkl -> MayRecNo (Alist1sep (Aentry Constr.binder, make_sep_rules tkl))
+| TTName -> MayRecNo (Aentry Prim.name)
+| TTOpenBinderList -> MayRecNo (Aentry Constr.open_binders)
+| TTBigint -> MayRecNo (Aentry Prim.bigint)
+| TTReference -> MayRecNo (Aentry Constr.global)
let interp_entry forpat e = match e with
| ETProdName -> TTAny TTName
@@ -406,8 +414,8 @@ match e with
| TTConstrList _ -> { subst with constrlists = v :: subst.constrlists }
type (_, _) ty_symbol =
-| TyTerm : Tok.t -> ('s, string) ty_symbol
-| TyNonTerm : 's target * ('s, 'a) entry * ('s, 'a) symbol * bool -> ('s, 'a) ty_symbol
+| TyTerm : string Tok.p -> ('s, string) ty_symbol
+| TyNonTerm : 's target * ('s, 'a) entry * ('s, 'a) mayrec_symbol * bool -> ('s, 'a) ty_symbol
type ('self, _, 'r) ty_rule =
| TyStop : ('self, 'r, 'r) ty_rule
@@ -444,11 +452,23 @@ let rec ty_eval : type s a. (s, a, Loc.t -> s) ty_rule -> s gen_eval -> s env ->
in
ty_eval rem f { env with constrs; constrlists; }
-let rec ty_erase : type s a r. (s, a, r) ty_rule -> (s, a, r) Extend.rule = function
-| TyStop -> Stop
+type ('s, 'a, 'r) mayrec_rule =
+| MayRecRNo : ('s, Extend.norec, 'a, 'r) Extend.rule -> ('s, 'a, 'r) mayrec_rule
+| MayRecRMay : ('s, Extend.mayrec, 'a, 'r) Extend.rule -> ('s, 'a, 'r) mayrec_rule
+
+let rec ty_erase : type s a r. (s, a, r) ty_rule -> (s, a, r) mayrec_rule = function
+| TyStop -> MayRecRNo Stop
| TyMark (_, _, _, r) -> ty_erase r
-| TyNext (rem, TyTerm tok) -> Next (ty_erase rem, Atoken tok)
-| TyNext (rem, TyNonTerm (_, _, s, _)) -> Next (ty_erase rem, s)
+| TyNext (rem, TyTerm tok) ->
+ begin match ty_erase rem with
+ | MayRecRNo rem -> MayRecRMay (Next (rem, Atoken tok))
+ | MayRecRMay rem -> MayRecRMay (Next (rem, Atoken tok)) end
+| TyNext (rem, TyNonTerm (_, _, s, _)) ->
+ begin match ty_erase rem, s with
+ | MayRecRNo rem, MayRecNo s -> MayRecRMay (Next (rem, s))
+ | MayRecRNo rem, MayRecMay s -> MayRecRMay (Next (rem, s))
+ | MayRecRMay rem, MayRecNo s -> MayRecRMay (Next (rem, s))
+ | MayRecRMay rem, MayRecMay s -> MayRecRMay (Next (rem, s)) end
type ('self, 'r) any_ty_rule =
| AnyTyRule : ('self, 'act, Loc.t -> 'r) ty_rule -> ('self, 'r) any_ty_rule
@@ -485,7 +505,7 @@ let rec pure_sublevels' custom assoc from forpat level = function
let rem = pure_sublevels' custom assoc from forpat level rem in
let push where p rem =
match symbol_of_target custom p assoc from forpat with
- | Aentryl (_,i) when level <> Some (int_of_string i) -> (where,int_of_string i) :: rem
+ | MayRecNo (Aentryl (_,i)) when level <> Some (int_of_string i) -> (where,int_of_string i) :: rem
| _ -> rem in
(match e with
| ETProdPattern i -> push InConstrEntry (NumLevel i,InternalProd) rem
@@ -507,7 +527,6 @@ let extend_constr state forpat ng =
let (entry, level) = interp_constr_entry_key custom forpat n in
let fold (accu, state) pt =
let AnyTyRule r = make_ty_rule assoc n forpat pt in
- let symbs = ty_erase r in
let pure_sublevels = pure_sublevels' custom assoc n forpat level pt in
let isforpat = target_to_bool forpat in
let needed_levels, state = register_empty_levels state isforpat pure_sublevels in
@@ -515,7 +534,11 @@ let extend_constr state forpat ng =
let empty_rules = List.map (prepare_empty_levels forpat) needed_levels in
let empty = { constrs = []; constrlists = []; binders = []; binderlists = [] } in
let act = ty_eval r (make_act forpat ng.notgram_notation) empty in
- let rule = (name, p4assoc, [Rule (symbs, act)]) in
+ let rule =
+ let r = match ty_erase r with
+ | MayRecRNo symbs -> Rule (symbs, act)
+ | MayRecRMay symbs -> Rule (symbs, act) in
+ name, p4assoc, [r] in
let r = ExtendRule (entry, reinit, (pos, [rule])) in
(accu @ empty_rules @ [r], state)
in
diff --git a/vernac/egramml.ml b/vernac/egramml.ml
index 89caff847f..bc58993a2e 100644
--- a/vernac/egramml.ml
+++ b/vernac/egramml.ml
@@ -19,17 +19,17 @@ open Vernacexpr
type 's grammar_prod_item =
| GramTerminal of string
| GramNonTerminal :
- ('a raw_abstract_argument_type * ('s, 'a) symbol) Loc.located -> 's grammar_prod_item
+ ('a raw_abstract_argument_type * ('s, _, 'a) symbol) Loc.located -> 's grammar_prod_item
type 'a ty_arg = ('a -> raw_generic_argument)
-type ('self, _, 'r) ty_rule =
-| TyStop : ('self, 'r, 'r) ty_rule
-| TyNext : ('self, 'a, 'r) ty_rule * ('self, 'b) Extend.symbol * 'b ty_arg option ->
- ('self, 'b -> 'a, 'r) ty_rule
+type ('self, 'tr, _, 'r) ty_rule =
+| TyStop : ('self, Extend.norec, 'r, 'r) ty_rule
+| TyNext : ('self, _, 'a, 'r) ty_rule * ('self, _, 'b) Extend.symbol * 'b ty_arg option ->
+ ('self, Extend.mayrec, 'b -> 'a, 'r) ty_rule
type ('self, 'r) any_ty_rule =
-| AnyTyRule : ('self, 'act, Loc.t -> 'r) ty_rule -> ('self, 'r) any_ty_rule
+| AnyTyRule : ('self, _, 'act, Loc.t -> 'r) ty_rule -> ('self, 'r) any_ty_rule
let rec ty_rule_of_gram = function
| [] -> AnyTyRule TyStop
@@ -44,13 +44,13 @@ let rec ty_rule_of_gram = function
let r = TyNext (rem, tok, inj) in
AnyTyRule r
-let rec ty_erase : type s a r. (s, a, r) ty_rule -> (s, a, r) Extend.rule = function
+let rec ty_erase : type s tr a r. (s, tr, a, r) ty_rule -> (s, tr, a, r) Extend.rule = function
| TyStop -> Extend.Stop
| TyNext (rem, tok, _) -> Extend.Next (ty_erase rem, tok)
type 'r gen_eval = Loc.t -> raw_generic_argument list -> 'r
-let rec ty_eval : type s a. (s, a, Loc.t -> s) ty_rule -> s gen_eval -> a = function
+let rec ty_eval : type s tr a. (s, tr, a, Loc.t -> s) ty_rule -> s gen_eval -> a = function
| TyStop -> fun f loc -> f loc []
| TyNext (rem, tok, None) -> fun f _ -> ty_eval rem f
| TyNext (rem, tok, Some inj) -> fun f x ->
diff --git a/vernac/egramml.mli b/vernac/egramml.mli
index 3689f60383..1cf75a55b1 100644
--- a/vernac/egramml.mli
+++ b/vernac/egramml.mli
@@ -18,7 +18,7 @@ open Vernacexpr
type 's grammar_prod_item =
| GramTerminal of string
| GramNonTerminal : ('a Genarg.raw_abstract_argument_type *
- ('s, 'a) Extend.symbol) Loc.located -> 's grammar_prod_item
+ ('s, _, 'a) Extend.symbol) Loc.located -> 's grammar_prod_item
val extend_vernac_command_grammar :
extend_name -> vernac_expr Pcoq.Entry.t option ->
diff --git a/vernac/lemmas.ml b/vernac/lemmas.ml
index 0d0732cbb4..1c7cc5e636 100644
--- a/vernac/lemmas.ml
+++ b/vernac/lemmas.ml
@@ -213,8 +213,11 @@ let save ?export_seff id const uctx do_guard (locality,poly,kind) hook universes
let default_thm_id = Id.of_string "Unnamed_thm"
-let fresh_name_for_anonymous_theorem () =
- let avoid = Id.Set.of_list (Proof_global.get_all_proof_names ()) in
+let fresh_name_for_anonymous_theorem ~pstate =
+ let avoid = match pstate with
+ | None -> Id.Set.empty
+ | Some pstate -> Id.Set.of_list (Proof_global.get_all_proof_names pstate)
+ in
next_global_ident_away default_thm_id avoid
let check_name_freshness locality {CAst.loc;v=id} : unit =
@@ -224,7 +227,7 @@ let check_name_freshness locality {CAst.loc;v=id} : unit =
then
user_err ?loc (Id.print id ++ str " already exists.")
-let save_remaining_recthms (locality,p,kind) norm univs body opaq i (id,(t_i,(_,imps))) =
+let save_remaining_recthms env sigma (locality,p,kind) norm univs body opaq i (id,(t_i,(_,imps))) =
let t_i = norm t_i in
let k = IsAssumption Conjectural in
match body with
@@ -260,7 +263,6 @@ let save_remaining_recthms (locality,p,kind) norm univs body opaq i (id,(t_i,(_,
| Lambda(na,ty,t) -> mkLambda(na,ty,body_i t)
| App (t, args) -> mkApp (body_i t, args)
| _ ->
- let sigma, env = Pfedit.get_current_context () in
anomaly Pp.(str "Not a proof by induction: " ++ Printer.pr_constr_env env sigma body ++ str ".") in
let body_i = body_i body in
match locality with
@@ -333,7 +335,7 @@ let initialize_named_context_for_proof () =
let d = if variable_opacity id then NamedDecl.drop_body d else d in
Environ.push_named_context_val d signv) sign Environ.empty_named_context_val
-let start_proof id ?pl kind sigma ?terminator ?sign ?(compute_guard=[]) ?(hook : declaration_hook option) c =
+let start_proof ~ontop id ?pl kind sigma ?terminator ?sign ?(compute_guard=[]) ?hook c =
let terminator = match terminator with
| None -> standard_proof_terminator ?hook compute_guard
| Some terminator -> terminator ?hook compute_guard
@@ -344,7 +346,7 @@ let start_proof id ?pl kind sigma ?terminator ?sign ?(compute_guard=[]) ?(hook :
| None -> initialize_named_context_for_proof ()
in
let goals = [ Global.env_of_context sign , c ] in
- Proof_global.start_proof sigma id ?pl kind goals terminator
+ Proof_global.start_proof ~ontop sigma id ?pl kind goals terminator
let rec_tac_initializer finite guard thms snl =
if finite then
@@ -360,7 +362,7 @@ let rec_tac_initializer finite guard thms snl =
| (id,n,_)::l -> Tactics.mutual_fix id n l 0
| _ -> assert false
-let start_proof_with_initialization ?hook kind sigma decl recguard thms snl =
+let start_proof_with_initialization ~ontop ?hook kind sigma decl recguard thms snl =
let intro_tac (_, (_, (ids, _))) = Tactics.auto_intros_tac ids in
let init_tac,guard = match recguard with
| Some (finite,guard,init_tac) ->
@@ -386,18 +388,20 @@ let start_proof_with_initialization ?hook kind sigma decl recguard thms snl =
let norm c = EConstr.to_constr (Evd.from_ctx ctx) c in
let body = Option.map EConstr.of_constr body in
let uctx = UState.check_univ_decl ~poly:(pi2 kind) ctx decl in
- List.map_i (save_remaining_recthms kind norm uctx body opaq) 1 other_thms in
+ let env = Global.env () in
+ List.map_i (save_remaining_recthms env sigma kind norm uctx body opaq) 1 other_thms in
let thms_data = (strength,ref,imps)::other_thms_data in
List.iter (fun (strength,ref,imps) ->
maybe_declare_manual_implicits false ref imps;
call_hook ?hook ctx [] strength ref) thms_data in
- start_proof id ~pl:decl kind sigma t ~hook ~compute_guard:guard;
- ignore (Proof_global.with_current_proof (fun _ p ->
+ let pstate = start_proof ~ontop id ~pl:decl kind sigma t ~hook ~compute_guard:guard in
+ let pstate, _ = Proof_global.with_current_proof (fun _ p ->
match init_tac with
| None -> p,(true,[])
- | Some tac -> Proof.run_tactic Global.(env ()) tac p))
+ | Some tac -> Proof.run_tactic Global.(env ()) tac p) pstate in
+ pstate
-let start_proof_com ~program_mode ?inference_hook ?hook kind thms =
+let start_proof_com ~program_mode ~ontop ?inference_hook ?hook kind thms =
let env0 = Global.env () in
let decl = fst (List.hd thms) in
let evd, decl = Constrexpr_ops.interp_univ_decl_opt env0 (snd decl) in
@@ -429,7 +433,7 @@ let start_proof_com ~program_mode ?inference_hook ?hook kind thms =
else (* We fix the variables to ensure they won't be lowered to Set *)
Evd.fix_undefined_variables evd
in
- start_proof_with_initialization ?hook kind evd decl recguard thms snl
+ start_proof_with_initialization ~ontop ?hook kind evd decl recguard thms snl
(* Saving a proof *)
@@ -444,58 +448,65 @@ let () =
optread = (fun () -> !keep_admitted_vars);
optwrite = (fun b -> keep_admitted_vars := b) }
-let save_proof ?proof = function
- | Vernacexpr.Admitted ->
- let pe =
- let open Proof_global in
- match proof with
- | Some ({ id; entries; persistence = k; universes }, _) ->
- if List.length entries <> 1 then
- user_err Pp.(str "Admitted does not support multiple statements");
- let { const_entry_secctx; const_entry_type } = List.hd entries in
- if const_entry_type = None then
- user_err Pp.(str "Admitted requires an explicit statement");
- let typ = Option.get const_entry_type in
- let ctx = UState.univ_entry ~poly:(pi2 k) universes in
- let sec_vars = if !keep_admitted_vars then const_entry_secctx else None in
- Admitted(id, k, (sec_vars, (typ, ctx), None), universes)
- | None ->
- let pftree = Proof_global.give_me_the_proof () in
- let gk = Proof_global.get_current_persistence () in
- let Proof.{ name; poly; entry } = Proof.data pftree in
- let typ = match Proofview.initial_goals entry with
- | [typ] -> snd typ
- | _ ->
- CErrors.anomaly
- ~label:"Lemmas.save_proof" (Pp.str "more than one statement.")
- in
- let typ = EConstr.Unsafe.to_constr typ in
- let universes = Proof.((data pftree).initial_euctx) in
- (* This will warn if the proof is complete *)
- let pproofs, _univs =
- Proof_global.return_proof ~allow_partial:true () in
- let sec_vars =
- if not !keep_admitted_vars then None
- else match Proof_global.get_used_variables(), pproofs with
- | Some _ as x, _ -> x
- | None, (pproof, _) :: _ ->
- let env = Global.env () in
- let ids_typ = Environ.global_vars_set env typ in
- let ids_def = Environ.global_vars_set env pproof in
- Some (Environ.keep_hyps env (Id.Set.union ids_typ ids_def))
- | _ -> None in
- let decl = Proof_global.get_universe_decl () in
- let ctx = UState.check_univ_decl ~poly universes decl in
- Admitted(name,gk,(sec_vars, (typ, ctx), None), universes)
- in
- Proof_global.apply_terminator (Proof_global.get_terminator ()) pe
- | Vernacexpr.Proved (opaque,idopt) ->
- let (proof_obj,terminator) =
- match proof with
- | None ->
- Proof_global.close_proof ~opaque ~keep_body_ucst_separate:false (fun x -> x)
- | Some proof -> proof
+let save_proof_admitted ?proof ~pstate =
+ let pe =
+ let open Proof_global in
+ match proof with
+ | Some ({ id; entries; persistence = k; universes }, _) ->
+ if List.length entries <> 1 then
+ user_err Pp.(str "Admitted does not support multiple statements");
+ let { const_entry_secctx; const_entry_type } = List.hd entries in
+ if const_entry_type = None then
+ user_err Pp.(str "Admitted requires an explicit statement");
+ let typ = Option.get const_entry_type in
+ let ctx = UState.univ_entry ~poly:(pi2 k) universes in
+ let sec_vars = if !keep_admitted_vars then const_entry_secctx else None in
+ Admitted(id, k, (sec_vars, (typ, ctx), None), universes)
+ | None ->
+ let pftree = Proof_global.give_me_the_proof pstate in
+ let gk = Proof_global.get_current_persistence pstate in
+ let Proof.{ name; poly; entry } = Proof.data pftree in
+ let typ = match Proofview.initial_goals entry with
+ | [typ] -> snd typ
+ | _ ->
+ CErrors.anomaly
+ ~label:"Lemmas.save_proof" (Pp.str "more than one statement.")
in
- (* if the proof is given explicitly, nothing has to be deleted *)
- if Option.is_empty proof then Proof_global.discard_current ();
- Proof_global.(apply_terminator terminator (Proved (opaque,idopt,proof_obj)))
+ let typ = EConstr.Unsafe.to_constr typ in
+ let universes = Proof.((data pftree).initial_euctx) in
+ (* This will warn if the proof is complete *)
+ let pproofs, _univs =
+ Proof_global.return_proof ~allow_partial:true pstate in
+ let sec_vars =
+ if not !keep_admitted_vars then None
+ else match Proof_global.get_used_variables pstate, pproofs with
+ | Some _ as x, _ -> x
+ | None, (pproof, _) :: _ ->
+ let env = Global.env () in
+ let ids_typ = Environ.global_vars_set env typ in
+ let ids_def = Environ.global_vars_set env pproof in
+ Some (Environ.keep_hyps env (Id.Set.union ids_typ ids_def))
+ | _ -> None in
+ let decl = Proof_global.get_universe_decl pstate in
+ let ctx = UState.check_univ_decl ~poly universes decl in
+ Admitted(name,gk,(sec_vars, (typ, ctx), None), universes)
+ in
+ Proof_global.apply_terminator (Proof_global.get_terminator pstate) pe
+
+let save_proof_proved ?proof ?pstate ~opaque ~idopt =
+ (* Invariant (uh) *)
+ if Option.is_empty pstate && Option.is_empty proof then
+ user_err (str "No focused proof (No proof-editing in progress).");
+ let (proof_obj,terminator) =
+ match proof with
+ | None ->
+ (* XXX: The close_proof and proof state API should be refactored
+ so it is possible to insert proofs properly into the state *)
+ let pstate = Option.get pstate in
+ Proof_global.close_proof ~opaque ~keep_body_ucst_separate:false (fun x -> x) pstate
+ | Some proof -> proof
+ in
+ (* if the proof is given explicitly, nothing has to be deleted *)
+ let pstate = if Option.is_empty proof then Proof_global.discard_current Option.(get pstate) else pstate in
+ Proof_global.(apply_terminator terminator (Proved (opaque,idopt,proof_obj)));
+ pstate
diff --git a/vernac/lemmas.mli b/vernac/lemmas.mli
index 72c666e903..1f70cfa1ad 100644
--- a/vernac/lemmas.mli
+++ b/vernac/lemmas.mli
@@ -37,30 +37,32 @@ val call_hook
-> ?fix_exn:Future.fix_exn
-> hook_type
-val start_proof : Id.t -> ?pl:UState.universe_decl -> goal_kind -> Evd.evar_map ->
+val start_proof : ontop:Proof_global.t option -> Id.t -> ?pl:UState.universe_decl -> goal_kind -> Evd.evar_map ->
?terminator:(?hook:declaration_hook -> Proof_global.lemma_possible_guards -> Proof_global.proof_terminator) ->
?sign:Environ.named_context_val ->
?compute_guard:Proof_global.lemma_possible_guards ->
- ?hook:declaration_hook -> EConstr.types -> unit
+ ?hook:declaration_hook -> EConstr.types -> Proof_global.t
-val start_proof_com :
- program_mode:bool -> ?inference_hook:Pretyping.inference_hook ->
- ?hook:declaration_hook -> goal_kind -> Vernacexpr.proof_expr list ->
- unit
+val start_proof_com
+ : program_mode:bool
+ -> ontop:Proof_global.t option
+ -> ?inference_hook:Pretyping.inference_hook
+ -> ?hook:declaration_hook -> goal_kind -> Vernacexpr.proof_expr list
+ -> Proof_global.t
-val start_proof_with_initialization :
+val start_proof_with_initialization : ontop:Proof_global.t option ->
?hook:declaration_hook ->
goal_kind -> Evd.evar_map -> UState.universe_decl ->
(bool * Proof_global.lemma_possible_guards * unit Proofview.tactic list option) option ->
(Id.t (* name of thm *) *
- (EConstr.types (* type of thm *) * (Name.t list (* names to pre-introduce *) * Impargs.manual_explicitation list))) list ->
- int list option -> unit
+ (EConstr.types (* type of thm *) * (Name.t list (* names to pre-introduce *) * Impargs.manual_explicitation list))) list
+ -> int list option -> Proof_global.t
val standard_proof_terminator :
?hook:declaration_hook -> Proof_global.lemma_possible_guards ->
Proof_global.proof_terminator
-val fresh_name_for_anonymous_theorem : unit -> Id.t
+val fresh_name_for_anonymous_theorem : pstate:Proof_global.t option -> Id.t
(* Prepare global named context for proof session: remove proofs of
opaque section definitions and remove vm-compiled code *)
@@ -69,4 +71,14 @@ val initialize_named_context_for_proof : unit -> Environ.named_context_val
(** {6 ... } *)
-val save_proof : ?proof:Proof_global.closed_proof -> Vernacexpr.proof_end -> unit
+val save_proof_admitted
+ : ?proof:Proof_global.closed_proof
+ -> pstate:Proof_global.t
+ -> unit
+
+val save_proof_proved
+ : ?proof:Proof_global.closed_proof
+ -> ?pstate:Proof_global.t
+ -> opaque:Proof_global.opacity_flag
+ -> idopt:Names.lident option
+ -> Proof_global.t option
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index 3da12e7714..b5e9e1b0d5 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -23,7 +23,6 @@ open Libobject
open Constrintern
open Vernacexpr
open Libnames
-open Tok
open Notation
open Nameops
@@ -575,20 +574,20 @@ let is_not_small_constr = function
| _ -> false
let rec define_keywords_aux = function
- | GramConstrNonTerminal(e,Some _) as n1 :: GramConstrTerminal(IDENT k) :: l
+ | GramConstrNonTerminal(e,Some _) as n1 :: GramConstrTerminal(Tok.PIDENT (Some k)) :: l
when is_not_small_constr e ->
Flags.if_verbose Feedback.msg_info (str "Identifier '" ++ str k ++ str "' now a keyword");
CLexer.add_keyword k;
- n1 :: GramConstrTerminal(KEYWORD k) :: define_keywords_aux l
+ n1 :: GramConstrTerminal(Tok.PKEYWORD k) :: define_keywords_aux l
| n :: l -> n :: define_keywords_aux l
| [] -> []
(* Ensure that IDENT articulation terminal symbols are keywords *)
let define_keywords = function
- | GramConstrTerminal(IDENT k)::l ->
+ | GramConstrTerminal(Tok.PIDENT (Some k))::l ->
Flags.if_verbose Feedback.msg_info (str "Identifier '" ++ str k ++ str "' now a keyword");
CLexer.add_keyword k;
- GramConstrTerminal(KEYWORD k) :: define_keywords_aux l
+ GramConstrTerminal(Tok.PKEYWORD k) :: define_keywords_aux l
| l -> define_keywords_aux l
let distribute a ll = List.map (fun l -> a @ l) ll
diff --git a/vernac/obligations.ml b/vernac/obligations.ml
index 9aca48f529..07194578c1 100644
--- a/vernac/obligations.ml
+++ b/vernac/obligations.ml
@@ -456,7 +456,7 @@ let obligation_substitution expand prg =
let ints = intset_to (pred (Array.length obls)) in
obl_substitution expand obls ints
-let declare_definition prg =
+let declare_definition ~ontop prg =
let varsubst = obligation_substitution true prg in
let body, typ = subst_prog varsubst prg in
let nf = UnivSubst.nf_evars_and_universes_opt_subst (fun x -> None)
@@ -475,7 +475,7 @@ let declare_definition prg =
let () = progmap_remove prg in
let ubinders = UState.universe_binders uctx in
let hook_data = Option.map (fun hook -> hook, uctx, obls) prg.prg_hook in
- DeclareDef.declare_definition prg.prg_name
+ DeclareDef.declare_definition ~ontop prg.prg_name
prg.prg_kind ce ubinders prg.prg_implicits ?hook_data
let rec lam_index n t acc =
@@ -554,16 +554,14 @@ let declare_mutual_definition l =
(* Declare the recursive definitions *)
let univs = UState.univ_entry ~poly first.prg_ctx in
let fix_exn = Hook.get get_fix_exn () in
- let kns = List.map4
- (DeclareDef.declare_fix ~opaque (local, poly, kind) UnivNames.empty_binders univs)
- fixnames fixdecls fixtypes fiximps
- in
- (* Declare notations *)
- List.iter (Metasyntax.add_notation_interpretation (Global.env())) first.prg_notations;
- Declare.recursive_message (fixkind != IsCoFixpoint) indexes fixnames;
- let gr = List.hd kns in
- Lemmas.call_hook ?hook:first.prg_hook ~fix_exn first.prg_ctx obls local gr;
- List.iter progmap_remove l; gr
+ let kns = List.map4 (DeclareDef.declare_fix ~ontop:None ~opaque (local, poly, kind) UnivNames.empty_binders univs)
+ fixnames fixdecls fixtypes fiximps in
+ (* Declare notations *)
+ List.iter (Metasyntax.add_notation_interpretation (Global.env())) first.prg_notations;
+ Declare.recursive_message (fixkind != IsCoFixpoint) indexes fixnames;
+ let gr = List.hd kns in
+ Lemmas.call_hook ?hook:first.prg_hook ~fix_exn first.prg_ctx obls local gr;
+ List.iter progmap_remove l; gr
let decompose_lam_prod c ty =
let open Context.Rel.Declaration in
@@ -763,7 +761,7 @@ let update_obls prg obls rem =
else (
match prg'.prg_deps with
| [] ->
- let kn = declare_definition prg' in
+ let kn = declare_definition ~ontop:None prg' in
progmap_remove prg';
Defined kn
| l ->
@@ -948,7 +946,7 @@ let obligation_hook prg obl num auto ctx' _ _ gr =
ignore (auto (Some prg.prg_name) None deps)
end
-let rec solve_obligation prg num tac =
+let rec solve_obligation ~ontop prg num tac =
let user_num = succ num in
let obls, rem = prg.prg_obligations in
let obl = obls.(num) in
@@ -967,20 +965,21 @@ let rec solve_obligation prg num tac =
let auto n tac oblset = auto_solve_obligations n ~oblset tac in
let terminator ?hook guard =
Proof_global.make_terminator
- (obligation_terminator ?hook prg.prg_name num guard auto) in
+ (obligation_terminator prg.prg_name num guard ?hook auto) in
let hook = Lemmas.mk_hook (obligation_hook prg obl num auto) in
- let () = Lemmas.start_proof ~sign:prg.prg_sign obl.obl_name kind evd (EConstr.of_constr obl.obl_type) ~terminator ~hook in
- let _ = Pfedit.by !default_tactic in
- Option.iter (fun tac -> Proof_global.set_endline_tactic tac) tac
+ let pstate = Lemmas.start_proof ~ontop ~sign:prg.prg_sign obl.obl_name kind evd (EConstr.of_constr obl.obl_type) ~terminator ~hook in
+ let pstate = fst @@ Pfedit.by !default_tactic pstate in
+ let pstate = Option.cata (fun tac -> Proof_global.set_endline_tactic tac pstate) pstate tac in
+ pstate
-and obligation (user_num, name, typ) tac =
+and obligation ~ontop (user_num, name, typ) tac =
let num = pred user_num in
let prg = get_prog_err name in
let obls, rem = prg.prg_obligations in
if num >= 0 && num < Array.length obls then
let obl = obls.(num) in
match obl.obl_body with
- None -> solve_obligation prg num tac
+ | None -> solve_obligation ~ontop prg num tac
| Some r -> error "Obligation already solved"
else error (sprintf "Unknown obligation number %i" (succ num))
@@ -1113,7 +1112,7 @@ let add_definition n ?term t ctx ?(univdecl=UState.default_univ_decl)
let obls,_ = prg.prg_obligations in
if Int.equal (Array.length obls) 0 then (
Flags.if_verbose Feedback.msg_info (info ++ str ".");
- let cst = declare_definition prg in
+ let cst = declare_definition ~ontop:None prg in
Defined cst)
else (
let len = Array.length obls in
@@ -1180,7 +1179,7 @@ let admit_obligations n =
let prg = get_prog_err n in
admit_prog prg
-let next_obligation n tac =
+let next_obligation ~ontop n tac =
let prg = match n with
| None -> get_any_prog_err ()
| Some _ -> get_prog_err n
@@ -1191,7 +1190,7 @@ let next_obligation n tac =
| Some i -> i
| None -> anomaly (Pp.str "Could not find a solvable obligation.")
in
- solve_obligation prg i tac
+ solve_obligation ~ontop prg i tac
let check_program_libraries () =
Coqlib.check_required_library Coqlib.datatypes_module_name;
diff --git a/vernac/obligations.mli b/vernac/obligations.mli
index c5720363b4..b1b7b1ec90 100644
--- a/vernac/obligations.mli
+++ b/vernac/obligations.mli
@@ -85,10 +85,17 @@ val add_mutual_definitions :
notations ->
fixpoint_kind -> unit
-val obligation : int * Names.Id.t option * Constrexpr.constr_expr option ->
- Genarg.glob_generic_argument option -> unit
-
-val next_obligation : Names.Id.t option -> Genarg.glob_generic_argument option -> unit
+val obligation
+ : ontop:Proof_global.t option
+ -> int * Names.Id.t option * Constrexpr.constr_expr option
+ -> Genarg.glob_generic_argument option
+ -> Proof_global.t
+
+val next_obligation
+ : ontop:Proof_global.t option
+ -> Names.Id.t option
+ -> Genarg.glob_generic_argument option
+ -> Proof_global.t
val solve_obligations : Names.Id.t option -> unit Proofview.tactic option -> progress
(* Number of remaining obligations to be solved for this program *)
diff --git a/vernac/pvernac.ml b/vernac/pvernac.ml
index 994fad85f0..d474ef8637 100644
--- a/vernac/pvernac.ml
+++ b/vernac/pvernac.ml
@@ -55,7 +55,7 @@ module Vernac_ =
let act_vernac v loc = Some CAst.(make ~loc v) in
let act_eoi _ loc = None in
let rule = [
- Rule (Next (Stop, Atoken Tok.EOI), act_eoi);
+ Rule (Next (Stop, Atoken Tok.PEOI), act_eoi);
Rule (Next (Stop, Aentry vernac_control), act_vernac);
] in
Pcoq.grammar_extend main_entry None (None, [None, None, rule])
diff --git a/vernac/record.ml b/vernac/record.ml
index 23274040b0..cb67548667 100644
--- a/vernac/record.ml
+++ b/vernac/record.ml
@@ -443,7 +443,7 @@ let declare_structure ~cum finite ubinders univs paramimpls params template ?(ki
let kinds,sp_projs = declare_projections rsp ctx ~kind binder_name.(i) coers fieldimpls fields in
let build = ConstructRef cstr in
let () = if is_coe then Class.try_add_new_coercion build ~local:false poly in
- let () = Recordops.declare_structure(rsp,cstr,List.rev kinds,List.rev sp_projs) in
+ let () = Recordops.declare_structure(cstr, List.rev kinds, List.rev sp_projs) in
rsp
in
List.mapi map record_data
diff --git a/vernac/search.ml b/vernac/search.ml
index 6610789626..e41378908f 100644
--- a/vernac/search.ml
+++ b/vernac/search.ml
@@ -59,11 +59,16 @@ let iter_constructors indsp u fn env nconstr =
let iter_named_context_name_type f =
List.iter (fun decl -> f (NamedDecl.get_id decl) (NamedDecl.get_type decl))
+let get_current_or_goal_context ?pstate glnum =
+ match pstate with
+ | None -> let env = Global.env () in Evd.(from_env env, env)
+ | Some p -> Pfedit.get_goal_context p glnum
+
(* General search over hypothesis of a goal *)
-let iter_hypothesis glnum (fn : GlobRef.t -> env -> constr -> unit) =
+let iter_hypothesis ?pstate glnum (fn : GlobRef.t -> env -> constr -> unit) =
let env = Global.env () in
let iter_hyp idh typ = fn (VarRef idh) env typ in
- let evmap,e = Pfedit.get_goal_context glnum in
+ let evmap,e = get_current_or_goal_context ?pstate glnum in
let pfctxt = named_context e in
iter_named_context_name_type iter_hyp pfctxt
@@ -99,10 +104,10 @@ let iter_declarations (fn : GlobRef.t -> env -> constr -> unit) =
try Declaremods.iter_all_segments iter_obj
with Not_found -> ()
-let generic_search glnumopt fn =
+let generic_search ?pstate glnumopt fn =
(match glnumopt with
| None -> ()
- | Some glnum -> iter_hypothesis glnum fn);
+ | Some glnum -> iter_hypothesis ?pstate glnum fn);
iter_declarations fn
(** This module defines a preference on constrs in the form of a
@@ -221,7 +226,7 @@ let search_about_filter query gr env typ = match query with
(** SearchPattern *)
-let search_pattern gopt pat mods pr_search =
+let search_pattern ?pstate gopt pat mods pr_search =
let blacklist_filter = blacklist_filter_aux () in
let filter ref env typ =
module_filter mods ref env typ &&
@@ -231,7 +236,7 @@ let search_pattern gopt pat mods pr_search =
let iter ref env typ =
if filter ref env typ then pr_search ref env typ
in
- generic_search gopt iter
+ generic_search ?pstate gopt iter
(** SearchRewrite *)
@@ -243,7 +248,7 @@ let rewrite_pat1 pat =
let rewrite_pat2 pat =
PApp (PRef (eq ()), [| PMeta None; PMeta None; pat |])
-let search_rewrite gopt pat mods pr_search =
+let search_rewrite ?pstate gopt pat mods pr_search =
let pat1 = rewrite_pat1 pat in
let pat2 = rewrite_pat2 pat in
let blacklist_filter = blacklist_filter_aux () in
@@ -256,11 +261,11 @@ let search_rewrite gopt pat mods pr_search =
let iter ref env typ =
if filter ref env typ then pr_search ref env typ
in
- generic_search gopt iter
+ generic_search ?pstate gopt iter
(** Search *)
-let search_by_head gopt pat mods pr_search =
+let search_by_head ?pstate gopt pat mods pr_search =
let blacklist_filter = blacklist_filter_aux () in
let filter ref env typ =
module_filter mods ref env typ &&
@@ -270,11 +275,11 @@ let search_by_head gopt pat mods pr_search =
let iter ref env typ =
if filter ref env typ then pr_search ref env typ
in
- generic_search gopt iter
+ generic_search ?pstate gopt iter
(** SearchAbout *)
-let search_about gopt items mods pr_search =
+let search_about ?pstate gopt items mods pr_search =
let blacklist_filter = blacklist_filter_aux () in
let filter ref env typ =
let eqb b1 b2 = if b1 then b2 else not b2 in
@@ -286,7 +291,7 @@ let search_about gopt items mods pr_search =
let iter ref env typ =
if filter ref env typ then pr_search ref env typ
in
- generic_search gopt iter
+ generic_search ?pstate gopt iter
type search_constraint =
| Name_Pattern of Str.regexp
@@ -301,7 +306,7 @@ type 'a coq_object = {
coq_object_object : 'a;
}
-let interface_search =
+let interface_search ?pstate =
let rec extract_flags name tpe subtpe mods blacklist = function
| [] -> (name, tpe, subtpe, mods, blacklist)
| (Name_Pattern regexp, b) :: l ->
@@ -371,7 +376,7 @@ let interface_search =
let iter ref env typ =
if filter_function ref env typ then print_function ref env typ
in
- let () = generic_search glnum iter in
+ let () = generic_search ?pstate glnum iter in
!ans
let blacklist_filter ref env typ =
diff --git a/vernac/search.mli b/vernac/search.mli
index ecbb02bc68..0f94ddc5b6 100644
--- a/vernac/search.mli
+++ b/vernac/search.mli
@@ -39,13 +39,13 @@ val search_about_filter : glob_search_about_item -> filter_function
goal and the global environment for things matching [pattern] and
satisfying module exclude/include clauses of [modinout]. *)
-val search_by_head : int option -> constr_pattern -> DirPath.t list * bool
+val search_by_head : ?pstate:Proof_global.t -> int option -> constr_pattern -> DirPath.t list * bool
-> display_function -> unit
-val search_rewrite : int option -> constr_pattern -> DirPath.t list * bool
+val search_rewrite : ?pstate:Proof_global.t -> int option -> constr_pattern -> DirPath.t list * bool
-> display_function -> unit
-val search_pattern : int option -> constr_pattern -> DirPath.t list * bool
+val search_pattern : ?pstate:Proof_global.t -> int option -> constr_pattern -> DirPath.t list * bool
-> display_function -> unit
-val search_about : int option -> (bool * glob_search_about_item) list
+val search_about : ?pstate:Proof_global.t -> int option -> (bool * glob_search_about_item) list
-> DirPath.t list * bool -> display_function -> unit
type search_constraint =
@@ -66,12 +66,12 @@ type 'a coq_object = {
coq_object_object : 'a;
}
-val interface_search : ?glnum:int -> (search_constraint * bool) list ->
+val interface_search : ?pstate:Proof_global.t -> ?glnum:int -> (search_constraint * bool) list ->
constr coq_object list
(** {6 Generic search function} *)
-val generic_search : int option -> display_function -> unit
+val generic_search : ?pstate:Proof_global.t -> int option -> display_function -> unit
(** This function iterates over all hypothesis of the goal numbered
[glnum] (if present) and all known declarations. *)
diff --git a/vernac/vernacentries.ml b/vernac/vernacentries.ml
index 4250ddb02c..d2ba882521 100644
--- a/vernac/vernacentries.ml
+++ b/vernac/vernacentries.ml
@@ -44,6 +44,28 @@ let vernac_pperr_endline pp =
(* Misc *)
+let there_are_pending_proofs ~pstate =
+ not Option.(is_empty pstate)
+
+let check_no_pending_proof ~pstate =
+ if there_are_pending_proofs ~pstate then
+ user_err Pp.(str "Command not supported (Open proofs remain)")
+
+let vernac_require_open_proof ~pstate f =
+ match pstate with
+ | Some pstate -> f ~pstate
+ | None -> user_err Pp.(str "Command not supported (No proof-editing in progress)")
+
+let get_current_or_global_context ~pstate =
+ match pstate with
+ | None -> let env = Global.env () in Evd.(from_env env, env)
+ | Some p -> Pfedit.get_current_context p
+
+let get_goal_or_global_context ~pstate glnum =
+ match pstate with
+ | None -> let env = Global.env () in Evd.(from_env env, env)
+ | Some p -> Pfedit.get_goal_context p glnum
+
let cl_of_qualid = function
| FunClass -> Classops.CL_FUN
| SortClass -> Classops.CL_SORT
@@ -72,30 +94,37 @@ end
(*******************)
(* "Show" commands *)
-let show_proof () =
+let show_proof ~pstate =
(* spiwack: this would probably be cooler with a bit of polishing. *)
- let p = Proof_global.give_me_the_proof () in
- let sigma, env = Pfedit.get_current_context () in
- let pprf = Proof.partial_proof p in
- Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf
+ try
+ let pstate = Option.get pstate in
+ let p = Proof_global.give_me_the_proof pstate in
+ let sigma, env = Pfedit.get_current_context pstate in
+ let pprf = Proof.partial_proof p in
+ Pp.prlist_with_sep Pp.fnl (Printer.pr_econstr_env env sigma) pprf
+ (* We print nothing if there are no goals left *)
+ with
+ | Pfedit.NoSuchGoal
+ | Option.IsNone ->
+ user_err (str "No goals to show.")
-let show_top_evars () =
+let show_top_evars ~pstate =
(* spiwack: new as of Feb. 2010: shows goal evars in addition to non-goal evars. *)
- let pfts = Proof_global.give_me_the_proof () in
+ let pfts = Proof_global.give_me_the_proof pstate in
let Proof.{goals;shelf;given_up;sigma} = Proof.data pfts in
pr_evars_int sigma ~shelf ~given_up 1 (Evd.undefined_map sigma)
-let show_universes () =
- let pfts = Proof_global.give_me_the_proof () in
+let show_universes ~pstate =
+ let pfts = Proof_global.give_me_the_proof pstate in
let Proof.{goals;sigma} = Proof.data pfts in
let ctx = Evd.universe_context_set (Evd.minimize_universes sigma) in
Termops.pr_evar_universe_context (Evd.evar_universe_context sigma) ++ fnl () ++
str "Normalized constraints: " ++ Univ.pr_universe_context_set (Termops.pr_evd_level sigma) ctx
(* Simulate the Intro(s) tactic *)
-let show_intro all =
+let show_intro ~pstate all =
let open EConstr in
- let pf = Proof_global.give_me_the_proof() in
+ let pf = Proof_global.give_me_the_proof pstate in
let Proof.{goals;sigma} = Proof.data pf in
if not (List.is_empty goals) then begin
let gl = {Evd.it=List.hd goals ; sigma = sigma; } in
@@ -224,7 +253,7 @@ let print_modtype qid =
with Not_found ->
user_err (str"Unknown Module Type or Module " ++ pr_qualid qid)
-let print_namespace ns =
+let print_namespace ~pstate ns =
let ns = List.rev (Names.DirPath.repr ns) in
(* [match_dirpath], [match_modulpath] are helpers for [matches]
which checks whether a constant is in the namespace [ns]. *)
@@ -272,10 +301,10 @@ let print_namespace ns =
let qn = (qualified_minus (List.length ns) mp)@[Names.Label.to_id lbl] in
print_list Id.print qn
in
- let print_constant k body =
+ let print_constant ~pstate k body =
(* FIXME: universes *)
let t = body.Declarations.const_type in
- let sigma, env = Pfedit.get_current_context () in
+ let sigma, env = get_current_or_global_context ~pstate in
print_kn k ++ str":" ++ spc() ++ Printer.pr_type_env env sigma t
in
let matches mp = match match_modulepath ns mp with
@@ -285,7 +314,7 @@ let print_namespace ns =
Environ.fold_constants (fun c body acc ->
let kn = Constant.user c in
if matches (KerName.modpath kn)
- then acc++fnl()++hov 2 (print_constant kn body)
+ then acc++fnl()++hov 2 (print_constant ~pstate kn body)
else acc)
(Global.env ()) (str"")
in
@@ -515,7 +544,7 @@ let () =
(***********)
(* Gallina *)
-let start_proof_and_print ~program_mode ?hook k l =
+let start_proof_and_print ~program_mode ~pstate ?hook k l =
let inference_hook =
if program_mode then
let hook env sigma ev =
@@ -537,7 +566,7 @@ let start_proof_and_print ~program_mode ?hook k l =
in Some hook
else None
in
- start_proof_com ~program_mode ?inference_hook ?hook k l
+ start_proof_com ~program_mode ~ontop:pstate ?inference_hook ?hook k l
let vernac_definition_hook p = function
| Coercion ->
@@ -548,7 +577,7 @@ let vernac_definition_hook p = function
Some (Class.add_subclass_hook p)
| _ -> None
-let vernac_definition ~atts discharge kind ({loc;v=id}, pl) def =
+let vernac_definition ~atts ~pstate discharge kind ({loc;v=id}, pl) def =
let open DefAttributes in
let local = enforce_locality_exp atts.locality discharge in
let hook = vernac_definition_hook atts.polymorphic kind in
@@ -563,41 +592,47 @@ let vernac_definition ~atts discharge kind ({loc;v=id}, pl) def =
let program_mode = atts.program in
let name =
match id with
- | Anonymous -> fresh_name_for_anonymous_theorem ()
+ | Anonymous -> fresh_name_for_anonymous_theorem ~pstate
| Name n -> n
in
(match def with
| ProveBody (bl,t) -> (* local binders, typ *)
- start_proof_and_print ~program_mode (local, atts.polymorphic, DefinitionBody kind)
- ?hook [(CAst.make ?loc name, pl), (bl, t)]
+ Some (start_proof_and_print ~program_mode ~pstate (local, atts.polymorphic, DefinitionBody kind)
+ ?hook [(CAst.make ?loc name, pl), (bl, t)])
| DefineBody (bl,red_option,c,typ_opt) ->
let red_option = match red_option with
- | None -> None
- | Some r ->
- let sigma, env = Pfedit.get_current_context () in
- Some (snd (Hook.get f_interp_redexp env sigma r)) in
- ComDefinition.do_definition ~program_mode name
- (local, atts.polymorphic, kind) pl bl red_option c typ_opt ?hook)
-
-let vernac_start_proof ~atts kind l =
+ | None -> None
+ | Some r ->
+ let sigma, env = get_current_or_global_context ~pstate in
+ Some (snd (Hook.get f_interp_redexp env sigma r)) in
+ ComDefinition.do_definition ~ontop:pstate ~program_mode name
+ (local, atts.polymorphic, kind) pl bl red_option c typ_opt ?hook;
+ pstate
+ )
+
+let vernac_start_proof ~atts ~pstate kind l =
let open DefAttributes in
let local = enforce_locality_exp atts.locality NoDischarge in
if Dumpglob.dump () then
List.iter (fun ((id, _), _) -> Dumpglob.dump_definition id false "prf") l;
- start_proof_and_print ~program_mode:atts.program (local, atts.polymorphic, Proof kind) l
+ Some (start_proof_and_print ~pstate ~program_mode:atts.program (local, atts.polymorphic, Proof kind) l)
-let vernac_end_proof ?proof = function
- | Admitted -> save_proof ?proof Admitted
- | Proved (_,_) as e -> save_proof ?proof e
+let vernac_end_proof ?pstate ?proof = function
+ | Admitted ->
+ vernac_require_open_proof ~pstate (save_proof_admitted ?proof);
+ pstate
+ | Proved (opaque,idopt) ->
+ save_proof_proved ?pstate ?proof ~opaque ~idopt
-let vernac_exact_proof c =
+let vernac_exact_proof ~pstate c =
(* spiwack: for simplicity I do not enforce that "Proof proof_term" is
called only at the begining of a proof. *)
- let status = Pfedit.by (Tactics.exact_proof c) in
- save_proof (Vernacexpr.(Proved(Proof_global.Opaque,None)));
- if not status then Feedback.feedback Feedback.AddedAxiom
+ let pstate, status = Pfedit.by (Tactics.exact_proof c) pstate in
+ let pstate = save_proof_proved ?proof:None ~pstate ~opaque:Proof_global.Opaque ~idopt:None in
+ if not status then Feedback.feedback Feedback.AddedAxiom;
+ pstate
-let vernac_assumption ~atts discharge kind l nl =
+let vernac_assumption ~atts ~pstate discharge kind l nl =
let open DefAttributes in
let local = enforce_locality_exp atts.locality discharge in
let global = local == Global in
@@ -607,7 +642,7 @@ let vernac_assumption ~atts discharge kind l nl =
List.iter (fun (lid, _) ->
if global then Dumpglob.dump_definition lid false "ax"
else Dumpglob.dump_definition lid true "var") idl) l;
- let status = ComAssumption.do_assumptions ~program_mode:atts.program kind nl l in
+ let status = ComAssumption.do_assumptions ~pstate ~program_mode:atts.program kind nl l in
if not status then Feedback.feedback Feedback.AddedAxiom
let is_polymorphic_inductive_cumulativity =
@@ -772,28 +807,28 @@ let vernac_inductive ~atts cum lo finite indl =
in vernac_record cum (Class true) atts.polymorphic finite [id, bl, c, None, [f]]
*)
-let vernac_fixpoint ~atts discharge l =
+let vernac_fixpoint ~atts ~pstate discharge l : Proof_global.t option =
let open DefAttributes in
let local = enforce_locality_exp atts.locality discharge in
if Dumpglob.dump () then
List.iter (fun (((lid,_), _, _, _, _), _) -> Dumpglob.dump_definition lid false "def") l;
(* XXX: Switch to the attribute system and match on ~atts *)
let do_fixpoint = if atts.program then
- ComProgramFixpoint.do_fixpoint
+ fun local sign l -> ComProgramFixpoint.do_fixpoint local sign l; None
else
- ComFixpoint.do_fixpoint
+ ComFixpoint.do_fixpoint ~ontop:pstate
in
do_fixpoint local atts.polymorphic l
-let vernac_cofixpoint ~atts discharge l =
+let vernac_cofixpoint ~atts ~pstate discharge l =
let open DefAttributes in
let local = enforce_locality_exp atts.locality discharge in
if Dumpglob.dump () then
List.iter (fun (((lid,_), _, _, _), _) -> Dumpglob.dump_definition lid false "def") l;
let do_cofixpoint = if atts.program then
- ComProgramFixpoint.do_cofixpoint
+ fun local sign l -> ComProgramFixpoint.do_cofixpoint local sign l; None
else
- ComFixpoint.do_cofixpoint
+ ComFixpoint.do_cofixpoint ~ontop:pstate
in
do_cofixpoint local atts.polymorphic l
@@ -851,14 +886,14 @@ let vernac_declare_module export {loc;v=id} binders_ast mty_ast =
Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is declared");
Option.iter (fun export -> vernac_import export [qualid_of_ident id]) export
-let vernac_define_module export {loc;v=id} (binders_ast : module_binder list) mty_ast_o mexpr_ast_l =
+let vernac_define_module ~pstate export {loc;v=id} (binders_ast : module_binder list) mty_ast_o mexpr_ast_l =
(* We check the state of the system (in section, in module type)
and what module information is supplied *)
if Lib.sections_are_opened () then
user_err Pp.(str "Modules and Module Types are not allowed inside sections.");
match mexpr_ast_l with
| [] ->
- Proof_global.check_no_pending_proof ();
+ check_no_pending_proof ~pstate;
let binders_ast,argsexport =
List.fold_right
(fun (export,idl,ty) (args,argsexport) ->
@@ -898,13 +933,13 @@ let vernac_end_module export {loc;v=id} =
Flags.if_verbose Feedback.msg_info (str "Module " ++ Id.print id ++ str " is defined");
Option.iter (fun export -> vernac_import export [qualid_of_ident ?loc id]) export
-let vernac_declare_module_type {loc;v=id} binders_ast mty_sign mty_ast_l =
+let vernac_declare_module_type ~pstate {loc;v=id} binders_ast mty_sign mty_ast_l =
if Lib.sections_are_opened () then
user_err Pp.(str "Modules and Module Types are not allowed inside sections.");
match mty_ast_l with
| [] ->
- Proof_global.check_no_pending_proof ();
+ check_no_pending_proof ~pstate;
let binders_ast,argsexport =
List.fold_right
(fun (export,idl,ty) (args,argsexport) ->
@@ -951,8 +986,8 @@ let vernac_include l =
(* Sections *)
-let vernac_begin_section ({v=id} as lid) =
- Proof_global.check_no_pending_proof ();
+let vernac_begin_section ~pstate ({v=id} as lid) =
+ check_no_pending_proof ~pstate;
Dumpglob.dump_definition lid true "sec";
Lib.open_section id
@@ -965,8 +1000,8 @@ let vernac_name_sec_hyp {v=id} set = Proof_using.name_set id set
(* Dispatcher of the "End" command *)
-let vernac_end_segment ({v=id} as lid) =
- Proof_global.check_no_pending_proof ();
+let vernac_end_segment ~pstate ({v=id} as lid) =
+ check_no_pending_proof ~pstate;
match Lib.find_opening_node id with
| Lib.OpenedModule (false,export,_,_) -> vernac_end_module export lid
| Lib.OpenedModule (true,_,_,_) -> vernac_end_modtype lid
@@ -1031,7 +1066,7 @@ let vernac_instance ~atts sup inst props pri =
let global = not (make_section_locality atts.locality) in
Dumpglob.dump_constraint (fst (pi1 inst)) false "inst";
let program_mode = atts.program in
- ignore(Classes.new_instance ~program_mode ~global atts.polymorphic sup inst props pri)
+ Classes.new_instance ~program_mode ~global atts.polymorphic sup inst props pri
let vernac_declare_instance ~atts sup inst pri =
let open DefAttributes in
@@ -1039,8 +1074,8 @@ let vernac_declare_instance ~atts sup inst pri =
Dumpglob.dump_definition (fst (pi1 inst)) false "inst";
Classes.declare_new_instance ~program_mode:atts.program ~global atts.polymorphic sup inst pri
-let vernac_context ~poly l =
- if not (Classes.context poly l) then Feedback.feedback Feedback.AddedAxiom
+let vernac_context ~pstate ~poly l =
+ if not (Classes.context ~pstate poly l) then Feedback.feedback Feedback.AddedAxiom
let vernac_existing_instance ~section_local insts =
let glob = not section_local in
@@ -1061,21 +1096,19 @@ let focus_command_cond = Proof.no_cond command_focus
there are no more goals to solve. It cannot be a tactic since
all tactics fail if there are no further goals to prove. *)
-let vernac_solve_existential = Pfedit.instantiate_nth_evar_com
+let vernac_solve_existential ~pstate i e = Pfedit.instantiate_nth_evar_com i e pstate
-let vernac_set_end_tac tac =
+let vernac_set_end_tac ~pstate tac =
let env = Genintern.empty_glob_sign (Global.env ()) in
let _, tac = Genintern.generic_intern env tac in
- if not (Proof_global.there_are_pending_proofs ()) then
- user_err Pp.(str "Unknown command of the non proof-editing mode.");
- Proof_global.set_endline_tactic tac
- (* TO DO verifier s'il faut pas mettre exist s | TacId s ici*)
+ (* TO DO verifier s'il faut pas mettre exist s | TacId s ici*)
+ Proof_global.set_endline_tactic tac pstate
-let vernac_set_used_variables e =
+let vernac_set_used_variables ~(pstate : Proof_global.t) e : Proof_global.t =
let env = Global.env () in
let initial_goals pf = Proofview.initial_goals Proof.(data pf).Proof.entry in
let tys =
- List.map snd (initial_goals (Proof_global.give_me_the_proof ())) in
+ List.map snd (initial_goals (Proof_global.give_me_the_proof pstate)) in
let tys = List.map EConstr.Unsafe.to_constr tys in
let l = Proof_using.process_expr env e tys in
let vars = Environ.named_context env in
@@ -1084,10 +1117,10 @@ let vernac_set_used_variables e =
user_err ~hdr:"vernac_set_used_variables"
(str "Unknown variable: " ++ Id.print id))
l;
- ignore (Proof_global.set_used_variables l);
- Proof_global.with_current_proof begin fun _ p ->
+ let _, pstate = Proof_global.set_used_variables pstate l in
+ fst @@ Proof_global.with_current_proof begin fun _ p ->
(p, ())
- end
+ end pstate
(*****************************)
(* Auxiliary file management *)
@@ -1132,12 +1165,10 @@ let vernac_chdir = function
(* State management *)
let vernac_write_state file =
- Proof_global.discard_all ();
let file = CUnix.make_suffix file ".coq" in
States.extern_state file
let vernac_restore_state file =
- Proof_global.discard_all ();
let file = Loadpath.locate_file (CUnix.make_suffix file ".coq") in
States.intern_state file
@@ -1730,9 +1761,14 @@ let vernac_print_option key =
try print_option_value key
with Not_found -> error_undeclared_key key
-let get_current_context_of_args = function
- | Some n -> Pfedit.get_goal_context n
- | None -> Pfedit.get_current_context ()
+let get_current_context_of_args ~pstate =
+ match pstate with
+ | None -> fun _ ->
+ let env = Global.env () in Evd.(from_env env, env)
+ | Some pstate ->
+ function
+ | Some n -> Pfedit.get_goal_context pstate n
+ | None -> Pfedit.get_current_context pstate
let query_command_selector ?loc = function
| None -> None
@@ -1740,9 +1776,9 @@ let query_command_selector ?loc = function
| _ -> user_err ?loc ~hdr:"query_command_selector"
(str "Query commands only support the single numbered goal selector.")
-let vernac_check_may_eval ~atts redexp glopt rc =
+let vernac_check_may_eval ~pstate ~atts redexp glopt rc =
let glopt = query_command_selector glopt in
- let (sigma, env) = get_current_context_of_args glopt in
+ let sigma, env = get_current_context_of_args ~pstate glopt in
let sigma, c = interp_open_constr env sigma rc in
let sigma = Evarconv.solve_unif_constraints_with_heuristics env sigma in
Evarconv.check_problems_are_solved env sigma;
@@ -1796,27 +1832,33 @@ let vernac_global_check c =
pr_universe_ctx_set sigma uctx
-let get_nth_goal n =
- let pf = Proof_global.give_me_the_proof() in
+let get_nth_goal ~pstate n =
+ let pf = Proof_global.give_me_the_proof pstate in
let Proof.{goals;sigma} = Proof.data pf in
let gl = {Evd.it=List.nth goals (n-1) ; sigma = sigma; } in
gl
exception NoHyp
+
(* Printing "About" information of a hypothesis of the current goal.
We only print the type and a small statement to this comes from the
goal. Precondition: there must be at least one current goal. *)
-let print_about_hyp_globs ?loc ref_or_by_not udecl glopt =
+let print_about_hyp_globs ~pstate ?loc ref_or_by_not udecl glopt =
let open Context.Named.Declaration in
try
+ (* Fallback early to globals *)
+ let pstate = match pstate with
+ | None -> raise Not_found
+ | Some pstate -> pstate
+ in
(* FIXME error on non None udecl if we find the hyp. *)
let glnumopt = query_command_selector ?loc glopt in
let gl,id =
match glnumopt, ref_or_by_not.v with
| None,AN qid when qualid_is_ident qid -> (* goal number not given, catch any failure *)
- (try get_nth_goal 1, qualid_basename qid with _ -> raise NoHyp)
+ (try get_nth_goal ~pstate 1, qualid_basename qid with _ -> raise NoHyp)
| Some n,AN qid when qualid_is_ident qid -> (* goal number given, catch if wong *)
- (try get_nth_goal n, qualid_basename qid
+ (try get_nth_goal ~pstate n, qualid_basename qid
with
Failure _ -> user_err ?loc ~hdr:"print_about_hyp_globs"
(str "No such goal: " ++ int n ++ str "."))
@@ -1826,15 +1868,16 @@ let print_about_hyp_globs ?loc ref_or_by_not udecl glopt =
let natureofid = match decl with
| LocalAssum _ -> "Hypothesis"
| LocalDef (_,bdy,_) ->"Constant (let in)" in
- let sigma, env = Pfedit.get_current_context () in
+ let sigma, env = Pfedit.get_current_context pstate in
v 0 (Id.print id ++ str":" ++ pr_econstr_env env sigma (NamedDecl.get_type decl) ++ fnl() ++ fnl()
++ str natureofid ++ str " of the goal context.")
with (* fallback to globals *)
| NoHyp | Not_found ->
- let sigma, env = Pfedit.get_current_context () in
+ let sigma, env = get_current_or_global_context ~pstate in
print_about env sigma ref_or_by_not udecl
-let vernac_print ~atts env sigma =
+let vernac_print ~(pstate : Proof_global.t option) ~atts =
+ let sigma, env = get_current_or_global_context ~pstate in
function
| PrintTables -> print_tables ()
| PrintFullContext-> print_full_context_typ env sigma
@@ -1845,7 +1888,7 @@ let vernac_print ~atts env sigma =
| PrintModules -> print_modules ()
| PrintModule qid -> print_module qid
| PrintModuleType qid -> print_modtype qid
- | PrintNamespace ns -> print_namespace ns
+ | PrintNamespace ns -> print_namespace ~pstate ns
| PrintMLLoadPath -> Mltop.print_ml_path ()
| PrintMLModules -> Mltop.print_ml_modules ()
| PrintDebugGC -> Mltop.print_gc ()
@@ -1862,7 +1905,13 @@ let vernac_print ~atts env sigma =
| PrintCanonicalConversions -> Prettyp.print_canonical_projections env sigma
| PrintUniverses (sort, subgraph, dst) -> print_universes ~sort ~subgraph dst
| PrintHint r -> Hints.pr_hint_ref env sigma (smart_global r)
- | PrintHintGoal -> Hints.pr_applicable_hint ()
+ | PrintHintGoal ->
+ begin match pstate with
+ | Some pstate ->
+ Hints.pr_applicable_hint pstate
+ | None ->
+ str "No proof in progress"
+ end
| PrintHintDbName s -> Hints.pr_hint_db_by_name env sigma s
| PrintHintDb -> Hints.pr_searchtable env sigma
| PrintScopes ->
@@ -1872,7 +1921,7 @@ let vernac_print ~atts env sigma =
| PrintVisibility s ->
Notation.pr_visibility (Constrextern.without_symbols (pr_lglob_constr_env env)) s
| PrintAbout (ref_or_by_not,udecl,glnumopt) ->
- print_about_hyp_globs ref_or_by_not udecl glnumopt
+ print_about_hyp_globs ~pstate ref_or_by_not udecl glnumopt
| PrintImplicit qid ->
dump_global qid;
print_impargs qid
@@ -1937,16 +1986,16 @@ let () =
optread = (fun () -> !search_output_name_only);
optwrite = (:=) search_output_name_only }
-let vernac_search ~atts s gopt r =
+let vernac_search ~pstate ~atts s gopt r =
let gopt = query_command_selector gopt in
let r = interp_search_restriction r in
let env,gopt =
match gopt with | None ->
(* 1st goal by default if it exists, otherwise no goal at all *)
- (try snd (Pfedit.get_goal_context 1) , Some 1
+ (try snd (get_goal_or_global_context ~pstate 1) , Some 1
with _ -> Global.env (),None)
(* if goal selector is given and wrong, then let exceptions be raised. *)
- | Some g -> snd (Pfedit.get_goal_context g) , Some g
+ | Some g -> snd (get_goal_or_global_context ~pstate g) , Some g
in
let get_pattern c = snd (intern_constr_pattern env Evd.(from_env env) c) in
let pr_search ref env c =
@@ -1961,21 +2010,21 @@ let vernac_search ~atts s gopt r =
in
match s with
| SearchPattern c ->
- (Search.search_pattern gopt (get_pattern c) r |> Search.prioritize_search) pr_search
+ (Search.search_pattern ?pstate gopt (get_pattern c) r |> Search.prioritize_search) pr_search
| SearchRewrite c ->
- (Search.search_rewrite gopt (get_pattern c) r |> Search.prioritize_search) pr_search
+ (Search.search_rewrite ?pstate gopt (get_pattern c) r |> Search.prioritize_search) pr_search
| SearchHead c ->
- (Search.search_by_head gopt (get_pattern c) r |> Search.prioritize_search) pr_search
+ (Search.search_by_head ?pstate gopt (get_pattern c) r |> Search.prioritize_search) pr_search
| SearchAbout sl ->
- (Search.search_about gopt (List.map (on_snd (interp_search_about_item env Evd.(from_env env))) sl) r |>
+ (Search.search_about ?pstate gopt (List.map (on_snd (interp_search_about_item env Evd.(from_env env))) sl) r |>
Search.prioritize_search) pr_search
-let vernac_locate = function
+let vernac_locate ~pstate = function
| LocateAny {v=AN qid} -> print_located_qualid qid
| LocateTerm {v=AN qid} -> print_located_term qid
| LocateAny {v=ByNotation (ntn, sc)} (* TODO : handle Ltac notations *)
| LocateTerm {v=ByNotation (ntn, sc)} ->
- let _, env = Pfedit.get_current_context () in
+ let _, env = get_current_or_global_context ~pstate in
Notation.locate_notation
(Constrextern.without_symbols (pr_lglob_constr_env env)) ntn sc
| LocateLibrary qid -> print_located_library qid
@@ -1983,9 +2032,9 @@ let vernac_locate = function
| LocateOther (s, qid) -> print_located_other s qid
| LocateFile f -> locate_file f
-let vernac_register qid r =
+let vernac_register ~pstate qid r =
let gr = Smartlocate.global_with_alias qid in
- if Proof_global.there_are_pending_proofs () then
+ if there_are_pending_proofs ~pstate then
user_err Pp.(str "Cannot register a primitive while in proof editing mode.");
match r with
| RegisterInline ->
@@ -2029,8 +2078,8 @@ let vernac_unfocus () =
(fun _ p -> Proof.unfocus command_focus p ())
(* Checks that a proof is fully unfocused. Raises an error if not. *)
-let vernac_unfocused () =
- let p = Proof_global.give_me_the_proof () in
+let vernac_unfocused ~pstate =
+ let p = Proof_global.give_me_the_proof pstate in
if Proof.unfocused p then
str"The proof is indeed fully unfocused."
else
@@ -2060,25 +2109,39 @@ let vernac_bullet (bullet : Proof_bullet.t) =
Proof_global.simple_with_current_proof (fun _ p ->
Proof_bullet.put p bullet)
-let vernac_show = function
- | ShowScript -> assert false (* Only the stm knows the script *)
- | ShowGoal goalref ->
- let proof = Proof_global.give_me_the_proof () in
- begin match goalref with
- | OpenSubgoals -> pr_open_subgoals ~proof
- | NthGoal n -> pr_nth_open_subgoal ~proof n
- | GoalId id -> pr_goal_by_id ~proof id
+let vernac_show ~pstate =
+ match pstate with
+ (* Show functions that don't require a proof state *)
+ | None ->
+ begin function
+ | ShowProof -> show_proof ~pstate
+ | ShowMatch id -> show_match id
+ | ShowScript -> assert false (* Only the stm knows the script *)
+ | _ ->
+ user_err (str "This command requires an open proof.")
end
- | ShowProof -> show_proof ()
- | ShowExistentials -> show_top_evars ()
- | ShowUniverses -> show_universes ()
- | ShowProofNames ->
- pr_sequence Id.print (Proof_global.get_all_proof_names())
- | ShowIntros all -> show_intro all
- | ShowMatch id -> show_match id
-
-let vernac_check_guard () =
- let pts = Proof_global.give_me_the_proof () in
+ (* Show functions that require a proof state *)
+ | Some pstate ->
+ begin function
+ | ShowGoal goalref ->
+ let proof = Proof_global.give_me_the_proof pstate in
+ begin match goalref with
+ | OpenSubgoals -> pr_open_subgoals ~proof
+ | NthGoal n -> pr_nth_open_subgoal ~proof n
+ | GoalId id -> pr_goal_by_id ~proof id
+ end
+ | ShowExistentials -> show_top_evars ~pstate
+ | ShowUniverses -> show_universes ~pstate
+ | ShowProofNames ->
+ pr_sequence Id.print (Proof_global.get_all_proof_names pstate)
+ | ShowIntros all -> show_intro ~pstate all
+ | ShowProof -> show_proof ~pstate:(Some pstate)
+ | ShowMatch id -> show_match id
+ | ShowScript -> assert false (* Only the stm knows the script *)
+ end
+
+let vernac_check_guard ~pstate =
+ let pts = Proof_global.give_me_the_proof pstate in
let pfterm = List.hd (Proof.partial_proof pts) in
let message =
try
@@ -2097,8 +2160,9 @@ exception End_of_input
the way the proof mode is set there makes the task non trivial
without a considerable amount of refactoring.
*)
-let vernac_load interp fname =
- if Proof_global.there_are_pending_proofs () then
+let vernac_load ~st interp fname =
+ let pstate = st.Vernacstate.proof in
+ if there_are_pending_proofs ~pstate then
CErrors.user_err Pp.(str "Load is not supported inside proofs.");
let parse_sentence proof_mode = Flags.with_option Flags.we_are_parsing
(fun po ->
@@ -2111,22 +2175,22 @@ let vernac_load interp fname =
let input =
let longfname = Loadpath.locate_file fname in
let in_chan = open_utf8_file_in longfname in
- Pcoq.Parsable.make ~file:(Loc.InFile longfname) (Stream.of_channel in_chan) in
- begin
- try while true do
- let proof_mode =
- if Proof_global.there_are_pending_proofs () then
- Some (get_default_proof_mode ())
- else
- None
- in
- interp (parse_sentence proof_mode input).CAst.v;
- done
- with End_of_input -> ()
- end;
+ Pcoq.Parsable.make ~loc:(Loc.initial (Loc.InFile longfname)) (Stream.of_channel in_chan) in
+ let rec load_loop ~pstate =
+ try
+ let proof_mode = Option.map (fun _ -> get_default_proof_mode ()) pstate in
+ let pstate = interp ~st:{ st with Vernacstate.proof = pstate }
+ (parse_sentence proof_mode input).CAst.v in
+ load_loop ~pstate
+ with
+ End_of_input ->
+ pstate
+ in
+ let pstate = load_loop ~pstate in
(* If Load left a proof open, we fail too. *)
- if Proof_global.there_are_pending_proofs () then
- CErrors.user_err Pp.(str "Files processed by Load cannot leave open proofs.")
+ if there_are_pending_proofs ~pstate then
+ CErrors.user_err Pp.(str "Files processed by Load cannot leave open proofs.");
+ pstate
let with_locality ~atts f =
let local = Attributes.(parse locality atts) in
@@ -2151,7 +2215,8 @@ let with_def_attributes ~atts f =
* is the outdated/deprecated "Local" attribute of some vernacular commands
* still parsed as the obsolete_locality grammar entry for retrocompatibility.
* loc is the Loc.t of the vernacular command being interpreted. *)
-let interp ?proof ~atts ~st c =
+let interp ?proof ~atts ~st c : Proof_global.t option =
+ let pstate = st.Vernacstate.proof in
vernac_pperr_endline (fun () -> str "interpreting: " ++ Ppvernac.pr_vernac_expr c);
match c with
@@ -2175,145 +2240,309 @@ let interp ?proof ~atts ~st c =
(* Syntax *)
| VernacSyntaxExtension (infix, sl) ->
- with_module_locality ~atts vernac_syntax_extension infix sl
- | VernacDeclareScope sc -> with_module_locality ~atts vernac_declare_scope sc
- | VernacDelimiters (sc,lr) -> with_module_locality ~atts vernac_delimiters sc lr
- | VernacBindScope (sc,rl) -> with_module_locality ~atts vernac_bind_scope sc rl
- | VernacOpenCloseScope (b, s) -> with_section_locality ~atts vernac_open_close_scope (b,s)
- | VernacInfix (mv,qid,sc) -> with_module_locality ~atts vernac_infix mv qid sc
- | VernacNotation (c,infpl,sc) -> with_module_locality ~atts vernac_notation c infpl sc
+ with_module_locality ~atts vernac_syntax_extension infix sl;
+ pstate
+ | VernacDeclareScope sc ->
+ with_module_locality ~atts vernac_declare_scope sc;
+ pstate
+ | VernacDelimiters (sc,lr) ->
+ with_module_locality ~atts vernac_delimiters sc lr;
+ pstate
+ | VernacBindScope (sc,rl) ->
+ with_module_locality ~atts vernac_bind_scope sc rl;
+ pstate
+ | VernacOpenCloseScope (b, s) ->
+ with_section_locality ~atts vernac_open_close_scope (b,s);
+ pstate
+ | VernacInfix (mv,qid,sc) ->
+ with_module_locality ~atts vernac_infix mv qid sc;
+ pstate
+ | VernacNotation (c,infpl,sc) ->
+ with_module_locality ~atts vernac_notation c infpl sc;
+ pstate
| VernacNotationAddFormat(n,k,v) ->
unsupported_attributes atts;
- Metasyntax.add_notation_extra_printing_rule n k v
+ Metasyntax.add_notation_extra_printing_rule n k v;
+ pstate
| VernacDeclareCustomEntry s ->
- with_module_locality ~atts vernac_custom_entry s
+ with_module_locality ~atts vernac_custom_entry s;
+ pstate
(* Gallina *)
| VernacDefinition ((discharge,kind),lid,d) ->
- with_def_attributes ~atts vernac_definition discharge kind lid d
- | VernacStartTheoremProof (k,l) -> with_def_attributes vernac_start_proof ~atts k l
- | VernacEndProof e -> unsupported_attributes atts; vernac_end_proof ?proof e
- | VernacExactProof c -> unsupported_attributes atts; vernac_exact_proof c
+ with_def_attributes ~atts vernac_definition ~pstate discharge kind lid d
+ | VernacStartTheoremProof (k,l) ->
+ with_def_attributes ~atts vernac_start_proof ~pstate k l
+ | VernacEndProof e ->
+ unsupported_attributes atts;
+ vernac_end_proof ?proof ?pstate e
+ | VernacExactProof c ->
+ unsupported_attributes atts;
+ vernac_require_open_proof ~pstate (vernac_exact_proof c)
| VernacAssumption ((discharge,kind),nl,l) ->
- with_def_attributes vernac_assumption ~atts discharge kind l nl
- | VernacInductive (cum, priv, finite, l) -> vernac_inductive ~atts cum priv finite l
- | VernacFixpoint (discharge, l) -> with_def_attributes vernac_fixpoint ~atts discharge l
- | VernacCoFixpoint (discharge, l) -> with_def_attributes vernac_cofixpoint ~atts discharge l
- | VernacScheme l -> unsupported_attributes atts; vernac_scheme l
- | VernacCombinedScheme (id, l) -> unsupported_attributes atts; vernac_combined_scheme id l
- | VernacUniverse l -> vernac_universe ~poly:(only_polymorphism atts) l
- | VernacConstraint l -> vernac_constraint ~poly:(only_polymorphism atts) l
+ with_def_attributes ~atts vernac_assumption ~pstate discharge kind l nl;
+ pstate
+ | VernacInductive (cum, priv, finite, l) ->
+ vernac_inductive ~atts cum priv finite l;
+ pstate
+ | VernacFixpoint (discharge, l) ->
+ with_def_attributes ~atts vernac_fixpoint ~pstate discharge l
+ | VernacCoFixpoint (discharge, l) ->
+ with_def_attributes ~atts vernac_cofixpoint ~pstate discharge l
+ | VernacScheme l ->
+ unsupported_attributes atts;
+ vernac_scheme l;
+ pstate
+ | VernacCombinedScheme (id, l) ->
+ unsupported_attributes atts;
+ vernac_combined_scheme id l;
+ pstate
+ | VernacUniverse l ->
+ vernac_universe ~poly:(only_polymorphism atts) l;
+ pstate
+ | VernacConstraint l ->
+ vernac_constraint ~poly:(only_polymorphism atts) l;
+ pstate
(* Modules *)
| VernacDeclareModule (export,lid,bl,mtyo) ->
- unsupported_attributes atts; vernac_declare_module export lid bl mtyo
+ unsupported_attributes atts;
+ vernac_declare_module export lid bl mtyo;
+ pstate
| VernacDefineModule (export,lid,bl,mtys,mexprl) ->
- unsupported_attributes atts; vernac_define_module export lid bl mtys mexprl
+ unsupported_attributes atts;
+ vernac_define_module ~pstate export lid bl mtys mexprl;
+ pstate
| VernacDeclareModuleType (lid,bl,mtys,mtyo) ->
- unsupported_attributes atts; vernac_declare_module_type lid bl mtys mtyo
+ unsupported_attributes atts;
+ vernac_declare_module_type ~pstate lid bl mtys mtyo;
+ pstate
| VernacInclude in_asts ->
- unsupported_attributes atts; vernac_include in_asts
+ unsupported_attributes atts;
+ vernac_include in_asts;
+ pstate
(* Gallina extensions *)
- | VernacBeginSection lid -> unsupported_attributes atts; vernac_begin_section lid
+ | VernacBeginSection lid ->
+ unsupported_attributes atts;
+ vernac_begin_section ~pstate lid;
+ pstate
- | VernacEndSegment lid -> unsupported_attributes atts; vernac_end_segment lid
+ | VernacEndSegment lid ->
+ unsupported_attributes atts;
+ vernac_end_segment ~pstate lid;
+ pstate
- | VernacNameSectionHypSet (lid, set) -> unsupported_attributes atts; vernac_name_sec_hyp lid set
+ | VernacNameSectionHypSet (lid, set) ->
+ unsupported_attributes atts;
+ vernac_name_sec_hyp lid set;
+ pstate
- | VernacRequire (from, export, qidl) -> unsupported_attributes atts; vernac_require from export qidl
- | VernacImport (export,qidl) -> unsupported_attributes atts; vernac_import export qidl
- | VernacCanonical qid -> unsupported_attributes atts; vernac_canonical qid
- | VernacCoercion (r,s,t) -> vernac_coercion ~atts r s t
+ | VernacRequire (from, export, qidl) ->
+ unsupported_attributes atts;
+ vernac_require from export qidl;
+ pstate
+ | VernacImport (export,qidl) ->
+ unsupported_attributes atts;
+ vernac_import export qidl;
+ pstate
+ | VernacCanonical qid ->
+ unsupported_attributes atts;
+ vernac_canonical qid;
+ pstate
+ | VernacCoercion (r,s,t) ->
+ vernac_coercion ~atts r s t;
+ pstate
| VernacIdentityCoercion ({v=id},s,t) ->
- vernac_identity_coercion ~atts id s t
+ vernac_identity_coercion ~atts id s t;
+ pstate
(* Type classes *)
| VernacInstance (sup, inst, props, info) ->
- with_def_attributes vernac_instance ~atts sup inst props info
+ snd @@ with_def_attributes ~atts (vernac_instance ~pstate sup inst props info)
| VernacDeclareInstance (sup, inst, info) ->
- with_def_attributes vernac_declare_instance ~atts sup inst info
- | VernacContext sup -> vernac_context ~poly:(only_polymorphism atts) sup
- | VernacExistingInstance insts -> with_section_locality ~atts vernac_existing_instance insts
- | VernacExistingClass id -> unsupported_attributes atts; vernac_existing_class id
+ with_def_attributes ~atts vernac_declare_instance sup inst info;
+ pstate
+ | VernacContext sup ->
+ let () = vernac_context ~pstate ~poly:(only_polymorphism atts) sup in
+ pstate
+ | VernacExistingInstance insts ->
+ with_section_locality ~atts vernac_existing_instance insts;
+ pstate
+ | VernacExistingClass id ->
+ unsupported_attributes atts;
+ vernac_existing_class id;
+ pstate
(* Solving *)
- | VernacSolveExistential (n,c) -> unsupported_attributes atts; vernac_solve_existential n c
+ | VernacSolveExistential (n,c) ->
+ unsupported_attributes atts;
+ Some (vernac_require_open_proof ~pstate (vernac_solve_existential n c))
(* Auxiliary file and library management *)
- | VernacAddLoadPath (isrec,s,alias) -> unsupported_attributes atts; vernac_add_loadpath isrec s alias
- | VernacRemoveLoadPath s -> unsupported_attributes atts; vernac_remove_loadpath s
- | VernacAddMLPath (isrec,s) -> unsupported_attributes atts; vernac_add_ml_path isrec s
- | VernacDeclareMLModule l -> with_locality ~atts vernac_declare_ml_module l
- | VernacChdir s -> unsupported_attributes atts; vernac_chdir s
+ | VernacAddLoadPath (isrec,s,alias) ->
+ unsupported_attributes atts;
+ vernac_add_loadpath isrec s alias;
+ pstate
+ | VernacRemoveLoadPath s ->
+ unsupported_attributes atts;
+ vernac_remove_loadpath s;
+ pstate
+ | VernacAddMLPath (isrec,s) ->
+ unsupported_attributes atts;
+ vernac_add_ml_path isrec s;
+ pstate
+ | VernacDeclareMLModule l ->
+ with_locality ~atts vernac_declare_ml_module l;
+ pstate
+ | VernacChdir s ->
+ unsupported_attributes atts;
+ vernac_chdir s;
+ pstate
(* State management *)
- | VernacWriteState s -> unsupported_attributes atts; vernac_write_state s
- | VernacRestoreState s -> unsupported_attributes atts; vernac_restore_state s
+ | VernacWriteState s ->
+ unsupported_attributes atts;
+ vernac_write_state s;
+ pstate
+ | VernacRestoreState s ->
+ unsupported_attributes atts;
+ vernac_restore_state s;
+ pstate
(* Commands *)
| VernacCreateHintDb (dbname,b) ->
- with_module_locality ~atts vernac_create_hintdb dbname b
+ with_module_locality ~atts vernac_create_hintdb dbname b;
+ pstate
| VernacRemoveHints (dbnames,ids) ->
- with_module_locality ~atts vernac_remove_hints dbnames ids
+ with_module_locality ~atts vernac_remove_hints dbnames ids;
+ pstate
| VernacHints (dbnames,hints) ->
- vernac_hints ~atts dbnames hints
+ vernac_hints ~atts dbnames hints;
+ pstate
| VernacSyntacticDefinition (id,c,b) ->
- with_module_locality ~atts vernac_syntactic_definition id c b
+ with_module_locality ~atts vernac_syntactic_definition id c b;
+ pstate
| VernacArguments (qid, args, more_implicits, nargs, flags) ->
- with_section_locality ~atts vernac_arguments qid args more_implicits nargs flags
- | VernacReserve bl -> unsupported_attributes atts; vernac_reserve bl
- | VernacGeneralizable gen -> with_locality ~atts vernac_generalizable gen
- | VernacSetOpacity qidl -> with_locality ~atts vernac_set_opacity qidl
- | VernacSetStrategy l -> with_locality ~atts vernac_set_strategy l
- | VernacSetOption (export, key,v) -> vernac_set_option ~local:(only_locality atts) export key v
- | VernacUnsetOption (export, key) -> vernac_unset_option ~local:(only_locality atts) export key
- | VernacRemoveOption (key,v) -> unsupported_attributes atts; vernac_remove_option key v
- | VernacAddOption (key,v) -> unsupported_attributes atts; vernac_add_option key v
- | VernacMemOption (key,v) -> unsupported_attributes atts; vernac_mem_option key v
- | VernacPrintOption key -> unsupported_attributes atts; vernac_print_option key
+ with_section_locality ~atts vernac_arguments qid args more_implicits nargs flags;
+ pstate
+ | VernacReserve bl ->
+ unsupported_attributes atts;
+ vernac_reserve bl;
+ pstate
+ | VernacGeneralizable gen ->
+ with_locality ~atts vernac_generalizable gen;
+ pstate
+ | VernacSetOpacity qidl ->
+ with_locality ~atts vernac_set_opacity qidl;
+ pstate
+ | VernacSetStrategy l ->
+ with_locality ~atts vernac_set_strategy l;
+ pstate
+ | VernacSetOption (export, key,v) ->
+ vernac_set_option ~local:(only_locality atts) export key v;
+ pstate
+ | VernacUnsetOption (export, key) ->
+ vernac_unset_option ~local:(only_locality atts) export key;
+ pstate
+ | VernacRemoveOption (key,v) ->
+ unsupported_attributes atts;
+ vernac_remove_option key v;
+ pstate
+ | VernacAddOption (key,v) ->
+ unsupported_attributes atts;
+ vernac_add_option key v;
+ pstate
+ | VernacMemOption (key,v) ->
+ unsupported_attributes atts;
+ vernac_mem_option key v;
+ pstate
+ | VernacPrintOption key ->
+ unsupported_attributes atts;
+ vernac_print_option key;
+ pstate
| VernacCheckMayEval (r,g,c) ->
- Feedback.msg_notice @@ vernac_check_may_eval ~atts r g c
- | VernacDeclareReduction (s,r) -> with_locality ~atts vernac_declare_reduction s r
+ Feedback.msg_notice @@
+ vernac_check_may_eval ~pstate ~atts r g c;
+ pstate
+ | VernacDeclareReduction (s,r) ->
+ with_locality ~atts vernac_declare_reduction s r;
+ pstate
| VernacGlobalCheck c ->
unsupported_attributes atts;
- Feedback.msg_notice @@ vernac_global_check c
+ Feedback.msg_notice @@ vernac_global_check c;
+ pstate
| VernacPrint p ->
- let sigma, env = Pfedit.get_current_context () in
- Feedback.msg_notice @@ vernac_print ~atts env sigma p
- | VernacSearch (s,g,r) -> unsupported_attributes atts; vernac_search ~atts s g r
+ Feedback.msg_notice @@ vernac_print ~pstate ~atts p;
+ pstate
+ | VernacSearch (s,g,r) ->
+ unsupported_attributes atts;
+ vernac_search ~pstate ~atts s g r;
+ pstate
| VernacLocate l -> unsupported_attributes atts;
- Feedback.msg_notice @@ vernac_locate l
- | VernacRegister (qid, r) -> unsupported_attributes atts; vernac_register qid r
- | VernacPrimitive (id, prim, typopt) -> unsupported_attributes atts; ComAssumption.do_primitive id prim typopt
- | VernacComments l -> unsupported_attributes atts;
- Flags.if_verbose Feedback.msg_info (str "Comments ok\n")
+ Feedback.msg_notice @@ vernac_locate ~pstate l;
+ pstate
+ | VernacRegister (qid, r) ->
+ unsupported_attributes atts;
+ vernac_register ~pstate qid r;
+ pstate
+ | VernacPrimitive (id, prim, typopt) ->
+ unsupported_attributes atts;
+ ComAssumption.do_primitive id prim typopt;
+ pstate
+ | VernacComments l ->
+ unsupported_attributes atts;
+ Flags.if_verbose Feedback.msg_info (str "Comments ok\n");
+ pstate
(* Proof management *)
- | VernacFocus n -> unsupported_attributes atts; vernac_focus n
- | VernacUnfocus -> unsupported_attributes atts; vernac_unfocus ()
- | VernacUnfocused -> unsupported_attributes atts;
- Feedback.msg_notice @@ vernac_unfocused ()
- | VernacBullet b -> unsupported_attributes atts; vernac_bullet b
- | VernacSubproof n -> unsupported_attributes atts; vernac_subproof n
- | VernacEndSubproof -> unsupported_attributes atts; vernac_end_subproof ()
- | VernacShow s -> unsupported_attributes atts;
- Feedback.msg_notice @@ vernac_show s
- | VernacCheckGuard -> unsupported_attributes atts;
- Feedback.msg_notice @@ vernac_check_guard ()
- | VernacProof (tac, using) -> unsupported_attributes atts;
+ | VernacFocus n ->
+ unsupported_attributes atts;
+ Option.map (vernac_focus n) pstate
+ | VernacUnfocus ->
+ unsupported_attributes atts;
+ Option.map (vernac_unfocus ()) pstate
+ | VernacUnfocused ->
+ unsupported_attributes atts;
+ Option.iter (fun pstate -> Feedback.msg_notice @@ vernac_unfocused ~pstate) pstate;
+ pstate
+ | VernacBullet b ->
+ unsupported_attributes atts;
+ Option.map (vernac_bullet b) pstate
+ | VernacSubproof n ->
+ unsupported_attributes atts;
+ Option.map (vernac_subproof n) pstate
+ | VernacEndSubproof ->
+ unsupported_attributes atts;
+ Option.map (vernac_end_subproof ()) pstate
+ | VernacShow s ->
+ unsupported_attributes atts;
+ Feedback.msg_notice @@ vernac_show ~pstate s;
+ pstate
+ | VernacCheckGuard ->
+ unsupported_attributes atts;
+ Feedback.msg_notice @@
+ vernac_require_open_proof ~pstate (vernac_check_guard);
+ pstate
+ | VernacProof (tac, using) ->
+ unsupported_attributes atts;
let using = Option.append using (Proof_using.get_default_proof_using ()) in
let tacs = if Option.is_empty tac then "tac:no" else "tac:yes" in
let usings = if Option.is_empty using then "using:no" else "using:yes" in
Aux_file.record_in_aux_at "VernacProof" (tacs^" "^usings);
- Option.iter vernac_set_end_tac tac;
- Option.iter vernac_set_used_variables using
- | VernacProofMode mn -> unsupported_attributes atts; ()
+ let pstate =
+ vernac_require_open_proof ~pstate (fun ~pstate ->
+ let pstate = Option.cata (vernac_set_end_tac ~pstate) pstate tac in
+ Option.cata (vernac_set_used_variables ~pstate) pstate using)
+ in Some pstate
+ | VernacProofMode mn ->
+ unsupported_attributes atts;
+ pstate
(* Extensions *)
| VernacExtend (opn,args) ->
(* XXX: Here we are returning the state! :) *)
- let _st : Vernacstate.t = Vernacextend.call ~atts opn args ~st in
- ()
+ let st : Vernacstate.t = Vernacextend.call ~atts opn args ~st in
+ st.Vernacstate.proof
(** A global default timeout, controlled by option "Set Default Timeout n".
Use "Unset Default Timeout" to deactivate it (or set it to 0). *)
@@ -2333,12 +2562,18 @@ let () =
let current_timeout = ref None
-let vernac_timeout f =
+let vernac_timeout (f : 'a -> 'b) (x : 'a) : 'b =
match !current_timeout, !default_timeout with
- | Some n, _ | None, Some n ->
- let f () = f (); current_timeout := None in
- Control.timeout n f () Timeout
- | None, None -> f ()
+ | Some n, _
+ | None, Some n ->
+ let f v =
+ let res = f v in
+ current_timeout := None;
+ res
+ in
+ Control.timeout n f x Timeout
+ | None, None ->
+ f x
let restore_timeout () = current_timeout := None
@@ -2354,84 +2589,87 @@ 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 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)
- | _ -> assert false
- end
-
-let interp ?(verbosely=true) ?proof ~st {CAst.loc;v=c} =
- let rec control = function
+ 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 v
- | VernacFail v -> with_fail st true (fun () -> control v)
+ aux ~atts ~st v
+ | VernacFail v ->
+ with_fail ~st (fun () -> ignore(control ~st v));
+ st.Vernacstate.proof
| VernacTimeout (n,v) ->
current_timeout := Some n;
- control v
+ control ~st v
| VernacRedirect (s, {v}) ->
- Topfmt.with_output_to_file s control v
- | VernacTime (batch, com) ->
+ Topfmt.with_output_to_file s (control ~st) v
+ | VernacTime (batch, ({v} as com)) ->
let header = if batch then Topfmt.pr_cmd_header com else Pp.mt () in
- System.with_time ~batch ~header control com.CAst.v;
+ System.with_time ~batch ~header (control ~st) v;
- and aux ~atts : _ -> unit =
+ and aux ~atts ~st : _ -> Proof_global.t option =
function
| VernacLoad (_,fname) ->
unsupported_attributes atts;
- vernac_load control fname
+ vernac_load ~st control fname
| c ->
(* NB: we keep polymorphism and program in the attributes, we're
just parsing them to do our option magic. *)
try
- vernac_timeout begin fun () ->
- if verbosely
- then Flags.verbosely (interp ?proof ~atts ~st) c
- else Flags.silently (interp ?proof ~atts ~st) c;
- end
- with
- | reraise when
- (match reraise with
- | Timeout -> true
- | e -> CErrors.noncritical e)
- ->
- let e = CErrors.push reraise in
- let e = locate_if_not_already ?loc e in
- let () = restore_timeout () in
- iraise e
+ vernac_timeout begin fun st ->
+ let pstate : Proof_global.t option =
+ if verbosely
+ then Flags.verbosely (interp ?proof ~atts ~st) c
+ else Flags.silently (interp ?proof ~atts ~st) c
+ in
+ pstate
+ end st
+ with
+ | reraise when
+ (match reraise with
+ | Timeout -> true
+ | e -> CErrors.noncritical e)
+ ->
+ let e = CErrors.push reraise in
+ let e = locate_if_not_already ?loc e in
+ let () = restore_timeout () in
+ iraise e
in
if verbosely
- then Flags.verbosely control c
- else control c
+ then Flags.verbosely (control ~st) c
+ else (control ~st) c
(* Be careful with the cache here in case of an exception. *)
let interp ?verbosely ?proof ~st cmd =
Vernacstate.unfreeze_interp_state st;
try
- interp ?verbosely ?proof ~st cmd;
+ let pstate = interp ?verbosely ?proof ~st cmd in
+ Vernacstate.Proof_global.set pstate;
Vernacstate.freeze_interp_state ~marshallable:false
with exn ->
let exn = CErrors.push exn in
diff --git a/vernac/vernacentries.mli b/vernac/vernacentries.mli
index f43cec48e9..71cc29b6e1 100644
--- a/vernac/vernacentries.mli
+++ b/vernac/vernacentries.mli
@@ -33,15 +33,17 @@ 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 : Vernacstate.t -> bool -> (unit -> unit) -> unit
+(** [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
val interp_redexp_hook : (Environ.env -> Evd.evar_map -> Genredexpr.raw_red_expr ->
Evd.evar_map * Redexpr.red_expr) Hook.t
+(** Helper *)
+val vernac_require_open_proof : pstate:Proof_global.t option -> (pstate:Proof_global.t -> 'a) -> 'a
+
(* Flag set when the test-suite is called. Its only effect to display
verbose information for `Fail` *)
val test_mode : bool ref
diff --git a/vernac/vernacextend.ml b/vernac/vernacextend.ml
index 4bfe5c66b5..ef06e59316 100644
--- a/vernac/vernacextend.ml
+++ b/vernac/vernacextend.ml
@@ -169,7 +169,7 @@ let rec untype_command : type r s. (r, s) ty_sig -> r -> plugin_args vernac_comm
| Some Refl -> untype_command ty (f v) args
end
-let rec untype_user_symbol : type s a b c. (a, b, c) Extend.ty_user_symbol -> (s, a) Extend.symbol =
+let rec untype_user_symbol : type s a b c. (a, b, c) Extend.ty_user_symbol -> (s, Extend.norec, a) Extend.symbol =
let open Extend in function
| TUlist1 l -> Alist1 (untype_user_symbol l)
| TUlist1sep (l, s) -> Alist1sep (untype_user_symbol l, Atoken (CLexer.terminal s))
diff --git a/vernac/vernacstate.ml b/vernac/vernacstate.ml
index c691dc8559..77f54361da 100644
--- a/vernac/vernacstate.ml
+++ b/vernac/vernacstate.ml
@@ -28,10 +28,10 @@ module Parser = struct
end
type t = {
- parsing: Parser.state;
- system : States.state; (* summary + libstack *)
- proof : Proof_global.t; (* proof state *)
- shallow : bool; (* is the state trimmed down (libstack) *)
+ parsing : Parser.state;
+ system : States.state; (* summary + libstack *)
+ proof : Proof_global.t option; (* proof state *)
+ shallow : bool (* is the state trimmed down (libstack) *)
}
let s_cache = ref None
@@ -55,14 +55,14 @@ let do_if_not_cached rf f v =
let freeze_interp_state ~marshallable =
{ system = update_cache s_cache (States.freeze ~marshallable);
- proof = update_cache s_proof (Proof_global.freeze ~marshallable);
+ proof = !s_proof;
shallow = false;
parsing = Parser.cur_state ();
}
let unfreeze_interp_state { system; proof; parsing } =
do_if_not_cached s_cache States.unfreeze system;
- do_if_not_cached s_proof Proof_global.unfreeze proof;
+ s_proof := proof;
Pcoq.unfreeze parsing
let make_shallow st =
@@ -71,3 +71,75 @@ let make_shallow st =
system = States.replace_lib st.system @@ Lib.drop_objects lib;
shallow = true;
}
+
+(* Compatibility module *)
+module Proof_global = struct
+
+ let get () = !s_proof
+ let set x = s_proof := x
+
+ let freeze ~marshallable:_ = get ()
+ let unfreeze x = s_proof := Some x
+
+ exception NoCurrentProof
+
+ let () =
+ CErrors.register_handler begin function
+ | NoCurrentProof ->
+ CErrors.user_err Pp.(str "No focused proof (No proof-editing in progress).")
+ | _ -> raise CErrors.Unhandled
+ end
+
+ open Proof_global
+
+ let cc f = match !s_proof with
+ | None -> raise NoCurrentProof
+ | Some x -> f x
+
+ let dd f = match !s_proof with
+ | None -> raise NoCurrentProof
+ | Some x -> s_proof := Some (f x)
+
+ let there_are_pending_proofs () = !s_proof <> None
+ let get_open_goals () = cc get_open_goals
+
+ let set_terminator x = dd (set_terminator x)
+ let give_me_the_proof_opt () = Option.map give_me_the_proof !s_proof
+ let give_me_the_proof () = cc give_me_the_proof
+ let get_current_proof_name () = cc get_current_proof_name
+
+ let simple_with_current_proof f =
+ dd (simple_with_current_proof f)
+
+ let with_current_proof f =
+ let pf, res = cc (with_current_proof f) in
+ s_proof := Some pf; res
+
+ let install_state s = s_proof := Some s
+
+ let return_proof ?allow_partial () =
+ cc (return_proof ?allow_partial)
+
+ let close_future_proof ~opaque ~feedback_id pf =
+ cc (fun st -> close_future_proof ~opaque ~feedback_id st pf)
+
+ let close_proof ~opaque ~keep_body_ucst_separate f =
+ cc (close_proof ~opaque ~keep_body_ucst_separate f)
+
+ let discard_all () = s_proof := None
+ let update_global_env () = dd update_global_env
+
+ let get_current_context () = cc Pfedit.get_current_context
+
+ let get_all_proof_names () =
+ try cc get_all_proof_names
+ with NoCurrentProof -> []
+
+ let copy_terminators ~src ~tgt =
+ match src, tgt with
+ | None, None -> None
+ | Some _ , None -> None
+ | None, Some x -> Some x
+ | Some src, Some tgt -> Some (copy_terminators ~src ~tgt)
+
+end
diff --git a/vernac/vernacstate.mli b/vernac/vernacstate.mli
index 581c23386a..b79f97796f 100644
--- a/vernac/vernacstate.mli
+++ b/vernac/vernacstate.mli
@@ -19,10 +19,10 @@ module Parser : sig
end
type t = {
- parsing: Parser.state;
- system : States.state; (* summary + libstack *)
- proof : Proof_global.t; (* proof state *)
- shallow : bool; (* is the state trimmed down (libstack) *)
+ parsing : Parser.state;
+ system : States.state; (* summary + libstack *)
+ proof : Proof_global.t option; (* proof state *)
+ shallow : bool (* is the state trimmed down (libstack) *)
}
val freeze_interp_state : marshallable:bool -> t
@@ -32,3 +32,53 @@ val make_shallow : t -> t
(* WARNING: Do not use, it will go away in future releases *)
val invalidate_cache : unit -> unit
+
+(* Compatibility module: Do Not Use *)
+module Proof_global : sig
+
+ open Proof_global
+
+ (* Low-level stuff *)
+ val get : unit -> t option
+ val set : t option -> unit
+
+ val freeze : marshallable:bool -> t option
+ val unfreeze : t -> unit
+
+ exception NoCurrentProof
+
+ val there_are_pending_proofs : unit -> bool
+ val get_open_goals : unit -> int
+
+ val set_terminator : proof_terminator -> unit
+ val give_me_the_proof : unit -> Proof.t
+ val give_me_the_proof_opt : unit -> Proof.t option
+ val get_current_proof_name : unit -> Names.Id.t
+
+ val simple_with_current_proof :
+ (unit Proofview.tactic -> Proof.t -> Proof.t) -> unit
+
+ val with_current_proof :
+ (unit Proofview.tactic -> Proof.t -> Proof.t * 'a) -> 'a
+
+ val install_state : t -> unit
+
+ val return_proof : ?allow_partial:bool -> unit -> closed_proof_output
+
+ val close_future_proof :
+ opaque:opacity_flag ->
+ feedback_id:Stateid.t ->
+ closed_proof_output Future.computation -> closed_proof
+
+ val close_proof : opaque:opacity_flag -> keep_body_ucst_separate:bool -> Future.fix_exn -> closed_proof
+
+ val discard_all : unit -> unit
+ val update_global_env : unit -> unit
+
+ val get_current_context : unit -> Evd.evar_map * Environ.env
+
+ val get_all_proof_names : unit -> Names.Id.t list
+
+ val copy_terminators : src:t option -> tgt:t option -> t option
+
+end