aboutsummaryrefslogtreecommitdiff
path: root/tactics
diff options
context:
space:
mode:
Diffstat (limited to 'tactics')
-rw-r--r--tactics/auto.ml77
-rw-r--r--tactics/auto.mli25
-rw-r--r--tactics/autorewrite.ml32
-rw-r--r--tactics/class_tactics.ml141
-rw-r--r--tactics/contradiction.ml42
-rw-r--r--tactics/coretactics.ml4116
-rw-r--r--tactics/eauto.ml (renamed from tactics/eauto.ml4)294
-rw-r--r--tactics/eauto.mli29
-rw-r--r--tactics/elim.ml50
-rw-r--r--tactics/elimschemes.ml9
-rw-r--r--tactics/eqdecide.ml25
-rw-r--r--tactics/eqschemes.ml102
-rw-r--r--tactics/equality.ml263
-rw-r--r--tactics/equality.mli5
-rw-r--r--tactics/evar_tactics.ml28
-rw-r--r--tactics/extraargs.ml441
-rw-r--r--tactics/extraargs.mli10
-rw-r--r--tactics/extratactics.ml4214
-rw-r--r--tactics/extratactics.mli2
-rw-r--r--tactics/ftactic.ml30
-rw-r--r--tactics/ftactic.mli22
-rw-r--r--tactics/g_auto.ml4211
-rw-r--r--tactics/g_class.ml47
-rw-r--r--tactics/g_ltac.ml4430
-rw-r--r--tactics/g_obligations.ml4147
-rw-r--r--tactics/g_rewrite.ml413
-rw-r--r--tactics/geninterp.ml15
-rw-r--r--tactics/geninterp.mli7
-rw-r--r--tactics/hightactics.mllib9
-rw-r--r--tactics/hints.ml36
-rw-r--r--tactics/hints.mli5
-rw-r--r--tactics/hipattern.ml410
-rw-r--r--tactics/hipattern.mli6
-rw-r--r--tactics/inv.ml66
-rw-r--r--tactics/leminv.ml30
-rw-r--r--tactics/rewrite.ml126
-rw-r--r--tactics/rewrite.mli2
-rw-r--r--tactics/taccoerce.ml44
-rw-r--r--tactics/taccoerce.mli9
-rw-r--r--tactics/tacentries.ml263
-rw-r--r--tactics/tacentries.mli21
-rw-r--r--tactics/tacenv.ml13
-rw-r--r--tactics/tacenv.mli13
-rw-r--r--tactics/tacintern.ml144
-rw-r--r--tactics/tacintern.mli1
-rw-r--r--tactics/tacinterp.ml1121
-rw-r--r--tactics/tacinterp.mli25
-rw-r--r--tactics/tacsubst.ml116
-rw-r--r--tactics/tactic_debug.ml400
-rw-r--r--tactics/tactic_debug.mli80
-rw-r--r--tactics/tactic_matching.ml14
-rw-r--r--tactics/tactic_matching.mli2
-rw-r--r--tactics/tacticals.ml238
-rw-r--r--tactics/tacticals.mli60
-rw-r--r--tactics/tactics.ml1654
-rw-r--r--tactics/tactics.mli103
-rw-r--r--tactics/tactics.mllib6
-rw-r--r--tactics/tauto.ml282
-rw-r--r--tactics/tauto.ml4398
-rw-r--r--tactics/tauto.mli0
60 files changed, 4582 insertions, 3102 deletions
diff --git a/tactics/auto.ml b/tactics/auto.ml
index 647ff97148..761c41da6f 100644
--- a/tactics/auto.ml
+++ b/tactics/auto.ml
@@ -67,16 +67,13 @@ let auto_unif_flags_of st1 st2 useeager =
let auto_unif_flags =
auto_unif_flags_of full_transparent_state empty_transparent_state false
-let auto_flags_of_state st =
- auto_unif_flags_of full_transparent_state st false
-
(* Try unification with the precompiled clause, then use registered Apply *)
let connect_hint_clenv poly (c, _, ctx) clenv gl =
(** [clenv] has been generated by a hint-making function, so the only relevant
data in its evarmap is the set of metas. The [evar_reset_evd] function
below just replaces the metas of sigma by those coming from the clenv. *)
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let evd = Evd.evars_reset_evd ~with_conv_pbs:true ~with_univs:false sigma clenv.evd in
(** Still, we need to update the universes *)
let clenv, c =
@@ -99,11 +96,11 @@ let connect_hint_clenv poly (c, _, ctx) clenv gl =
in clenv, c
let unify_resolve poly flags ((c : raw_hint), clenv) =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let clenv, c = connect_hint_clenv poly c clenv gl in
let clenv = Tacmach.New.of_old (fun gl -> clenv_unique_resolver ~flags clenv gl) gl in
Clenvtac.clenv_refine false clenv
- end
+ end }
let unify_resolve_nodelta poly h = unify_resolve poly auto_unif_flags h
@@ -122,10 +119,12 @@ let exact poly (c,clenv) =
let ctx = Evd.evar_universe_context clenv.evd in
ctx, c
in
- Proofview.Goal.enter begin fun gl ->
- let sigma = Evd.merge_universe_context (Proofview.Goal.sigma gl) ctx in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma) (exact_check c')
- end
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
+ let sigma = Evd.merge_universe_context sigma ctx in
+ Sigma.Unsafe.of_pair (exact_check c', sigma)
+ end }
(* Util *)
@@ -153,11 +152,12 @@ let conclPattern concl pat tac =
with Constr_matching.PatternMatchingFailure ->
Tacticals.New.tclZEROMSG (str "conclPattern")
in
- Proofview.Goal.enter (fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
constr_bindings env sigma >>= fun constr_bindings ->
- Hook.get forward_interp_tactic constr_bindings tac)
+ Hook.get forward_interp_tactic constr_bindings tac
+ end }
(***********************************************************)
(** A debugging / verbosity framework for trivial and auto *)
@@ -296,9 +296,6 @@ let tclTRY_dbg d tac =
(* Papageno : cette fonction a été pas mal simplifiée depuis que la base
de Hint impérative a été remplacée par plusieurs bases fonctionnelles *)
-let auto_unif_flags =
- auto_unif_flags_of full_transparent_state empty_transparent_state false
-
let flags_of_state st =
auto_unif_flags_of st st false
@@ -322,24 +319,24 @@ let dbg_assumption dbg = tclLOG dbg (fun () -> str "assumption") assumption
let rec trivial_fail_db dbg mod_delta db_list local_db =
let intro_tac =
Tacticals.New.tclTHEN (dbg_intro dbg)
- ( Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ ( Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
let nf c = Evarutil.nf_evar sigma c in
let decl = Tacmach.New.pf_last_hyp (Proofview.Goal.assume gl) in
- let hyp = Context.map_named_declaration nf decl in
+ let hyp = Context.Named.Declaration.map_constr nf decl in
let hintl = make_resolve_hyp env sigma hyp
in trivial_fail_db dbg mod_delta db_list
(Hint_db.add_list env sigma hintl local_db)
- end)
+ end })
in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let concl = Tacmach.New.pf_nf_concl gl in
Tacticals.New.tclFIRST
((dbg_assumption dbg)::intro_tac::
(List.map Tacticals.New.tclCOMPLETE
(trivial_resolve dbg mod_delta db_list local_db concl)))
- end
+ end }
and my_find_search_nodelta db_list local_db hdc concl =
List.map (fun hint -> (None,hint))
@@ -393,7 +390,7 @@ and tac_of_hint dbg db_list local_db concl (flags, ({pat=p; code=t;poly=poly}))
| Unfold_nth c ->
Proofview.V82.tactic (fun gl ->
if exists_evaluable_reference (pf_env gl) c then
- tclPROGRESS (reduce (Unfold [AllOccurrences,c]) Locusops.onConcl) gl
+ tclPROGRESS (Proofview.V82.of_tactic (reduce (Unfold [AllOccurrences,c]) Locusops.onConcl)) gl
else tclFAIL 0 (str"Unbound reference") gl)
| Extern tacast ->
conclPattern concl p tacast
@@ -416,26 +413,26 @@ and trivial_resolve dbg mod_delta db_list local_db cl =
"nocore" amongst the databases. *)
let trivial ?(debug=Off) lems dbnames =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let db_list = make_db_list dbnames in
let d = mk_trivial_dbg debug in
let hints = make_local_hint_db env sigma false lems in
tclTRY_dbg d
(trivial_fail_db d false db_list hints)
- end
+ end }
let full_trivial ?(debug=Off) lems =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let db_list = current_pure_db () in
let d = mk_trivial_dbg debug in
let hints = make_local_hint_db env sigma false lems in
tclTRY_dbg d
(trivial_fail_db d false db_list hints)
- end
+ end }
let gen_trivial ?(debug=Off) lems = function
| None -> full_trivial ~debug lems
@@ -460,7 +457,7 @@ let possible_resolve dbg mod_delta db_list local_db cl =
let extend_local_db decl db gl =
let env = Tacmach.New.pf_env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
Hint_db.add_list env sigma (make_resolve_hyp env sigma decl) db
(* Introduce an hypothesis, then call the continuation tactic [kont]
@@ -468,10 +465,10 @@ let extend_local_db decl db gl =
let intro_register dbg kont db =
Tacticals.New.tclTHEN (dbg_intro dbg)
- (Proofview.Goal.enter begin fun gl ->
+ (Proofview.Goal.enter { enter = begin fun gl ->
let extend_local_db decl db = extend_local_db decl db gl in
Tacticals.New.onLastDecl (fun decl -> kont (extend_local_db decl db))
- end)
+ end })
(* n is the max depth of search *)
(* local_db contains the local Hypotheses *)
@@ -484,14 +481,14 @@ let search d n mod_delta db_list local_db =
if Int.equal n 0 then Tacticals.New.tclZEROMSG (str"BOUND 2") else
Tacticals.New.tclORELSE0 (dbg_assumption d)
(Tacticals.New.tclORELSE0 (intro_register d (search d n) local_db)
- ( Proofview.Goal.enter begin fun gl ->
+ ( Proofview.Goal.enter { enter = begin fun gl ->
let concl = Tacmach.New.pf_nf_concl gl in
let d' = incr_dbg d in
Tacticals.New.tclFIRST
(List.map
(fun ntac -> Tacticals.New.tclTHEN ntac (search d' (n-1) local_db))
(possible_resolve d mod_delta db_list local_db concl))
- end))
+ end }))
end []
in
search d n local_db
@@ -499,15 +496,15 @@ let search d n mod_delta db_list local_db =
let default_search_depth = ref 5
let delta_auto debug mod_delta n lems dbnames =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let db_list = make_db_list dbnames in
let d = mk_auto_dbg debug in
let hints = make_local_hint_db env sigma false lems in
tclTRY_dbg d
(search d n mod_delta db_list hints)
- end
+ end }
let delta_auto =
if Flags.profile then
@@ -522,15 +519,15 @@ let new_auto ?(debug=Off) n = delta_auto debug true n
let default_auto = auto !default_search_depth [] []
let delta_full_auto ?(debug=Off) mod_delta n lems =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let db_list = current_pure_db () in
let d = mk_auto_dbg debug in
let hints = make_local_hint_db env sigma false lems in
tclTRY_dbg d
(search d n mod_delta db_list hints)
- end
+ end }
let full_auto ?(debug=Off) n = delta_full_auto ~debug false n
let new_full_auto ?(debug=Off) n = delta_full_auto ~debug true n
diff --git a/tactics/auto.mli b/tactics/auto.mli
index 2e5647f872..cd2de99be5 100644
--- a/tactics/auto.mli
+++ b/tactics/auto.mli
@@ -10,7 +10,6 @@ open Names
open Term
open Clenv
open Pattern
-open Evd
open Decl_kinds
open Hints
@@ -26,11 +25,9 @@ val default_search_depth : int ref
val auto_flags_of_state : transparent_state -> Unification.unify_flags
val connect_hint_clenv : polymorphic -> raw_hint -> clausenv ->
- [ `NF ] Proofview.Goal.t -> clausenv * constr
+ ([ `NF ], 'r) Proofview.Goal.t -> clausenv * constr
(** Try unification with the precompiled clause, then use registered Apply *)
-val unify_resolve_nodelta : polymorphic -> (raw_hint * clausenv) -> unit Proofview.tactic
-
val unify_resolve : polymorphic -> Unification.unify_flags -> (raw_hint * clausenv) -> unit Proofview.tactic
(** [ConclPattern concl pat tacast]:
@@ -46,24 +43,24 @@ val conclPattern : constr -> constr_pattern option -> Tacexpr.glob_tactic_expr -
"nocore" amongst the databases. *)
val auto : ?debug:Tacexpr.debug ->
- int -> open_constr list -> hint_db_name list -> unit Proofview.tactic
+ int -> Tacexpr.delayed_open_constr list -> hint_db_name list -> unit Proofview.tactic
(** Auto with more delta. *)
val new_auto : ?debug:Tacexpr.debug ->
- int -> open_constr list -> hint_db_name list -> unit Proofview.tactic
+ int -> Tacexpr.delayed_open_constr list -> hint_db_name list -> unit Proofview.tactic
(** auto with default search depth and with the hint database "core" *)
val default_auto : unit Proofview.tactic
(** auto with all hint databases except the "v62" compatibility database *)
val full_auto : ?debug:Tacexpr.debug ->
- int -> open_constr list -> unit Proofview.tactic
+ int -> Tacexpr.delayed_open_constr list -> unit Proofview.tactic
(** auto with all hint databases except the "v62" compatibility database
and doing delta *)
val new_full_auto : ?debug:Tacexpr.debug ->
- int -> open_constr list -> unit Proofview.tactic
+ int -> Tacexpr.delayed_open_constr list -> unit Proofview.tactic
(** auto with default search depth and with all hint databases
except the "v62" compatibility database *)
@@ -71,19 +68,19 @@ val default_full_auto : unit Proofview.tactic
(** The generic form of auto (second arg [None] means all bases) *)
val gen_auto : ?debug:Tacexpr.debug ->
- int option -> open_constr list -> hint_db_name list option -> unit Proofview.tactic
+ int option -> Tacexpr.delayed_open_constr list -> hint_db_name list option -> unit Proofview.tactic
(** The hidden version of auto *)
val h_auto : ?debug:Tacexpr.debug ->
- int option -> open_constr list -> hint_db_name list option -> unit Proofview.tactic
+ int option -> Tacexpr.delayed_open_constr list -> hint_db_name list option -> unit Proofview.tactic
(** Trivial *)
val trivial : ?debug:Tacexpr.debug ->
- open_constr list -> hint_db_name list -> unit Proofview.tactic
+ Tacexpr.delayed_open_constr list -> hint_db_name list -> unit Proofview.tactic
val gen_trivial : ?debug:Tacexpr.debug ->
- open_constr list -> hint_db_name list option -> unit Proofview.tactic
+ Tacexpr.delayed_open_constr list -> hint_db_name list option -> unit Proofview.tactic
val full_trivial : ?debug:Tacexpr.debug ->
- open_constr list -> unit Proofview.tactic
+ Tacexpr.delayed_open_constr list -> unit Proofview.tactic
val h_trivial : ?debug:Tacexpr.debug ->
- open_constr list -> hint_db_name list option -> unit Proofview.tactic
+ Tacexpr.delayed_open_constr list -> hint_db_name list option -> unit Proofview.tactic
diff --git a/tactics/autorewrite.ml b/tactics/autorewrite.ml
index 49e5c6204d..ea598b61ca 100644
--- a/tactics/autorewrite.ml
+++ b/tactics/autorewrite.ml
@@ -18,6 +18,8 @@ open Util
open Tacexpr
open Mod_subst
open Locus
+open Sigma.Notations
+open Proofview.Notations
(* Rewriting rules *)
type rew_rule = { rew_lemma: constr;
@@ -91,14 +93,16 @@ type raw_rew_rule = Loc.t * constr Univ.in_universe_context_set * bool * raw_tac
(* Applies all the rules of one base *)
let one_base general_rewrite_maybe_in tac_main bas =
let lrul = find_rewrites bas in
- let try_rewrite dir ctx c tc = Proofview.Goal.nf_enter (fun gl ->
+ let try_rewrite dir ctx c tc =
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
let subst, ctx' = Universes.fresh_universe_context_set_instance ctx in
let c' = Vars.subst_univs_level_constr subst c in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
let sigma = Evd.merge_context_set Evd.univ_flexible sigma ctx' in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
- (general_rewrite_maybe_in dir c' tc)
- ) in
+ let tac = general_rewrite_maybe_in dir c' tc in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end } in
let lrul = List.map (fun h ->
let tac = match h.rew_tac with None -> Proofview.tclUNIT () | Some t -> Tacinterp.eval_tactic t in
(h.rew_ctx,h.rew_lemma,h.rew_l2r,tac)) lrul in
@@ -120,7 +124,7 @@ let autorewrite ?(conds=Naive) tac_main lbas =
(Proofview.tclUNIT()) lbas))
let autorewrite_multi_in ?(conds=Naive) idl tac_main lbas =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
(* let's check at once if id exists (to raise the appropriate error) *)
let _ = List.map (fun id -> Tacmach.New.pf_get_hyp id gl) idl in
let general_rewrite_in id =
@@ -129,7 +133,7 @@ let autorewrite_multi_in ?(conds=Naive) idl tac_main lbas =
fun dir cstr tac gl ->
let last_hyp_id =
match Tacmach.pf_hyps gl with
- (last_hyp_id,_,_)::_ -> last_hyp_id
+ d :: _ -> Context.Named.Declaration.get_id d
| _ -> (* even the hypothesis id is missing *)
raise (Logic.RefinerError (Logic.NoSuchHyp !id))
in
@@ -138,7 +142,8 @@ let autorewrite_multi_in ?(conds=Naive) idl tac_main lbas =
match gls with
g::_ ->
(match Environ.named_context_of_val (Goal.V82.hyps gl'.Evd.sigma g) with
- (lastid,_,_)::_ ->
+ d ::_ ->
+ let lastid = Context.Named.Declaration.get_id d in
if not (Id.equal last_hyp_id lastid) then
begin
let gl'' =
@@ -163,7 +168,7 @@ let autorewrite_multi_in ?(conds=Naive) idl tac_main lbas =
(List.fold_left (fun tac bas ->
Tacticals.New.tclTHEN tac (one_base (general_rewrite_in id) tac_main bas)) (Proofview.tclUNIT()) lbas)))
idl
- end
+ end }
let autorewrite_in ?(conds=Naive) id = autorewrite_multi_in ~conds [id]
@@ -188,12 +193,13 @@ let gen_auto_multi_rewrite conds tac_main lbas cl =
| None ->
(* try to rewrite in all hypothesis
(except maybe the rewritten one) *)
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let ids = Tacmach.New.pf_ids_of_hyps gl in
try_do_hyps (fun id -> id) ids
- end)
+ end })
-let auto_multi_rewrite ?(conds=Naive) = gen_auto_multi_rewrite conds (Proofview.tclUNIT())
+let auto_multi_rewrite ?(conds=Naive) lems cl =
+ Proofview.V82.wrap_exceptions (fun () -> gen_auto_multi_rewrite conds (Proofview.tclUNIT()) lems cl)
let auto_multi_rewrite_with ?(conds=Naive) tac_main lbas cl =
let onconcl = match cl.Locus.concl_occs with NoOccurrences -> false | _ -> true in
@@ -202,7 +208,7 @@ let auto_multi_rewrite_with ?(conds=Naive) tac_main lbas cl =
(* autorewrite with .... in clause using tac n'est sur que
si clause represente soit le but soit UNE hypothese
*)
- gen_auto_multi_rewrite conds tac_main lbas cl
+ Proofview.V82.wrap_exceptions (fun () -> gen_auto_multi_rewrite conds tac_main lbas cl)
| _ ->
Tacticals.New.tclZEROMSG (strbrk "autorewrite .. in .. using can only be used either with a unique hypothesis or on the conclusion.")
diff --git a/tactics/class_tactics.ml b/tactics/class_tactics.ml
index 5b3231dea8..4855598989 100644
--- a/tactics/class_tactics.ml
+++ b/tactics/class_tactics.ml
@@ -39,6 +39,10 @@ let typeclasses_dependency_order = ref false
let set_typeclasses_dependency_order d = (:=) typeclasses_dependency_order d
let get_typeclasses_dependency_order () = !typeclasses_dependency_order
+let typeclasses_iterative_deepening = ref false
+let set_typeclasses_iterative_deepening d = (:=) typeclasses_iterative_deepening d
+let get_typeclasses_iterative_deepening () = !typeclasses_iterative_deepening
+
open Goptions
let _ =
@@ -59,6 +63,15 @@ let _ =
optread = get_typeclasses_dependency_order;
optwrite = set_typeclasses_dependency_order; }
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "use iterative deepening strategy";
+ optkey = ["Typeclasses";"Iterative";"Deepening"];
+ optread = get_typeclasses_iterative_deepening;
+ optwrite = set_typeclasses_iterative_deepening; }
+
(** We transform the evars that are concerned by this resolution
(according to predicate p) into goals.
Invariant: function p only manipulates and returns undefined evars *)
@@ -127,17 +140,17 @@ let rec eq_constr_mod_evars x y =
| _, _ -> compare_constr eq_constr_mod_evars x y
let progress_evars t =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let check =
- Proofview.Goal.nf_enter begin fun gl' ->
+ Proofview.Goal.nf_enter { enter = begin fun gl' ->
let newconcl = Proofview.Goal.concl gl' in
if eq_constr_mod_evars concl newconcl
then Tacticals.New.tclFAIL 0 (str"No progress made (modulo evars)")
else Proofview.tclUNIT ()
- end
+ end }
in t <*> check
- end
+ end }
let e_give_exact flags poly (c,clenv) gl =
@@ -145,23 +158,25 @@ let e_give_exact flags poly (c,clenv) gl =
let c, gl =
if poly then
let clenv', subst = Clenv.refresh_undefined_univs clenv in
- let clenv' = connect_clenv gl clenv' in
+ let evd = evars_reset_evd ~with_conv_pbs:true gl.sigma clenv'.evd in
let c = Vars.subst_univs_level_constr subst c in
- c, {gl with sigma = clenv'.evd}
+ c, {gl with sigma = evd}
else c, gl
in
let t1 = pf_unsafe_type_of gl c in
tclTHEN (Proofview.V82.of_tactic (Clenvtac.unify ~flags t1)) (exact_no_check c) gl
-let unify_e_resolve poly flags (c,clenv) gls =
+let unify_e_resolve poly flags = { enter = begin fun gls (c,clenv) ->
let clenv', c = connect_hint_clenv poly c clenv gls in
let clenv' = Tacmach.New.of_old (clenv_unique_resolver ~flags clenv') gls in
Clenvtac.clenv_refine true ~with_classes:false clenv'
+ end }
-let unify_resolve poly flags (c,clenv) gls =
+let unify_resolve poly flags = { enter = begin fun gls (c,clenv) ->
let clenv', _ = connect_hint_clenv poly c clenv gls in
let clenv' = Tacmach.New.of_old (clenv_unique_resolver ~flags clenv') gls in
Clenvtac.clenv_refine false ~with_classes:false clenv'
+ end }
let clenv_of_prods poly nprods (c, clenv) gl =
let (c, _, _) = c in
@@ -175,16 +190,17 @@ let clenv_of_prods poly nprods (c, clenv) gl =
else None
let with_prods nprods poly (c, clenv) f =
- Proofview.Goal.nf_enter (fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
match clenv_of_prods poly nprods (c, clenv) gl with
| None -> Tacticals.New.tclZEROMSG (str"Not enough premisses")
- | Some clenv' -> f (c, clenv') gl)
+ | Some clenv' -> f.enter gl (c, clenv')
+ end }
(** Hack to properly solve dependent evars that are typeclasses *)
let rec e_trivial_fail_db db_list local_db goal =
let tacl =
- Eauto.registered_e_assumption ::
+ Proofview.V82.of_tactic Eauto.registered_e_assumption ::
(tclTHEN (Proofview.V82.of_tactic Tactics.intro)
(function g'->
let d = pf_last_hyp g' in
@@ -229,7 +245,7 @@ and e_my_find_search db_list local_db hdc complete sigma concl =
Proofview.V82.tactic (tclTHEN
(Proofview.V82.of_tactic ((with_prods nprods poly (term,cl) (unify_e_resolve poly flags))))
(if complete then tclIDTAC else e_trivial_fail_db db_list local_db))
- | Unfold_nth c -> Proofview.V82.tactic (tclWEAK_PROGRESS (unfold_in_concl [AllOccurrences,c]))
+ | Unfold_nth c -> Proofview.V82.tactic (tclWEAK_PROGRESS (Proofview.V82.of_tactic (unfold_in_concl [AllOccurrences,c])))
| Extern tacast -> conclPattern concl p tacast
in
let tac = Proofview.V82.of_tactic (run_hint t tac) in
@@ -267,7 +283,8 @@ type autoinfo = { hints : hint_db; is_evar: existential_key option;
auto_path : global_reference option list;
auto_cut : hints_path }
type autogoal = goal * autoinfo
-type 'ans fk = unit -> 'ans
+type failure = NotApplicable | ReachedLimit
+type 'ans fk = failure -> 'ans
type ('a,'ans) sk = 'a -> 'ans fk -> 'ans
type 'a tac = { skft : 'ans. ('a,'ans) sk -> 'ans fk -> autogoal sigma -> 'ans }
@@ -282,11 +299,13 @@ type 'a optionk =
| Somek of 'a * 'a optionk fk
type ('a,'b) optionk2 =
- | Nonek2
+ | Nonek2 of failure
| Somek2 of 'a * 'b * ('a,'b) optionk2 fk
-let make_resolve_hyp env sigma st flags only_classes pri (id, _, cty) =
- let cty = Evarutil.nf_evar sigma cty in
+let make_resolve_hyp env sigma st flags only_classes pri decl =
+ let open Context.Named.Declaration in
+ let id = get_id decl in
+ let cty = Evarutil.nf_evar sigma (get_type decl) in
let rec iscl env ty =
let ctx, ar = decompose_prod_assum ty in
match kind_of_term (fst (decompose_app ar)) with
@@ -328,9 +347,10 @@ let make_hints g st only_classes sign =
List.fold_left
(fun (paths, hints) hyp ->
let consider =
- try let (_, b, t) = Global.lookup_named (pi1 hyp) in
+ let open Context.Named.Declaration in
+ try let t = Global.lookup_named (get_id hyp) |> get_type in
(* Section variable, reindex only if the type changed *)
- not (Term.eq_constr t (pi3 hyp))
+ not (Term.eq_constr t (get_type hyp))
with Not_found -> true
in
if consider then
@@ -364,7 +384,7 @@ let lift_tactic tac (f : goal list sigma -> autoinfo -> autogoal list sigma) : '
with e when catchable e -> None in
match res with
| Some gls -> sk (f gls hints) fk
- | None -> fk () }
+ | None -> fk NotApplicable }
let intro_tac : atac =
lift_tactic (Proofview.V82.of_tactic Tactics.intro)
@@ -385,8 +405,19 @@ let normevars_tac : atac =
let info' = { info with auto_last_tac = lazy (str"normevars") } in
sk {it = [gl', info']; sigma = sigma';} fk }
+let merge_failures x y =
+ match x, y with
+ | _, ReachedLimit
+ | ReachedLimit, _ -> ReachedLimit
+ | NotApplicable, NotApplicable -> NotApplicable
+
let or_tac (x : 'a tac) (y : 'a tac) : 'a tac =
- { skft = fun sk fk gls -> x.skft sk (fun () -> y.skft sk fk gls) gls }
+ { skft = fun sk fk gls -> x.skft sk
+ (fun f -> y.skft sk (fun f' -> fk (merge_failures f f')) gls) gls }
+
+let or_else_tac (x : 'a tac) (y : failure -> 'a tac) : 'a tac =
+ { skft = fun sk fk gls -> x.skft sk
+ (fun f -> (y f).skft sk fk gls) gls }
let is_Prop env sigma concl =
let ty = Retyping.get_type_of env sigma concl in
@@ -463,7 +494,7 @@ let hints_tac hints =
in g, info) 1 newgls in
let glsv = {it = gls'; sigma = s';} in
let fk' =
- (fun () ->
+ (fun e ->
let do_backtrack =
if unique then occur_existential concl
else if info.unique then true
@@ -471,22 +502,25 @@ let hints_tac hints =
needs_backtrack env s' info.is_evar concl
else true
in
+ let e' = match foundone with None -> e | Some e' -> merge_failures e e' in
if !typeclasses_debug then
msg_debug
((if do_backtrack then str"Backtracking after "
else str "Not backtracking after ")
++ Lazy.force pp);
- if do_backtrack then aux (succ i) true tl
- else fk ())
+ if do_backtrack then aux (succ i) (Some e') tl
+ else fk e')
in
sk glsv fk')
| [] ->
- if not foundone && !typeclasses_debug then
+ if foundone == None && !typeclasses_debug then
msg_debug (pr_depth info.auto_depth ++ str": no match for " ++
Printer.pr_constr_env (Goal.V82.env s gl) s concl ++
spc () ++ str ", " ++ int (List.length poss) ++ str" possibilities");
- fk ()
- in aux 1 false poss }
+ match foundone with
+ | Some e -> fk e
+ | None -> fk NotApplicable
+ in aux 1 None poss }
let then_list (second : atac) (sk : (auto_result, 'a) sk) : (auto_result, 'a) sk =
let rec aux s (acc : autogoal list list) fk = function
@@ -509,11 +543,11 @@ let then_list (second : atac) (sk : (auto_result, 'a) sk) : (auto_result, 'a) sk
| [] -> Somek2 (List.rev acc, s, fk)
in fun {it = gls; sigma = s; } fk ->
let rec aux' = function
- | Nonek2 -> fk ()
+ | Nonek2 e -> fk e
| Somek2 (res, s', fk') ->
let goals' = List.concat res in
- sk {it = goals'; sigma = s'; } (fun () -> aux' (fk' ()))
- in aux' (aux s [] (fun () -> Nonek2) gls)
+ sk {it = goals'; sigma = s'; } (fun e -> aux' (fk' e))
+ in aux' (aux s [] (fun e -> Nonek2 e) gls)
let then_tac (first : atac) (second : atac) : atac =
{ skft = fun sk fk -> first.skft (then_list second sk) fk }
@@ -528,16 +562,30 @@ let run_list_tac (t : 'a tac) p goals (gl : autogoal list sigma) : run_list_res
gl
(fun _ -> Nonek)
-let fail_tac : atac =
- { skft = fun sk fk _ -> fk () }
+let fail_tac reason : atac =
+ { skft = fun sk fk _ -> fk reason }
let rec fix (t : 'a tac) : 'a tac =
then_tac t { skft = fun sk fk -> (fix t).skft sk fk }
let rec fix_limit limit (t : 'a tac) : 'a tac =
- if Int.equal limit 0 then fail_tac
+ if Int.equal limit 0 then fail_tac ReachedLimit
else then_tac t { skft = fun sk fk -> (fix_limit (pred limit) t).skft sk fk }
+let fix_iterative t =
+ let rec aux depth =
+ or_else_tac (fix_limit depth t)
+ (function
+ | NotApplicable as e -> fail_tac e
+ | ReachedLimit -> aux (succ depth))
+ in aux 1
+
+let fix_iterative_limit limit (t : 'a tac) : 'a tac =
+ let rec aux depth =
+ if Int.equal depth limit then fail_tac ReachedLimit
+ else or_tac (fix_limit depth t) { skft = fun sk fk -> (aux (succ depth)).skft sk fk }
+ in aux 1
+
let make_autogoal ?(only_classes=true) ?(unique=false) ?(st=full_transparent_state) cut ev g =
let hints = make_autogoal_hints only_classes ~st g in
(g.it, { hints = hints ; is_evar = ev; unique = unique;
@@ -581,16 +629,14 @@ let eauto_tac hints =
then_tac normevars_tac (or_tac (hints_tac hints) intro_tac)
let eauto_tac ?limit hints =
- match limit with
- | None -> fix (eauto_tac hints)
- | Some limit -> fix_limit limit (eauto_tac hints)
-
-let eauto ?(only_classes=true) ?st ?limit hints g =
- let gl = { it = make_autogoal ~only_classes ?st (cut_of_hints hints) None g; sigma = project g; } in
- match run_tac (eauto_tac ?limit hints) gl with
- | None -> raise Not_found
- | Some {it = goals; sigma = s; } ->
- {it = List.map fst goals; sigma = s;}
+ if get_typeclasses_iterative_deepening () then
+ match limit with
+ | None -> fix_iterative (eauto_tac hints)
+ | Some limit -> fix_iterative_limit limit (eauto_tac hints)
+ else
+ match limit with
+ | None -> fix (eauto_tac hints)
+ | Some limit -> fix_limit limit (eauto_tac hints)
let real_eauto ?limit unique st hints p evd =
let res =
@@ -600,7 +646,7 @@ let real_eauto ?limit unique st hints p evd =
| None -> evd
| Some (evd', fk) ->
if unique then
- (match get_result (fk ()) with
+ (match get_result (fk NotApplicable) with
| Some (evd'', fk') -> error "Typeclass resolution gives multiple solutions"
| None -> evd')
else evd'
@@ -609,6 +655,13 @@ let resolve_all_evars_once debug limit unique p evd =
let db = searchtable_map typeclasses_db in
real_eauto ?limit unique (Hint_db.transparent_state db) [db] p evd
+let eauto ?(only_classes=true) ?st ?limit hints g =
+ let gl = { it = make_autogoal ~only_classes ?st (cut_of_hints hints) None g; sigma = project g; } in
+ match run_tac (eauto_tac ?limit hints) gl with
+ | None -> raise Not_found
+ | Some {it = goals; sigma = s; } ->
+ {it = List.map fst goals; sigma = s;}
+
(** We compute dependencies via a union-find algorithm.
Beware of the imperative effects on the partition structure,
it should not be shared, but only used locally. *)
@@ -846,5 +899,5 @@ let autoapply c i gl =
(Hints.Hint_db.transparent_state (Hints.searchtable_map i)) in
let cty = pf_unsafe_type_of gl c in
let ce = mk_clenv_from gl (c,cty) in
- let tac = unify_e_resolve false flags ((c,cty,Univ.ContextSet.empty),ce) in
+ let tac = { enter = fun gl -> (unify_e_resolve false flags).enter gl ((c,cty,Univ.ContextSet.empty),ce) } in
Proofview.V82.of_tactic (Proofview.Goal.nf_enter tac) gl
diff --git a/tactics/contradiction.ml b/tactics/contradiction.ml
index 6eebf4941b..ab6fb37fd1 100644
--- a/tactics/contradiction.ml
+++ b/tactics/contradiction.ml
@@ -13,6 +13,9 @@ open Tactics
open Coqlib
open Reductionops
open Misctypes
+open Sigma.Notations
+open Proofview.Notations
+open Context.Named.Declaration
(* Absurd *)
@@ -22,18 +25,20 @@ let mk_absurd_proof t =
mkLambda (Names.Name id,t,mkApp (mkRel 2,[|mkRel 1|])))
let absurd c =
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map sigma in
let j = Retyping.get_judgment_of env sigma c in
let sigma, j = Coercion.inh_coerce_to_sort Loc.ghost env sigma j in
let t = j.Environ.utj_val in
+ let tac =
Tacticals.New.tclTHENLIST [
- Proofview.Unsafe.tclEVARS sigma;
elim_type (build_coq_False ());
Simple.apply (mk_absurd_proof t)
- ]
- end
+ ] in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
let absurd c = absurd c
@@ -43,32 +48,33 @@ let absurd c = absurd c
let filter_hyp f tac =
let rec seek = function
| [] -> Proofview.tclZERO Not_found
- | (id,_,t)::rest when f t -> tac id
+ | d::rest when f (get_type d) -> tac (get_id d)
| _::rest -> seek rest in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
seek hyps
- end
+ end }
let contradiction_context =
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
let rec seek_neg l = match l with
| [] -> Tacticals.New.tclZEROMSG (Pp.str"No such contradiction")
- | (id,_,typ)::rest ->
- let typ = nf_evar sigma typ in
+ | d :: rest ->
+ let id = get_id d in
+ let typ = nf_evar sigma (get_type d) in
let typ = whd_betadeltaiota env sigma typ in
if is_empty_type typ then
simplest_elim (mkVar id)
else match kind_of_term typ with
| Prod (na,t,u) when is_empty_type u ->
(Proofview.tclORELSE
- (Proofview.Goal.enter begin fun gl ->
+ (Proofview.Goal.enter { enter = begin fun gl ->
let is_conv_leq = Tacmach.New.pf_apply is_conv_leq gl in
filter_hyp (fun typ -> is_conv_leq typ t)
(fun id' -> simplest_elim (mkApp (mkVar id,[|mkVar id'|])))
- end)
+ end })
begin function (e, info) -> match e with
| Not_found -> seek_neg rest
| e -> Proofview.tclZERO ~info e
@@ -77,7 +83,7 @@ let contradiction_context =
in
let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
seek_neg hyps
- end
+ end }
let is_negation_of env sigma typ t =
match kind_of_term (whd_betadeltaiota env sigma t) with
@@ -87,8 +93,8 @@ let is_negation_of env sigma typ t =
| _ -> false
let contradiction_term (c,lbind as cl) =
- Proofview.Goal.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
let type_of = Tacmach.New.pf_unsafe_type_of gl in
let typ = type_of c in
@@ -110,7 +116,7 @@ let contradiction_term (c,lbind as cl) =
| Not_found -> Tacticals.New.tclZEROMSG (Pp.str"Not a contradiction.")
| e -> Proofview.tclZERO ~info e
end
- end
+ end }
let contradiction = function
| None -> Tacticals.New.tclTHEN intros contradiction_context
diff --git a/tactics/coretactics.ml4 b/tactics/coretactics.ml4
index 3efa65eb54..6c02a7202f 100644
--- a/tactics/coretactics.ml4
+++ b/tactics/coretactics.ml4
@@ -13,11 +13,20 @@ open Names
open Locus
open Misctypes
open Genredexpr
+open Stdarg
+open Constrarg
+open Extraargs
+open Pcoq.Constr
+open Pcoq.Prim
+open Pcoq.Tactic
open Proofview.Notations
+open Sigma.Notations
DECLARE PLUGIN "coretactics"
+(** Basic tactics *)
+
TACTIC EXTEND reflexivity
[ "reflexivity" ] -> [ Tactics.intros_reflexivity ]
END
@@ -74,15 +83,13 @@ END
TACTIC EXTEND left_with
[ "left" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES false (Tactics.left_with_bindings false bl) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.left_with_bindings false bl)
]
END
TACTIC EXTEND eleft_with
[ "eleft" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES true (Tactics.left_with_bindings true bl) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.left_with_bindings true bl)
]
END
@@ -98,15 +105,13 @@ END
TACTIC EXTEND right_with
[ "right" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES false (Tactics.right_with_bindings false bl) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.right_with_bindings false bl)
]
END
TACTIC EXTEND eright_with
[ "eright" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES true (Tactics.right_with_bindings true bl) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.right_with_bindings true bl)
]
END
@@ -115,28 +120,22 @@ END
TACTIC EXTEND constructor
[ "constructor" ] -> [ Tactics.any_constructor false None ]
| [ "constructor" int_or_var(i) ] -> [
- let i = Tacinterp.interp_int_or_var ist i in
Tactics.constructor_tac false None i NoBindings
]
| [ "constructor" int_or_var(i) "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma; it = bl } = bl in
- let i = Tacinterp.interp_int_or_var ist i in
- let tac = Tactics.constructor_tac false None i bl in
- Tacticals.New.tclWITHHOLES false tac sigma
+ let tac bl = Tactics.constructor_tac false None i bl in
+ Tacticals.New.tclDELAYEDWITHHOLES false bl tac
]
END
TACTIC EXTEND econstructor
[ "econstructor" ] -> [ Tactics.any_constructor true None ]
| [ "econstructor" int_or_var(i) ] -> [
- let i = Tacinterp.interp_int_or_var ist i in
Tactics.constructor_tac true None i NoBindings
]
| [ "econstructor" int_or_var(i) "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma; it = bl } = bl in
- let i = Tacinterp.interp_int_or_var ist i in
- let tac = Tactics.constructor_tac true None i bl in
- Tacticals.New.tclWITHHOLES true tac sigma
+ let tac bl = Tactics.constructor_tac true None i bl in
+ Tacticals.New.tclDELAYEDWITHHOLES true bl tac
]
END
@@ -144,18 +143,25 @@ END
TACTIC EXTEND specialize
[ "specialize" constr_with_bindings(c) ] -> [
- let { Evd.sigma = sigma; it = c } = c in
- let specialize = Proofview.V82.tactic (Tactics.specialize c) in
- Tacticals.New.tclWITHHOLES false specialize sigma
+ Tacticals.New.tclDELAYEDWITHHOLES false c Tactics.specialize
]
END
TACTIC EXTEND symmetry
[ "symmetry" ] -> [ Tactics.intros_symmetry {onhyps=Some[];concl_occs=AllOccurrences} ]
+| [ "symmetry" clause_dft_concl(cl) ] -> [ Tactics.intros_symmetry cl ]
END
(** Split *)
+let rec delayed_list = function
+| [] -> { Tacexpr.delayed = fun _ sigma -> Sigma.here [] sigma }
+| x :: l ->
+ { Tacexpr.delayed = fun env sigma ->
+ let Sigma (x, sigma, p) = x.Tacexpr.delayed env sigma in
+ let Sigma (l, sigma, q) = (delayed_list l).Tacexpr.delayed env sigma in
+ Sigma (x :: l, sigma, p +> q) }
+
TACTIC EXTEND split
[ "split" ] -> [ Tactics.split_with_bindings false [NoBindings] ]
END
@@ -166,15 +172,27 @@ END
TACTIC EXTEND split_with
[ "split" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES false (Tactics.split_with_bindings false [bl]) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES false bl (fun bl -> Tactics.split_with_bindings false [bl])
]
END
TACTIC EXTEND esplit_with
[ "esplit" "with" bindings(bl) ] -> [
- let { Evd.sigma = sigma ; it = bl } = bl in
- Tacticals.New.tclWITHHOLES true (Tactics.split_with_bindings true [bl]) sigma
+ Tacticals.New.tclDELAYEDWITHHOLES true bl (fun bl -> Tactics.split_with_bindings true [bl])
+ ]
+END
+
+TACTIC EXTEND exists
+ [ "exists" ] -> [ Tactics.split_with_bindings false [NoBindings] ]
+| [ "exists" ne_bindings_list_sep(bll, ",") ] -> [
+ Tacticals.New.tclDELAYEDWITHHOLES false (delayed_list bll) (fun bll -> Tactics.split_with_bindings false bll)
+ ]
+END
+
+TACTIC EXTEND eexists
+ [ "eexists" ] -> [ Tactics.split_with_bindings true [NoBindings] ]
+| [ "eexists" ne_bindings_list_sep(bll, ",") ] -> [
+ Tacticals.New.tclDELAYEDWITHHOLES true (delayed_list bll) (fun bll -> Tactics.split_with_bindings true bll)
]
END
@@ -184,6 +202,15 @@ TACTIC EXTEND intros_until
[ "intros" "until" quantified_hypothesis(h) ] -> [ Tactics.intros_until h ]
END
+(** Move *)
+
+TACTIC EXTEND move
+ [ "move" hyp(id) "at" "top" ] -> [ Proofview.V82.tactic (Tactics.move_hyp id MoveFirst) ]
+| [ "move" hyp(id) "at" "bottom" ] -> [ Proofview.V82.tactic (Tactics.move_hyp id MoveLast) ]
+| [ "move" hyp(id) "after" hyp(h) ] -> [ Proofview.V82.tactic (Tactics.move_hyp id (MoveAfter h)) ]
+| [ "move" hyp(id) "before" hyp(h) ] -> [ Proofview.V82.tactic (Tactics.move_hyp id (MoveBefore h)) ]
+END
+
(** Revert *)
TACTIC EXTEND revert
@@ -206,6 +233,42 @@ TACTIC EXTEND admit
[ "admit" ] -> [ Proofview.give_up ]
END
+(* Fix *)
+
+TACTIC EXTEND fix
+ [ "fix" natural(n) ] -> [ Proofview.V82.tactic (Tactics.fix None n) ]
+| [ "fix" ident(id) natural(n) ] -> [ Proofview.V82.tactic (Tactics.fix (Some id) n) ]
+END
+
+(* Cofix *)
+
+TACTIC EXTEND cofix
+ [ "cofix" ] -> [ Proofview.V82.tactic (Tactics.cofix None) ]
+| [ "cofix" ident(id) ] -> [ Proofview.V82.tactic (Tactics.cofix (Some id)) ]
+END
+
+(* Clear *)
+
+TACTIC EXTEND clear
+ [ "clear" hyp_list(ids) ] -> [
+ if List.is_empty ids then Tactics.keep []
+ else Proofview.V82.tactic (Tactics.clear ids)
+ ]
+| [ "clear" "-" ne_hyp_list(ids) ] -> [ Tactics.keep ids ]
+END
+
+(* Clearbody *)
+
+TACTIC EXTEND clearbody
+ [ "clearbody" ne_hyp_list(ids) ] -> [ Tactics.clear_body ids ]
+END
+
+(* Generalize dependent *)
+
+TACTIC EXTEND generalize_dependent
+ [ "generalize" "dependent" constr(c) ] -> [ Proofview.V82.tactic (Tactics.generalize_dep c) ]
+END
+
(* Table of "pervasives" macros tactics (e.g. auto, simpl, etc.) *)
open Tacexpr
@@ -224,9 +287,6 @@ let initial_atomic () =
"compute", TacReduce(Cbv Redops.all_flags,nocl);
"intro", TacIntroMove(None,MoveLast);
"intros", TacIntroPattern [];
- "cofix", TacCofix None;
- "trivial", TacTrivial (Off,[],None);
- "auto", TacAuto(Off,None,[],None);
]
in
let iter (s, t) = Tacenv.register_ltac false false (Id.of_string s) t in
diff --git a/tactics/eauto.ml4 b/tactics/eauto.ml
index 568b1d17c0..0449467598 100644
--- a/tactics/eauto.ml4
+++ b/tactics/eauto.ml
@@ -6,8 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i camlp4deps: "grammar/grammar.cma" i*)
-
open Pp
open Errors
open Util
@@ -28,33 +26,41 @@ open Misctypes
open Locus
open Locusops
open Hints
-
-DECLARE PLUGIN "eauto"
+open Proofview.Notations
let eauto_unif_flags = auto_flags_of_state full_transparent_state
-let e_give_exact ?(flags=eauto_unif_flags) c gl =
- let t1 = (pf_unsafe_type_of gl c) and t2 = pf_concl gl in
+let e_give_exact ?(flags=eauto_unif_flags) c =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let t1 = Tacmach.New.pf_unsafe_type_of gl c in
+ let t2 = Tacmach.New.pf_concl gl in
if occur_existential t1 || occur_existential t2 then
- tclTHEN (Proofview.V82.of_tactic (Clenvtac.unify ~flags t1)) (exact_no_check c) gl
- else Proofview.V82.of_tactic (exact_check c) gl
+ Tacticals.New.tclTHEN (Clenvtac.unify ~flags t1) (Proofview.V82.tactic (exact_no_check c))
+ else exact_check c
+ end }
let assumption id = e_give_exact (mkVar id)
-let e_assumption gl =
- tclFIRST (List.map assumption (pf_ids_of_hyps gl)) gl
-
-TACTIC EXTEND eassumption
-| [ "eassumption" ] -> [ Proofview.V82.tactic e_assumption ]
-END
-
-TACTIC EXTEND eexact
-| [ "eexact" constr(c) ] -> [ Proofview.V82.tactic (e_give_exact c) ]
-END
-
-let registered_e_assumption gl =
- tclFIRST (List.map (fun id gl -> e_give_exact (mkVar id) gl)
- (pf_ids_of_hyps gl)) gl
+let e_assumption =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ Tacticals.New.tclFIRST (List.map assumption (Tacmach.New.pf_ids_of_hyps gl))
+ end }
+
+let registered_e_assumption =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ Tacticals.New.tclFIRST (List.map (fun id -> e_give_exact (mkVar id))
+ (Tacmach.New.pf_ids_of_hyps gl))
+ end }
+
+let eval_uconstrs ist cs =
+ let flags = {
+ Pretyping.use_typeclasses = false;
+ use_unif_heuristics = true;
+ use_hook = Some Pfedit.solve_by_implicit_tactic;
+ fail_evar = false;
+ expand_evars = true
+ } in
+ List.map (fun c -> Tacinterp.type_uconstr ~flags ist c) cs
(************************************************************************)
(* PROLOG tactic *)
@@ -83,7 +89,7 @@ let one_step l gl =
[Proofview.V82.of_tactic Tactics.intro]
@ (List.map (fun c -> Proofview.V82.of_tactic (Tactics.Simple.eapply c)) (List.map mkVar (pf_ids_of_hyps gl)))
@ (List.map (fun c -> Proofview.V82.of_tactic (Tactics.Simple.eapply c)) l)
- @ (List.map assumption (pf_ids_of_hyps gl))
+ @ (List.map (fun c -> Proofview.V82.of_tactic (assumption c)) (pf_ids_of_hyps gl))
let rec prolog l n gl =
if n <= 0 then error "prolog - failure";
@@ -94,20 +100,18 @@ let out_term = function
| IsConstr (c, _) -> c
| IsGlobRef gr -> fst (Universes.fresh_global_instance (Global.env ()) gr)
-let prolog_tac l n gl =
- let l = List.map (fun x -> out_term (pf_apply (prepare_hint false (false,true)) gl x)) l in
- let n =
- match n with
- | ArgArg n -> n
- | _ -> error "Prolog called with a non closed argument."
+let prolog_tac l n =
+ Proofview.V82.tactic begin fun gl ->
+ let map c =
+ let (c, sigma) = Tactics.run_delayed (pf_env gl) (project gl) c in
+ let c = pf_apply (prepare_hint false (false,true)) gl (sigma, c) in
+ out_term c
in
+ let l = List.map map l in
try (prolog l n gl)
with UserError ("Refiner.tclFIRST",_) ->
errorlabstrm "Prolog.prolog" (str "Prolog failed.")
-
-TACTIC EXTEND prolog
-| [ "prolog" "[" open_constr_list(l) "]" int_or_var(n) ] -> [ Proofview.V82.tactic (prolog_tac l n) ]
-END
+ end
open Auto
open Unification
@@ -119,15 +123,14 @@ open Unification
let priority l = List.map snd (List.filter (fun (pr,_) -> Int.equal pr 0) l)
let unify_e_resolve poly flags (c,clenv) =
- Proofview.Goal.nf_enter begin
- fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let clenv', c = connect_hint_clenv poly c clenv gl in
Proofview.V82.tactic
(fun gls ->
let clenv' = clenv_unique_resolver ~flags clenv' gls in
tclTHEN (Refiner.tclEVARUNIVCONTEXT (Evd.evar_universe_context clenv'.evd))
(Proofview.V82.of_tactic (Tactics.Simple.eapply c)) gls)
- end
+ end }
let hintmap_of hdc concl =
match hdc with
@@ -143,19 +146,21 @@ let e_exact poly flags (c,clenv) =
if poly then Clenv.refresh_undefined_univs clenv
else clenv, Univ.empty_level_subst
in e_give_exact (* ~flags *) (Vars.subst_univs_level_constr subst c)
-
-let rec e_trivial_fail_db db_list local_db goal =
+
+let rec e_trivial_fail_db db_list local_db =
+ let next = Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let d = Tacmach.New.pf_last_hyp gl in
+ let hintl = make_resolve_hyp (Tacmach.New.pf_env gl) (Tacmach.New.project gl) d in
+ e_trivial_fail_db db_list (Hint_db.add_list (Tacmach.New.pf_env gl) (Tacmach.New.project gl) hintl local_db)
+ end } in
+ Proofview.Goal.enter { enter = begin fun gl ->
let tacl =
registered_e_assumption ::
- (tclTHEN (Proofview.V82.of_tactic Tactics.intro)
- (function g'->
- let d = pf_last_hyp g' in
- let hintl = make_resolve_hyp (pf_env g') (project g') d in
- (e_trivial_fail_db db_list
- (Hint_db.add_list (pf_env g') (project g') hintl local_db) g'))) ::
- (List.map fst (e_trivial_resolve db_list local_db (pf_concl goal)) )
+ (Tacticals.New.tclTHEN Tactics.intro next) ::
+ (List.map fst (e_trivial_resolve db_list local_db (Tacmach.New.pf_nf_concl gl)))
in
- tclFIRST (List.map tclCOMPLETE tacl) goal
+ Tacticals.New.tclFIRST (List.map Tacticals.New.tclCOMPLETE tacl)
+ end }
and e_my_find_search db_list local_db hdc concl =
let hint_of_db = hintmap_of hdc concl in
@@ -174,14 +179,14 @@ and e_my_find_search db_list local_db hdc concl =
let tac = function
| Res_pf (term,cl) -> unify_resolve poly st (term,cl)
| ERes_pf (term,cl) -> unify_e_resolve poly st (term,cl)
- | Give_exact (c,cl) -> Proofview.V82.tactic (e_exact poly st (c,cl))
+ | Give_exact (c,cl) -> e_exact poly st (c,cl)
| Res_pf_THEN_trivial_fail (term,cl) ->
- Proofview.V82.tactic (tclTHEN (Proofview.V82.of_tactic (unify_e_resolve poly st (term,cl)))
- (e_trivial_fail_db db_list local_db))
- | Unfold_nth c -> Proofview.V82.tactic (reduce (Unfold [AllOccurrences,c]) onConcl)
+ Tacticals.New.tclTHEN (unify_e_resolve poly st (term,cl))
+ (e_trivial_fail_db db_list local_db)
+ | Unfold_nth c -> reduce (Unfold [AllOccurrences,c]) onConcl
| Extern tacast -> conclPattern concl p tacast
in
- let tac = Proofview.V82.of_tactic (run_hint t tac) in
+ let tac = run_hint t tac in
(tac, lazy (pr_hint t)))
in
List.map tac_of_hint hintl
@@ -210,7 +215,7 @@ type search_state = {
dblist : hint_db list;
localdb : hint_db list;
prev : prev_search_state;
- local_lemmas : Evd.open_constr list;
+ local_lemmas : Tacexpr.delayed_open_constr list;
}
and prev_search_state = (* for info eauto *)
@@ -234,7 +239,7 @@ module SearchProblem = struct
| [] -> []
| (tac, cost, pptac) :: tacl ->
try
- let lgls = apply_tac_list tac glls in
+ let lgls = apply_tac_list (Proofview.V82.of_tactic tac) glls in
(* let gl = Proof_trees.db_pr_goal (List.hd (sig_it glls)) in *)
(* msg (hov 1 (pptac ++ str" gives: \n" ++ pr_goals lgls ++ str"\n")); *)
(lgls, cost, pptac) :: aux tacl
@@ -272,7 +277,7 @@ module SearchProblem = struct
prev = ps; local_lemmas = s.local_lemmas}) l
in
let intro_tac =
- let l = filter_tactics s.tacres [Proofview.V82.of_tactic Tactics.intro, (-1), lazy (str "intro")] in
+ let l = filter_tactics s.tacres [Tactics.intro, (-1), lazy (str "intro")] in
List.map
(fun (lgls, cost, pp) ->
let g' = first_goal lgls in
@@ -422,83 +427,16 @@ let full_eauto ?(debug=Off) n lems gl =
tclTRY (e_search_auto debug n lems db_list) gl
let gen_eauto ?(debug=Off) np lems = function
- | None -> full_eauto ~debug np lems
- | Some l -> eauto ~debug np lems l
+ | None -> Proofview.V82.tactic (full_eauto ~debug np lems)
+ | Some l -> Proofview.V82.tactic (eauto ~debug np lems l)
let make_depth = function
| None -> !default_search_depth
- | Some (ArgArg d) -> d
- | _ -> error "eauto called with a non closed argument."
+ | Some d -> d
let make_dimension n = function
| None -> (true,make_depth n)
- | Some (ArgArg d) -> (false,d)
- | _ -> error "eauto called with a non closed argument."
-
-open Genarg
-
-(* Hint bases *)
-
-let pr_hintbases _prc _prlc _prt = Pptactic.pr_hintbases
-
-ARGUMENT EXTEND hintbases
- TYPED AS preident_list_opt
- PRINTED BY pr_hintbases
-| [ "with" "*" ] -> [ None ]
-| [ "with" ne_preident_list(l) ] -> [ Some l ]
-| [ ] -> [ Some [] ]
-END
-
-let pr_constr_coma_sequence prc _ _ =
- prlist_with_sep pr_comma (fun (_,c) -> prc c)
-
-ARGUMENT EXTEND constr_coma_sequence
- TYPED AS open_constr_list
- PRINTED BY pr_constr_coma_sequence
-| [ open_constr(c) "," constr_coma_sequence(l) ] -> [ c::l ]
-| [ open_constr(c) ] -> [ [c] ]
-END
-
-let pr_auto_using prc _prlc _prt = Pptactic.pr_auto_using (fun (_,c) -> prc c)
-
-ARGUMENT EXTEND auto_using
- TYPED AS open_constr_list
- PRINTED BY pr_auto_using
-| [ "using" constr_coma_sequence(l) ] -> [ l ]
-| [ ] -> [ [] ]
-END
-
-TACTIC EXTEND eauto
-| [ "eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
- hintbases(db) ] ->
- [ Proofview.V82.tactic (gen_eauto (make_dimension n p) lems db) ]
-END
-
-TACTIC EXTEND new_eauto
-| [ "new" "auto" int_or_var_opt(n) auto_using(lems)
- hintbases(db) ] ->
- [ match db with
- | None -> new_full_auto (make_depth n) lems
- | Some l -> new_auto (make_depth n) lems l ]
-END
-
-TACTIC EXTEND debug_eauto
-| [ "debug" "eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
- hintbases(db) ] ->
- [ Proofview.V82.tactic (gen_eauto ~debug:Debug (make_dimension n p) lems db) ]
-END
-
-TACTIC EXTEND info_eauto
-| [ "info_eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
- hintbases(db) ] ->
- [ Proofview.V82.tactic (gen_eauto ~debug:Info (make_dimension n p) lems db) ]
-END
-
-TACTIC EXTEND dfs_eauto
-| [ "dfs" "eauto" int_or_var_opt(p) auto_using(lems)
- hintbases(db) ] ->
- [ Proofview.V82.tactic (gen_eauto (true, make_depth p) lems db) ]
-END
+ | Some d -> (false,d)
let cons a l = a :: l
@@ -512,27 +450,26 @@ let autounfolds db occs cls gl =
let ids = Idset.filter (fun id -> List.mem id hyps) ids in
Cset.fold (fun cst -> cons (AllOccurrences, EvalConstRef cst)) csts
(Id.Set.fold (fun id -> cons (AllOccurrences, EvalVarRef id)) ids [])) db)
- in unfold_option unfolds cls gl
+ in Proofview.V82.of_tactic (unfold_option unfolds cls) gl
-let autounfold db cls gl =
+let autounfold db cls =
+ Proofview.V82.tactic begin fun gl ->
let cls = concrete_clause_of (fun () -> pf_ids_of_hyps gl) cls in
let tac = autounfolds db in
tclMAP (function
| OnHyp (id,occs,where) -> tac occs (Some (id,where))
| OnConcl occs -> tac occs None)
cls gl
+ end
-let autounfold_tac db cls gl =
+let autounfold_tac db cls =
+ Proofview.tclUNIT () >>= fun () ->
let dbs = match db with
| None -> String.Set.elements (current_db_names ())
| Some [] -> ["core"]
| Some l -> l
in
- autounfold dbs cls gl
-
-TACTIC EXTEND autounfold
-| [ "autounfold" hintbases(db) clause(cl) ] -> [ Proofview.V82.tactic (autounfold_tac db cl) ]
-END
+ autounfold dbs cls
let unfold_head env (ids, csts) c =
let rec aux c =
@@ -567,7 +504,7 @@ let unfold_head env (ids, csts) c =
in aux c
let autounfold_one db cl =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let concl = Proofview.Goal.concl gl in
let st =
@@ -586,91 +523,4 @@ let autounfold_one db cl =
| Some hyp -> change_in_hyp None (make_change_arg c') hyp
| None -> convert_concl_no_check c' DEFAULTcast
else Tacticals.New.tclFAIL 0 (str "Nothing to unfold")
- end
-
-(* Cset.fold (fun cst -> cons (all_occurrences, EvalConstRef cst)) csts *)
-(* (Id.Set.fold (fun id -> cons (all_occurrences, EvalVarRef id)) ids [])) db) *)
-(* in unfold_option unfolds cl *)
-
-(* let db = try searchtable_map dbname *)
-(* with Not_found -> errorlabstrm "autounfold" (str "Unknown database " ++ str dbname) *)
-(* in *)
-(* let (ids, csts) = Hint_db.unfolds db in *)
-(* Cset.fold (fun cst -> tclORELSE (unfold_option [(occ, EvalVarRef id)] cst)) csts *)
-(* (Id.Set.fold (fun id -> tclORELSE (unfold_option [(occ, EvalVarRef id)] cl) ids acc))) *)
-(* (tclFAIL 0 (mt())) db *)
-
-TACTIC EXTEND autounfold_one
-| [ "autounfold_one" hintbases(db) "in" hyp(id) ] ->
- [ autounfold_one (match db with None -> ["core"] | Some x -> "core"::x) (Some (id, InHyp)) ]
-| [ "autounfold_one" hintbases(db) ] ->
- [ autounfold_one (match db with None -> ["core"] | Some x -> "core"::x) None ]
- END
-
-TACTIC EXTEND autounfoldify
-| [ "autounfoldify" constr(x) ] -> [
- Proofview.V82.tactic (
- let db = match kind_of_term x with
- | Const (c,_) -> Label.to_string (con_label c)
- | _ -> assert false
- in autounfold ["core";db] onConcl
- )]
-END
-
-TACTIC EXTEND unify
-| ["unify" constr(x) constr(y) ] -> [ unify x y ]
-| ["unify" constr(x) constr(y) "with" preident(base) ] -> [
- let table = try Some (searchtable_map base) with Not_found -> None in
- match table with
- | None ->
- let msg = str "Hint table " ++ str base ++ str " not found" in
- Tacticals.New.tclZEROMSG msg
- | Some t ->
- let state = Hint_db.transparent_state t in
- unify ~state x y
- ]
-END
-
-
-TACTIC EXTEND convert_concl_no_check
-| ["convert_concl_no_check" constr(x) ] -> [ convert_concl_no_check x DEFAULTcast ]
-END
-
-let pr_hints_path_atom _ _ _ = Hints.pp_hints_path_atom
-
-ARGUMENT EXTEND hints_path_atom
- TYPED AS hints_path_atom
- PRINTED BY pr_hints_path_atom
-| [ global_list(g) ] -> [ PathHints (List.map Nametab.global g) ]
-| [ "*" ] -> [ PathAny ]
-END
-
-let pr_hints_path prc prx pry c = Hints.pp_hints_path c
-
-ARGUMENT EXTEND hints_path
- TYPED AS hints_path
- PRINTED BY pr_hints_path
-| [ "(" hints_path(p) ")" ] -> [ p ]
-| [ "!" hints_path(p) ] -> [ PathStar p ]
-| [ "emp" ] -> [ PathEmpty ]
-| [ "eps" ] -> [ PathEpsilon ]
-| [ hints_path_atom(a) ] -> [ PathAtom a ]
-| [ hints_path(p) "|" hints_path(q) ] -> [ PathOr (p, q) ]
-| [ hints_path(p) ";" hints_path(q) ] -> [ PathSeq (p, q) ]
-END
-
-let pr_hintbases _prc _prlc _prt = Pptactic.pr_hintbases
-
-ARGUMENT EXTEND opthints
- TYPED AS preident_list_opt
- PRINTED BY pr_hintbases
-| [ ":" ne_preident_list(l) ] -> [ Some l ]
-| [ ] -> [ None ]
-END
-
-VERNAC COMMAND EXTEND HintCut CLASSIFIED AS SIDEFF
-| [ "Hint" "Cut" "[" hints_path(p) "]" opthints(dbnames) ] -> [
- let entry = HintsCutEntry p in
- Hints.add_hints (Locality.make_section_locality (Locality.LocalityFixme.consume ()))
- (match dbnames with None -> ["core"] | Some l -> l) entry ]
-END
+ end }
diff --git a/tactics/eauto.mli b/tactics/eauto.mli
index 1bb15d6cb9..8812093d5f 100644
--- a/tactics/eauto.mli
+++ b/tactics/eauto.mli
@@ -8,31 +8,26 @@
open Term
open Proof_type
-open Evd
open Hints
-val hintbases : hint_db_name list option Pcoq.Gram.entry
+val e_assumption : unit Proofview.tactic
-val wit_hintbases : hint_db_name list option Genarg.uniform_genarg_type
+val registered_e_assumption : unit Proofview.tactic
-val wit_auto_using :
- (Tacexpr.open_constr_expr list,
- Tacexpr.open_glob_constr list, Evd.open_constr list)
- Genarg.genarg_type
+val e_give_exact : ?flags:Unification.unify_flags -> constr -> unit Proofview.tactic
+val prolog_tac : Tacexpr.delayed_open_constr list -> int -> unit Proofview.tactic
-val e_assumption : tactic
-
-val registered_e_assumption : tactic
-
-val e_give_exact : ?flags:Unification.unify_flags -> constr -> tactic
-
-val gen_eauto : ?debug:Tacexpr.debug -> bool * int -> open_constr list ->
- hint_db_name list option -> tactic
+val gen_eauto : ?debug:Tacexpr.debug -> bool * int -> Tacexpr.delayed_open_constr list ->
+ hint_db_name list option -> unit Proofview.tactic
val eauto_with_bases :
?debug:Tacexpr.debug ->
bool * int ->
- open_constr list -> hint_db list -> Proof_type.tactic
+ Tacexpr.delayed_open_constr list -> hint_db list -> Proof_type.tactic
+
+val autounfold : hint_db_name list -> Locus.clause -> unit Proofview.tactic
+val autounfold_tac : hint_db_name list option -> Locus.clause -> unit Proofview.tactic
+val autounfold_one : hint_db_name list -> Locus.hyp_location option -> unit Proofview.tactic
-val autounfold : hint_db_name list -> Locus.clause -> tactic
+val make_dimension : int option -> int option -> bool * int
diff --git a/tactics/elim.ml b/tactics/elim.ml
index 1c7e1f0d55..d441074f6a 100644
--- a/tactics/elim.ml
+++ b/tactics/elim.ml
@@ -16,29 +16,21 @@ open Tacmach.New
open Tacticals.New
open Tactics
open Proofview.Notations
+open Context.Named.Declaration
+(* Supposed to be called without as clause *)
let introElimAssumsThen tac ba =
- let nassums =
- List.fold_left
- (fun acc b -> if b then acc+2 else acc+1)
- 0 ba.Tacticals.branchsign
- in
- let introElimAssums = tclDO nassums intro in
+ assert (ba.Tacticals.branchnames == []);
+ let introElimAssums = tclDO ba.Tacticals.nassums intro in
(tclTHEN introElimAssums (elim_on_ba tac ba))
+(* Supposed to be called with a non-recursive scheme *)
let introCaseAssumsThen tac ba =
- let case_thin_sign =
- List.flatten
- (List.map (function b -> if b then [false;true] else [false])
- ba.Tacticals.branchsign)
- in
- let n1 = List.length case_thin_sign in
+ let n1 = List.length ba.Tacticals.branchsign in
let n2 = List.length ba.Tacticals.branchnames in
let (l1,l2),l3 =
if n1 < n2 then List.chop n1 ba.Tacticals.branchnames, []
- else
- (ba.Tacticals.branchnames, []),
- if n1 > n2 then snd (List.chop n2 case_thin_sign) else [] in
+ else (ba.Tacticals.branchnames, []), List.make (n1-n2) false in
let introCaseAssums =
tclTHEN (intro_patterns l1) (intros_clearing l3) in
(tclTHEN introCaseAssums (case_on_ba (tac l2) ba))
@@ -84,7 +76,7 @@ let tmphyp_name = Id.of_string "_TmpHyp"
let up_to_delta = ref false (* true *)
let general_decompose recognizer c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let type_of = pf_unsafe_type_of gl in
let typc = type_of c in
tclTHENS (cut typc)
@@ -93,11 +85,11 @@ let general_decompose recognizer c =
(ifOnHyp recognizer (general_decompose_aux recognizer)
(fun id -> Proofview.V82.tactic (clear [id]))));
Proofview.V82.tactic (exact_no_check c) ]
- end
+ end }
let head_in indl t gl =
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
try
let ity,_ =
if !up_to_delta
@@ -107,10 +99,10 @@ let head_in indl t gl =
with Not_found -> false
let decompose_these c l =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let indl = List.map (fun x -> x, Univ.Instance.empty) l in
general_decompose (fun (_,t) -> head_in indl t gl) c
- end
+ end }
let decompose_and c =
general_decompose
@@ -138,7 +130,7 @@ let induction_trailer abs_i abs_j bargs =
(tclDO (abs_j - abs_i) intro)
(onLastHypId
(fun id ->
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let idty = pf_unsafe_type_of gl (mkVar id) in
let fvty = global_vars (pf_env gl) idty in
let possible_bring_hyps =
@@ -146,7 +138,8 @@ let induction_trailer abs_i abs_j bargs =
in
let (hyps,_) =
List.fold_left
- (fun (bring_ids,leave_ids) (cid,_,_ as d) ->
+ (fun (bring_ids,leave_ids) d ->
+ let cid = get_id d in
if not (List.mem cid leave_ids)
then (d::bring_ids,leave_ids)
else (bring_ids,cid::leave_ids))
@@ -154,15 +147,14 @@ let induction_trailer abs_i abs_j bargs =
in
let ids = List.rev (ids_of_named_context hyps) in
(tclTHENLIST
- [bring_hyps hyps; tclTRY (Proofview.V82.tactic (clear ids));
- simple_elimination (mkVar id)])
- end
+ [revert ids; simple_elimination (mkVar id)])
+ end }
))
let double_ind h1 h2 =
- Proofview.Goal.nf_enter begin fun gl ->
- let abs_i = of_old (depth_of_quantified_hypothesis true h1) gl in
- let abs_j = of_old (depth_of_quantified_hypothesis true h2) gl in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let abs_i = depth_of_quantified_hypothesis true h1 gl in
+ let abs_j = depth_of_quantified_hypothesis true h2 gl in
let abs =
if abs_i < abs_j then Proofview.tclUNIT (abs_i,abs_j) else
if abs_i > abs_j then Proofview.tclUNIT (abs_j,abs_i) else
@@ -173,7 +165,7 @@ let double_ind h1 h2 =
(fun id ->
elimination_then
(introElimAssumsThen (induction_trailer abs_i abs_j)) (mkVar id))))
- end
+ end }
let h_double_induction = double_ind
diff --git a/tactics/elimschemes.ml b/tactics/elimschemes.ml
index 4ff774b8e5..de28189023 100644
--- a/tactics/elimschemes.ml
+++ b/tactics/elimschemes.ml
@@ -18,6 +18,7 @@ open Indrec
open Declarations
open Typeops
open Ind_tables
+open Sigma.Notations
(* Induction/recursion schemes *)
@@ -102,10 +103,10 @@ let rec_dep_scheme_kind_from_type =
let build_case_analysis_scheme_in_type dep sort ind =
let env = Global.env () in
- let sigma = Evd.from_env env in
- let sigma, indu = Evd.fresh_inductive_instance env sigma ind in
- let sigma, c = build_case_analysis_scheme env sigma indu dep sort in
- c, Evd.evar_universe_context sigma
+ let sigma = Sigma.Unsafe.of_evar_map (Evd.from_env env) in
+ let Sigma (indu, sigma, _) = Sigma.fresh_inductive_instance env sigma ind in
+ let Sigma (c, sigma, _) = build_case_analysis_scheme env sigma indu dep sort in
+ c, Evd.evar_universe_context (Sigma.to_evar_map sigma)
let case_scheme_kind_from_type =
declare_individual_scheme_object "_case_nodep"
diff --git a/tactics/eqdecide.ml b/tactics/eqdecide.ml
index 8ba8f7b6d7..7d0df2f522 100644
--- a/tactics/eqdecide.ml
+++ b/tactics/eqdecide.ml
@@ -12,8 +12,6 @@
(* by Eduardo Gimenez *)
(************************************************************************)
-(*i camlp4deps: "grammar/grammar.cma" i*)
-
open Errors
open Util
open Names
@@ -27,6 +25,7 @@ open Constr_matching
open Hipattern
open Tacmach.New
open Coqlib
+open Proofview.Notations
(* This file containts the implementation of the tactics ``Decide
Equality'' and ``Compare''. They can be used to decide the
@@ -122,7 +121,7 @@ let diseqCase hyps eqonleft =
(tclTHEN (intro_using diseq)
(tclTHEN (choose_noteq eqonleft)
(tclTHEN (rewrite_and_clear (List.rev hyps))
- (tclTHEN (Proofview.V82.tactic red_in_concl)
+ (tclTHEN (red_in_concl)
(tclTHEN (intro_using absurd)
(tclTHEN (Simple.apply (mkVar diseq))
(tclTHEN (Extratactics.injHyp absurd)
@@ -146,7 +145,7 @@ let rec solveArg hyps eqonleft op largs rargs = match largs, rargs with
intros_reflexivity;
]
| a1 :: largs, a2 :: rargs ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let rectype = pf_unsafe_type_of gl a1 in
let decide = mkDecideEqGoal eqonleft op rectype a1 a2 in
let tac hyp = solveArg (hyp :: hyps) eqonleft op largs rargs in
@@ -154,13 +153,13 @@ let rec solveArg hyps eqonleft op largs rargs = match largs, rargs with
if eqonleft then [eqCase tac;diseqCase hyps eqonleft;default_auto]
else [diseqCase hyps eqonleft;eqCase tac;default_auto] in
(tclTHENS (elim_type decide) subtacs)
- end
+ end }
| _ -> invalid_arg "List.fold_right2"
let solveEqBranch rectype =
Proofview.tclORELSE
begin
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let concl = pf_nf_concl gl in
match_eqdec concl >>= fun (eqonleft,op,lhs,rhs,_) ->
let (mib,mip) = Global.lookup_inductive rectype in
@@ -169,7 +168,7 @@ let solveEqBranch rectype =
let rargs = getargs rhs
and largs = getargs lhs in
solveArg [] eqonleft op largs rargs
- end
+ end }
end
begin function (e, info) -> match e with
| PatternMatchingFailure -> Tacticals.New.tclZEROMSG (Pp.str"Unexpected conclusion!")
@@ -185,7 +184,7 @@ let hd_app c = match kind_of_term c with
let decideGralEquality =
Proofview.tclORELSE
begin
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let concl = pf_nf_concl gl in
match_eqdec concl >>= fun (eqonleft,_,c1,c2,typ) ->
let headtyp = hd_app (pf_compute gl typ) in
@@ -196,7 +195,7 @@ let decideGralEquality =
(tclTHEN
(mkBranches c1 c2)
(tclORELSE (solveNoteqBranch eqonleft) (solveEqBranch rectype)))
- end
+ end }
end
begin function (e, info) -> match e with
| PatternMatchingFailure ->
@@ -207,20 +206,20 @@ let decideGralEquality =
let decideEqualityGoal = tclTHEN intros decideGralEquality
let decideEquality rectype =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let decide = mkGenDecideEqGoal rectype gl in
(tclTHENS (cut decide) [default_auto;decideEqualityGoal])
- end
+ end }
(* The tactic Compare *)
let compare c1 c2 =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let rectype = pf_unsafe_type_of gl c1 in
let decide = mkDecideEqGoal true (build_coq_sumbool ()) rectype c1 c2 in
(tclTHENS (cut decide)
[(tclTHEN intro
(tclTHEN (onLastHyp simplest_case) clear_last));
decideEquality rectype])
- end
+ end }
diff --git a/tactics/eqschemes.ml b/tactics/eqschemes.ml
index c9764af1c1..a03489c805 100644
--- a/tactics/eqschemes.ml
+++ b/tactics/eqschemes.ml
@@ -49,7 +49,6 @@ open Util
open Names
open Term
open Vars
-open Context
open Declarations
open Environ
open Inductive
@@ -58,6 +57,8 @@ open Namegen
open Inductiveops
open Ind_tables
open Indrec
+open Sigma.Notations
+open Context.Rel.Declaration
let hid = Id.of_string "H"
let xid = Id.of_string "X"
@@ -70,8 +71,8 @@ let build_dependent_inductive ind (mib,mip) =
let realargs,_ = List.chop mip.mind_nrealdecls mip.mind_arity_ctxt in
applist
(mkIndU ind,
- extended_rel_list mip.mind_nrealdecls mib.mind_params_ctxt
- @ extended_rel_list 0 realargs)
+ Context.Rel.to_extended_list mip.mind_nrealdecls mib.mind_params_ctxt
+ @ Context.Rel.to_extended_list 0 realargs)
let my_it_mkLambda_or_LetIn s c = it_mkLambda_or_LetIn c s
let my_it_mkProd_or_LetIn s c = it_mkProd_or_LetIn c s
@@ -104,11 +105,11 @@ let get_sym_eq_data env (ind,u) =
error "Not an inductive type with a single constructor.";
let arityctxt = Vars.subst_instance_context u mip.mind_arity_ctxt in
let realsign,_ = List.chop mip.mind_nrealdecls arityctxt in
- if List.exists (fun (_,b,_) -> not (Option.is_empty b)) realsign then
+ if List.exists is_local_def realsign then
error "Inductive equalities with local definitions in arity not supported.";
let constrsign,ccl = decompose_prod_assum mip.mind_nf_lc.(0) in
let _,constrargs = decompose_app ccl in
- if not (Int.equal (rel_context_length constrsign) (rel_context_length mib.mind_params_ctxt)) then
+ if not (Int.equal (Context.Rel.length constrsign) (Context.Rel.length mib.mind_params_ctxt)) then
error "Constructor must have no arguments"; (* This can be relaxed... *)
let params,constrargs = List.chop mib.mind_nparams constrargs in
if mip.mind_nrealargs > mib.mind_nparams then
@@ -139,11 +140,11 @@ let get_non_sym_eq_data env (ind,u) =
error "Not an inductive type with a single constructor.";
let arityctxt = Vars.subst_instance_context u mip.mind_arity_ctxt in
let realsign,_ = List.chop mip.mind_nrealdecls arityctxt in
- if List.exists (fun (_,b,_) -> not (Option.is_empty b)) realsign then
+ if List.exists is_local_def realsign then
error "Inductive equalities with local definitions in arity not supported";
let constrsign,ccl = decompose_prod_assum mip.mind_nf_lc.(0) in
let _,constrargs = decompose_app ccl in
- if not (Int.equal (rel_context_length constrsign) (rel_context_length mib.mind_params_ctxt)) then
+ if not (Int.equal (Context.Rel.length constrsign) (Context.Rel.length mib.mind_params_ctxt)) then
error "Constructor must have no arguments";
let _,constrargs = List.chop mib.mind_nparams constrargs in
let constrargs = List.map (Vars.subst_instance_constr u) constrargs in
@@ -169,11 +170,11 @@ let build_sym_scheme env ind =
let (mib,mip as specif),nrealargs,realsign,paramsctxt,paramsctxt1 =
get_sym_eq_data env indu in
let cstr n =
- mkApp (mkConstructUi(indu,1),extended_rel_vect n mib.mind_params_ctxt) in
+ mkApp (mkConstructUi(indu,1),Context.Rel.to_extended_vect n mib.mind_params_ctxt) in
let varH = fresh env (default_id_of_sort (snd (mind_arity mip))) in
let applied_ind = build_dependent_inductive indu specif in
let realsign_ind =
- name_context env ((Name varH,None,applied_ind)::realsign) in
+ name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
let ci = make_case_info (Global.env()) ind RegularStyle in
let c =
(my_it_mkLambda_or_LetIn paramsctxt
@@ -182,7 +183,7 @@ let build_sym_scheme env ind =
my_it_mkLambda_or_LetIn_name
(lift_rel_context (nrealargs+1) realsign_ind)
(mkApp (mkIndU indu,Array.concat
- [extended_rel_vect (3*nrealargs+2) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+2) paramsctxt1;
rel_vect 1 nrealargs;
rel_vect (2*nrealargs+2) nrealargs])),
mkRel 1 (* varH *),
@@ -223,16 +224,16 @@ let build_sym_involutive_scheme env ind =
get_sym_eq_data env indu in
let eq,eqrefl,ctx = get_coq_eq ctx in
let sym, ctx, eff = const_of_scheme sym_scheme_kind env ind ctx in
- let cstr n = mkApp (mkConstructUi (indu,1),extended_rel_vect n paramsctxt) in
+ let cstr n = mkApp (mkConstructUi (indu,1),Context.Rel.to_extended_vect n paramsctxt) in
let varH = fresh env (default_id_of_sort (snd (mind_arity mip))) in
let applied_ind = build_dependent_inductive indu specif in
let applied_ind_C =
mkApp
(mkIndU indu, Array.append
- (extended_rel_vect (nrealargs+1) mib.mind_params_ctxt)
+ (Context.Rel.to_extended_vect (nrealargs+1) mib.mind_params_ctxt)
(rel_vect (nrealargs+1) nrealargs)) in
let realsign_ind =
- name_context env ((Name varH,None,applied_ind)::realsign) in
+ name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
let ci = make_case_info (Global.env()) ind RegularStyle in
let c =
(my_it_mkLambda_or_LetIn paramsctxt
@@ -243,15 +244,15 @@ let build_sym_involutive_scheme env ind =
(mkApp (eq,[|
mkApp
(mkIndU indu, Array.concat
- [extended_rel_vect (3*nrealargs+2) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+2) paramsctxt1;
rel_vect (2*nrealargs+2) nrealargs;
rel_vect 1 nrealargs]);
mkApp (sym,Array.concat
- [extended_rel_vect (3*nrealargs+2) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+2) paramsctxt1;
rel_vect 1 nrealargs;
rel_vect (2*nrealargs+2) nrealargs;
[|mkApp (sym,Array.concat
- [extended_rel_vect (3*nrealargs+2) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+2) paramsctxt1;
rel_vect (2*nrealargs+2) nrealargs;
rel_vect 1 nrealargs;
[|mkRel 1|]])|]]);
@@ -334,7 +335,7 @@ let build_l2r_rew_scheme dep env ind kind =
let eq,eqrefl,ctx = get_coq_eq ctx in
let cstr n p =
mkApp (mkConstructUi(indu,1),
- Array.concat [extended_rel_vect n paramsctxt1;
+ Array.concat [Context.Rel.to_extended_vect n paramsctxt1;
rel_vect p nrealargs]) in
let varH = fresh env (default_id_of_sort (snd (mind_arity mip))) in
let varHC = fresh env (Id.of_string "HC") in
@@ -342,26 +343,26 @@ let build_l2r_rew_scheme dep env ind kind =
let applied_ind = build_dependent_inductive indu specif in
let applied_ind_P =
mkApp (mkIndU indu, Array.concat
- [extended_rel_vect (3*nrealargs) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs) paramsctxt1;
rel_vect 0 nrealargs;
rel_vect nrealargs nrealargs]) in
let applied_ind_G =
mkApp (mkIndU indu, Array.concat
- [extended_rel_vect (3*nrealargs+3) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+3) paramsctxt1;
rel_vect (nrealargs+3) nrealargs;
rel_vect 0 nrealargs]) in
let realsign_P = lift_rel_context nrealargs realsign in
let realsign_ind_P =
- name_context env ((Name varH,None,applied_ind_P)::realsign_P) in
+ name_context env ((LocalAssum (Name varH,applied_ind_P))::realsign_P) in
let realsign_ind_G =
- name_context env ((Name varH,None,applied_ind_G)::
+ name_context env ((LocalAssum (Name varH,applied_ind_G))::
lift_rel_context (nrealargs+3) realsign) in
let applied_sym_C n =
mkApp(sym,
- Array.append (extended_rel_vect n mip.mind_arity_ctxt) [|mkVar varH|]) in
+ Array.append (Context.Rel.to_extended_vect n mip.mind_arity_ctxt) [|mkVar varH|]) in
let applied_sym_G =
mkApp(sym,
- Array.concat [extended_rel_vect (nrealargs*3+4) paramsctxt1;
+ Array.concat [Context.Rel.to_extended_vect (nrealargs*3+4) paramsctxt1;
rel_vect (nrealargs+4) nrealargs;
rel_vect 1 nrealargs;
[|mkRel 1|]]) in
@@ -371,7 +372,7 @@ let build_l2r_rew_scheme dep env ind kind =
let ci = make_case_info (Global.env()) ind RegularStyle in
let cieq = make_case_info (Global.env()) (fst (destInd eq)) RegularStyle in
let applied_PC =
- mkApp (mkVar varP,Array.append (extended_rel_vect 1 realsign)
+ mkApp (mkVar varP,Array.append (Context.Rel.to_extended_vect 1 realsign)
(if dep then [|cstr (2*nrealargs+1) 1|] else [||])) in
let applied_PG =
mkApp (mkVar varP,Array.append (rel_vect 1 nrealargs)
@@ -381,11 +382,11 @@ let build_l2r_rew_scheme dep env ind kind =
(if dep then [|mkRel 2|] else [||])) in
let applied_sym_sym =
mkApp (sym,Array.concat
- [extended_rel_vect (2*nrealargs+4) paramsctxt1;
+ [Context.Rel.to_extended_vect (2*nrealargs+4) paramsctxt1;
rel_vect 4 nrealargs;
rel_vect (nrealargs+4) nrealargs;
[|mkApp (sym,Array.concat
- [extended_rel_vect (2*nrealargs+4) paramsctxt1;
+ [Context.Rel.to_extended_vect (2*nrealargs+4) paramsctxt1;
rel_vect (nrealargs+4) nrealargs;
rel_vect 4 nrealargs;
[|mkRel 2|]])|]]) in
@@ -408,7 +409,7 @@ let build_l2r_rew_scheme dep env ind kind =
mkApp (eq,[|lift 4 applied_ind;applied_sym_sym;mkRel 1|]),
applied_PR)),
mkApp (sym_involutive,
- Array.append (extended_rel_vect 3 mip.mind_arity_ctxt) [|mkVar varH|]),
+ Array.append (Context.Rel.to_extended_vect 3 mip.mind_arity_ctxt) [|mkVar varH|]),
[|main_body|])
else
main_body))))))
@@ -447,7 +448,7 @@ let build_l2r_forward_rew_scheme dep env ind kind =
get_sym_eq_data env indu in
let cstr n p =
mkApp (mkConstructUi(indu,1),
- Array.concat [extended_rel_vect n paramsctxt1;
+ Array.concat [Context.Rel.to_extended_vect n paramsctxt1;
rel_vect p nrealargs]) in
let varH = fresh env (default_id_of_sort (snd (mind_arity mip))) in
let varHC = fresh env (Id.of_string "HC") in
@@ -455,19 +456,19 @@ let build_l2r_forward_rew_scheme dep env ind kind =
let applied_ind = build_dependent_inductive indu specif in
let applied_ind_P =
mkApp (mkIndU indu, Array.concat
- [extended_rel_vect (4*nrealargs+2) paramsctxt1;
+ [Context.Rel.to_extended_vect (4*nrealargs+2) paramsctxt1;
rel_vect 0 nrealargs;
rel_vect (nrealargs+1) nrealargs]) in
let applied_ind_P' =
mkApp (mkIndU indu, Array.concat
- [extended_rel_vect (3*nrealargs+1) paramsctxt1;
+ [Context.Rel.to_extended_vect (3*nrealargs+1) paramsctxt1;
rel_vect 0 nrealargs;
rel_vect (2*nrealargs+1) nrealargs]) in
let realsign_P n = lift_rel_context (nrealargs*n+n) realsign in
let realsign_ind =
- name_context env ((Name varH,None,applied_ind)::realsign) in
+ name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
let realsign_ind_P n aP =
- name_context env ((Name varH,None,aP)::realsign_P n) in
+ name_context env ((LocalAssum (Name varH,aP))::realsign_P n) in
let s, ctx' = Universes.fresh_sort_in_family (Global.env ()) kind in
let ctx = Univ.ContextSet.union ctx ctx' in
let s = mkSort s in
@@ -538,14 +539,14 @@ let build_r2l_forward_rew_scheme dep env ind kind =
let ((mib,mip as specif),constrargs,realsign,paramsctxt,nrealargs) =
get_non_sym_eq_data env indu in
let cstr n =
- mkApp (mkConstructUi(indu,1),extended_rel_vect n mib.mind_params_ctxt) in
+ mkApp (mkConstructUi(indu,1),Context.Rel.to_extended_vect n mib.mind_params_ctxt) in
let constrargs_cstr = constrargs@[cstr 0] in
let varH = fresh env (default_id_of_sort (snd (mind_arity mip))) in
let varHC = fresh env (Id.of_string "HC") in
let varP = fresh env (Id.of_string "P") in
let applied_ind = build_dependent_inductive indu specif in
let realsign_ind =
- name_context env ((Name varH,None,applied_ind)::realsign) in
+ name_context env ((LocalAssum (Name varH,applied_ind))::realsign) in
let s, ctx' = Universes.fresh_sort_in_family (Global.env ()) kind in
let ctx = Univ.ContextSet.union ctx ctx' in
let s = mkSort s in
@@ -554,8 +555,8 @@ let build_r2l_forward_rew_scheme dep env ind kind =
applist (mkVar varP,if dep then constrargs_cstr else constrargs) in
let applied_PG =
mkApp (mkVar varP,
- if dep then extended_rel_vect 0 realsign_ind
- else extended_rel_vect 1 realsign) in
+ if dep then Context.Rel.to_extended_vect 0 realsign_ind
+ else Context.Rel.to_extended_vect 1 realsign) in
let c =
(my_it_mkLambda_or_LetIn paramsctxt
(my_it_mkLambda_or_LetIn_name realsign_ind
@@ -599,12 +600,12 @@ let fix_r2l_forward_rew_scheme (c, ctx') =
| hp :: p :: ind :: indargs ->
let c' =
my_it_mkLambda_or_LetIn indargs
- (mkLambda_or_LetIn (map_rel_declaration (liftn (-1) 1) p)
- (mkLambda_or_LetIn (map_rel_declaration (liftn (-1) 2) hp)
- (mkLambda_or_LetIn (map_rel_declaration (lift 2) ind)
+ (mkLambda_or_LetIn (map_constr (liftn (-1) 1) p)
+ (mkLambda_or_LetIn (map_constr (liftn (-1) 2) hp)
+ (mkLambda_or_LetIn (map_constr (lift 2) ind)
(Reductionops.whd_beta Evd.empty
(applist (c,
- extended_rel_list 3 indargs @ [mkRel 1;mkRel 3;mkRel 2]))))))
+ Context.Rel.to_extended_list 3 indargs @ [mkRel 1;mkRel 3;mkRel 2]))))))
in c', ctx'
| _ -> anomaly (Pp.str "Ill-formed non-dependent left-to-right rewriting scheme")
@@ -630,9 +631,10 @@ let fix_r2l_forward_rew_scheme (c, ctx') =
(**********************************************************************)
let build_r2l_rew_scheme dep env ind k =
- let sigma, indu = Evd.fresh_inductive_instance env (Evd.from_env env) ind in
- let sigma', c = build_case_analysis_scheme env sigma indu dep k in
- c, Evd.evar_universe_context sigma'
+ let sigma = Sigma.Unsafe.of_evar_map (Evd.from_env env) in
+ let Sigma (indu, sigma, _) = Sigma.fresh_inductive_instance env sigma ind in
+ let Sigma (c, sigma, _) = build_case_analysis_scheme env sigma indu dep k in
+ c, Evd.evar_universe_context (Sigma.to_evar_map sigma)
let build_l2r_rew_scheme = build_l2r_rew_scheme
let build_l2r_forward_rew_scheme = build_l2r_forward_rew_scheme
@@ -736,13 +738,13 @@ let build_congr env (eq,refl,ctx) ind =
let arityctxt = Vars.subst_instance_context u mip.mind_arity_ctxt in
let paramsctxt = Vars.subst_instance_context u mib.mind_params_ctxt in
let realsign,_ = List.chop mip.mind_nrealdecls arityctxt in
- if List.exists (fun (_,b,_) -> not (Option.is_empty b)) realsign then
+ if List.exists is_local_def realsign then
error "Inductive equalities with local definitions in arity not supported.";
let env_with_arity = push_rel_context arityctxt env in
- let (_,_,ty) = lookup_rel (mip.mind_nrealargs - i + 1) env_with_arity in
+ let ty = get_type (lookup_rel (mip.mind_nrealargs - i + 1) env_with_arity) in
let constrsign,ccl = decompose_prod_assum mip.mind_nf_lc.(0) in
let _,constrargs = decompose_app ccl in
- if Int.equal (rel_context_length constrsign) (rel_context_length mib.mind_params_ctxt) then
+ if Int.equal (Context.Rel.length constrsign) (Context.Rel.length mib.mind_params_ctxt) then
error "Constructor must have no arguments";
let b = List.nth constrargs (i + mib.mind_nparams - 1) in
let varB = fresh env (Id.of_string "B") in
@@ -758,8 +760,8 @@ let build_congr env (eq,refl,ctx) ind =
(mkNamedLambda varH
(applist
(mkIndU indu,
- extended_rel_list (mip.mind_nrealargs+2) paramsctxt @
- extended_rel_list 0 realsign))
+ Context.Rel.to_extended_list (mip.mind_nrealargs+2) paramsctxt @
+ Context.Rel.to_extended_list 0 realsign))
(mkCase (ci,
my_it_mkLambda_or_LetIn_name
(lift_rel_context (mip.mind_nrealargs+3) realsign)
@@ -767,9 +769,9 @@ let build_congr env (eq,refl,ctx) ind =
(Anonymous,
applist
(mkIndU indu,
- extended_rel_list (2*mip.mind_nrealdecls+3)
+ Context.Rel.to_extended_list (2*mip.mind_nrealdecls+3)
paramsctxt
- @ extended_rel_list 0 realsign),
+ @ Context.Rel.to_extended_list 0 realsign),
mkApp (eq,
[|mkVar varB;
mkApp (mkVar varf, [|lift (2*mip.mind_nrealdecls+4) b|]);
diff --git a/tactics/equality.ml b/tactics/equality.ml
index f72a72f46d..bc03baf264 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -40,8 +40,10 @@ open Eqschemes
open Locus
open Locusops
open Misctypes
+open Sigma.Notations
open Proofview.Notations
open Unification
+open Context.Named.Declaration
(* Options *)
@@ -158,7 +160,7 @@ let instantiate_lemma_all frzevars gl c ty l l2r concl =
let try_occ (evd', c') =
Clenvtac.clenv_pose_dependent_evars true {eqclause with evd = evd'}
in
- let flags = make_flags frzevars (Proofview.Goal.sigma gl) rewrite_unif_flags eqclause in
+ let flags = make_flags frzevars (Tacmach.New.project gl) rewrite_unif_flags eqclause in
let occs =
w_unify_to_subterm_all ~flags env eqclause.evd
((if l2r then c1 else c2),concl)
@@ -242,12 +244,12 @@ let rewrite_keyed_unif_flags = {
}
let rewrite_elim with_evars frzevars cls c e =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let flags = if Unification.is_keyed_unification ()
then rewrite_keyed_unif_flags else rewrite_conv_closed_unif_flags in
- let flags = make_flags frzevars (Proofview.Goal.sigma gl) flags c in
+ let flags = make_flags frzevars (Tacmach.New.project gl) flags c in
general_elim_clause with_evars flags cls c e
- end
+ end }
(* Ad hoc asymmetric general_elim_clause *)
let general_elim_clause with_evars frzevars cls rew elim =
@@ -282,7 +284,7 @@ let general_elim_clause with_evars frzevars tac cls c t l l2r elim =
(general_elim_clause with_evars frzevars cls c elim))
tac
in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let instantiate_lemma concl =
if not all then instantiate_lemma gl c t l l2r concl
else instantiate_lemma_all frzevars gl c t l l2r concl
@@ -294,7 +296,7 @@ let general_elim_clause with_evars frzevars tac cls c t l l2r elim =
let cs = instantiate_lemma typ in
if firstonly then tclFIRST (List.map try_clause cs)
else tclMAP try_clause cs
- end
+ end }
(* The next function decides in particular whether to try a regular
rewrite or a generalized rewrite.
@@ -313,7 +315,7 @@ let jmeq_same_dom gl = function
let rels, t = decompose_prod_assum t in
let env = Environ.push_rel_context rels (Proofview.Goal.env gl) in
match decompose_app t with
- | _, [dom1; _; dom2;_] -> is_conv env (Proofview.Goal.sigma gl) dom1 dom2
+ | _, [dom1; _; dom2;_] -> is_conv env (Tacmach.New.project gl) dom1 dom2
| _ -> false
(* find_elim determines which elimination principle is necessary to
@@ -354,8 +356,8 @@ let find_elim hdcncl lft2rgt dep cls ot gl =
Logic.eq or Jmeq just before *)
assert false
in
- let sigma, elim = Evd.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c) in
- sigma, elim, Safe_typing.empty_private_constants
+ let Sigma (elim, sigma, p) = Sigma.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c) in
+ Sigma ((elim, Safe_typing.empty_private_constants), sigma, p)
else
let scheme_name = match dep, lft2rgt, inccl with
(* Non dependent case *)
@@ -373,10 +375,10 @@ let find_elim hdcncl lft2rgt dep cls ot gl =
| Ind (ind,u) ->
let c, eff = find_scheme scheme_name ind in
(* MS: cannot use pf_constr_of_global as the eliminator might be generated by side-effect *)
- let sigma, elim =
- Evd.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c)
+ let Sigma (elim, sigma, p) =
+ Sigma.fresh_global (Global.env ()) (Proofview.Goal.sigma gl) (ConstRef c)
in
- sigma, elim, eff
+ Sigma ((elim, eff), sigma, p)
| _ -> assert false
let type_of_clause cls gl = match cls with
@@ -384,17 +386,20 @@ let type_of_clause cls gl = match cls with
| Some id -> pf_get_hyp_typ id gl
let leibniz_rewrite_ebindings_clause cls lft2rgt tac c t l with_evars frzevars dep_proof_ok hdcncl =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let isatomic = isProd (whd_zeta hdcncl) in
let dep_fun = if isatomic then dependent else dependent_no_evar in
let type_of_cls = type_of_clause cls gl in
let dep = dep_proof_ok && dep_fun c type_of_cls in
- let (sigma,elim,effs) = find_elim hdcncl lft2rgt dep cls (Some t) gl in
- Proofview.Unsafe.tclEVARS sigma <*> Proofview.tclEFFECTS effs <*>
+ let Sigma ((elim, effs), sigma, p) = find_elim hdcncl lft2rgt dep cls (Some t) gl in
+ let tac =
+ Proofview.tclEFFECTS effs <*>
general_elim_clause with_evars frzevars tac cls c t l
(match lft2rgt with None -> false | Some b -> b)
{elimindex = None; elimbody = (elim,NoBindings); elimrename = None}
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
let adjust_rewriting_direction args lft2rgt =
match args with
@@ -417,8 +422,8 @@ let general_rewrite_ebindings_clause cls lft2rgt occs frzevars dep_proof_ok ?tac
if occs != AllOccurrences then (
rewrite_side_tac (Hook.get forward_general_setoid_rewrite_clause cls lft2rgt occs (c,l) ~new_goals:[]) tac)
else
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
let ctype = get_type_of env sigma c in
let rels, t = decompose_prod_assum (whd_betaiotazeta sigma ctype) in
@@ -445,7 +450,7 @@ let general_rewrite_ebindings_clause cls lft2rgt occs frzevars dep_proof_ok ?tac
| None -> Proofview.tclZERO ~info e
(* error "The provided term does not end with an equality or a declared rewrite relation." *)
end
- end
+ end }
let general_rewrite_ebindings =
general_rewrite_ebindings_clause None
@@ -507,9 +512,9 @@ let general_rewrite_clause l2r with_evars ?tac c cl =
let ids_of_hyps = pf_ids_of_hyps gl in
Id.Set.fold (fun id l -> List.remove Id.equal id l) ids_in_c ids_of_hyps
in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
do_hyps_atleastonce (ids gl)
- end
+ end }
in
if cl.concl_occs == NoOccurrences then do_hyps else
tclIFTHENTRYELSEMUST
@@ -517,25 +522,25 @@ let general_rewrite_clause l2r with_evars ?tac c cl =
do_hyps
let apply_special_clear_request clear_flag f =
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
try
- let sigma,(c,bl) = f env sigma in
+ let ((c, bl), sigma) = run_delayed env sigma f in
apply_clear_request clear_flag (use_clear_hyp_by_default ()) c
with
e when catchable_exception e -> tclIDTAC
- end
+ end }
let general_multi_rewrite with_evars l cl tac =
let do1 l2r f =
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
- let sigma,c = f env sigma in
+ let (c, sigma) = run_delayed env sigma f in
tclWITHHOLES with_evars
(general_rewrite_clause l2r with_evars ?tac c cl) sigma
- end
+ end }
in
let rec doN l2r c = function
| Precisely n when n <= 0 -> Proofview.tclUNIT ()
@@ -598,14 +603,14 @@ let replace_using_leibniz clause c1 c2 l2r unsafe try_prove_eq_opt =
| None -> Proofview.tclUNIT ()
| Some tac -> tclCOMPLETE tac
in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let get_type_of = pf_apply get_type_of gl in
let t1 = get_type_of c1
and t2 = get_type_of c2 in
let evd =
- if unsafe then Some (Proofview.Goal.sigma gl)
+ if unsafe then Some (Tacmach.New.project gl)
else
- try Some (Evarconv.the_conv_x (Proofview.Goal.env gl) t1 t2 (Proofview.Goal.sigma gl))
+ try Some (Evarconv.the_conv_x (Proofview.Goal.env gl) t1 t2 (Tacmach.New.project gl))
with Evarconv.UnableToUnify _ -> None
in
match evd with
@@ -624,7 +629,7 @@ let replace_using_leibniz clause c1 c2 l2r unsafe try_prove_eq_opt =
tclTHEN (apply sym) assumption;
try_prove_eq
])))
- end
+ end }
let replace c1 c2 =
replace_using_leibniz onConcl c2 c1 false false None
@@ -856,13 +861,13 @@ let descend_then env sigma head dirn =
*)
-(* [construct_discriminator env dirn headval]
- constructs a case-split on [headval], with the [dirn]-th branch
- giving [True], and all the rest giving False. *)
+(* [construct_discriminator env sigma dirn c ind special default]]
+ constructs a case-split on [c] of type [ind], with the [dirn]-th
+ branch giving [special], and all the rest giving [default]. *)
-let construct_discriminator env sigma dirn c sort =
+let build_selector env sigma dirn c ind special default =
let IndType(indf,_) =
- try find_rectype env sigma (get_type_of env sigma c)
+ try find_rectype env sigma ind
with Not_found ->
(* one can find Rel(k) in case of dependent constructors
like T := c : (A:Set)A->T and a discrimination
@@ -874,25 +879,29 @@ let construct_discriminator env sigma dirn c sort =
dependent types.") in
let (indp,_) = dest_ind_family indf in
let ind, _ = check_privacy env indp in
+ let typ = Retyping.get_type_of env sigma default in
let (mib,mip) = lookup_mind_specif env ind in
- let (true_0,false_0,sort_0) = build_coq_True(),build_coq_False(),Prop Null in
let deparsign = make_arity_signature env true indf in
- let p = it_mkLambda_or_LetIn (mkSort sort_0) deparsign in
+ let p = it_mkLambda_or_LetIn typ deparsign in
let cstrs = get_constructors env indf in
let build_branch i =
- let endpt = if Int.equal i dirn then true_0 else false_0 in
+ let endpt = if Int.equal i dirn then special else default in
it_mkLambda_or_LetIn endpt cstrs.(i-1).cs_args in
let brl =
List.map build_branch(List.interval 1 (Array.length mip.mind_consnames)) in
let ci = make_case_info env ind RegularStyle in
mkCase (ci, p, c, Array.of_list brl)
-let rec build_discriminator env sigma dirn c sort = function
- | [] -> construct_discriminator env sigma dirn c sort
+let rec build_discriminator env sigma dirn c = function
+ | [] ->
+ let ind = get_type_of env sigma c in
+ let true_0,false_0 =
+ build_coq_True(),build_coq_False() in
+ build_selector env sigma dirn c ind true_0 false_0
| ((sp,cnum),argnum)::l ->
let (cnum_nlams,cnum_env,kont) = descend_then env sigma c cnum in
let newc = mkRel(cnum_nlams-argnum) in
- let subval = build_discriminator cnum_env sigma dirn newc sort l in
+ let subval = build_discriminator cnum_env sigma dirn newc l in
kont subval (build_coq_False (),mkSort (Prop Null))
(* Note: discrimination could be more clever: if some elimination is
@@ -907,7 +916,7 @@ let rec build_discriminator env sigma dirn c sort = function
*)
let gen_absurdity id =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let hyp_typ = pf_get_hyp_typ id (Proofview.Goal.assume gl) in
let hyp_typ = pf_nf_evar gl hyp_typ in
if is_empty_type hyp_typ
@@ -915,7 +924,7 @@ let gen_absurdity id =
simplest_elim (mkVar id)
else
tclZEROMSG (str "Not the negation of an equality.")
- end
+ end }
(* Precondition: eq is leibniz equality
@@ -954,11 +963,11 @@ let apply_on_clause (f,t) clause =
| _ -> errorlabstrm "" (str "Ill-formed clause applicator.")) in
clenv_fchain ~with_univs:false argmv f_clause clause
-let discr_positions env sigma (lbeq,eqn,(t,t1,t2)) eq_clause cpath dirn sort =
+let discr_positions env sigma (lbeq,eqn,(t,t1,t2)) eq_clause cpath dirn =
let e = next_ident_away eq_baseid (ids_of_context env) in
- let e_env = push_named (e,None,t) env in
+ let e_env = push_named (Context.Named.Declaration.LocalAssum (e,t)) env in
let discriminator =
- build_discriminator e_env sigma dirn (mkVar e) sort cpath in
+ build_discriminator e_env sigma dirn (mkVar e) cpath in
let sigma,(pf, absurd_term), eff =
discrimination_pf env sigma e (t,t1,t2) discriminator lbeq in
let pf_ty = mkArrow eqn absurd_term in
@@ -971,19 +980,17 @@ let discr_positions env sigma (lbeq,eqn,(t,t1,t2)) eq_clause cpath dirn sort =
let discrEq (lbeq,_,(t,t1,t2) as u) eq_clause =
let sigma = eq_clause.evd in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let concl = Proofview.Goal.concl gl in
match find_positions env sigma t1 t2 with
| Inr _ ->
tclZEROMSG (str"Not a discriminable equality.")
| Inl (cpath, (_,dirn), _) ->
- let sort = pf_apply get_type_of gl concl in
- discr_positions env sigma u eq_clause cpath dirn sort
- end
+ discr_positions env sigma u eq_clause cpath dirn
+ end }
let onEquality with_evars tac (c,lbindc) =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let type_of = pf_unsafe_type_of gl in
let reduce_to_quantified_ind = pf_apply Tacred.reduce_to_quantified_ind gl in
let t = type_of c in
@@ -995,11 +1002,11 @@ let onEquality with_evars tac (c,lbindc) =
tclTHEN
(Proofview.Unsafe.tclEVARS eq_clause'.evd)
(tac (eq,eqn,eq_args) eq_clause')
- end
+ end }
let onNegatedEquality with_evars tac =
- Proofview.Goal.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let ccl = Proofview.Goal.concl gl in
let env = Proofview.Goal.env gl in
match kind_of_term (hnf_constr env sigma ccl) with
@@ -1009,7 +1016,7 @@ let onNegatedEquality with_evars tac =
onEquality with_evars tac (mkVar id,NoBindings)))
| _ ->
tclZEROMSG (str "Not a negated primitive equality.")
- end
+ end }
let discrSimpleClause with_evars = function
| None -> onNegatedEquality with_evars discrEq
@@ -1060,7 +1067,7 @@ let make_tuple env sigma (rterm,rty) lind =
assert (dependent (mkRel lind) rty);
let sigdata = find_sigma_data env (get_sort_of env sigma rty) in
let sigma, a = type_of ~refresh:true env sigma (mkRel lind) in
- let (na,_,_) = lookup_rel lind env in
+ let na = Context.Rel.Declaration.get_name (lookup_rel lind env) in
(* We move [lind] to [1] and lift other rels > [lind] by 1 *)
let rty = lift (1-lind) (liftn lind (lind+1) rty) in
(* Now [lind] is [mkRel 1] and we abstract on (na:a) *)
@@ -1135,7 +1142,7 @@ let minimal_free_rels_rec env sigma =
let sig_clausal_form env sigma sort_of_ty siglen ty dflt =
let sigdata = find_sigma_data env sort_of_ty in
- let evdref = ref (Evd.create_goal_evar_defs sigma) in
+ let evdref = ref (Evd.clear_metas sigma) in
let rec sigrec_clausal_form siglen p_i =
if Int.equal siglen 0 then
(* is the default value typable with the expected type *)
@@ -1278,7 +1285,7 @@ let eq_dec_scheme_kind_name = ref (fun _ -> failwith "eq_dec_scheme undefined")
let set_eq_dec_scheme_kind k = eq_dec_scheme_kind_name := (fun _ -> k)
let inject_if_homogenous_dependent_pair ty =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
try
let eq,u,(t,t1,t2) = find_this_eq_data_decompose gl ty in
(* fetch the informations of the pair *)
@@ -1316,7 +1323,7 @@ let inject_if_homogenous_dependent_pair ty =
])]
with Exit ->
Proofview.tclUNIT ()
- end
+ end }
(* Given t1=t2 Inj calculates the whd normal forms of t1 and t2 and it
expands then only when the whdnf has a constructor of an inductive type
@@ -1331,7 +1338,7 @@ let simplify_args env sigma t =
let inject_at_positions env sigma l2r (eq,_,(t,t1,t2)) eq_clause posns tac =
let e = next_ident_away eq_baseid (ids_of_context env) in
- let e_env = push_named (e, None,t) env in
+ let e_env = push_named (LocalAssum (e,t)) env in
let evdref = ref sigma in
let filter (cpath, t1', t2') =
try
@@ -1353,13 +1360,13 @@ let inject_at_positions env sigma l2r (eq,_,(t,t1,t2)) eq_clause posns tac =
tclZEROMSG (str "Failed to decompose the equality.")
else
Proofview.tclTHEN (Proofview.Unsafe.tclEVARS !evdref)
- (Proofview.tclBIND
- (Proofview.Monad.List.map
+ (Tacticals.New.tclTHENFIRST
+ (Proofview.tclIGNORE (Proofview.Monad.List.map
(fun (pf,ty) -> tclTHENS (cut ty)
[inject_if_homogenous_dependent_pair ty;
Proofview.V82.tactic (refine pf)])
- (if l2r then List.rev injectors else injectors))
- (fun _ -> tac (List.length injectors)))
+ (if l2r then List.rev injectors else injectors)))
+ (tac (List.length injectors)))
let injEqThen tac l2r (eq,_,(t,t1,t2) as u) eq_clause =
let sigma = eq_clause.evd in
@@ -1390,7 +1397,7 @@ let postInjEqTac clear_flag ipats c n =
then intro_patterns_bound_to n MoveLast ipats
else intro_patterns_to MoveLast ipats in
tclTHEN clear_tac intro_tac
- | None -> tclIDTAC
+ | None -> apply_clear_request clear_flag false c
let injEq clear_flag ipats =
let l2r =
@@ -1408,19 +1415,18 @@ let injConcl = injClause None false None
let injHyp clear_flag id = injClause None false (Some (clear_flag,ElimOnIdent (Loc.ghost,id)))
let decompEqThen ntac (lbeq,_,(t,t1,t2) as u) clause =
- Proofview.Goal.nf_enter begin fun gl ->
- let sort = pf_apply get_type_of gl (Proofview.Goal.concl gl) in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let sigma = clause.evd in
let env = Proofview.Goal.env gl in
match find_positions env sigma t1 t2 with
| Inl (cpath, (_,dirn), _) ->
- discr_positions env sigma u clause cpath dirn sort
+ discr_positions env sigma u clause cpath dirn
| Inr [] -> (* Change: do not fail, simplify clear this trivial hyp *)
ntac (clenv_value clause) 0
| Inr posns ->
inject_at_positions env sigma true u clause posns
(ntac (clenv_value clause))
- end
+ end }
let dEqThen with_evars ntac = function
| None -> onNegatedEquality with_evars (decompEqThen (ntac None))
@@ -1431,10 +1437,10 @@ let dEq with_evars =
(apply_clear_request clear_flag (use_clear_hyp_by_default ()) c))
let intro_decompe_eq tac data cl =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let cl = pf_apply make_clenv_binding gl cl NoBindings in
decompEqThen (fun _ -> tac) data cl
- end
+ end }
let _ = declare_intro_decomp_eq intro_decompe_eq
@@ -1485,6 +1491,7 @@ let decomp_tuple_term env c t =
in decomprec (mkRel 1) c t
let subst_tuple_term env sigma dep_pair1 dep_pair2 b =
+ let sigma = Sigma.to_evar_map sigma in
let typ = get_type_of env sigma dep_pair1 in
(* We find all possible decompositions *)
let decomps1 = decomp_tuple_term env dep_pair1 typ in
@@ -1509,7 +1516,7 @@ let subst_tuple_term env sigma dep_pair1 dep_pair2 b =
(* Retype to get universes right *)
let sigma, expected_goal_ty = Typing.type_of env sigma expected_goal in
let sigma, _ = Typing.type_of env sigma body in
- sigma,body,expected_goal
+ Sigma.Unsafe.of_pair ((body, expected_goal), sigma)
(* Like "replace" but decompose dependent equalities *)
(* i.e. if equality is "exists t v = exists u w", and goal is "phi(t,u)", *)
@@ -1517,34 +1524,42 @@ let subst_tuple_term env sigma dep_pair1 dep_pair2 b =
(* on for further iterated sigma-tuples *)
let cutSubstInConcl l2r eqn =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Proofview.Goal.sigma gl in
let (lbeq,u,(t,e1,e2)) = find_eq_data_decompose gl eqn in
let typ = pf_concl gl in
let (e1,e2) = if l2r then (e1,e2) else (e2,e1) in
- let sigma,typ,expected = pf_apply subst_tuple_term gl e1 e2 typ in
+ let Sigma ((typ, expected), sigma, p) = subst_tuple_term env sigma e1 e2 typ in
+ let tac =
tclTHENFIRST
(tclTHENLIST [
- (Proofview.Unsafe.tclEVARS sigma);
(change_concl typ); (* Put in pattern form *)
(replace_core onConcl l2r eqn)
])
(change_concl expected) (* Put in normalized form *)
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
let cutSubstInHyp l2r eqn id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Proofview.Goal.sigma gl in
let (lbeq,u,(t,e1,e2)) = find_eq_data_decompose gl eqn in
let typ = pf_get_hyp_typ id gl in
let (e1,e2) = if l2r then (e1,e2) else (e2,e1) in
- let sigma,typ,expected = pf_apply subst_tuple_term gl e1 e2 typ in
- tclTHENFIRST
+ let Sigma ((typ, expected), sigma, p) = subst_tuple_term env sigma e1 e2 typ in
+ let tac =
+ tclTHENFIRST
(tclTHENLIST [
- (Proofview.Unsafe.tclEVARS sigma);
(change_in_hyp None (make_change_arg typ) (id,InHypTypeOnly));
(replace_core (onHyp id) l2r eqn)
])
(change_in_hyp None (make_change_arg expected) (id,InHypTypeOnly))
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
let try_rewrite tac =
Proofview.tclORELSE tac begin function (e, info) -> match e with
@@ -1566,11 +1581,11 @@ let cutRewriteInHyp l2r eqn id = cutRewriteClause l2r eqn (Some id)
let cutRewriteInConcl l2r eqn = cutRewriteClause l2r eqn None
let substClause l2r c cls =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let eq = pf_apply get_type_of gl c in
tclTHENS (cutSubstClause l2r eq cls)
[Proofview.tclUNIT (); Proofview.V82.tactic (exact_no_check c)]
- end
+ end }
let rewriteClause l2r c cls = try_rewrite (substClause l2r c cls)
let rewriteInHyp l2r c id = rewriteClause l2r c (Some id)
@@ -1595,26 +1610,6 @@ user = raise user error specific to rewrite
(**********************************************************************)
(* Substitutions tactics (JCF) *)
-let unfold_body x =
- Proofview.Goal.enter begin fun gl ->
- (** We normalize the given hypothesis immediately. *)
- let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
- let (_, xval, _) = Context.lookup_named x hyps in
- let xval = match xval with
- | None -> errorlabstrm "unfold_body"
- (pr_id x ++ str" is not a defined hypothesis.")
- | Some xval -> pf_nf_evar gl xval
- in
- afterHyp x begin fun aft ->
- let hl = List.fold_right (fun (y,yval,_) cl -> (y,InHyp) :: cl) aft [] in
- let xvar = mkVar x in
- let rfun _ _ c = replace_term xvar xval c in
- let reducth h = Proofview.V82.tactic (fun gl -> reduct_in_hyp rfun h gl) in
- let reductc = Proofview.V82.tactic (fun gl -> reduct_in_concl (rfun, DEFAULTcast) gl) in
- tclTHENLIST [tclMAP reducth hl; reductc]
- end
- end
-
let restrict_to_eq_and_identity eq = (* compatibility *)
if not (is_global glob_eq eq) &&
not (is_global glob_identity eq)
@@ -1623,9 +1618,10 @@ let restrict_to_eq_and_identity eq = (* compatibility *)
exception FoundHyp of (Id.t * constr * bool)
(* tests whether hyp [c] is [x = t] or [t = x], [x] not occurring in [t] *)
-let is_eq_x gl x (id,_,c) =
+let is_eq_x gl x d =
+ let id = get_id d in
try
- let c = pf_nf_evar gl c in
+ let c = pf_nf_evar gl (get_type d) in
let (_,lhs,rhs) = pi3 (find_eq_data_decompose gl c) in
if (Term.eq_constr x lhs) && not (occur_term x rhs) then raise (FoundHyp (id,rhs,true));
if (Term.eq_constr x rhs) && not (occur_term x lhs) then raise (FoundHyp (id,lhs,false))
@@ -1636,17 +1632,18 @@ let is_eq_x gl x (id,_,c) =
erase hyp and x; proceed by generalizing all dep hyps *)
let subst_one dep_proof_ok x (hyp,rhs,dir) =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
let concl = Proofview.Goal.concl (Proofview.Goal.assume gl) in
(* The set of hypotheses using x *)
let dephyps =
- List.rev (snd (List.fold_right (fun (id,b,_ as dcl) (deps,allhyps) ->
+ List.rev (snd (List.fold_right (fun dcl (deps,allhyps) ->
+ let id = get_id dcl in
if not (Id.equal id hyp)
&& List.exists (fun y -> occur_var_in_decl env y dcl) deps
then
- ((if b = None then deps else id::deps), id::allhyps)
+ ((if is_local_assum dcl then deps else id::deps), id::allhyps)
else
(deps,allhyps))
hyps
@@ -1662,15 +1659,15 @@ let subst_one dep_proof_ok x (hyp,rhs,dir) =
else
[Proofview.tclUNIT ()]) @
[tclTRY (clear [x; hyp])])
- end
+ end }
(* Look for an hypothesis hyp of the form "x=rhs" or "rhs=x", rewrite
it everywhere, and erase hyp and x; proceed by generalizing all dep hyps *)
let subst_one_var dep_proof_ok x =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let gl = Proofview.Goal.assume gl in
- let (_,xval,_) = pf_get_hyp x gl in
+ let xval = pf_get_hyp x gl |> get_value in
(* If x has a body, simply replace x with body and clear x *)
if not (Option.is_empty xval) then tclTHEN (unfold_body x) (clear [x]) else
(* x is a variable: *)
@@ -1681,13 +1678,13 @@ let subst_one_var dep_proof_ok x =
(** [is_eq_x] ensures nf_evar on its side *)
let hyps = Proofview.Goal.hyps gl in
let test hyp _ = is_eq_x gl varx hyp in
- Context.fold_named_context test ~init:() hyps;
+ Context.Named.fold_outside test ~init:() hyps;
errorlabstrm "Subst"
(str "Cannot find any non-recursive equality over " ++ pr_id x ++
str".")
with FoundHyp res -> res in
subst_one dep_proof_ok x res
- end
+ end }
let subst_gen dep_proof_ok ids =
tclTHEN Proofview.V82.nf_evar_goals (tclMAP (subst_one_var dep_proof_ok) ids)
@@ -1709,7 +1706,7 @@ let default_subst_tactic_flags () =
else
{ only_leibniz = true; rewrite_dependent_proof = false }
-let regular_subst_tactic = ref false
+let regular_subst_tactic = ref true
let _ =
declare_bool_option
@@ -1729,14 +1726,14 @@ let subst_all ?(flags=default_subst_tactic_flags ()) () =
let gl = Proofview.Goal.assume gl in
let env = Proofview.Goal.env gl in
let find_eq_data_decompose = find_eq_data_decompose gl in
- let test (hyp,_,c) =
+ let test decl =
try
- let lbeq,u,(_,x,y) = find_eq_data_decompose c in
+ let lbeq,u,(_,x,y) = find_eq_data_decompose (get_type decl) in
let eq = Universes.constr_of_global_univ (lbeq.eq,u) in
if flags.only_leibniz then restrict_to_eq_and_identity eq;
match kind_of_term x, kind_of_term y with
| Var z, _ | _, Var z when not (is_evaluable env (EvalVarRef z)) ->
- Some hyp
+ Some (get_id decl)
| _ ->
None
with Constr_matching.PatternMatchingFailure -> None
@@ -1747,10 +1744,10 @@ let subst_all ?(flags=default_subst_tactic_flags ()) () =
(* Second step: treat equations *)
let process hyp =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let gl = Proofview.Goal.assume gl in
let find_eq_data_decompose = find_eq_data_decompose gl in
- let (_,_,c) = pf_get_hyp hyp gl in
+ let c = pf_get_hyp hyp gl |> get_type in
let _,_,(_,x,y) = find_eq_data_decompose c in
(* J.F.: added to prevent failure on goal containing x=x as an hyp *)
if Term.eq_constr x y then Proofview.tclUNIT () else
@@ -1761,19 +1758,19 @@ let subst_all ?(flags=default_subst_tactic_flags ()) () =
subst_one flags.rewrite_dependent_proof y' (hyp,x,false)
| _ ->
Proofview.tclUNIT ()
- end
+ end }
in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let ids = find_equations gl in
tclMAP process ids
- end
+ end }
else
(* Old implementation, not able to manage configurations like a=b, a=t,
or situations like "a = S b, b = S a", or also accidentally unfolding
let-ins *)
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let find_eq_data_decompose = find_eq_data_decompose gl in
let test (_,c) =
try
@@ -1790,7 +1787,7 @@ let subst_all ?(flags=default_subst_tactic_flags ()) () =
let ids = List.map_filter test hyps in
let ids = List.uniquize ids in
subst_gen flags.rewrite_dependent_proof ids
- end
+ end }
(* Rewrite the first assumption for which a condition holds
and gives the direction of the rewrite *)
@@ -1818,18 +1815,20 @@ let cond_eq_term c t gl =
let rewrite_assumption_cond cond_eq_term cl =
let rec arec hyps gl = match hyps with
| [] -> error "No such assumption."
- | (id,_,t) ::rest ->
+ | hyp ::rest ->
+ let id = get_id hyp in
begin
try
- let dir = cond_eq_term t gl in
+ let dir = cond_eq_term (get_type hyp) gl in
general_rewrite_clause dir false (mkVar id,NoBindings) cl
with | Failure _ | UserError _ -> arec rest gl
end
in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let gl = Proofview.Goal.lift gl Sigma.Unsafe.le in
let hyps = Proofview.Goal.hyps gl in
arec hyps gl
- end
+ end }
(* Generalize "subst x" to substitution of subterm appearing as an
equation in the context, but not clearing the hypothesis *)
diff --git a/tactics/equality.mli b/tactics/equality.mli
index f84dafb31f..458d8f3722 100644
--- a/tactics/equality.mli
+++ b/tactics/equality.mli
@@ -117,3 +117,8 @@ val subst_all : ?flags:subst_tactic_flags -> unit -> unit Proofview.tactic
val replace_term : bool option -> constr -> clause -> unit Proofview.tactic
val set_eq_dec_scheme_kind : mutual scheme_kind -> unit
+
+(* [build_selector env sigma i c t u v] matches on [c] of
+ type [t] and returns [u] in branch [i] and [v] on other branches *)
+val build_selector : env -> evar_map -> int -> constr -> types ->
+ constr -> constr -> constr
diff --git a/tactics/evar_tactics.ml b/tactics/evar_tactics.ml
index 2887fc2284..2e0996bf5a 100644
--- a/tactics/evar_tactics.ml
+++ b/tactics/evar_tactics.ml
@@ -14,6 +14,9 @@ open Tacexpr
open Refiner
open Evd
open Locus
+open Sigma.Notations
+open Proofview.Notations
+open Context.Named.Declaration
(* The instantiate tactic *)
@@ -41,14 +44,14 @@ let instantiate_tac n c ido =
match hloc with
InHyp ->
(match decl with
- (_,None,typ) -> evar_list typ
+ | LocalAssum (_,typ) -> evar_list typ
| _ -> error
"Please be more specific: in type or value?")
| InHypTypeOnly ->
- let (_, _, typ) = decl in evar_list typ
+ evar_list (get_type decl)
| InHypValueOnly ->
(match decl with
- (_,Some body,_) -> evar_list body
+ | LocalDef (_,body,_) -> evar_list body
| _ -> error "Not a defined hypothesis.") in
if List.length evl < n then
error "Not enough uninstantiated existential variables.";
@@ -68,18 +71,21 @@ let instantiate_tac_by_name id c =
let let_evar name typ =
let src = (Loc.ghost,Evar_kinds.GoalEvar) in
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
let sigma = ref sigma in
- let _ = Typing.sort_of env sigma typ in
- let sigma = !sigma in
+ let _ = Typing.e_sort_of env sigma typ in
+ let sigma = Sigma.Unsafe.of_evar_map !sigma in
let id = match name with
| Names.Anonymous ->
let id = Namegen.id_of_name_using_hdchar env typ name in
Namegen.next_ident_away_in_goal id (Termops.ids_of_named_context (Environ.named_context env))
- | Names.Name id -> id in
- let sigma',evar = Evarutil.new_evar env sigma ~src ~naming:(Misctypes.IntroFresh id) typ in
- Tacticals.New.tclTHEN (Proofview.V82.tactic (Refiner.tclEVARS sigma'))
+ | Names.Name id -> id
+ in
+ let Sigma (evar, sigma, p) = Evarutil.new_evar env sigma ~src ~naming:(Misctypes.IntroFresh id) typ in
+ let tac =
(Tactics.letin_tac None (Names.Name id) evar None Locusops.nowhere)
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
diff --git a/tactics/extraargs.ml4 b/tactics/extraargs.ml4
index 8f336cdb30..d33ec91f9d 100644
--- a/tactics/extraargs.ml4
+++ b/tactics/extraargs.ml4
@@ -10,6 +10,10 @@
open Pp
open Genarg
+open Stdarg
+open Constrarg
+open Pcoq.Prim
+open Pcoq.Constr
open Names
open Tacexpr
open Taccoerce
@@ -17,6 +21,25 @@ open Tacinterp
open Misctypes
open Locus
+(** Adding scopes for generic arguments not defined through ARGUMENT EXTEND *)
+
+let create_generic_quotation name e wit =
+ let inject (loc, v) = Tacexpr.TacGeneric (Genarg.in_gen (Genarg.rawwit wit) v) in
+ Egramcoq.create_ltac_quotation name inject (e, None)
+
+let () = create_generic_quotation "integer" Pcoq.Prim.integer Stdarg.wit_int
+let () = create_generic_quotation "string" Pcoq.Prim.string Stdarg.wit_string
+
+let () = create_generic_quotation "ident" Pcoq.Prim.ident Constrarg.wit_ident
+let () = create_generic_quotation "reference" Pcoq.Prim.reference Constrarg.wit_ref
+let () = create_generic_quotation "uconstr" Pcoq.Constr.lconstr Constrarg.wit_uconstr
+let () = create_generic_quotation "constr" Pcoq.Constr.lconstr Constrarg.wit_constr
+let () = create_generic_quotation "ipattern" Pcoq.Tactic.simple_intropattern Constrarg.wit_intro_pattern
+let () = create_generic_quotation "open_constr" Pcoq.Constr.lconstr Constrarg.wit_open_constr
+let () =
+ let inject (loc, v) = Tacexpr.Tacexp v in
+ Egramcoq.create_ltac_quotation "ltac" inject (Pcoq.Tactic.tactic_expr, Some 5)
+
(* Rewriting orientation *)
let _ = Metasyntax.add_token_obj "<-"
@@ -32,6 +55,14 @@ ARGUMENT EXTEND orient TYPED AS bool PRINTED BY pr_orient
| [ ] -> [ true ]
END
+let pr_int _ _ _ i = Pp.int i
+
+let _natural = Pcoq.Prim.natural
+
+ARGUMENT EXTEND natural TYPED AS int PRINTED BY pr_int
+| [ _natural(i) ] -> [ i ]
+END
+
let pr_orient = pr_orient () () ()
@@ -99,6 +130,8 @@ let interp_glob ist gl (t,_) = Tacmach.project gl , (ist,t)
let glob_glob = Tacintern.intern_constr
+let pr_lconstr _ prc _ c = prc c
+
let subst_glob = Tacsubst.subst_glob_constr_and_expr
ARGUMENT EXTEND glob
@@ -116,6 +149,14 @@ ARGUMENT EXTEND glob
[ constr(c) ] -> [ c ]
END
+let l_constr = Pcoq.Constr.lconstr
+
+ARGUMENT EXTEND lconstr
+ TYPED AS constr
+ PRINTED BY pr_lconstr
+ [ l_constr(c) ] -> [ c ]
+END
+
ARGUMENT EXTEND lglob
PRINTED BY pr_globc
diff --git a/tactics/extraargs.mli b/tactics/extraargs.mli
index 7c206d95cb..14aa69875f 100644
--- a/tactics/extraargs.mli
+++ b/tactics/extraargs.mli
@@ -21,6 +21,8 @@ val wit_occurrences : (int list or_var, int list or_var, int list) Genarg.genarg
val pr_occurrences : int list or_var -> Pp.std_ppcmds
val occurrences_of : int list -> Locus.occurrences
+val wit_natural : int Genarg.uniform_genarg_type
+
val wit_glob :
(constr_expr,
Tacexpr.glob_constr_and_expr,
@@ -31,6 +33,11 @@ val wit_lglob :
Tacexpr.glob_constr_and_expr,
Tacinterp.interp_sign * glob_constr) Genarg.genarg_type
+val wit_lconstr :
+ (constr_expr,
+ Tacexpr.glob_constr_and_expr,
+ Constr.t) Genarg.genarg_type
+
val glob : constr_expr Pcoq.Gram.entry
val lglob : constr_expr Pcoq.Gram.entry
@@ -47,13 +54,12 @@ val by_arg_tac : Tacexpr.raw_tactic_expr option Pcoq.Gram.entry
val wit_by_arg_tac :
(raw_tactic_expr option,
glob_tactic_expr option,
- glob_tactic_expr option) Genarg.genarg_type
+ Genarg.Val.t option) Genarg.genarg_type
val pr_by_arg_tac :
(int * Ppextend.parenRelation -> raw_tactic_expr -> Pp.std_ppcmds) ->
raw_tactic_expr option -> Pp.std_ppcmds
-
(** Spiwack: Primitive for retroknowledge registration *)
val retroknowledge_field : Retroknowledge.field Pcoq.Gram.entry
diff --git a/tactics/extratactics.ml4 b/tactics/extratactics.ml4
index 15613c7ecc..0cc796886c 100644
--- a/tactics/extratactics.ml4
+++ b/tactics/extratactics.ml4
@@ -10,7 +10,12 @@
open Pp
open Genarg
+open Stdarg
+open Constrarg
open Extraargs
+open Pcoq.Prim
+open Pcoq.Constr
+open Pcoq.Tactic
open Mod_subst
open Names
open Tacexpr
@@ -19,8 +24,10 @@ open Tactics
open Errors
open Util
open Evd
+open Termops
open Equality
open Misctypes
+open Sigma.Notations
open Proofview.Notations
DECLARE PLUGIN "extratactics"
@@ -29,34 +36,44 @@ DECLARE PLUGIN "extratactics"
(* replace, discriminate, injection, simplify_eq *)
(* cutrewrite, dependent rewrite *)
-let replace_in_clause_maybe_by (sigma1,c1) c2 cl tac =
- Tacticals.New.tclWITHHOLES false
- (replace_in_clause_maybe_by c1 c2 cl (Option.map Tacinterp.eval_tactic tac))
- sigma1
+let with_delayed_uconstr ist c tac =
+ let flags = {
+ Pretyping.use_typeclasses = false;
+ use_unif_heuristics = true;
+ use_hook = Some Pfedit.solve_by_implicit_tactic;
+ fail_evar = false;
+ expand_evars = true
+ } in
+ let c = Tacinterp.type_uconstr ~flags ist c in
+ Tacticals.New.tclDELAYEDWITHHOLES false c tac
-let replace_term dir_opt (sigma,c) cl =
- Tacticals.New.tclWITHHOLES false
- (replace_term dir_opt c cl)
- sigma
+let replace_in_clause_maybe_by ist c1 c2 cl tac =
+ with_delayed_uconstr ist c1
+ (fun c1 -> replace_in_clause_maybe_by c1 c2 cl (Option.map (Tacinterp.tactic_of_value ist) tac))
+
+let replace_term ist dir_opt c cl =
+ with_delayed_uconstr ist c (fun c -> replace_term dir_opt c cl)
+
+let clause = Pcoq.Tactic.clause_dft_concl
TACTIC EXTEND replace
- ["replace" open_constr(c1) "with" constr(c2) clause(cl) by_arg_tac(tac) ]
--> [ replace_in_clause_maybe_by c1 c2 cl tac ]
+ ["replace" uconstr(c1) "with" constr(c2) clause(cl) by_arg_tac(tac) ]
+-> [ replace_in_clause_maybe_by ist c1 c2 cl tac ]
END
TACTIC EXTEND replace_term_left
- [ "replace" "->" open_constr(c) clause(cl) ]
- -> [ replace_term (Some true) c cl ]
+ [ "replace" "->" uconstr(c) clause(cl) ]
+ -> [ replace_term ist (Some true) c cl ]
END
TACTIC EXTEND replace_term_right
- [ "replace" "<-" open_constr(c) clause(cl) ]
- -> [ replace_term (Some false) c cl ]
+ [ "replace" "<-" uconstr(c) clause(cl) ]
+ -> [ replace_term ist (Some false) c cl ]
END
TACTIC EXTEND replace_term
- [ "replace" open_constr(c) clause(cl) ]
- -> [ replace_term None c cl ]
+ [ "replace" uconstr(c) clause(cl) ]
+ -> [ replace_term ist None c cl ]
END
let induction_arg_of_quantified_hyp = function
@@ -68,8 +85,8 @@ let induction_arg_of_quantified_hyp = function
ElimOnIdent and not as "constr" *)
let elimOnConstrWithHoles tac with_evars c =
- Tacticals.New.tclWITHHOLES with_evars
- (tac with_evars (Some (None,ElimOnConstr c.it))) c.sigma
+ Tacticals.New.tclDELAYEDWITHHOLES with_evars c
+ (fun c -> tac with_evars (Some (None,ElimOnConstr c)))
TACTIC EXTEND simplify_eq_main
| [ "simplify_eq" constr_with_bindings(c) ] ->
@@ -114,7 +131,7 @@ END
open Proofview.Notations
let discrHyp id =
Proofview.tclEVARMAP >>= fun sigma ->
- discr_main {it = Term.mkVar id,NoBindings; sigma = sigma;}
+ discr_main { delayed = fun env sigma -> Sigma.here (Term.mkVar id, NoBindings) sigma }
let injection_main c =
elimOnConstrWithHoles (injClause None) false c
@@ -137,29 +154,29 @@ TACTIC EXTEND einjection
| [ "einjection" quantified_hypothesis(h) ] -> [ injClause None true (Some (induction_arg_of_quantified_hyp h)) ]
END
TACTIC EXTEND injection_as_main
-| [ "injection" constr_with_bindings(c) "as" simple_intropattern_list(ipat)] ->
+| [ "injection" constr_with_bindings(c) "as" intropattern_list(ipat)] ->
[ elimOnConstrWithHoles (injClause (Some ipat)) false c ]
END
TACTIC EXTEND injection_as
-| [ "injection" "as" simple_intropattern_list(ipat)] ->
+| [ "injection" "as" intropattern_list(ipat)] ->
[ injClause (Some ipat) false None ]
-| [ "injection" quantified_hypothesis(h) "as" simple_intropattern_list(ipat) ] ->
+| [ "injection" quantified_hypothesis(h) "as" intropattern_list(ipat) ] ->
[ injClause (Some ipat) false (Some (induction_arg_of_quantified_hyp h)) ]
END
TACTIC EXTEND einjection_as_main
-| [ "einjection" constr_with_bindings(c) "as" simple_intropattern_list(ipat)] ->
+| [ "einjection" constr_with_bindings(c) "as" intropattern_list(ipat)] ->
[ elimOnConstrWithHoles (injClause (Some ipat)) true c ]
END
TACTIC EXTEND einjection_as
-| [ "einjection" "as" simple_intropattern_list(ipat)] ->
+| [ "einjection" "as" intropattern_list(ipat)] ->
[ injClause (Some ipat) true None ]
-| [ "einjection" quantified_hypothesis(h) "as" simple_intropattern_list(ipat) ] ->
+| [ "einjection" quantified_hypothesis(h) "as" intropattern_list(ipat) ] ->
[ injClause (Some ipat) true (Some (induction_arg_of_quantified_hyp h)) ]
END
let injHyp id =
Proofview.tclEVARMAP >>= fun sigma ->
- injection_main { it = Term.mkVar id,NoBindings; sigma = sigma; }
+ injection_main { delayed = fun env sigma -> Sigma.here (Term.mkVar id, NoBindings) sigma }
TACTIC EXTEND dependent_rewrite
| [ "dependent" "rewrite" orient(b) constr(c) ] -> [ rewriteInConcl b c ]
@@ -199,7 +216,7 @@ END
let onSomeWithHoles tac = function
| None -> tac None
- | Some c -> Tacticals.New.tclWITHHOLES false (tac (Some c.it)) c.sigma
+ | Some c -> Tacticals.New.tclDELAYEDWITHHOLES false c (fun c -> tac (Some c))
TACTIC EXTEND contradiction
[ "contradiction" constr_with_bindings_opt(c) ] ->
@@ -227,7 +244,7 @@ TACTIC EXTEND autorewrite
[ auto_multi_rewrite l ( cl) ]
| [ "autorewrite" "with" ne_preident_list(l) clause(cl) "using" tactic(t) ] ->
[
- auto_multi_rewrite_with (Tacinterp.eval_tactic t) l cl
+ auto_multi_rewrite_with (Tacinterp.tactic_of_value ist t) l cl
]
END
@@ -235,28 +252,28 @@ TACTIC EXTEND autorewrite_star
| [ "autorewrite" "*" "with" ne_preident_list(l) clause(cl) ] ->
[ auto_multi_rewrite ~conds:AllMatches l cl ]
| [ "autorewrite" "*" "with" ne_preident_list(l) clause(cl) "using" tactic(t) ] ->
- [ auto_multi_rewrite_with ~conds:AllMatches (Tacinterp.eval_tactic t) l cl ]
+ [ auto_multi_rewrite_with ~conds:AllMatches (Tacinterp.tactic_of_value ist t) l cl ]
END
(**********************************************************************)
(* Rewrite star *)
-let rewrite_star clause orient occs (sigma,c) (tac : glob_tactic_expr option) =
- let tac' = Option.map (fun t -> Tacinterp.eval_tactic t, FirstSolved) tac in
- Tacticals.New.tclWITHHOLES false
- (general_rewrite_ebindings_clause clause orient occs ?tac:tac' true true (c,NoBindings) true) sigma
+let rewrite_star ist clause orient occs c (tac : Val.t option) =
+ let tac' = Option.map (fun t -> Tacinterp.tactic_of_value ist t, FirstSolved) tac in
+ with_delayed_uconstr ist c
+ (fun c -> general_rewrite_ebindings_clause clause orient occs ?tac:tac' true true (c,NoBindings) true)
TACTIC EXTEND rewrite_star
-| [ "rewrite" "*" orient(o) open_constr(c) "in" hyp(id) "at" occurrences(occ) by_arg_tac(tac) ] ->
- [ rewrite_star (Some id) o (occurrences_of occ) c tac ]
-| [ "rewrite" "*" orient(o) open_constr(c) "at" occurrences(occ) "in" hyp(id) by_arg_tac(tac) ] ->
- [ rewrite_star (Some id) o (occurrences_of occ) c tac ]
-| [ "rewrite" "*" orient(o) open_constr(c) "in" hyp(id) by_arg_tac(tac) ] ->
- [ rewrite_star (Some id) o Locus.AllOccurrences c tac ]
-| [ "rewrite" "*" orient(o) open_constr(c) "at" occurrences(occ) by_arg_tac(tac) ] ->
- [ rewrite_star None o (occurrences_of occ) c tac ]
-| [ "rewrite" "*" orient(o) open_constr(c) by_arg_tac(tac) ] ->
- [ rewrite_star None o Locus.AllOccurrences c tac ]
+| [ "rewrite" "*" orient(o) uconstr(c) "in" hyp(id) "at" occurrences(occ) by_arg_tac(tac) ] ->
+ [ rewrite_star ist (Some id) o (occurrences_of occ) c tac ]
+| [ "rewrite" "*" orient(o) uconstr(c) "at" occurrences(occ) "in" hyp(id) by_arg_tac(tac) ] ->
+ [ rewrite_star ist (Some id) o (occurrences_of occ) c tac ]
+| [ "rewrite" "*" orient(o) uconstr(c) "in" hyp(id) by_arg_tac(tac) ] ->
+ [ rewrite_star ist (Some id) o Locus.AllOccurrences c tac ]
+| [ "rewrite" "*" orient(o) uconstr(c) "at" occurrences(occ) by_arg_tac(tac) ] ->
+ [ rewrite_star ist None o (occurrences_of occ) c tac ]
+| [ "rewrite" "*" orient(o) uconstr(c) by_arg_tac(tac) ] ->
+ [ rewrite_star ist None o Locus.AllOccurrences c tac ]
END
(**********************************************************************)
@@ -269,7 +286,7 @@ let add_rewrite_hint bases ort t lcsr =
let f ce =
let c, ctx = Constrintern.interp_constr env sigma ce in
let ctx =
- let ctx = Evd.evar_universe_context_set Univ.UContext.empty ctx in
+ let ctx = UState.context_set ctx in
if poly then ctx
else (Global.push_context_set false ctx; Univ.ContextSet.empty)
in
@@ -313,7 +330,7 @@ let project_hint pri l2r r =
| _ -> assert false in
let p =
if l2r then build_coq_iff_left_proj () else build_coq_iff_right_proj () in
- let c = Reductionops.whd_beta Evd.empty (mkApp (c,Termops.extended_rel_vect 0 sign)) in
+ let c = Reductionops.whd_beta Evd.empty (mkApp (c, Context.Rel.to_extended_vect 0 sign)) in
let c = it_mkLambda_or_LetIn
(mkApp (p,[|mkArrow a (lift 1 b);mkArrow b (lift 1 a);c|])) sign in
let id =
@@ -345,31 +362,27 @@ END
(**********************************************************************)
(* Refine *)
-let refine_tac simple {Glob_term.closure=closure;term=term} =
- Proofview.Goal.nf_enter begin fun gl ->
+let refine_tac ist simple c =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let env = Proofview.Goal.env gl in
let flags = Pretyping.all_no_fail_flags in
- let tycon = Pretyping.OfType concl in
- let lvar = { Pretyping.empty_lvar with
- Pretyping.ltac_constrs = closure.Glob_term.typed;
- Pretyping.ltac_uconstrs = closure.Glob_term.untyped;
- Pretyping.ltac_idents = closure.Glob_term.idents;
- } in
- let update evd = Pretyping.understand_ltac flags env evd lvar tycon term in
+ let expected_type = Pretyping.OfType concl in
+ let c = Tacinterp.type_uconstr ~flags ~expected_type ist c in
+ let update = { run = fun sigma -> c.delayed env sigma } in
let refine = Proofview.Refine.refine ~unsafe:false update in
if simple then refine
else refine <*>
Tactics.New.reduce_after_refine <*>
Proofview.shelve_unifiable
- end
+ end }
TACTIC EXTEND refine
-| [ "refine" uconstr(c) ] -> [ refine_tac false c ]
+| [ "refine" uconstr(c) ] -> [ refine_tac ist false c ]
END
TACTIC EXTEND simple_refine
-| [ "simple" "refine" uconstr(c) ] -> [ refine_tac true c ]
+| [ "simple" "refine" uconstr(c) ] -> [ refine_tac ist true c ]
END
(**********************************************************************)
@@ -506,12 +519,12 @@ let add_transitivity_lemma left lem =
(* Vernacular syntax *)
TACTIC EXTEND stepl
-| ["stepl" constr(c) "by" tactic(tac) ] -> [ step true c (Tacinterp.eval_tactic tac) ]
+| ["stepl" constr(c) "by" tactic(tac) ] -> [ step true c (Tacinterp.tactic_of_value ist tac) ]
| ["stepl" constr(c) ] -> [ step true c (Proofview.tclUNIT ()) ]
END
TACTIC EXTEND stepr
-| ["stepr" constr(c) "by" tactic(tac) ] -> [ step false c (Tacinterp.eval_tactic tac) ]
+| ["stepr" constr(c) "by" tactic(tac) ] -> [ step false c (Tacinterp.tactic_of_value ist tac) ]
| ["stepr" constr(c) ] -> [ step false c (Proofview.tclUNIT ()) ]
END
@@ -616,13 +629,10 @@ let subst_hole_with_term occ tc t =
open Tacmach
-let out_arg = function
- | ArgVar _ -> anomaly (Pp.str "Unevaluated or_var variable")
- | ArgArg x -> x
-
let hResolve id c occ t =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
let env = Termops.clear_named_body id (Proofview.Goal.env gl) in
let concl = Proofview.Goal.concl gl in
let env_ids = Termops.ids_of_context env in
@@ -640,10 +650,11 @@ let hResolve id c occ t =
let t_constr,ctx = resolve_hole (subst_var_with_hole occ id t_raw) in
let sigma = Evd.merge_universe_context sigma ctx in
let t_constr_type = Retyping.get_type_of env sigma t_constr in
- Tacticals.New.tclTHEN
- (Proofview.Unsafe.tclEVARS sigma)
+ let tac =
(change_concl (mkLetIn (Anonymous,t_constr,t_constr_type,concl)))
- end
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
let hResolve_auto id c t =
let rec resolve_auto n =
@@ -656,7 +667,7 @@ let hResolve_auto id c t =
resolve_auto 1
TACTIC EXTEND hresolve_core
-| [ "hresolve_core" "(" ident(id) ":=" constr(c) ")" "at" int_or_var(occ) "in" constr(t) ] -> [ hResolve id c (out_arg occ) t ]
+| [ "hresolve_core" "(" ident(id) ":=" constr(c) ")" "at" int_or_var(occ) "in" constr(t) ] -> [ hResolve id c occ t ]
| [ "hresolve_core" "(" ident(id) ":=" constr(c) ")" "in" constr(t) ] -> [ hResolve_auto id c t ]
END
@@ -665,8 +676,8 @@ END
*)
let hget_evar n =
- Proofview.Goal.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let concl = Proofview.Goal.concl gl in
let evl = evar_list concl in
if List.length evl < n then
@@ -675,10 +686,10 @@ let hget_evar n =
let ev = List.nth evl (n-1) in
let ev_type = existential_type sigma ev in
change_concl (mkLetIn (Anonymous,mkEvar ev,ev_type,concl))
- end
+ end }
TACTIC EXTEND hget_evar
-| [ "hget_evar" int_or_var(n) ] -> [ hget_evar (out_arg n) ]
+| [ "hget_evar" int_or_var(n) ] -> [ hget_evar n ]
END
(**********************************************************************)
@@ -694,12 +705,12 @@ END
exception Found of unit Proofview.tactic
let rewrite_except h =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let hyps = Tacmach.New.pf_ids_of_hyps gl in
Tacticals.New.tclMAP (fun id -> if Id.equal id h then Proofview.tclUNIT () else
Tacticals.New.tclTRY (Equality.general_rewrite_in true Locus.AllOccurrences true true id (mkVar h) false))
hyps
- end
+ end }
let refl_equal =
@@ -713,27 +724,28 @@ let refl_equal =
should be replaced by a call to the tactic but I don't know how to
call it before it is defined. *)
let mkCaseEq a : unit Proofview.tactic =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let type_of_a = Tacmach.New.of_old (fun g -> Tacmach.pf_unsafe_type_of g a) gl in
Tacticals.New.tclTHENLIST
- [Proofview.V82.tactic (Tactics.Simple.generalize [mkApp(delayed_force refl_equal, [| type_of_a; a|])]);
- Proofview.Goal.nf_enter begin fun gl ->
+ [Proofview.V82.tactic (Tactics.generalize [mkApp(delayed_force refl_equal, [| type_of_a; a|])]);
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let env = Proofview.Goal.env gl in
- change_concl
- (snd (Tacred.pattern_occs [Locus.OnlyOccurrences [1], a] env Evd.empty concl))
- end;
+ (** FIXME: this looks really wrong. Does anybody really use this tactic? *)
+ let Sigma (c, _, _) = (Tacred.pattern_occs [Locus.OnlyOccurrences [1], a]).Reductionops.e_redfun env (Sigma.Unsafe.of_evar_map Evd.empty) concl in
+ change_concl c
+ end };
simplest_case a]
- end
+ end }
let case_eq_intros_rewrite x =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let n = nb_prod (Proofview.Goal.concl gl) in
(* Pp.msgnl (Printer.pr_lconstr x); *)
Tacticals.New.tclTHENLIST [
mkCaseEq x;
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let hyps = Tacmach.New.pf_ids_of_hyps gl in
let n' = nb_prod concl in
@@ -742,16 +754,19 @@ let case_eq_intros_rewrite x =
Tacticals.New.tclDO (n'-n-1) intro;
introduction h;
rewrite_except h]
- end
+ end }
]
- end
+ end }
let rec find_a_destructable_match t =
+ let cl = induction_arg_of_quantified_hyp (NamedHyp (Id.of_string "x")) in
+ let cl = [cl, (None, None), None], None in
+ let dest = TacAtom (Loc.ghost, TacInductionDestruct(false, false, cl)) in
match kind_of_term t with
| Case (_,_,x,_) when closed0 x ->
if isVar x then
(* TODO check there is no rel n. *)
- raise (Found (Tacinterp.eval_tactic(<:tactic<destruct x>>)))
+ raise (Found (Tacinterp.eval_tactic dest))
else
(* let _ = Pp.msgnl (Printer.pr_lconstr x) in *)
raise (Found (case_eq_intros_rewrite x))
@@ -764,15 +779,15 @@ let destauto t =
with Found tac -> tac
let destauto_in id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let ctype = Tacmach.New.of_old (fun g -> Tacmach.pf_unsafe_type_of g (mkVar id)) gl in
(* Pp.msgnl (Printer.pr_lconstr (mkVar id)); *)
(* Pp.msgnl (Printer.pr_lconstr (ctype)); *)
destauto ctype
- end
+ end }
TACTIC EXTEND destauto
-| [ "destauto" ] -> [ Proofview.Goal.nf_enter (fun gl -> destauto (Proofview.Goal.concl gl)) ]
+| [ "destauto" ] -> [ Proofview.Goal.nf_enter { enter = begin fun gl -> destauto (Proofview.Goal.concl gl) end } ]
| [ "destauto" "in" hyp(id) ] -> [ destauto_in id ]
END
@@ -780,10 +795,11 @@ END
(* ********************************************************************* *)
let eq_constr x y =
- Proofview.Goal.enter (fun gl ->
- let evd = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let evd = Tacmach.New.project gl in
if Evarutil.eq_constr_univs_test evd evd x y then Proofview.tclUNIT ()
- else Tacticals.New.tclFAIL 0 (str "Not equal"))
+ else Tacticals.New.tclFAIL 0 (str "Not equal")
+ end }
TACTIC EXTEND constr_eq
| [ "constr_eq" constr(x) constr(y) ] -> [ eq_constr x y ]
@@ -877,7 +893,7 @@ END
TACTIC EXTEND unshelve
| [ "unshelve" tactic1(t) ] ->
[
- Proofview.with_shelf (Tacinterp.eval_tactic t) >>= fun (gls, ()) ->
+ Proofview.with_shelf (Tacinterp.tactic_of_value ist t) >>= fun (gls, ()) ->
Proofview.Unsafe.tclGETGOALS >>= fun ogls ->
Proofview.Unsafe.tclSETGOALS (gls @ ogls)
]
@@ -900,12 +916,12 @@ END
(* cycles [n] goals *)
TACTIC EXTEND cycle
-| [ "cycle" int_or_var(n) ] -> [ Proofview.cycle (out_arg n) ]
+| [ "cycle" int_or_var(n) ] -> [ Proofview.cycle n ]
END
(* swaps goals number [i] and [j] *)
TACTIC EXTEND swap
-| [ "swap" int_or_var(i) int_or_var(j) ] -> [ Proofview.swap (out_arg i) (out_arg j) ]
+| [ "swap" int_or_var(i) int_or_var(j) ] -> [ Proofview.swap i j ]
END
(* reverses the list of focused goals *)
@@ -922,9 +938,9 @@ type cmp =
type 'i test =
| Test of cmp * 'i * 'i
-let wit_cmp : (cmp,cmp,cmp) Genarg.genarg_type = Genarg.make0 None "cmp"
+let wit_cmp : (cmp,cmp,cmp) Genarg.genarg_type = Genarg.make0 "cmp"
let wit_test : (int or_var test,int or_var test,int test) Genarg.genarg_type =
- Genarg.make0 None "tactest"
+ Genarg.make0 "tactest"
let pr_cmp = function
| Eq -> Pp.str"="
@@ -994,14 +1010,14 @@ TACTIC EXTEND guard
END
let decompose l c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let to_ind c =
if isInd c then Univ.out_punivs (destInd c)
else error "not an inductive type"
in
let l = List.map to_ind l in
Elim.h_decompose l c
- end
+ end }
TACTIC EXTEND decompose
| [ "decompose" "[" ne_constr_list(l) "]" constr(c) ] -> [ decompose l c ]
diff --git a/tactics/extratactics.mli b/tactics/extratactics.mli
index e0e9f37709..18334dafe7 100644
--- a/tactics/extratactics.mli
+++ b/tactics/extratactics.mli
@@ -11,4 +11,4 @@ val injHyp : Names.Id.t -> unit Proofview.tactic
(* val refine_tac : Evd.open_constr -> unit Proofview.tactic *)
-val onSomeWithHoles : ('a option -> unit Proofview.tactic) -> 'a Evd.sigma option -> unit Proofview.tactic
+val onSomeWithHoles : ('a option -> unit Proofview.tactic) -> 'a Tacexpr.delayed_open option -> unit Proofview.tactic
diff --git a/tactics/ftactic.ml b/tactics/ftactic.ml
index 8e42dcba74..588709873e 100644
--- a/tactics/ftactic.ml
+++ b/tactics/ftactic.ml
@@ -37,16 +37,32 @@ let bind (type a) (type b) (m : a t) (f : a -> b t) : b t = m >>= function
Proofview.tclDISPATCHL (List.map f l) >>= fun l ->
Proofview.tclUNIT (Depends (List.concat l))
+let goals = Proofview.Goal.goals >>= fun l -> Proofview.tclUNIT (Depends l)
+let set_sigma r =
+ let Sigma.Sigma (ans, sigma, _) = r in
+ Proofview.Unsafe.tclEVARS (Sigma.to_evar_map sigma) >>= fun () -> ans
+
let nf_enter f =
- bind (Proofview.Goal.goals >>= fun l -> Proofview.tclUNIT (Depends l))
+ bind goals
+ (fun gl ->
+ gl >>= fun gl ->
+ Proofview.Goal.normalize gl >>= fun nfgl ->
+ Proofview.V82.wrap_exceptions (fun () -> f.enter nfgl))
+
+let nf_s_enter f =
+ bind goals
(fun gl ->
gl >>= fun gl ->
Proofview.Goal.normalize gl >>= fun nfgl ->
- Proofview.V82.wrap_exceptions (fun () -> f nfgl))
+ Proofview.V82.wrap_exceptions (fun () -> set_sigma (f.s_enter nfgl)))
let enter f =
- bind (Proofview.Goal.goals >>= fun l -> Proofview.tclUNIT (Depends l))
- (fun gl -> gl >>= fun gl -> Proofview.V82.wrap_exceptions (fun () -> f gl))
+ bind goals
+ (fun gl -> gl >>= fun gl -> Proofview.V82.wrap_exceptions (fun () -> f.enter gl))
+
+let s_enter f =
+ bind goals
+ (fun gl -> gl >>= fun gl -> Proofview.V82.wrap_exceptions (fun () -> set_sigma (f.s_enter gl)))
let with_env t =
t >>= function
@@ -83,4 +99,8 @@ end
module Ftac = Monad.Make(Self)
module List = Ftac.List
-let debug_prompt = Tactic_debug.debug_prompt
+module Notations =
+struct
+ let (>>=) = bind
+ let (<*>) = fun m n -> bind m (fun () -> n)
+end
diff --git a/tactics/ftactic.mli b/tactics/ftactic.mli
index 3f4da2a832..19041f1698 100644
--- a/tactics/ftactic.mli
+++ b/tactics/ftactic.mli
@@ -6,6 +6,8 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
+open Proofview.Notations
+
(** Potentially focussing tactics *)
type +'a focus
@@ -37,13 +39,20 @@ val run : 'a t -> ('a -> unit Proofview.tactic) -> unit Proofview.tactic
(** {5 Focussing} *)
-val nf_enter : ([ `NF ] Proofview.Goal.t -> 'a t) -> 'a t
+val nf_enter : ([ `NF ], 'a t) enter -> 'a t
(** Enter a goal. The resulting tactic is focussed. *)
-val enter : ([ `LZ ] Proofview.Goal.t -> 'a t) -> 'a t
+val enter : ([ `LZ ], 'a t) enter -> 'a t
(** Enter a goal, without evar normalization. The resulting tactic is
focussed. *)
+val s_enter : ([ `LZ ], 'a t) s_enter -> 'a t
+(** Enter a goal and put back an evarmap. The resulting tactic is focussed. *)
+
+val nf_s_enter : ([ `NF ], 'a t) s_enter -> 'a t
+(** Enter a goal, without evar normalization and put back an evarmap. The
+ resulting tactic is focussed. *)
+
val with_env : 'a t -> (Environ.env*'a) t
(** [with_env t] returns, in addition to the return type of [t], an
environment, which is the global environment if [t] does not focus on
@@ -61,7 +70,10 @@ val (<*>) : unit t -> 'a t -> 'a t
module List : Monad.ListS with type 'a t := 'a t
-(** {5 Debug} *)
+(** {5 Notations} *)
-val debug_prompt :
- int -> Tacexpr.glob_tactic_expr -> (Tactic_debug.debug_info -> 'a t) -> 'a t
+module Notations :
+sig
+ val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
+ val (<*>) : unit t -> 'a t -> 'a t
+end
diff --git a/tactics/g_auto.ml4 b/tactics/g_auto.ml4
new file mode 100644
index 0000000000..788443944f
--- /dev/null
+++ b/tactics/g_auto.ml4
@@ -0,0 +1,211 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2015 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(*i camlp4deps: "grammar/grammar.cma" i*)
+
+open Pp
+open Genarg
+open Stdarg
+open Constrarg
+open Pcoq.Prim
+open Pcoq.Constr
+open Pcoq.Tactic
+open Tacexpr
+
+DECLARE PLUGIN "g_auto"
+
+(* Hint bases *)
+
+
+TACTIC EXTEND eassumption
+| [ "eassumption" ] -> [ Eauto.e_assumption ]
+END
+
+TACTIC EXTEND eexact
+| [ "eexact" constr(c) ] -> [ Eauto.e_give_exact c ]
+END
+
+let pr_hintbases _prc _prlc _prt = Pptactic.pr_hintbases
+
+ARGUMENT EXTEND hintbases
+ TYPED AS preident_list_opt
+ PRINTED BY pr_hintbases
+| [ "with" "*" ] -> [ None ]
+| [ "with" ne_preident_list(l) ] -> [ Some l ]
+| [ ] -> [ Some [] ]
+END
+
+let eval_uconstrs ist cs =
+ let flags = {
+ Pretyping.use_typeclasses = false;
+ use_unif_heuristics = true;
+ use_hook = Some Pfedit.solve_by_implicit_tactic;
+ fail_evar = false;
+ expand_evars = true
+ } in
+ List.map (fun c -> Tacinterp.type_uconstr ~flags ist c) cs
+
+let pr_auto_using _ _ _ = Pptactic.pr_auto_using (fun _ -> mt ())
+
+ARGUMENT EXTEND auto_using
+ TYPED AS uconstr_list
+ PRINTED BY pr_auto_using
+| [ "using" ne_uconstr_list_sep(l, ",") ] -> [ l ]
+| [ ] -> [ [] ]
+END
+
+(** Auto *)
+
+TACTIC EXTEND trivial
+| [ "trivial" auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_trivial (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND info_trivial
+| [ "info_trivial" auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_trivial ~debug:Info (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND debug_trivial
+| [ "debug" "trivial" auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_trivial ~debug:Debug (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND auto
+| [ "auto" int_or_var_opt(n) auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_auto n (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND info_auto
+| [ "info_auto" int_or_var_opt(n) auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_auto ~debug:Info n (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND debug_auto
+| [ "debug" "auto" int_or_var_opt(n) auto_using(lems) hintbases(db) ] ->
+ [ Auto.h_auto ~debug:Debug n (eval_uconstrs ist lems) db ]
+END
+
+(** Eauto *)
+
+TACTIC EXTEND prolog
+| [ "prolog" "[" uconstr_list(l) "]" int_or_var(n) ] ->
+ [ Eauto.prolog_tac (eval_uconstrs ist l) n ]
+END
+
+let make_depth n = snd (Eauto.make_dimension n None)
+
+TACTIC EXTEND eauto
+| [ "eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
+ hintbases(db) ] ->
+ [ Eauto.gen_eauto (Eauto.make_dimension n p) (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND new_eauto
+| [ "new" "auto" int_or_var_opt(n) auto_using(lems)
+ hintbases(db) ] ->
+ [ match db with
+ | None -> Auto.new_full_auto (make_depth n) (eval_uconstrs ist lems)
+ | Some l -> Auto.new_auto (make_depth n) (eval_uconstrs ist lems) l ]
+END
+
+TACTIC EXTEND debug_eauto
+| [ "debug" "eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
+ hintbases(db) ] ->
+ [ Eauto.gen_eauto ~debug:Debug (Eauto.make_dimension n p) (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND info_eauto
+| [ "info_eauto" int_or_var_opt(n) int_or_var_opt(p) auto_using(lems)
+ hintbases(db) ] ->
+ [ Eauto.gen_eauto ~debug:Info (Eauto.make_dimension n p) (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND dfs_eauto
+| [ "dfs" "eauto" int_or_var_opt(p) auto_using(lems)
+ hintbases(db) ] ->
+ [ Eauto.gen_eauto (Eauto.make_dimension p None) (eval_uconstrs ist lems) db ]
+END
+
+TACTIC EXTEND autounfold
+| [ "autounfold" hintbases(db) clause_dft_concl(cl) ] -> [ Eauto.autounfold_tac db cl ]
+END
+
+TACTIC EXTEND autounfold_one
+| [ "autounfold_one" hintbases(db) "in" hyp(id) ] ->
+ [ Eauto.autounfold_one (match db with None -> ["core"] | Some x -> "core"::x) (Some (id, Locus.InHyp)) ]
+| [ "autounfold_one" hintbases(db) ] ->
+ [ Eauto.autounfold_one (match db with None -> ["core"] | Some x -> "core"::x) None ]
+ END
+
+TACTIC EXTEND autounfoldify
+| [ "autounfoldify" constr(x) ] -> [
+ let db = match Term.kind_of_term x with
+ | Term.Const (c,_) -> Names.Label.to_string (Names.con_label c)
+ | _ -> assert false
+ in Eauto.autounfold ["core";db] Locusops.onConcl
+ ]
+END
+
+TACTIC EXTEND unify
+| ["unify" constr(x) constr(y) ] -> [ Tactics.unify x y ]
+| ["unify" constr(x) constr(y) "with" preident(base) ] -> [
+ let table = try Some (Hints.searchtable_map base) with Not_found -> None in
+ match table with
+ | None ->
+ let msg = str "Hint table " ++ str base ++ str " not found" in
+ Tacticals.New.tclZEROMSG msg
+ | Some t ->
+ let state = Hints.Hint_db.transparent_state t in
+ Tactics.unify ~state x y
+ ]
+END
+
+
+TACTIC EXTEND convert_concl_no_check
+| ["convert_concl_no_check" constr(x) ] -> [ Tactics.convert_concl_no_check x Term.DEFAULTcast ]
+END
+
+let pr_hints_path_atom _ _ _ = Hints.pp_hints_path_atom
+
+ARGUMENT EXTEND hints_path_atom
+ TYPED AS hints_path_atom
+ PRINTED BY pr_hints_path_atom
+| [ global_list(g) ] -> [ Hints.PathHints (List.map Nametab.global g) ]
+| [ "*" ] -> [ Hints.PathAny ]
+END
+
+let pr_hints_path prc prx pry c = Hints.pp_hints_path c
+
+ARGUMENT EXTEND hints_path
+ TYPED AS hints_path
+ PRINTED BY pr_hints_path
+| [ "(" hints_path(p) ")" ] -> [ p ]
+| [ "!" hints_path(p) ] -> [ Hints.PathStar p ]
+| [ "emp" ] -> [ Hints.PathEmpty ]
+| [ "eps" ] -> [ Hints.PathEpsilon ]
+| [ hints_path_atom(a) ] -> [ Hints.PathAtom a ]
+| [ hints_path(p) "|" hints_path(q) ] -> [ Hints.PathOr (p, q) ]
+| [ hints_path(p) ";" hints_path(q) ] -> [ Hints.PathSeq (p, q) ]
+END
+
+let pr_hintbases _prc _prlc _prt = Pptactic.pr_hintbases
+
+ARGUMENT EXTEND opthints
+ TYPED AS preident_list_opt
+ PRINTED BY pr_hintbases
+| [ ":" ne_preident_list(l) ] -> [ Some l ]
+| [ ] -> [ None ]
+END
+
+VERNAC COMMAND EXTEND HintCut CLASSIFIED AS SIDEFF
+| [ "Hint" "Cut" "[" hints_path(p) "]" opthints(dbnames) ] -> [
+ let entry = Hints.HintsCutEntry p in
+ Hints.add_hints (Locality.make_section_locality (Locality.LocalityFixme.consume ()))
+ (match dbnames with None -> ["core"] | Some l -> l) entry ]
+END
diff --git a/tactics/g_class.ml4 b/tactics/g_class.ml4
index e0c1f671fd..9ef1545416 100644
--- a/tactics/g_class.ml4
+++ b/tactics/g_class.ml4
@@ -10,11 +10,16 @@
open Misctypes
open Class_tactics
+open Pcoq.Prim
+open Pcoq.Constr
+open Pcoq.Tactic
+open Stdarg
+open Constrarg
DECLARE PLUGIN "g_class"
TACTIC EXTEND progress_evars
- [ "progress_evars" tactic(t) ] -> [ progress_evars (Tacinterp.eval_tactic t) ]
+ [ "progress_evars" tactic(t) ] -> [ progress_evars (Tacinterp.tactic_of_value ist t) ]
END
(** Options: depth, debug and transparency settings. *)
diff --git a/tactics/g_ltac.ml4 b/tactics/g_ltac.ml4
new file mode 100644
index 0000000000..b55ac9ad06
--- /dev/null
+++ b/tactics/g_ltac.ml4
@@ -0,0 +1,430 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(*i camlp4deps: "grammar/grammar.cma" i*)
+
+open Util
+open Pp
+open Compat
+open Constrexpr
+open Tacexpr
+open Misctypes
+open Genarg
+open Genredexpr
+open Tok (* necessary for camlp4 *)
+
+open Pcoq
+open Pcoq.Prim
+open Pcoq.Tactic
+
+let fail_default_value = ArgArg 0
+
+let arg_of_expr = function
+ TacArg (loc,a) -> a
+ | e -> Tacexp (e:raw_tactic_expr)
+
+let genarg_of_unit () = in_gen (rawwit Stdarg.wit_unit) ()
+let genarg_of_int n = in_gen (rawwit Stdarg.wit_int) n
+let genarg_of_ipattern pat = in_gen (rawwit Constrarg.wit_intro_pattern) pat
+let genarg_of_uconstr c = in_gen (rawwit Constrarg.wit_uconstr) c
+
+let reference_to_id = function
+ | Libnames.Ident (loc, id) -> (loc, id)
+ | Libnames.Qualid (loc,_) ->
+ Errors.user_err_loc (loc, "",
+ str "This expression should be a simple identifier.")
+
+let tactic_mode = Gram.entry_create "vernac:tactic_command"
+
+let new_entry name =
+ let e = Gram.entry_create name in
+ let entry = Entry.create name in
+ let () = Pcoq.set_grammar entry e in
+ e
+
+let selector = new_entry "vernac:selector"
+let tacdef_body = new_entry "tactic:tacdef_body"
+
+(* Registers the Classic Proof Mode (which uses [tactic_mode] as a parser for
+ proof editing and changes nothing else). Then sets it as the default proof mode. *)
+let _ =
+ let mode = {
+ Proof_global.name = "Classic";
+ set = (fun () -> set_command_entry tactic_mode);
+ reset = (fun () -> set_command_entry Pcoq.Vernac_.noedit_mode);
+ } in
+ Proof_global.register_proof_mode mode
+
+(* Hack to parse "[ id" without dropping [ *)
+let test_bracket_ident =
+ Gram.Entry.of_parser "test_bracket_ident"
+ (fun strm ->
+ match get_tok (stream_nth 0 strm) with
+ | KEYWORD "[" ->
+ (match get_tok (stream_nth 1 strm) with
+ | IDENT _ -> ()
+ | _ -> raise Stream.Failure)
+ | _ -> raise Stream.Failure)
+
+(* Tactics grammar rules *)
+
+GEXTEND Gram
+ GLOBAL: tactic tacdef_body tactic_expr binder_tactic tactic_arg
+ tactic_mode constr_may_eval constr_eval selector;
+
+ tactic_then_last:
+ [ [ "|"; lta = LIST0 OPT tactic_expr SEP "|" ->
+ Array.map (function None -> TacId [] | Some t -> t) (Array.of_list lta)
+ | -> [||]
+ ] ]
+ ;
+ tactic_then_gen:
+ [ [ ta = tactic_expr; "|"; (first,last) = tactic_then_gen -> (ta::first, last)
+ | ta = tactic_expr; ".."; l = tactic_then_last -> ([], Some (ta, l))
+ | ".."; l = tactic_then_last -> ([], Some (TacId [], l))
+ | ta = tactic_expr -> ([ta], None)
+ | "|"; (first,last) = tactic_then_gen -> (TacId [] :: first, last)
+ | -> ([TacId []], None)
+ ] ]
+ ;
+ tactic_then_locality: (* [true] for the local variant [TacThens] and [false]
+ for [TacExtend] *)
+ [ [ "[" ; l = OPT">" -> if Option.is_empty l then true else false ] ]
+ ;
+ tactic_expr:
+ [ "5" RIGHTA
+ [ te = binder_tactic -> te ]
+ | "4" LEFTA
+ [ ta0 = tactic_expr; ";"; ta1 = binder_tactic -> TacThen (ta0, ta1)
+ | ta0 = tactic_expr; ";"; ta1 = tactic_expr -> TacThen (ta0,ta1)
+ | ta0 = tactic_expr; ";"; l = tactic_then_locality; (first,tail) = tactic_then_gen; "]" ->
+ match l , tail with
+ | false , Some (t,last) -> TacThen (ta0,TacExtendTac (Array.of_list first, t, last))
+ | true , Some (t,last) -> TacThens3parts (ta0, Array.of_list first, t, last)
+ | false , None -> TacThen (ta0,TacDispatch first)
+ | true , None -> TacThens (ta0,first) ]
+ | "3" RIGHTA
+ [ IDENT "try"; ta = tactic_expr -> TacTry ta
+ | IDENT "do"; n = int_or_var; ta = tactic_expr -> TacDo (n,ta)
+ | IDENT "timeout"; n = int_or_var; ta = tactic_expr -> TacTimeout (n,ta)
+ | IDENT "time"; s = OPT string; ta = tactic_expr -> TacTime (s,ta)
+ | IDENT "repeat"; ta = tactic_expr -> TacRepeat ta
+ | IDENT "progress"; ta = tactic_expr -> TacProgress ta
+ | IDENT "once"; ta = tactic_expr -> TacOnce ta
+ | IDENT "exactly_once"; ta = tactic_expr -> TacExactlyOnce ta
+ | IDENT "infoH"; ta = tactic_expr -> TacShowHyps ta
+(*To do: put Abstract in Refiner*)
+ | IDENT "abstract"; tc = NEXT -> TacAbstract (tc,None)
+ | IDENT "abstract"; tc = NEXT; "using"; s = ident ->
+ TacAbstract (tc,Some s) ]
+(*End of To do*)
+ | "2" RIGHTA
+ [ ta0 = tactic_expr; "+"; ta1 = binder_tactic -> TacOr (ta0,ta1)
+ | ta0 = tactic_expr; "+"; ta1 = tactic_expr -> TacOr (ta0,ta1)
+ | IDENT "tryif" ; ta = tactic_expr ;
+ "then" ; tat = tactic_expr ;
+ "else" ; tae = tactic_expr -> TacIfThenCatch(ta,tat,tae)
+ | ta0 = tactic_expr; "||"; ta1 = binder_tactic -> TacOrelse (ta0,ta1)
+ | ta0 = tactic_expr; "||"; ta1 = tactic_expr -> TacOrelse (ta0,ta1) ]
+ | "1" RIGHTA
+ [ b = match_key; IDENT "goal"; "with"; mrl = match_context_list; "end" ->
+ TacMatchGoal (b,false,mrl)
+ | b = match_key; IDENT "reverse"; IDENT "goal"; "with";
+ mrl = match_context_list; "end" ->
+ TacMatchGoal (b,true,mrl)
+ | b = match_key; c = tactic_expr; "with"; mrl = match_list; "end" ->
+ TacMatch (b,c,mrl)
+ | IDENT "first" ; "["; l = LIST0 tactic_expr SEP "|"; "]" ->
+ TacFirst l
+ | IDENT "solve" ; "["; l = LIST0 tactic_expr SEP "|"; "]" ->
+ TacSolve l
+ | IDENT "idtac"; l = LIST0 message_token -> TacId l
+ | g=failkw; n = [ n = int_or_var -> n | -> fail_default_value ];
+ l = LIST0 message_token -> TacFail (g,n,l)
+ | st = simple_tactic -> st
+ | a = tactic_arg -> TacArg(!@loc,a)
+ | r = reference; la = LIST0 tactic_arg_compat ->
+ TacArg(!@loc,TacCall (!@loc,r,la)) ]
+ | "0"
+ [ "("; a = tactic_expr; ")" -> a
+ | "["; ">"; (tf,tail) = tactic_then_gen; "]" ->
+ begin match tail with
+ | Some (t,tl) -> TacExtendTac(Array.of_list tf,t,tl)
+ | None -> TacDispatch tf
+ end
+ | a = tactic_atom -> TacArg (!@loc,a) ] ]
+ ;
+ failkw:
+ [ [ IDENT "fail" -> TacLocal | IDENT "gfail" -> TacGlobal ] ]
+ ;
+ (* binder_tactic: level 5 of tactic_expr *)
+ binder_tactic:
+ [ RIGHTA
+ [ "fun"; it = LIST1 input_fun ; "=>"; body = tactic_expr LEVEL "5" ->
+ TacFun (it,body)
+ | "let"; isrec = [IDENT "rec" -> true | -> false];
+ llc = LIST1 let_clause SEP "with"; "in";
+ body = tactic_expr LEVEL "5" -> TacLetIn (isrec,llc,body)
+ | IDENT "info"; tc = tactic_expr LEVEL "5" -> TacInfo tc ] ]
+ ;
+ (* Tactic arguments to the right of an application *)
+ tactic_arg_compat:
+ [ [ a = tactic_arg -> a
+ | r = reference -> Reference r
+ | c = Constr.constr -> ConstrMayEval (ConstrTerm c)
+ (* Unambigous entries: tolerated w/o "ltac:" modifier *)
+ | "()" -> TacGeneric (genarg_of_unit ()) ] ]
+ ;
+ (* Can be used as argument and at toplevel in tactic expressions. *)
+ tactic_arg:
+ [ [ c = constr_eval -> ConstrMayEval c
+ | IDENT "fresh"; l = LIST0 fresh_id -> TacFreshId l
+ | IDENT "type_term"; c=uconstr -> TacPretype c
+ | IDENT "numgoals" -> TacNumgoals ] ]
+ ;
+ (* If a qualid is given, use its short name. TODO: have the shortest
+ non ambiguous name where dots are replaced by "_"? Probably too
+ verbose most of the time. *)
+ fresh_id:
+ [ [ s = STRING -> ArgArg s (*| id = ident -> ArgVar (!@loc,id)*)
+ | qid = qualid -> let (_pth,id) = Libnames.repr_qualid (snd qid) in ArgVar (!@loc,id) ] ]
+ ;
+ constr_eval:
+ [ [ IDENT "eval"; rtc = red_expr; "in"; c = Constr.constr ->
+ ConstrEval (rtc,c)
+ | IDENT "context"; id = identref; "["; c = Constr.lconstr; "]" ->
+ ConstrContext (id,c)
+ | IDENT "type"; IDENT "of"; c = Constr.constr ->
+ ConstrTypeOf c ] ]
+ ;
+ constr_may_eval: (* For extensions *)
+ [ [ c = constr_eval -> c
+ | c = Constr.constr -> ConstrTerm c ] ]
+ ;
+ tactic_atom:
+ [ [ n = integer -> TacGeneric (genarg_of_int n)
+ | r = reference -> TacCall (!@loc,r,[])
+ | "()" -> TacGeneric (genarg_of_unit ()) ] ]
+ ;
+ match_key:
+ [ [ "match" -> Once
+ | "lazymatch" -> Select
+ | "multimatch" -> General ] ]
+ ;
+ input_fun:
+ [ [ "_" -> None
+ | l = ident -> Some l ] ]
+ ;
+ let_clause:
+ [ [ id = identref; ":="; te = tactic_expr ->
+ (id, arg_of_expr te)
+ | id = identref; args = LIST1 input_fun; ":="; te = tactic_expr ->
+ (id, arg_of_expr (TacFun(args,te))) ] ]
+ ;
+ match_pattern:
+ [ [ IDENT "context"; oid = OPT Constr.ident;
+ "["; pc = Constr.lconstr_pattern; "]" ->
+ let mode = not (!Flags.tactic_context_compat) in
+ Subterm (mode, oid, pc)
+ | IDENT "appcontext"; oid = OPT Constr.ident;
+ "["; pc = Constr.lconstr_pattern; "]" ->
+ msg_warning (strbrk "appcontext is deprecated");
+ Subterm (true,oid, pc)
+ | pc = Constr.lconstr_pattern -> Term pc ] ]
+ ;
+ match_hyps:
+ [ [ na = name; ":"; mp = match_pattern -> Hyp (na, mp)
+ | na = name; ":="; "["; mpv = match_pattern; "]"; ":"; mpt = match_pattern -> Def (na, mpv, mpt)
+ | na = name; ":="; mpv = match_pattern ->
+ let t, ty =
+ match mpv with
+ | Term t -> (match t with
+ | CCast (loc, t, (CastConv ty | CastVM ty | CastNative ty)) -> Term t, Some (Term ty)
+ | _ -> mpv, None)
+ | _ -> mpv, None
+ in Def (na, t, Option.default (Term (CHole (Loc.ghost, None, IntroAnonymous, None))) ty)
+ ] ]
+ ;
+ match_context_rule:
+ [ [ largs = LIST0 match_hyps SEP ","; "|-"; mp = match_pattern;
+ "=>"; te = tactic_expr -> Pat (largs, mp, te)
+ | "["; largs = LIST0 match_hyps SEP ","; "|-"; mp = match_pattern;
+ "]"; "=>"; te = tactic_expr -> Pat (largs, mp, te)
+ | "_"; "=>"; te = tactic_expr -> All te ] ]
+ ;
+ match_context_list:
+ [ [ mrl = LIST1 match_context_rule SEP "|" -> mrl
+ | "|"; mrl = LIST1 match_context_rule SEP "|" -> mrl ] ]
+ ;
+ match_rule:
+ [ [ mp = match_pattern; "=>"; te = tactic_expr -> Pat ([],mp,te)
+ | "_"; "=>"; te = tactic_expr -> All te ] ]
+ ;
+ match_list:
+ [ [ mrl = LIST1 match_rule SEP "|" -> mrl
+ | "|"; mrl = LIST1 match_rule SEP "|" -> mrl ] ]
+ ;
+ message_token:
+ [ [ id = identref -> MsgIdent id
+ | s = STRING -> MsgString s
+ | n = integer -> MsgInt n ] ]
+ ;
+
+ ltac_def_kind:
+ [ [ ":=" -> false
+ | "::=" -> true ] ]
+ ;
+
+ (* Definitions for tactics *)
+ tacdef_body:
+ [ [ name = Constr.global; it=LIST1 input_fun; redef = ltac_def_kind; body = tactic_expr ->
+ if redef then Vernacexpr.TacticRedefinition (name, TacFun (it, body))
+ else
+ let id = reference_to_id name in
+ Vernacexpr.TacticDefinition (id, TacFun (it, body))
+ | name = Constr.global; redef = ltac_def_kind; body = tactic_expr ->
+ if redef then Vernacexpr.TacticRedefinition (name, body)
+ else
+ let id = reference_to_id name in
+ Vernacexpr.TacticDefinition (id, body)
+ ] ]
+ ;
+ tactic:
+ [ [ tac = tactic_expr -> tac ] ]
+ ;
+ selector:
+ [ [ n=natural; ":" -> Vernacexpr.SelectNth n
+ | test_bracket_ident; "["; id = ident; "]"; ":" -> Vernacexpr.SelectId id
+ | IDENT "all" ; ":" -> Vernacexpr.SelectAll ] ]
+ ;
+ tactic_mode:
+ [ [ g = OPT selector; tac = G_vernac.subgoal_command -> tac g ] ]
+ ;
+ END
+
+open Stdarg
+open Constrarg
+open Vernacexpr
+open Vernac_classifier
+open Goptions
+open Libnames
+
+let print_info_trace = ref None
+
+let _ = declare_int_option {
+ optsync = true;
+ optdepr = false;
+ optname = "print info trace";
+ optkey = ["Info" ; "Level"];
+ optread = (fun () -> !print_info_trace);
+ optwrite = fun n -> print_info_trace := n;
+}
+
+let vernac_solve n info tcom b =
+ let status = Proof_global.with_current_proof (fun etac p ->
+ let with_end_tac = if b then Some etac else None in
+ let global = match n with SelectAll -> true | _ -> false in
+ let info = Option.append info !print_info_trace in
+ let (p,status) =
+ Pfedit.solve n info (Tacinterp.hide_interp global tcom None) ?with_end_tac p
+ in
+ (* in case a strict subtree was completed,
+ go back to the top of the prooftree *)
+ let p = Proof.maximal_unfocus Vernacentries.command_focus p in
+ p,status) in
+ if not status then Pp.feedback Feedback.AddedAxiom
+
+let pr_ltac_selector = function
+| SelectNth i -> int i ++ str ":"
+| SelectId id -> str "[" ++ Nameops.pr_id id ++ str "]" ++ str ":"
+| SelectAll -> str "all" ++ str ":"
+
+VERNAC ARGUMENT EXTEND ltac_selector PRINTED BY pr_ltac_selector
+| [ selector(s) ] -> [ s ]
+END
+
+let pr_ltac_info n = str "Info" ++ spc () ++ int n
+
+VERNAC ARGUMENT EXTEND ltac_info PRINTED BY pr_ltac_info
+| [ "Info" natural(n) ] -> [ n ]
+END
+
+let pr_ltac_use_default b = if b then str ".." else mt ()
+
+VERNAC ARGUMENT EXTEND ltac_use_default PRINTED BY pr_ltac_use_default
+| [ "." ] -> [ false ]
+| [ "..." ] -> [ true ]
+END
+
+VERNAC tactic_mode EXTEND VernacSolve
+| [ - ltac_selector_opt(g) ltac_info_opt(n) tactic(t) ltac_use_default(def) ] =>
+ [ classify_as_proofstep ] -> [
+ let g = Option.default (Proof_global.get_default_goal_selector ()) g in
+ vernac_solve g n t def
+ ]
+| [ - "par" ":" ltac_info_opt(n) tactic(t) ltac_use_default(def) ] =>
+ [ VtProofStep true, VtLater ] -> [
+ vernac_solve SelectAll n t def
+ ]
+END
+
+let pr_ltac_tactic_level n = str "(at level " ++ int n ++ str ")"
+
+VERNAC ARGUMENT EXTEND ltac_tactic_level PRINTED BY pr_ltac_tactic_level
+| [ "(" "at" "level" natural(n) ")" ] -> [ n ]
+END
+
+VERNAC ARGUMENT EXTEND ltac_production_sep
+| [ "," string(sep) ] -> [ sep ]
+END
+
+let pr_ltac_production_item = function
+| TacTerm s -> quote (str s)
+| TacNonTerm (_, arg, (id, sep)) ->
+ let sep = match sep with
+ | "" -> mt ()
+ | sep -> str "," ++ spc () ++ quote (str sep)
+ in
+ str arg ++ str "(" ++ Nameops.pr_id id ++ sep ++ str ")"
+
+VERNAC ARGUMENT EXTEND ltac_production_item PRINTED BY pr_ltac_production_item
+| [ string(s) ] -> [ TacTerm s ]
+| [ ident(nt) "(" ident(p) ltac_production_sep_opt(sep) ")" ] ->
+ [ TacNonTerm (loc, Names.Id.to_string nt, (p, Option.default "" sep)) ]
+END
+
+VERNAC COMMAND EXTEND VernacTacticNotation
+| [ "Tactic" "Notation" ltac_tactic_level_opt(n) ne_ltac_production_item_list(r) ":=" tactic(e) ] =>
+ [ VtUnknown, VtNow ] ->
+ [
+ let l = Locality.LocalityFixme.consume () in
+ let n = Option.default 0 n in
+ Tacentries.add_tactic_notation (Locality.make_module_locality l, n, r, e)
+ ]
+END
+
+VERNAC COMMAND EXTEND VernacPrintLtac CLASSIFIED AS QUERY
+| [ "Print" "Ltac" reference(r) ] ->
+ [ msg_notice (Tacintern.print_ltac (snd (Libnames.qualid_of_reference r))) ]
+END
+
+VERNAC ARGUMENT EXTEND ltac_tacdef_body
+| [ tacdef_body(t) ] -> [ t ]
+END
+
+VERNAC COMMAND EXTEND VernacDeclareTacticDefinition
+| [ "Ltac" ne_ltac_tacdef_body_list_sep(l, "with") ] => [
+ VtSideff (List.map (function
+ | TacticDefinition ((_,r),_) -> r
+ | TacticRedefinition (Ident (_,r),_) -> r
+ | TacticRedefinition (Qualid (_,q),_) -> snd(repr_qualid q)) l), VtLater
+ ] -> [
+ let lc = Locality.LocalityFixme.consume () in
+ Tacentries.register_ltac (Locality.make_module_locality lc) l
+ ]
+END
diff --git a/tactics/g_obligations.ml4 b/tactics/g_obligations.ml4
new file mode 100644
index 0000000000..4cd8bf1feb
--- /dev/null
+++ b/tactics/g_obligations.ml4
@@ -0,0 +1,147 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(*i camlp4deps: "grammar/grammar.cma" i*)
+
+(*
+ Syntax for the subtac terms and types.
+ Elaborated from correctness/psyntax.ml4 by Jean-Christophe Filliâtre *)
+
+
+open Libnames
+open Constrexpr
+open Constrexpr_ops
+open Stdarg
+open Constrarg
+open Extraargs
+
+let (set_default_tactic, get_default_tactic, print_default_tactic) =
+ Tactic_option.declare_tactic_option "Program tactic"
+
+let () =
+ (** Delay to recover the tactic imperatively *)
+ let tac = Proofview.tclBIND (Proofview.tclUNIT ()) begin fun () ->
+ snd (get_default_tactic ())
+ end in
+ Obligations.default_tactic := tac
+
+(* We define new entries for programs, with the use of this module
+ * Subtac. These entries are named Subtac.<foo>
+ *)
+
+module Gram = Pcoq.Gram
+module Tactic = Pcoq.Tactic
+
+open Pcoq
+
+let sigref = mkRefC (Qualid (Loc.ghost, Libnames.qualid_of_string "Coq.Init.Specif.sig"))
+
+type 'a withtac_argtype = (Tacexpr.raw_tactic_expr option, 'a) Genarg.abstract_argument_type
+
+let wit_withtac : Tacexpr.raw_tactic_expr option Genarg.uniform_genarg_type =
+ Genarg.create_arg "withtac"
+
+let withtac = Pcoq.create_generic_entry Pcoq.utactic "withtac" (Genarg.rawwit wit_withtac)
+
+GEXTEND Gram
+ GLOBAL: withtac;
+
+ withtac:
+ [ [ "with"; t = Tactic.tactic -> Some t
+ | -> None ] ]
+ ;
+
+ Constr.closed_binder:
+ [[ "("; id=Prim.name; ":"; t=Constr.lconstr; "|"; c=Constr.lconstr; ")" ->
+ let typ = mkAppC (sigref, [mkLambdaC ([id], default_binder_kind, t, c)]) in
+ [LocalRawAssum ([id], default_binder_kind, typ)]
+ ] ];
+
+ END
+
+open Obligations
+
+let classify_obbl _ = Vernacexpr.(VtStartProof ("Classic",Doesn'tGuaranteeOpacity,[]), VtLater)
+
+VERNAC COMMAND EXTEND Obligations CLASSIFIED BY classify_obbl
+| [ "Obligation" integer(num) "of" ident(name) ":" lglob(t) withtac(tac) ] ->
+ [ obligation (num, Some name, Some t) tac ]
+| [ "Obligation" integer(num) "of" ident(name) withtac(tac) ] ->
+ [ obligation (num, Some name, None) tac ]
+| [ "Obligation" integer(num) ":" lglob(t) withtac(tac) ] ->
+ [ obligation (num, None, Some t) tac ]
+| [ "Obligation" integer(num) withtac(tac) ] ->
+ [ obligation (num, None, None) tac ]
+| [ "Next" "Obligation" "of" ident(name) withtac(tac) ] ->
+ [ next_obligation (Some name) tac ]
+| [ "Next" "Obligation" withtac(tac) ] -> [ next_obligation None tac ]
+END
+
+VERNAC COMMAND EXTEND Solve_Obligation CLASSIFIED AS SIDEFF
+| [ "Solve" "Obligation" integer(num) "of" ident(name) "with" tactic(t) ] ->
+ [ try_solve_obligation num (Some name) (Some (Tacinterp.interp t)) ]
+| [ "Solve" "Obligation" integer(num) "with" tactic(t) ] ->
+ [ try_solve_obligation num None (Some (Tacinterp.interp t)) ]
+END
+
+VERNAC COMMAND EXTEND Solve_Obligations CLASSIFIED AS SIDEFF
+| [ "Solve" "Obligations" "of" ident(name) "with" tactic(t) ] ->
+ [ try_solve_obligations (Some name) (Some (Tacinterp.interp t)) ]
+| [ "Solve" "Obligations" "with" tactic(t) ] ->
+ [ try_solve_obligations None (Some (Tacinterp.interp t)) ]
+| [ "Solve" "Obligations" ] ->
+ [ try_solve_obligations None None ]
+END
+
+VERNAC COMMAND EXTEND Solve_All_Obligations CLASSIFIED AS SIDEFF
+| [ "Solve" "All" "Obligations" "with" tactic(t) ] ->
+ [ solve_all_obligations (Some (Tacinterp.interp t)) ]
+| [ "Solve" "All" "Obligations" ] ->
+ [ solve_all_obligations None ]
+END
+
+VERNAC COMMAND EXTEND Admit_Obligations CLASSIFIED AS SIDEFF
+| [ "Admit" "Obligations" "of" ident(name) ] -> [ admit_obligations (Some name) ]
+| [ "Admit" "Obligations" ] -> [ admit_obligations None ]
+END
+
+VERNAC COMMAND EXTEND Set_Solver CLASSIFIED AS SIDEFF
+| [ "Obligation" "Tactic" ":=" tactic(t) ] -> [
+ set_default_tactic
+ (Locality.make_section_locality (Locality.LocalityFixme.consume ()))
+ (Tacintern.glob_tactic t) ]
+END
+
+open Pp
+
+VERNAC COMMAND EXTEND Show_Solver CLASSIFIED AS QUERY
+| [ "Show" "Obligation" "Tactic" ] -> [
+ msg_info (str"Program obligation tactic is " ++ print_default_tactic ()) ]
+END
+
+VERNAC COMMAND EXTEND Show_Obligations CLASSIFIED AS QUERY
+| [ "Obligations" "of" ident(name) ] -> [ show_obligations (Some name) ]
+| [ "Obligations" ] -> [ show_obligations None ]
+END
+
+VERNAC COMMAND EXTEND Show_Preterm CLASSIFIED AS QUERY
+| [ "Preterm" "of" ident(name) ] -> [ msg_info (show_term (Some name)) ]
+| [ "Preterm" ] -> [ msg_info (show_term None) ]
+END
+
+open Pp
+
+(* Declare a printer for the content of Program tactics *)
+let () =
+ let printer _ _ _ = function
+ | None -> mt ()
+ | Some tac -> str "with" ++ spc () ++ Pptactic.pr_raw_tactic tac
+ in
+ (* should not happen *)
+ let dummy _ _ _ expr = assert false in
+ Pptactic.declare_extra_genarg_pprule wit_withtac printer dummy dummy
diff --git a/tactics/g_rewrite.ml4 b/tactics/g_rewrite.ml4
index 72cfb01a57..c4ef1f297e 100644
--- a/tactics/g_rewrite.ml4
+++ b/tactics/g_rewrite.ml4
@@ -20,6 +20,11 @@ open Extraargs
open Tacmach
open Tacticals
open Rewrite
+open Stdarg
+open Constrarg
+open Pcoq.Prim
+open Pcoq.Constr
+open Pcoq.Tactic
DECLARE PLUGIN "g_rewrite"
@@ -184,9 +189,9 @@ END
type binders_argtype = local_binder list
let wit_binders =
- (Genarg.create_arg None "binders" : binders_argtype Genarg.uniform_genarg_type)
+ (Genarg.create_arg "binders" : binders_argtype Genarg.uniform_genarg_type)
-let binders = Pcoq.create_generic_entry "binders" (Genarg.rawwit wit_binders)
+let binders = Pcoq.create_generic_entry Pcoq.utactic "binders" (Genarg.rawwit wit_binders)
open Pcoq
@@ -261,3 +266,7 @@ TACTIC EXTEND setoid_transitivity
[ "setoid_transitivity" constr(t) ] -> [ setoid_transitivity (Some t) ]
| [ "setoid_etransitivity" ] -> [ setoid_transitivity None ]
END
+
+VERNAC COMMAND EXTEND PrintRewriteHintDb CLASSIFIED AS QUERY
+ [ "Print" "Rewrite" "HintDb" preident(s) ] -> [ Pp.msg_notice (Autorewrite.print_rewrite_hintdb s) ]
+END
diff --git a/tactics/geninterp.ml b/tactics/geninterp.ml
index 0ad3abb53d..0080758000 100644
--- a/tactics/geninterp.ml
+++ b/tactics/geninterp.ml
@@ -12,11 +12,10 @@ open Genarg
module TacStore = Store.Make(struct end)
type interp_sign = {
- lfun : tlevel generic_argument Id.Map.t;
+ lfun : Val.t Id.Map.t;
extra : TacStore.t }
-type ('glb, 'top) interp_fun = interp_sign ->
- Goal.goal Evd.sigma -> 'glb -> Evd.evar_map * 'top
+type ('glb, 'top) interp_fun = interp_sign -> 'glb -> 'top Ftactic.t
module InterpObj =
struct
@@ -30,9 +29,7 @@ module Interp = Register(InterpObj)
let interp = Interp.obj
let register_interp0 = Interp.register0
-let generic_interp ist gl v =
- let unpacker wit v =
- let (sigma, ans) = interp wit ist gl (glb v) in
- (sigma, in_gen (topwit wit) ans)
- in
- unpack { unpacker; } v
+let generic_interp ist (GenArg (Glbwit wit, v)) =
+ let open Ftactic.Notations in
+ interp wit ist v >>= fun ans ->
+ Ftactic.return (Val.Dyn (val_tag (topwit wit), ans))
diff --git a/tactics/geninterp.mli b/tactics/geninterp.mli
index 7f25a022c4..0992db7a29 100644
--- a/tactics/geninterp.mli
+++ b/tactics/geninterp.mli
@@ -14,15 +14,14 @@ open Genarg
module TacStore : Store.S
type interp_sign = {
- lfun : tlevel generic_argument Id.Map.t;
+ lfun : Val.t Id.Map.t;
extra : TacStore.t }
-type ('glb, 'top) interp_fun = interp_sign ->
- Goal.goal Evd.sigma -> 'glb -> Evd.evar_map * 'top
+type ('glb, 'top) interp_fun = interp_sign -> 'glb -> 'top Ftactic.t
val interp : ('raw, 'glb, 'top) genarg_type -> ('glb, 'top) interp_fun
-val generic_interp : (glob_generic_argument, typed_generic_argument) interp_fun
+val generic_interp : (glob_generic_argument, Val.t) interp_fun
val register_interp0 :
('raw, 'glb, 'top) genarg_type -> ('glb, 'top) interp_fun -> unit
diff --git a/tactics/hightactics.mllib b/tactics/hightactics.mllib
index ff2e1ff6aa..468b938b6a 100644
--- a/tactics/hightactics.mllib
+++ b/tactics/hightactics.mllib
@@ -1,7 +1,15 @@
+Tacintern
+Tacentries
+Tacinterp
+Evar_tactics
+Tactic_option
Extraargs
+G_obligations
Coretactics
+Autorewrite
Extratactics
Eauto
+G_auto
Class_tactics
G_class
Rewrite
@@ -9,3 +17,4 @@ G_rewrite
Tauto
Eqdecide
G_eqdecide
+G_ltac
diff --git a/tactics/hints.ml b/tactics/hints.ml
index 42e5067c9d..730da147af 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -33,6 +33,8 @@ open Pfedit
open Tacred
open Printer
open Vernacexpr
+open Sigma.Notations
+open Context.Named.Declaration
(****************************************)
(* General functions *)
@@ -153,27 +155,6 @@ let fresh_key =
in
KerName.make mp dir (Label.of_id lbl)
-let eq_hints_path_atom p1 p2 = match p1, p2 with
-| PathHints gr1, PathHints gr2 -> List.equal eq_gr gr1 gr2
-| PathAny, PathAny -> true
-| (PathHints _ | PathAny), _ -> false
-
-let eq_auto_tactic t1 t2 = match t1, t2 with
-| Res_pf (c1, _), Res_pf (c2, _) -> Constr.equal c1 c2
-| ERes_pf (c1, _), ERes_pf (c2, _) -> Constr.equal c1 c2
-| Give_exact (c1, _), Give_exact (c2, _) -> Constr.equal c1 c2
-| Res_pf_THEN_trivial_fail (c1, _), Res_pf_THEN_trivial_fail (c2, _) -> Constr.equal c1 c2
-| Unfold_nth gr1, Unfold_nth gr2 -> eq_egr gr1 gr2
-| Extern tac1, Extern tac2 -> tac1 == tac2 (** May cause redundancy in addkv *)
-| (Res_pf _ | ERes_pf _ | Give_exact _ | Res_pf_THEN_trivial_fail _
- | Unfold_nth _ | Extern _), _ -> false
-
-let eq_hint_metadata t1 t2 =
- Int.equal t1.pri t2.pri &&
- Option.equal constr_pattern_eq t1.pat t2.pat &&
- eq_hints_path_atom t1.name t2.name &&
- eq_auto_tactic t1.code t2.code
-
let pri_order_int (id1, {pri=pri1}) (id2, {pri=pri2}) =
let d = pri1 - pri2 in
if Int.equal d 0 then id2 - id1
@@ -747,11 +728,12 @@ let make_resolves env sigma flags pri poly ?name cr =
ents
(* used to add an hypothesis to the local hint database *)
-let make_resolve_hyp env sigma (hname,_,htyp) =
+let make_resolve_hyp env sigma decl =
+ let hname = get_id decl in
try
[make_apply_entry env sigma (true, true, false) None false
~name:(PathHints [VarRef hname])
- (mkVar hname, htyp, Univ.ContextSet.empty)]
+ (mkVar hname, get_type decl, Univ.ContextSet.empty)]
with
| Failure _ -> []
| e when Logic.catchable_exception e -> anomaly (Pp.str "make_resolve_hyp")
@@ -1081,7 +1063,7 @@ let prepare_hint check (poly,local) env init (sigma,c) =
(* Not clever enough to construct dependency graph of evars *)
error "Not clever enough to deal with evars dependent in other evars.";
raise (Found (c,t))
- | _ -> iter_constr find_next_evar c in
+ | _ -> Constr.iter find_next_evar c in
let rec iter c =
try find_next_evar c; c
with Found (evar,t) ->
@@ -1184,6 +1166,12 @@ let add_hint_lemmas env sigma eapply lems hint_db =
Hint_db.add_list env sigma hintlist' hint_db
let make_local_hint_db env sigma ts eapply lems =
+ let map c =
+ let sigma = Sigma.Unsafe.of_evar_map sigma in
+ let Sigma (c, sigma, _) = c.delayed env sigma in
+ (Sigma.to_evar_map sigma, c)
+ in
+ let lems = List.map map lems in
let sign = Environ.named_context env in
let ts = match ts with
| None -> Hint_db.transparent_state (searchtable_map "core")
diff --git a/tactics/hints.mli b/tactics/hints.mli
index 08ea71bb14..3e08060f81 100644
--- a/tactics/hints.mli
+++ b/tactics/hints.mli
@@ -10,7 +10,6 @@ open Pp
open Util
open Names
open Term
-open Context
open Environ
open Globnames
open Decl_kinds
@@ -192,7 +191,7 @@ val make_resolves :
If the hyp cannot be used as a Hint, the empty list is returned. *)
val make_resolve_hyp :
- env -> evar_map -> named_declaration -> hint_entry list
+ env -> evar_map -> Context.Named.Declaration.t -> hint_entry list
(** [make_extern pri pattern tactic_expr] *)
@@ -214,7 +213,7 @@ val extern_intern_tac :
Useful to take the current goal hypotheses as hints;
Boolean tells if lemmas with evars are allowed *)
-val make_local_hint_db : env -> evar_map -> ?ts:transparent_state -> bool -> open_constr list -> hint_db
+val make_local_hint_db : env -> evar_map -> ?ts:transparent_state -> bool -> Tacexpr.delayed_open_constr list -> hint_db
val make_db_list : hint_db_name list -> hint_db list
diff --git a/tactics/hipattern.ml4 b/tactics/hipattern.ml4
index 29d848ca13..bcec90f803 100644
--- a/tactics/hipattern.ml4
+++ b/tactics/hipattern.ml4
@@ -19,6 +19,7 @@ open Constr_matching
open Coqlib
open Declarations
open Tacmach.New
+open Context.Rel.Declaration
(* I implemented the following functions which test whether a term t
is an inductive but non-recursive type, a general conjuction, a
@@ -101,13 +102,16 @@ let match_with_one_constructor style onlybinary allow_rec t =
(decompose_prod_n_assum mib.mind_nparams mip.mind_nf_lc.(0)))) in
if
List.for_all
- (fun (_,b,c) -> Option.is_empty b && isRel c && Int.equal (destRel c) mib.mind_nparams) ctx
+ (fun decl -> let c = get_type decl in
+ is_local_assum decl &&
+ isRel c &&
+ Int.equal (destRel c) mib.mind_nparams) ctx
then
Some (hdapp,args)
else None
else
let ctyp = prod_applist mip.mind_nf_lc.(0) args in
- let cargs = List.map pi3 ((prod_assum ctyp)) in
+ let cargs = List.map get_type (prod_assum ctyp) in
if not (is_lax_conjunction style) || has_nodep_prod ctyp then
(* Record or non strict conjunction *)
Some (hdapp,List.rev cargs)
@@ -152,7 +156,7 @@ let is_tuple t =
let test_strict_disjunction n lc =
Array.for_all_i (fun i c ->
match (prod_assum (snd (decompose_prod_n_assum n c))) with
- | [_,None,c] -> isRel c && Int.equal (destRel c) (n - i)
+ | [LocalAssum (_,c)] -> isRel c && Int.equal (destRel c) (n - i)
| _ -> false) 0 lc
let match_with_disjunction ?(strict=false) ?(onlybinary=false) t =
diff --git a/tactics/hipattern.mli b/tactics/hipattern.mli
index 32938ce50f..7cc41f1b93 100644
--- a/tactics/hipattern.mli
+++ b/tactics/hipattern.mli
@@ -119,11 +119,11 @@ val match_with_equation:
(** Match terms [eq A t u], [identity A t u] or [JMeq A t A u]
Returns associated lemmas and [A,t,u] or fails PatternMatchingFailure *)
-val find_eq_data_decompose : [ `NF ] Proofview.Goal.t -> constr ->
+val find_eq_data_decompose : ([ `NF ], 'r) Proofview.Goal.t -> constr ->
coq_eq_data * Univ.universe_instance * (types * constr * constr)
(** Idem but fails with an error message instead of PatternMatchingFailure *)
-val find_this_eq_data_decompose : [ `NF ] Proofview.Goal.t -> constr ->
+val find_this_eq_data_decompose : ([ `NF ], 'r) Proofview.Goal.t -> constr ->
coq_eq_data * Univ.universe_instance * (types * constr * constr)
(** A variant that returns more informative structure on the equality found *)
@@ -144,7 +144,7 @@ val is_matching_sigma : constr -> bool
val match_eqdec : constr -> bool * constr * constr * constr * constr
(** Match an equality up to conversion; returns [(eq,t1,t2)] in normal form *)
-val dest_nf_eq : [ `NF ] Proofview.Goal.t -> constr -> (constr * constr * constr)
+val dest_nf_eq : ([ `NF ], 'r) Proofview.Goal.t -> constr -> (constr * constr * constr)
(** Match a negation *)
val is_matching_not : constr -> bool
diff --git a/tactics/inv.ml b/tactics/inv.ml
index 22bacdfc2b..6841ab0ecd 100644
--- a/tactics/inv.ml
+++ b/tactics/inv.ml
@@ -13,7 +13,6 @@ open Names
open Nameops
open Term
open Vars
-open Context
open Termops
open Namegen
open Environ
@@ -27,7 +26,9 @@ open Elim
open Equality
open Misctypes
open Tacexpr
+open Sigma.Notations
open Proofview.Notations
+open Context.Named.Declaration
let clear hyps = Proofview.V82.tactic (clear hyps)
@@ -96,7 +97,7 @@ let make_inv_predicate env evd indf realargs id status concl =
(* We lift to make room for the equations *)
(hyps,lift nrealargs bodypred)
in
- let nhyps = rel_context_length hyps in
+ let nhyps = Context.Rel.length hyps in
let env' = push_rel_context hyps env in
(* Now the arity is pushed, and we need to construct the pairs
* ai,mkRel(n-i+1) *)
@@ -181,9 +182,9 @@ let make_inv_predicate env evd indf realargs id status concl =
let dependent_hyps env id idlist gl =
let rec dep_rec =function
| [] -> []
- | (id1,_,_)::l ->
+ | d::l ->
(* Update the type of id1: it may have been subject to rewriting *)
- let d = pf_get_hyp id1 gl in
+ let d = pf_get_hyp (get_id d) gl in
if occur_var_in_decl env id d
then d :: dep_rec l
else dep_rec l
@@ -192,8 +193,8 @@ let dependent_hyps env id idlist gl =
let split_dep_and_nodep hyps gl =
List.fold_right
- (fun (id,_,_ as d) (l1,l2) ->
- if var_occurs_in_pf gl id then (d::l1,l2) else (l1,d::l2))
+ (fun d (l1,l2) ->
+ if var_occurs_in_pf gl (get_id d) then (d::l1,l2) else (l1,d::l2))
hyps ([],[])
(* Computation of dids is late; must have been done in rewrite_equations*)
@@ -269,14 +270,14 @@ Nota: with Inversion_clear, only four useless hypotheses
let generalizeRewriteIntros as_mode tac depids id =
Proofview.tclENV >>= fun env ->
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let dids = dependent_hyps env id depids gl in
let reintros = if as_mode then intros_replacing else intros_possibly_replacing in
(tclTHENLIST
[bring_hyps dids; tac;
(* may actually fail to replace if dependent in a previous eq *)
reintros (ids_of_named_context dids)])
- end
+ end }
let error_too_many_names pats =
let loc = Loc.join_loc (fst (List.hd pats)) (fst (List.last pats)) in
@@ -284,10 +285,10 @@ let error_too_many_names pats =
tclZEROMSG ~loc (
str "Unexpected " ++
str (String.plural (List.length pats) "introduction pattern") ++
- str ": " ++ pr_enum (Miscprint.pr_intro_pattern (fun c -> Printer.pr_constr (snd (c env Evd.empty)))) pats ++
+ str ": " ++ pr_enum (Miscprint.pr_intro_pattern (fun c -> Printer.pr_constr (fst (run_delayed env Evd.empty c)))) pats ++
str ".")
-let rec get_names (allow_conj,issimple) (loc,pat as x) = match pat with
+let get_names (allow_conj,issimple) (loc, pat as x) = match pat with
| IntroNaming IntroAnonymous | IntroForthcoming _ ->
error "Anonymous pattern not allowed for inversion equations."
| IntroNaming (IntroFresh _) ->
@@ -296,17 +297,17 @@ let rec get_names (allow_conj,issimple) (loc,pat as x) = match pat with
error "Discarding pattern not allowed for inversion equations."
| IntroAction (IntroRewrite _) ->
error "Rewriting pattern not allowed for inversion equations."
- | IntroAction (IntroOrAndPattern [[]]) when allow_conj -> (None, [])
- | IntroAction (IntroOrAndPattern [(_,IntroNaming (IntroIdentifier id)) :: _ as l])
+ | IntroAction (IntroOrAndPattern (IntroAndPattern [])) when allow_conj -> (None, [])
+ | IntroAction (IntroOrAndPattern (IntroAndPattern ((_,IntroNaming (IntroIdentifier id)) :: _ as l) | IntroOrPattern [(_,IntroNaming (IntroIdentifier id)) :: _ as l ]))
when allow_conj -> (Some id,l)
- | IntroAction (IntroOrAndPattern [_]) ->
+ | IntroAction (IntroOrAndPattern (IntroAndPattern _)) ->
if issimple then
error"Conjunctive patterns not allowed for simple inversion equations."
else
error"Nested conjunctive patterns not allowed for inversion equations."
| IntroAction (IntroInjection l) ->
error "Injection patterns not allowed for inversion equations."
- | IntroAction (IntroOrAndPattern l) ->
+ | IntroAction (IntroOrAndPattern (IntroOrPattern _)) ->
error "Disjunctive patterns not allowed for inversion equations."
| IntroAction (IntroApplyOn (c,pat)) ->
error "Apply patterns not allowed for inversion equations."
@@ -338,7 +339,7 @@ let projectAndApply as_mode thin avoid id eqname names depids =
(if thin then clear [id] else (remember_first_eq id eqname; tclIDTAC))
in
let substHypIfVariable tac id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
(** We only look at the type of hypothesis "id" *)
let hyp = pf_nf_evar gl (pf_get_hyp_typ id (Proofview.Goal.assume gl)) in
let (t,t1,t2) = Hipattern.dest_nf_eq gl hyp in
@@ -346,7 +347,7 @@ let projectAndApply as_mode thin avoid id eqname names depids =
| Var id1, _ -> generalizeRewriteIntros as_mode (subst_hyp true id) depids id1
| _, Var id2 -> generalizeRewriteIntros as_mode (subst_hyp false id) depids id2
| _ -> tac id
- end
+ end }
in
let deq_trailer id clear_flag _ neqns =
assert (clear_flag == None);
@@ -373,7 +374,7 @@ let projectAndApply as_mode thin avoid id eqname names depids =
id
let nLastDecls i tac =
- Proofview.Goal.nf_enter (fun gl -> tac (nLastDecls gl i))
+ Proofview.Goal.nf_enter { enter = begin fun gl -> tac (nLastDecls gl i) end }
(* Introduction of the equations on arguments
othin: discriminates Simple Inversion, Inversion and Inversion_clear
@@ -381,10 +382,10 @@ let nLastDecls i tac =
Some thin: the equations are rewritten, and cleared if thin is true *)
let rewrite_equations as_mode othin neqns names ba =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let (depids,nodepids) = split_dep_and_nodep ba.Tacticals.assums gl in
let first_eq = ref MoveLast in
- let avoid = if as_mode then List.map pi1 nodepids else [] in
+ let avoid = if as_mode then List.map get_id nodepids else [] in
match othin with
| Some thin ->
tclTHENLIST
@@ -399,11 +400,11 @@ let rewrite_equations as_mode othin neqns names ba =
(onLastHypId (fun id ->
tclTRY (projectAndApply as_mode thin avoid id first_eq names depids)))))
names;
- tclMAP (fun (id,_,_) -> tclIDTAC >>= fun () -> (* delay for [first_eq]. *)
- let idopt = if as_mode then Some id else None in
+ tclMAP (fun d -> tclIDTAC >>= fun () -> (* delay for [first_eq]. *)
+ let idopt = if as_mode then Some (get_id d) else None in
intro_move idopt (if thin then MoveLast else !first_eq))
nodepids;
- (tclMAP (fun (id,_,_) -> tclTRY (clear [id])) depids)]
+ (tclMAP (fun d -> tclTRY (clear [get_id d])) depids)]
| None ->
(* simple inversion *)
if as_mode then
@@ -414,7 +415,7 @@ let rewrite_equations as_mode othin neqns names ba =
[tclDO neqns intro;
bring_hyps nodepids;
clear (ids_of_named_context nodepids)])
- end
+ end }
let interp_inversion_kind = function
| SimpleInversion -> None
@@ -431,8 +432,9 @@ let rewrite_equations_tac as_mode othin id neqns names ba =
tac
let raw_inversion inv_kind id status names =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
let env = Proofview.Goal.env gl in
let concl = Proofview.Goal.concl gl in
let c = mkVar id in
@@ -457,11 +459,11 @@ let raw_inversion inv_kind id status names =
in
let refined id =
let prf = mkApp (mkVar id, args) in
- Proofview.Refine.refine (fun h -> h, prf)
+ Proofview.Refine.refine { run = fun h -> Sigma (prf, h, Sigma.refl) }
in
let neqns = List.length realargs in
let as_mode = names != None in
- tclTHEN (Proofview.Unsafe.tclEVARS sigma)
+ let tac =
(tclTHENS
(assert_before Anonymous cut_concl)
[case_tac names
@@ -469,7 +471,9 @@ let raw_inversion inv_kind id status names =
(rewrite_equations_tac as_mode inv_kind id neqns))
(Some elim_predicate) ind (c, t);
onLastHypId (fun id -> tclTHEN (refined id) reflexivity)])
- end
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
(* Error messages of the inversion tactics *)
let wrap_inv_error id = function (e, info) -> match e with
@@ -511,12 +515,12 @@ let dinv_clear_tac id = dinv FullInversionClear None None (NamedHyp id)
* back to their places in the hyp-list. *)
let invIn k names ids id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let hyps = List.map (fun id -> pf_get_hyp id gl) ids in
let concl = Proofview.Goal.concl gl in
let nb_prod_init = nb_prod concl in
let intros_replace_ids =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let concl = pf_nf_concl gl in
let nb_of_new_hyp =
nb_prod concl - (List.length hyps + nb_prod_init)
@@ -525,7 +529,7 @@ let invIn k names ids id =
intros_replacing ids
else
tclTHEN (tclDO nb_of_new_hyp intro) (intros_replacing ids)
- end
+ end }
in
Proofview.tclORELSE
(tclTHENLIST
@@ -533,7 +537,7 @@ let invIn k names ids id =
inversion k NoDep names id;
intros_replace_ids])
(wrap_inv_error id)
- end
+ end }
let invIn_gen k names idl = try_intros_until (invIn k names idl)
diff --git a/tactics/leminv.ml b/tactics/leminv.ml
index 894d447443..70782ec648 100644
--- a/tactics/leminv.ml
+++ b/tactics/leminv.ml
@@ -14,7 +14,6 @@ open Term
open Vars
open Termops
open Namegen
-open Context
open Evd
open Printer
open Reductionops
@@ -27,6 +26,8 @@ open Declare
open Tacticals.New
open Tactics
open Decl_kinds
+open Proofview.Notations
+open Context.Named.Declaration
let no_inductive_inconstr env sigma constr =
(str "Cannot recognize an inductive predicate in " ++
@@ -117,11 +118,11 @@ let rec add_prods_sign env sigma t =
| Prod (na,c1,b) ->
let id = id_of_name_using_hdchar env t na in
let b'= subst1 (mkVar id) b in
- add_prods_sign (push_named (id,None,c1) env) sigma b'
+ add_prods_sign (push_named (LocalAssum (id,c1)) env) sigma b'
| LetIn (na,c1,t1,b) ->
let id = id_of_name_using_hdchar env t na in
let b'= subst1 (mkVar id) b in
- add_prods_sign (push_named (id,Some c1,t1) env) sigma b'
+ add_prods_sign (push_named (LocalDef (id,c1,t1)) env) sigma b'
| _ -> (env,t)
(* [dep_option] indicates whether the inversion lemma is dependent or not.
@@ -154,9 +155,10 @@ let compute_first_inversion_scheme env sigma ind sort dep_option =
let ivars = global_vars env i in
let revargs,ownsign =
fold_named_context
- (fun env (id,_,_ as d) (revargs,hyps) ->
+ (fun env d (revargs,hyps) ->
+ let id = get_id d in
if Id.List.mem id ivars then
- ((mkVar id)::revargs,add_named_decl d hyps)
+ ((mkVar id)::revargs, Context.Named.add d hyps)
else
(revargs,hyps))
env ~init:([],[])
@@ -166,7 +168,7 @@ let compute_first_inversion_scheme env sigma ind sort dep_option =
(pty,goal)
in
let npty = nf_betadeltaiota env sigma pty in
- let extenv = push_named (p,None,npty) env in
+ let extenv = push_named (LocalAssum (p,npty)) env in
extenv, goal
(* [inversion_scheme sign I]
@@ -203,10 +205,10 @@ let inversion_scheme env sigma t sort dep_option inv_op =
let global_named_context = Global.named_context () in
let ownSign = ref begin
fold_named_context
- (fun env (id,_,_ as d) sign ->
- if mem_named_context id global_named_context then sign
- else add_named_decl d sign)
- invEnv ~init:empty_named_context
+ (fun env d sign ->
+ if mem_named_context (get_id d) global_named_context then sign
+ else Context.Named.add d sign)
+ invEnv ~init:Context.Named.empty
end in
let avoid = ref [] in
let { sigma=sigma } = Proof.V82.subgoals pf in
@@ -217,9 +219,9 @@ let inversion_scheme env sigma t sort dep_option inv_op =
let h = next_ident_away (Id.of_string "H") !avoid in
let ty,inst = Evarutil.generalize_evar_over_rels sigma (e,args) in
avoid := h::!avoid;
- ownSign := add_named_decl (h,None,ty) !ownSign;
+ ownSign := Context.Named.add (LocalAssum (h,ty)) !ownSign;
applist (mkVar h, inst)
- | _ -> map_constr fill_holes c
+ | _ -> Constr.map fill_holes c
in
let c = fill_holes pfterm in
(* warning: side-effect on ownSign *)
@@ -269,7 +271,7 @@ let lemInv id c gls =
let lemInv_gen id c = try_intros_until (fun id -> Proofview.V82.tactic (lemInv id c)) id
let lemInvIn id c ids =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let hyps = List.map (fun id -> pf_get_hyp id gl) ids in
let intros_replace_ids =
let concl = Proofview.Goal.concl gl in
@@ -281,7 +283,7 @@ let lemInvIn id c ids =
in
((tclTHEN (tclTHEN (bring_hyps hyps) (Proofview.V82.tactic (lemInv id c)))
(intros_replace_ids)))
- end
+ end }
let lemInvIn_gen id c l = try_intros_until (fun id -> lemInvIn id c l) id
diff --git a/tactics/rewrite.ml b/tactics/rewrite.ml
index 803e187ff5..67d21886b2 100644
--- a/tactics/rewrite.ml
+++ b/tactics/rewrite.ml
@@ -6,8 +6,6 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i camlp4deps: "grammar/grammar.cma" i*)
-
open Names
open Pp
open Errors
@@ -34,6 +32,9 @@ open Elimschemes
open Environ
open Termops
open Libnames
+open Sigma.Notations
+open Proofview.Notations
+open Context.Named.Declaration
(** Typeclass-based generalized rewriting. *)
@@ -66,8 +67,10 @@ type evars = evar_map * Evar.Set.t (* goal evars, constraint evars *)
let find_global dir s =
let gr = lazy (try_find_global_reference dir s) in
- fun (evd,cstrs) ->
- let evd, c = Evarutil.new_global evd (Lazy.force gr) in
+ fun (evd,cstrs) ->
+ let sigma = Sigma.Unsafe.of_evar_map evd in
+ let Sigma (c, sigma, _) = Evarutil.new_global sigma (Lazy.force gr) in
+ let evd = Sigma.to_evar_map sigma in
(evd, cstrs), c
(** Utility for dealing with polymorphic applications *)
@@ -88,7 +91,9 @@ let cstrevars evars = snd evars
let new_cstr_evar (evd,cstrs) env t =
let s = Typeclasses.set_resolvable Evd.Store.empty false in
- let evd', t = Evarutil.new_evar ~store:s env evd t in
+ let evd = Sigma.Unsafe.of_evar_map evd in
+ let Sigma (t, evd', _) = Evarutil.new_evar ~store:s env evd t in
+ let evd' = Sigma.to_evar_map evd' in
let ev, _ = destEvar t in
(evd', Evar.Set.add ev cstrs), t
@@ -105,7 +110,7 @@ let extends_undefined evars evars' =
let app_poly_check env evars f args =
let (evars, cstrs), fc = f evars in
let evdref = ref evars in
- let t = Typing.solve_evars env evdref (mkApp (fc, args)) in
+ let t = Typing.e_solve_evars env evdref (mkApp (fc, args)) in
(!evdref, cstrs), t
let app_poly_nocheck env evars f args =
@@ -134,6 +139,7 @@ module GlobalBindings (M : sig
val arrow : evars -> evars * constr
end) = struct
open M
+ open Context.Rel.Declaration
let relation : evars -> evars * constr = find_global (fst relation) (snd relation)
let reflexive_type = find_global relation_classes "Reflexive"
@@ -172,13 +178,17 @@ end) = struct
let proper_type =
let l = lazy (Lazy.force proper_class).cl_impl in
fun (evd,cstrs) ->
- let evd, c = Evarutil.new_global evd (Lazy.force l) in
+ let sigma = Sigma.Unsafe.of_evar_map evd in
+ let Sigma (c, sigma, _) = Evarutil.new_global sigma (Lazy.force l) in
+ let evd = Sigma.to_evar_map sigma in
(evd, cstrs), c
let proper_proxy_type =
let l = lazy (Lazy.force proper_proxy_class).cl_impl in
fun (evd,cstrs) ->
- let evd, c = Evarutil.new_global evd (Lazy.force l) in
+ let sigma = Sigma.Unsafe.of_evar_map evd in
+ let Sigma (c, sigma, _) = Evarutil.new_global sigma (Lazy.force l) in
+ let evd = Sigma.to_evar_map sigma in
(evd, cstrs), c
let proper_proof env evars carrier relation x =
@@ -219,8 +229,8 @@ end) = struct
let evars, newarg = app_poly env evars respectful [| ty ; b' ; relty ; arg |] in
evars, mkProd(na, ty, b), newarg, (ty, Some relty) :: cstrs
else
- let (evars, b, arg, cstrs) =
- aux (Environ.push_rel (na, None, ty) env) evars b cstrs
+ let (evars, b, arg, cstrs) =
+ aux (Environ.push_rel (LocalAssum (na, ty)) env) evars b cstrs
in
let ty = Reductionops.nf_betaiota (goalevars evars) ty in
let pred = mkLambda (na, ty, b) in
@@ -318,7 +328,7 @@ end) = struct
let evars, rb = aux evars env b' (pred n) in
app_poly env evars pointwise_relation [| ty; b'; rb |]
else
- let evars, rb = aux evars (Environ.push_rel (na, None, ty) env) b (pred n) in
+ let evars, rb = aux evars (Environ.push_rel (LocalAssum (na, ty)) env) b (pred n) in
app_poly env evars forall_relation
[| ty; mkLambda (na, ty, b); mkLambda (na, ty, rb) |]
| _ -> raise Not_found
@@ -347,7 +357,9 @@ end) = struct
(try
let params, args = Array.chop (Array.length args - 2) args in
let env' = Environ.push_rel_context rels env in
- let evars, (evar, _) = Evarutil.new_type_evar env' sigma Evd.univ_flexible in
+ let sigma = Sigma.Unsafe.of_evar_map sigma in
+ let Sigma ((evar, _), evars, _) = Evarutil.new_type_evar env' sigma Evd.univ_flexible in
+ let evars = Sigma.to_evar_map sigma in
let evars, inst =
app_poly env (evars,Evar.Set.empty)
rewrite_relation_class [| evar; mkApp (c, params) |] in
@@ -407,7 +419,9 @@ module TypeGlobal = struct
let inverse env (evd,cstrs) car rel =
- let evd, sort = Evarutil.new_Type ~rigid:Evd.univ_flexible env evd in
+ let sigma = Sigma.Unsafe.of_evar_map evd in
+ let Sigma (sort, sigma, _) = Evarutil.new_Type ~rigid:Evd.univ_flexible env sigma in
+ let evd = Sigma.to_evar_map sigma in
app_poly_check env (evd,cstrs) coq_inverse [| car ; car; sort; rel |]
end
@@ -478,6 +492,7 @@ let decompose_app_rel env evd t =
(rel, t1, t2)
let decompose_applied_relation env sigma (c,l) =
+ let open Context.Rel.Declaration in
let ctype = Retyping.get_type_of env sigma c in
let find_rel ty =
let sigma, cl = Clenv.make_evar_clause env sigma ty in
@@ -500,7 +515,7 @@ let decompose_applied_relation env sigma (c,l) =
| Some c -> c
| None ->
let ctx,t' = Reductionops.splay_prod env sigma ctype in (* Search for underlying eq *)
- match find_rel (it_mkProd_or_LetIn t' (List.map (fun (n,t) -> n, None, t) ctx)) with
+ match find_rel (it_mkProd_or_LetIn t' (List.map (fun (n,t) -> LocalAssum (n, t)) ctx)) with
| Some c -> c
| None -> error "Cannot find an homogeneous relation to rewrite."
@@ -775,9 +790,9 @@ let resolve_morphism env avoid oldt m ?(fnewt=fun x -> x) args args' (b,cstr) ev
else TypeGlobal.do_subrelation, TypeGlobal.apply_subrelation
in
Environ.push_named
- (Id.of_string "do_subrelation",
- Some (snd (app_poly_sort b env evars dosub [||])),
- snd (app_poly_nocheck env evars appsub [||]))
+ (LocalDef (Id.of_string "do_subrelation",
+ snd (app_poly_sort b env evars dosub [||]),
+ snd (app_poly_nocheck env evars appsub [||])))
env
in
let evars, morph = new_cstr_evar evars env' app in
@@ -1119,8 +1134,9 @@ let subterm all flags (s : 'a pure_strategy) : 'a pure_strategy =
(* | _ -> b') *)
| Lambda (n, t, b) when flags.under_lambdas ->
- let n' = name_app (fun id -> Tactics.fresh_id_in_env unfresh id env) n in
- let env' = Environ.push_rel (n', None, t) env in
+ let n' = name_app (fun id -> Tactics.fresh_id_in_env unfresh id env) n in
+ let open Context.Rel.Declaration in
+ let env' = Environ.push_rel (LocalAssum (n', t)) env in
let bty = Retyping.get_type_of env' (goalevars evars) b in
let unlift = if prop then PropGlobal.unlift_cstr else TypeGlobal.unlift_cstr in
let state, b' = s.strategy { state ; env = env' ; unfresh ;
@@ -1369,7 +1385,9 @@ module Strategies =
let reduce (r : Redexpr.red_expr) : 'a pure_strategy = { strategy =
fun { state = state ; env = env ; term1 = t ; ty1 = ty ; cstr = cstr ; evars = evars } ->
let rfn, ckind = Redexpr.reduction_of_red_expr env r in
- let evars', t' = rfn env (goalevars evars) t in
+ let sigma = Sigma.Unsafe.of_evar_map (goalevars evars) in
+ let Sigma (t', sigma, _) = rfn.Reductionops.e_redfun env sigma t in
+ let evars' = Sigma.to_evar_map sigma in
if eq_constr t' t then
state, Identity
else
@@ -1451,7 +1469,7 @@ type result = (evar_map * constr option * types) option option
let cl_rewrite_clause_aux ?(abs=None) strat env avoid sigma concl is_hyp : result =
let evdref = ref sigma in
- let sort = Typing.sort_of env evdref concl in
+ let sort = Typing.e_sort_of env evdref concl in
let evars = (!evdref, Evar.Set.empty) in
let evars, cstr =
let prop, (evars, arrow) =
@@ -1504,31 +1522,34 @@ let cl_rewrite_clause_aux ?(abs=None) strat env avoid sigma concl is_hyp : resul
(** Insert a declaration after the last declaration it depends on *)
let rec insert_dependent env decl accu hyps = match hyps with
| [] -> List.rev_append accu [decl]
-| (id, _, _ as ndecl) :: rem ->
- if occur_var_in_decl env id decl then
+| ndecl :: rem ->
+ if occur_var_in_decl env (get_id ndecl) decl then
List.rev_append accu (decl :: hyps)
else
insert_dependent env decl (ndecl :: accu) rem
let assert_replacing id newt tac =
- let prf = Proofview.Goal.nf_enter begin fun gl ->
+ let prf = Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let env = Proofview.Goal.env gl in
let ctx = Environ.named_context env in
- let after, before = List.split_when (fun (n, b, t) -> Id.equal n id) ctx in
+ let after, before = List.split_when (Id.equal id % get_id) ctx in
let nc = match before with
| [] -> assert false
- | (id, b, _) :: rem -> insert_dependent env (id, None, newt) [] after @ rem
+ | d :: rem -> insert_dependent env (LocalAssum (get_id d, newt)) [] after @ rem
in
let env' = Environ.reset_with_named_context (val_of_named_context nc) env in
- Proofview.Refine.refine ~unsafe:false begin fun sigma ->
- let sigma, ev = Evarutil.new_evar env' sigma concl in
- let sigma, ev' = Evarutil.new_evar env sigma newt in
- let map (n, _, _) = if Id.equal n id then ev' else mkVar n in
+ Proofview.Refine.refine ~unsafe:false { run = begin fun sigma ->
+ let Sigma (ev, sigma, p) = Evarutil.new_evar env' sigma concl in
+ let Sigma (ev', sigma, q) = Evarutil.new_evar env sigma newt in
+ let map d =
+ let n = get_id d in
+ if Id.equal n id then ev' else mkVar n
+ in
let (e, _) = destEvar ev in
- sigma, mkEvar (e, Array.map_of_list map nc)
- end
- end in
+ Sigma (mkEvar (e, Array.map_of_list map nc), sigma, p +> q)
+ end }
+ end } in
Proofview.tclTHEN prf (Proofview.tclFOCUS 2 2 tac)
let newfail n s =
@@ -1547,36 +1568,36 @@ let cl_rewrite_clause_newtac ?abs ?origsigma ~progress strat clause =
let gls = List.rev (Evd.fold_undefined fold undef []) in
match clause, prf with
| Some id, Some p ->
- let tac = Proofview.Refine.refine ~unsafe:false (fun h -> (h, p)) <*> Proofview.Unsafe.tclNEWGOALS gls in
+ let tac = Proofview.Refine.refine ~unsafe:false { run = fun h -> Sigma (p, h, Sigma.refl) } <*> Proofview.Unsafe.tclNEWGOALS gls in
Proofview.Unsafe.tclEVARS undef <*>
assert_replacing id newt tac
| Some id, None ->
Proofview.Unsafe.tclEVARS undef <*>
- convert_hyp_no_check (id, None, newt)
+ convert_hyp_no_check (LocalAssum (id, newt))
| None, Some p ->
Proofview.Unsafe.tclEVARS undef <*>
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let make sigma =
- let (sigma, ev) = Evarutil.new_evar env sigma newt in
- sigma, mkApp (p, [| ev |])
- in
+ let make = { run = begin fun sigma ->
+ let Sigma (ev, sigma, q) = Evarutil.new_evar env sigma newt in
+ Sigma (mkApp (p, [| ev |]), sigma, q)
+ end } in
Proofview.Refine.refine ~unsafe:false make <*> Proofview.Unsafe.tclNEWGOALS gls
- end
+ end }
| None, None ->
Proofview.Unsafe.tclEVARS undef <*>
convert_concl_no_check newt DEFAULTcast
in
let beta_red _ sigma c = Reductionops.nf_betaiota sigma c in
- let beta = Proofview.V82.tactic (Tactics.reduct_in_concl (beta_red, DEFAULTcast)) in
+ let beta = Tactics.reduct_in_concl (beta_red, DEFAULTcast) in
let opt_beta = match clause with
| None -> Proofview.tclUNIT ()
- | Some id -> Proofview.V82.tactic (Tactics.reduct_in_hyp beta_red (id, InHyp))
+ | Some id -> Tactics.reduct_in_hyp beta_red (id, InHyp)
in
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let ty = match clause with
| None -> concl
| Some id -> Environ.named_type id env
@@ -1601,7 +1622,7 @@ let cl_rewrite_clause_newtac ?abs ?origsigma ~progress strat clause =
with
| PretypeError (env, evd, (UnsatisfiableConstraints _ as e)) ->
raise (RewriteFailure (Himsg.explain_pretype_error env evd e))
- end
+ end }
let tactic_init_setoid () =
try init_setoid (); tclIDTAC
@@ -1724,7 +1745,7 @@ let declare_instance a aeq n s = declare_an_instance n s [a;aeq]
let anew_instance global binders instance fields =
new_instance (Flags.is_universe_polymorphism ())
- binders instance (Some (true, CRecord (Loc.ghost,None,fields)))
+ binders instance (Some (true, CRecord (Loc.ghost,fields)))
~global ~generalize:false None
let declare_instance_refl global binders a aeq n lemma =
@@ -1939,7 +1960,7 @@ let add_morphism glob binders m s n =
in
let tac = Tacinterp.interp (make_tactic "add_morphism_tactic") in
ignore(new_instance ~global:glob poly binders instance
- (Some (true, CRecord (Loc.ghost,None,[])))
+ (Some (true, CRecord (Loc.ghost,[])))
~generalize:false ~tac ~hook:(declare_projection n instance_id) None)
(** Bind to "rewrite" too *)
@@ -2054,16 +2075,17 @@ let not_declared env ty rel =
str ty ++ str" relation. Maybe you need to require the Coq.Classes.RelationClasses library")
let setoid_proof ty fn fallback =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let concl = Proofview.Goal.concl gl in
Proofview.tclORELSE
begin
try
let rel, _, _ = decompose_app_rel env sigma concl in
+ let open Context.Rel.Declaration in
let (sigma, t) = Typing.type_of env sigma rel in
- let car = pi3 (List.hd (fst (Reduction.dest_prod env t))) in
+ let car = get_type (List.hd (fst (Reduction.dest_prod env t))) in
(try init_relation_classes () with _ -> raise Not_found);
fn env sigma car rel
with e -> Proofview.tclZERO e
@@ -2083,7 +2105,7 @@ let setoid_proof ty fn fallback =
| e' -> Proofview.tclZERO ~info e'
end
end
- end
+ end }
let tac_open ((evm,_), c) tac =
Proofview.V82.tactic
diff --git a/tactics/rewrite.mli b/tactics/rewrite.mli
index b4d47d62d9..01709f29fb 100644
--- a/tactics/rewrite.mli
+++ b/tactics/rewrite.mli
@@ -71,7 +71,7 @@ val cl_rewrite_clause :
bool -> Locus.occurrences -> Id.t option -> tactic
val is_applied_rewrite_relation :
- env -> evar_map -> Context.rel_context -> constr -> types option
+ env -> evar_map -> Context.Rel.t -> constr -> types option
val declare_relation :
?binders:local_binder list -> constr_expr -> constr_expr -> Id.t ->
diff --git a/tactics/taccoerce.ml b/tactics/taccoerce.ml
index 25f5c8e9f1..358f6d6468 100644
--- a/tactics/taccoerce.ml
+++ b/tactics/taccoerce.ml
@@ -18,21 +18,33 @@ open Constrarg
exception CannotCoerceTo of string
let (wit_constr_context : (Empty.t, Empty.t, constr) Genarg.genarg_type) =
- Genarg.create_arg None "constr_context"
+ Genarg.create_arg "constr_context"
(* includes idents known to be bound and references *)
let (wit_constr_under_binders : (Empty.t, Empty.t, constr_under_binders) Genarg.genarg_type) =
- Genarg.create_arg None "constr_under_binders"
+ Genarg.create_arg "constr_under_binders"
+
+let has_type : type a. Val.t -> a typed_abstract_argument_type -> bool = fun v wit ->
+ let Val.Dyn (t, _) = v in
+ match Val.eq t (val_tag wit) with
+ | None -> false
+ | Some Refl -> true
+
+let prj : type a. a Val.tag -> Val.t -> a option = fun t v ->
+ let Val.Dyn (t', x) = v in
+ match Val.eq t t' with
+ | None -> None
+ | Some Refl -> Some x
+
+let in_gen wit v = Val.Dyn (val_tag wit, v)
+let out_gen wit v = match prj (val_tag wit) v with None -> assert false | Some x -> x
module Value =
struct
-type t = tlevel generic_argument
+type t = Val.t
-let rec normalize v =
- if has_type v (topwit wit_genarg) then
- normalize (out_gen (topwit wit_genarg) v)
- else v
+let normalize v = v
let of_constr c = in_gen (topwit wit_constr) c
@@ -64,9 +76,21 @@ let to_int v =
let to_list v =
let v = normalize v in
- let list_unpacker wit l = List.map (fun v -> in_gen (topwit wit) v) (top l) in
- try Some (list_unpack { list_unpacker } v)
- with Failure _ -> None
+ let Val.Dyn (tag, v) = v in
+ match tag with
+ | Val.List t -> Some (List.map (fun x -> Val.Dyn (t, x)) v)
+ | _ -> None
+
+let of_list t v = Val.Dyn (Val.List t, v)
+
+let to_option v =
+ let v = normalize v in
+ let Val.Dyn (tag, v) = v in
+ match tag with
+ | Val.Opt t -> Some (Option.map (fun x -> Val.Dyn (t, x)) v)
+ | _ -> None
+
+let of_option t v = Val.Dyn (Val.Opt t, v)
end
diff --git a/tactics/taccoerce.mli b/tactics/taccoerce.mli
index d26a477ee2..87137fd2e7 100644
--- a/tactics/taccoerce.mli
+++ b/tactics/taccoerce.mli
@@ -29,8 +29,7 @@ exception CannotCoerceTo of string
module Value :
sig
- type t = tlevel generic_argument
- (** Tactics manipulate [tlevel generic_argument]. *)
+ type t = Val.t
val normalize : t -> t
(** Eliminated the leading dynamic type casts. *)
@@ -42,6 +41,9 @@ sig
val of_int : int -> t
val to_int : t -> int option
val to_list : t -> t list option
+ val of_list : 'a Val.tag -> 'a list -> t
+ val to_option : t -> t option option
+ val of_option : 'a Val.tag -> 'a option -> t
end
(** {5 Coercion functions} *)
@@ -55,9 +57,6 @@ val coerce_to_intro_pattern : Environ.env -> Value.t -> Tacexpr.delayed_open_con
val coerce_to_intro_pattern_naming :
Environ.env -> Value.t -> intro_pattern_naming_expr
-val coerce_to_intro_pattern_naming :
- Environ.env -> Value.t -> intro_pattern_naming_expr
-
val coerce_to_hint_base : Value.t -> string
val coerce_to_int : Value.t -> int
diff --git a/tactics/tacentries.ml b/tactics/tacentries.ml
new file mode 100644
index 0000000000..711cd8d9d0
--- /dev/null
+++ b/tactics/tacentries.ml
@@ -0,0 +1,263 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Pp
+open Errors
+open Util
+open Names
+open Libobject
+open Pcoq
+open Egramml
+open Egramcoq
+open Vernacexpr
+open Libnames
+open Nameops
+
+(**********************************************************************)
+(* Tactic Notation *)
+
+let interp_prod_item lev = function
+ | TacTerm s -> GramTerminal s
+ | TacNonTerm (loc, nt, (_, sep)) ->
+ let EntryName (etyp, e) = interp_entry_name lev nt sep in
+ GramNonTerminal (loc, etyp, e)
+
+let make_terminal_status = function
+ | GramTerminal s -> Some s
+ | GramNonTerminal _ -> None
+
+let make_fresh_key =
+ let id = Summary.ref ~name:"TACTIC-NOTATION-COUNTER" 0 in
+ fun () ->
+ let cur = incr id; !id in
+ let lbl = Id.of_string ("_" ^ string_of_int cur) in
+ let kn = Lib.make_kn lbl in
+ let (mp, dir, _) = KerName.repr kn in
+ (** We embed the full path of the kernel name in the label so that the
+ identifier should be unique. This ensures that including two modules
+ together won't confuse the corresponding labels. *)
+ let lbl = Id.of_string_soft (Printf.sprintf "%s#%s#%i"
+ (ModPath.to_string mp) (DirPath.to_string dir) cur)
+ in
+ KerName.make mp dir (Label.of_id lbl)
+
+type tactic_grammar_obj = {
+ tacobj_key : KerName.t;
+ tacobj_local : locality_flag;
+ tacobj_tacgram : tactic_grammar;
+ tacobj_tacpp : Pptactic.pp_tactic;
+ tacobj_body : Id.t list * Tacexpr.glob_tactic_expr;
+}
+
+let check_key key =
+ if Tacenv.check_alias key then
+ error "Conflicting tactic notations keys. This can happen when including \
+ twice the same module."
+
+let cache_tactic_notation (_, tobj) =
+ let key = tobj.tacobj_key in
+ let () = check_key key in
+ Tacenv.register_alias key tobj.tacobj_body;
+ Egramcoq.extend_tactic_grammar key tobj.tacobj_tacgram;
+ Pptactic.declare_notation_tactic_pprule key tobj.tacobj_tacpp
+
+let open_tactic_notation i (_, tobj) =
+ let key = tobj.tacobj_key in
+ if Int.equal i 1 && not tobj.tacobj_local then
+ Egramcoq.extend_tactic_grammar key tobj.tacobj_tacgram
+
+let load_tactic_notation i (_, tobj) =
+ let key = tobj.tacobj_key in
+ let () = check_key key in
+ (** Only add the printing and interpretation rules. *)
+ Tacenv.register_alias key tobj.tacobj_body;
+ Pptactic.declare_notation_tactic_pprule key tobj.tacobj_tacpp;
+ if Int.equal i 1 && not tobj.tacobj_local then
+ Egramcoq.extend_tactic_grammar key tobj.tacobj_tacgram
+
+let subst_tactic_notation (subst, tobj) =
+ let (ids, body) = tobj.tacobj_body in
+ { tobj with
+ tacobj_key = Mod_subst.subst_kn subst tobj.tacobj_key;
+ tacobj_body = (ids, Tacsubst.subst_tactic subst body);
+ }
+
+let classify_tactic_notation tacobj = Substitute tacobj
+
+let inTacticGrammar : tactic_grammar_obj -> obj =
+ declare_object {(default_object "TacticGrammar") with
+ open_function = open_tactic_notation;
+ load_function = load_tactic_notation;
+ cache_function = cache_tactic_notation;
+ subst_function = subst_tactic_notation;
+ classify_function = classify_tactic_notation}
+
+let cons_production_parameter = function
+| TacTerm _ -> None
+| TacNonTerm (_, _, (id, _)) -> Some id
+
+let add_tactic_notation (local,n,prods,e) =
+ let ids = List.map_filter cons_production_parameter prods in
+ let prods = List.map (interp_prod_item n) prods in
+ let pprule = {
+ Pptactic.pptac_level = n;
+ pptac_prods = prods;
+ } in
+ let tac = Tacintern.glob_tactic_env ids (Global.env()) e in
+ let parule = {
+ tacgram_level = n;
+ tacgram_prods = prods;
+ } in
+ let tacobj = {
+ tacobj_key = make_fresh_key ();
+ tacobj_local = local;
+ tacobj_tacgram = parule;
+ tacobj_tacpp = pprule;
+ tacobj_body = (ids, tac);
+ } in
+ Lib.add_anonymous_leaf (inTacticGrammar tacobj)
+
+(**********************************************************************)
+(* ML Tactic entries *)
+
+type ml_tactic_grammar_obj = {
+ mltacobj_name : Tacexpr.ml_tactic_name;
+ (** ML-side unique name *)
+ mltacobj_prod : Tacexpr.raw_tactic_expr grammar_prod_item list list;
+ (** Grammar rules generating the ML tactic. *)
+}
+
+exception NonEmptyArgument
+
+(** ML tactic notations whose use can be restricted to an identifier are added
+ as true Ltac entries. *)
+let extend_atomic_tactic name entries =
+ let open Tacexpr in
+ let map_prod prods =
+ let (hd, rem) = match prods with
+ | GramTerminal s :: rem -> (s, rem)
+ | _ -> assert false (** Not handled by the ML extension syntax *)
+ in
+ let empty_value = function
+ | GramTerminal s -> raise NonEmptyArgument
+ | GramNonTerminal (_, typ, e) ->
+ let Genarg.Rawwit wit = typ in
+ let inj x = TacArg (Loc.ghost, TacGeneric (Genarg.in_gen typ x)) in
+ let default = epsilon_value inj e in
+ match default with
+ | None -> raise NonEmptyArgument
+ | Some def -> Tacintern.intern_tactic_or_tacarg Tacintern.fully_empty_glob_sign def
+ in
+ try Some (hd, List.map empty_value rem) with NonEmptyArgument -> None
+ in
+ let entries = List.map map_prod entries in
+ let add_atomic i args = match args with
+ | None -> ()
+ | Some (id, args) ->
+ let args = List.map (fun a -> Tacexp a) args in
+ let entry = { mltac_name = name; mltac_index = i } in
+ let body = TacML (Loc.ghost, entry, args) in
+ Tacenv.register_ltac false false (Names.Id.of_string id) body
+ in
+ List.iteri add_atomic entries
+
+let cache_ml_tactic_notation (_, obj) =
+ extend_ml_tactic_grammar obj.mltacobj_name obj.mltacobj_prod
+
+let open_ml_tactic_notation i obj =
+ if Int.equal i 1 then cache_ml_tactic_notation obj
+
+let inMLTacticGrammar : ml_tactic_grammar_obj -> obj =
+ declare_object { (default_object "MLTacticGrammar") with
+ open_function = open_ml_tactic_notation;
+ cache_function = cache_ml_tactic_notation;
+ classify_function = (fun o -> Substitute o);
+ subst_function = (fun (_, o) -> o);
+ }
+
+let add_ml_tactic_notation name prods =
+ let obj = {
+ mltacobj_name = name;
+ mltacobj_prod = prods;
+ } in
+ Lib.add_anonymous_leaf (inMLTacticGrammar obj);
+ extend_atomic_tactic name prods
+
+(** Command *)
+
+
+type tacdef_kind =
+ | NewTac of Id.t
+ | UpdateTac of Nametab.ltac_constant
+
+let is_defined_tac kn =
+ try ignore (Tacenv.interp_ltac kn); true with Not_found -> false
+
+let register_ltac local tacl =
+ let map tactic_body =
+ match tactic_body with
+ | TacticDefinition ((loc,id), body) ->
+ let kn = Lib.make_kn id in
+ let id_pp = pr_id id in
+ let () = if is_defined_tac kn then
+ Errors.user_err_loc (loc, "",
+ str "There is already an Ltac named " ++ id_pp ++ str".")
+ in
+ let is_primitive =
+ try
+ match Pcoq.parse_string Pcoq.Tactic.tactic (Id.to_string id) with
+ | Tacexpr.TacArg _ -> false
+ | _ -> true (* most probably TacAtom, i.e. a primitive tactic ident *)
+ with e when Errors.noncritical e -> true (* prim tactics with args, e.g. "apply" *)
+ in
+ let () = if is_primitive then
+ msg_warning (str "The Ltac name " ++ id_pp ++
+ str " may be unusable because of a conflict with a notation.")
+ in
+ NewTac id, body
+ | TacticRedefinition (ident, body) ->
+ let loc = loc_of_reference ident in
+ let kn =
+ try Nametab.locate_tactic (snd (qualid_of_reference ident))
+ with Not_found ->
+ Errors.user_err_loc (loc, "",
+ str "There is no Ltac named " ++ pr_reference ident ++ str ".")
+ in
+ UpdateTac kn, body
+ in
+ let rfun = List.map map tacl in
+ let recvars =
+ let fold accu (op, _) = match op with
+ | UpdateTac _ -> accu
+ | NewTac id -> (Lib.make_path id, Lib.make_kn id) :: accu
+ in
+ List.fold_left fold [] rfun
+ in
+ let ist = Tacintern.make_empty_glob_sign () in
+ let map (name, body) =
+ let body = Flags.with_option Tacintern.strict_check (Tacintern.intern_tactic_or_tacarg ist) body in
+ (name, body)
+ in
+ let defs () =
+ (** Register locally the tactic to handle recursivity. This function affects
+ the whole environment, so that we transactify it afterwards. *)
+ let iter_rec (sp, kn) = Nametab.push_tactic (Nametab.Until 1) sp kn in
+ let () = List.iter iter_rec recvars in
+ List.map map rfun
+ in
+ let defs = Future.transactify defs () in
+ let iter (def, tac) = match def with
+ | NewTac id ->
+ Tacenv.register_ltac false local id tac;
+ Flags.if_verbose msg_info (Nameops.pr_id id ++ str " is defined")
+ | UpdateTac kn ->
+ Tacenv.redefine_ltac local kn tac;
+ let name = Nametab.shortest_qualid_of_tactic kn in
+ Flags.if_verbose msg_info (Libnames.pr_qualid name ++ str " is redefined")
+ in
+ List.iter iter defs
diff --git a/tactics/tacentries.mli b/tactics/tacentries.mli
new file mode 100644
index 0000000000..3cf0bc5cc9
--- /dev/null
+++ b/tactics/tacentries.mli
@@ -0,0 +1,21 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Vernacexpr
+open Tacexpr
+
+(** Adding a tactic notation in the environment *)
+
+val add_tactic_notation :
+ locality_flag * int * grammar_tactic_prod_item_expr list * raw_tactic_expr ->
+ unit
+
+val add_ml_tactic_notation : ml_tactic_name ->
+ Tacexpr.raw_tactic_expr Egramml.grammar_prod_item list list -> unit
+
+val register_ltac : bool -> Vernacexpr.tacdef_body list -> unit
diff --git a/tactics/tacenv.ml b/tactics/tacenv.ml
index dc89a71efc..d2d3f3117f 100644
--- a/tactics/tacenv.ml
+++ b/tactics/tacenv.ml
@@ -15,9 +15,10 @@ open Tacexpr
(** Tactic notations (TacAlias) *)
type alias = KerName.t
+type alias_tactic = Id.t list * glob_tactic_expr
let alias_map = Summary.ref ~name:"tactic-alias"
- (KNmap.empty : glob_tactic_expr KNmap.t)
+ (KNmap.empty : alias_tactic KNmap.t)
let register_alias key tac =
alias_map := KNmap.add key tac !alias_map
@@ -31,7 +32,7 @@ let check_alias key = KNmap.mem key !alias_map
(** ML tactic extensions (TacML) *)
type ml_tactic =
- typed_generic_argument list -> Geninterp.interp_sign -> unit Proofview.tactic
+ Val.t list -> Geninterp.interp_sign -> unit Proofview.tactic
module MLName =
struct
@@ -49,7 +50,7 @@ let pr_tacname t =
let tac_tab = ref MLTacMap.empty
-let register_ml_tactic ?(overwrite = false) s (t : ml_tactic) =
+let register_ml_tactic ?(overwrite = false) s (t : ml_tactic array) =
let () =
if MLTacMap.mem s !tac_tab then
if overwrite then
@@ -60,9 +61,11 @@ let register_ml_tactic ?(overwrite = false) s (t : ml_tactic) =
in
tac_tab := MLTacMap.add s t !tac_tab
-let interp_ml_tactic s =
+let interp_ml_tactic { mltac_name = s; mltac_index = i } =
try
- MLTacMap.find s !tac_tab
+ let tacs = MLTacMap.find s !tac_tab in
+ let () = if Array.length tacs <= i then raise Not_found in
+ tacs.(i)
with Not_found ->
Errors.errorlabstrm ""
(str "The tactic " ++ pr_tacname s ++ str " is not installed.")
diff --git a/tactics/tacenv.mli b/tactics/tacenv.mli
index 87cdce6526..88b54993b1 100644
--- a/tactics/tacenv.mli
+++ b/tactics/tacenv.mli
@@ -17,10 +17,13 @@ open Tacexpr
type alias = KerName.t
(** Type of tactic alias, used in the [TacAlias] node. *)
-val register_alias : alias -> glob_tactic_expr -> unit
+type alias_tactic = Id.t list * glob_tactic_expr
+(** Contents of a tactic notation *)
+
+val register_alias : alias -> alias_tactic -> unit
(** Register a tactic alias. *)
-val interp_alias : alias -> glob_tactic_expr
+val interp_alias : alias -> alias_tactic
(** Recover the the body of an alias. Raises an anomaly if it does not exist. *)
val check_alias : alias -> bool
@@ -61,11 +64,11 @@ val ltac_entries : unit -> ltac_entry KNmap.t
(** {5 ML tactic extensions} *)
type ml_tactic =
- typed_generic_argument list -> Geninterp.interp_sign -> unit Proofview.tactic
+ Val.t list -> Geninterp.interp_sign -> unit Proofview.tactic
(** Type of external tactics, used by [TacML]. *)
-val register_ml_tactic : ?overwrite:bool -> ml_tactic_name -> ml_tactic -> unit
+val register_ml_tactic : ?overwrite:bool -> ml_tactic_name -> ml_tactic array -> unit
(** Register an external tactic. *)
-val interp_ml_tactic : ml_tactic_name -> ml_tactic
+val interp_ml_tactic : ml_tactic_entry -> ml_tactic
(** Get the named tactic. Raises a user error if it does not exist. *)
diff --git a/tactics/tacintern.ml b/tactics/tacintern.ml
index 11f2c5943d..89dc843cb8 100644
--- a/tactics/tacintern.ml
+++ b/tactics/tacintern.ml
@@ -35,11 +35,6 @@ let dloc = Loc.ghost
let error_global_not_found_loc (loc,qid) =
error_global_not_found_loc loc qid
-let error_syntactic_metavariables_not_allowed loc =
- user_err_loc
- (loc,"out_ident",
- str "Syntactic metavariables allowed only in quotations.")
-
let error_tactic_expected loc =
user_err_loc (loc,"",str "Tactic expected.")
@@ -97,7 +92,6 @@ let intern_or_var f ist = function
| ArgArg x -> ArgArg (f x)
let intern_int_or_var = intern_or_var (fun (n : int) -> n)
-let intern_id_or_var = intern_or_var (fun (id : Id.t) -> id)
let intern_string_or_var = intern_or_var (fun (s : string) -> s)
let intern_global_reference ist = function
@@ -259,8 +253,11 @@ and intern_intro_pattern_action lf ist = function
| IntroApplyOn (c,pat) ->
IntroApplyOn (intern_constr ist c, intern_intro_pattern lf ist pat)
-and intern_or_and_intro_pattern lf ist =
- List.map (List.map (intern_intro_pattern lf ist))
+and intern_or_and_intro_pattern lf ist = function
+ | IntroAndPattern l ->
+ IntroAndPattern (List.map (intern_intro_pattern lf ist) l)
+ | IntroOrPattern ll ->
+ IntroOrPattern (List.map (List.map (intern_intro_pattern lf ist)) ll)
let intern_or_and_intro_pattern_loc lf ist = function
| ArgVar (_,id) as x ->
@@ -339,7 +336,7 @@ let intern_typed_pattern ist p =
(* type it, so we remember the pattern as a glob_constr only *)
(intern_constr_gen true false ist p,dummy_pat)
-let rec intern_typed_pattern_or_ref_with_occurrences ist (l,p) =
+let intern_typed_pattern_or_ref_with_occurrences ist (l,p) =
let interp_ref r =
try Inl (intern_evaluable ist r)
with e when Logic.catchable_exception e ->
@@ -494,11 +491,9 @@ let rec intern_atomic lf ist x =
TacElim (ev,intern_constr_with_bindings_arg ist cb,
Option.map (intern_constr_with_bindings ist) cbo)
| TacCase (ev,cb) -> TacCase (ev,intern_constr_with_bindings_arg ist cb)
- | TacFix (idopt,n) -> TacFix (Option.map (intern_ident lf ist) idopt,n)
| TacMutualFix (id,n,l) ->
let f (id,n,c) = (intern_ident lf ist id,n,intern_type ist c) in
TacMutualFix (intern_ident lf ist id, n, List.map f l)
- | TacCofix idopt -> TacCofix (Option.map (intern_ident lf ist) idopt)
| TacMutualCofix (id,l) ->
let f (id,c) = (intern_ident lf ist id,intern_type ist c) in
TacMutualCofix (intern_ident lf ist id, List.map f l)
@@ -510,19 +505,12 @@ let rec intern_atomic lf ist x =
TacGeneralize (List.map (fun (c,na) ->
intern_constr_with_occurrences ist c,
intern_name lf ist na) cl)
- | TacGeneralizeDep c -> TacGeneralizeDep (intern_constr ist c)
| TacLetTac (na,c,cls,b,eqpat) ->
let na = intern_name lf ist na in
TacLetTac (na,intern_constr ist c,
(clause_app (intern_hyp_location ist) cls),b,
(Option.map (intern_intro_pattern_naming_loc lf ist) eqpat))
- (* Automation tactics *)
- | TacTrivial (d,lems,l) -> TacTrivial (d,List.map (intern_constr ist) lems,l)
- | TacAuto (d,n,lems,l) ->
- TacAuto (d,Option.map (intern_int_or_var ist) n,
- List.map (intern_constr ist) lems,l)
-
(* Derived basic tactics *)
| TacInductionDestruct (ev,isrec,(l,el)) ->
TacInductionDestruct (ev,isrec,(List.map (fun (c,(ipato,ipats),cls) ->
@@ -536,18 +524,11 @@ let rec intern_atomic lf ist x =
let h2 = intern_quantified_hypothesis ist h2 in
TacDoubleInduction (h1,h2)
(* Context management *)
- | TacClear (b,l) -> TacClear (b,List.map (intern_hyp ist) l)
- | TacClearBody l -> TacClearBody (List.map (intern_hyp ist) l)
- | TacMove (id1,id2) ->
- TacMove (intern_hyp ist id1,intern_move_location ist id2)
| TacRename l ->
TacRename (List.map (fun (id1,id2) ->
intern_hyp ist id1,
intern_hyp ist id2) l)
- (* Constructors *)
- | TacSplit (ev,bll) -> TacSplit (ev,List.map (intern_bindings ist) bll)
-
(* Conversion *)
| TacReduce (r,cl) ->
dump_glob_red_expr r;
@@ -569,10 +550,6 @@ let rec intern_atomic lf ist x =
TacChange (Some (intern_typed_pattern ist p),intern_constr ist c,
clause_app (intern_hyp_location ist) cl)
- (* Equivalence relations *)
- | TacSymmetry idopt ->
- TacSymmetry (clause_app (intern_hyp_location ist) idopt)
-
(* Equality and inversion *)
| TacRewrite (ev,l,cl,by) ->
TacRewrite
@@ -663,20 +640,19 @@ and intern_tactic_seq onlytac ist = function
(* For extensions *)
| TacAlias (loc,s,l) ->
- let l = List.map (fun (id,a) -> (id,intern_genarg ist a)) l in
+ let l = List.map (intern_tacarg !strict_check false ist) l in
ist.ltacvars, TacAlias (loc,s,l)
| TacML (loc,opn,l) ->
let _ignore = Tacenv.interp_ml_tactic opn in
- ist.ltacvars, TacML (adjust_loc loc,opn,List.map (intern_genarg ist) l)
+ ist.ltacvars, TacML (adjust_loc loc,opn,List.map (intern_tacarg !strict_check false ist) l)
and intern_tactic_as_arg loc onlytac ist a =
match intern_tacarg !strict_check onlytac ist a with
| TacCall _ | Reference _
- | TacDynamic _ | TacGeneric _ as a -> TacArg (loc,a)
+ | TacGeneric _ as a -> TacArg (loc,a)
| Tacexp a -> a
- | ConstrMayEval _ | UConstr _ | TacFreshId _ | TacPretype _ | TacNumgoals as a ->
+ | ConstrMayEval _ | TacFreshId _ | TacPretype _ | TacNumgoals as a ->
if onlytac then error_tactic_expected loc else TacArg (loc,a)
- | MetaIdArg _ -> assert false
and intern_tactic_or_tacarg ist = intern_tactic false ist
@@ -689,14 +665,6 @@ and intern_tactic_fun ist (var,body) =
and intern_tacarg strict onlytac ist = function
| Reference r -> intern_non_tactic_reference strict ist r
| ConstrMayEval c -> ConstrMayEval (intern_constr_may_eval ist c)
- | UConstr c -> UConstr (intern_constr ist c)
- | MetaIdArg (loc,istac,s) ->
- (* $id can occur in Grammar tactic... *)
- let id = Id.of_string s in
- if find_var id ist then
- if istac then Reference (ArgVar (adjust_loc loc,id))
- else ConstrMayEval (ConstrTerm (GVar (adjust_loc loc,id), None))
- else error_syntactic_metavariables_not_allowed loc
| TacCall (loc,f,[]) -> intern_isolated_tactic_reference strict ist f
| TacCall (loc,f,l) ->
TacCall (loc,
@@ -707,15 +675,8 @@ and intern_tacarg strict onlytac ist = function
| TacNumgoals -> TacNumgoals
| Tacexp t -> Tacexp (intern_tactic onlytac ist t)
| TacGeneric arg ->
- let (_, arg) = Genintern.generic_intern ist arg in
+ let arg = intern_genarg ist arg in
TacGeneric arg
- | TacDynamic(loc,t) as x ->
- if Dyn.has_tag t "tactic" || Dyn.has_tag t "value" then x
- else if Dyn.has_tag t "constr" then
- if onlytac then error_tactic_expected loc else x
- else
- let tag = Dyn.tag t in
- anomaly ~loc (str "Unknown dynamic: <" ++ str tag ++ str ">")
(* Reads the rules of a Match Context or a Match *)
and intern_match_rule onlytac ist = function
@@ -732,57 +693,29 @@ and intern_match_rule onlytac ist = function
Pat (hyps,pat,intern_tactic onlytac ist' tc) :: (intern_match_rule onlytac ist tl)
| [] -> []
-and intern_genarg ist x =
- match genarg_tag x with
- | IntOrVarArgType -> map_raw wit_int_or_var intern_int_or_var ist x
- | IdentArgType ->
- let lf = ref Id.Set.empty in
- map_raw wit_ident (intern_ident lf) ist x
- | VarArgType ->
- map_raw wit_var intern_hyp ist x
- | GenArgType ->
- map_raw wit_genarg intern_genarg ist x
- | ConstrArgType ->
- map_raw wit_constr intern_constr ist x
- | ConstrMayEvalArgType ->
- map_raw wit_constr_may_eval intern_constr_may_eval ist x
- | QuantHypArgType ->
- map_raw wit_quant_hyp intern_quantified_hypothesis ist x
- | RedExprArgType ->
- map_raw wit_red_expr intern_red_expr ist x
- | OpenConstrArgType ->
- map_raw wit_open_constr (fun ist -> on_snd (intern_constr ist)) ist x
- | ConstrWithBindingsArgType ->
- map_raw wit_constr_with_bindings intern_constr_with_bindings ist x
- | BindingsArgType ->
- map_raw wit_bindings intern_bindings ist x
- | ListArgType _ ->
- let list_unpacker wit l =
- let map x =
- let ans = intern_genarg ist (in_gen (rawwit wit) x) in
- out_gen (glbwit wit) ans
- in
- in_gen (glbwit (wit_list wit)) (List.map map (raw l))
+and intern_genarg ist (GenArg (Rawwit wit, x)) =
+ match wit with
+ | ListArg wit ->
+ let map x =
+ let ans = intern_genarg ist (in_gen (rawwit wit) x) in
+ out_gen (glbwit wit) ans
in
- list_unpack { list_unpacker } x
- | OptArgType _ ->
- let opt_unpacker wit o = match raw o with
+ in_gen (glbwit (wit_list wit)) (List.map map x)
+ | OptArg wit ->
+ let ans = match x with
| None -> in_gen (glbwit (wit_opt wit)) None
| Some x ->
let s = out_gen (glbwit wit) (intern_genarg ist (in_gen (rawwit wit) x)) in
in_gen (glbwit (wit_opt wit)) (Some s)
in
- opt_unpack { opt_unpacker } x
- | PairArgType _ ->
- let pair_unpacker wit1 wit2 o =
- let p, q = raw o in
- let p = out_gen (glbwit wit1) (intern_genarg ist (in_gen (rawwit wit1) p)) in
- let q = out_gen (glbwit wit2) (intern_genarg ist (in_gen (rawwit wit2) q)) in
- in_gen (glbwit (wit_pair wit1 wit2)) (p, q)
- in
- pair_unpack { pair_unpacker } x
- | ExtraArgType s ->
- snd (Genintern.generic_intern ist x)
+ ans
+ | PairArg (wit1, wit2) ->
+ let p, q = x in
+ let p = out_gen (glbwit wit1) (intern_genarg ist (in_gen (rawwit wit1) p)) in
+ let q = out_gen (glbwit wit2) (intern_genarg ist (in_gen (rawwit wit2) q)) in
+ in_gen (glbwit (wit_pair wit1 wit2)) (p, q)
+ | ExtraArg s ->
+ snd (Genintern.generic_intern ist (in_gen (rawwit wit) x))
(** Other entry points *)
@@ -852,13 +785,26 @@ let () =
in
Genintern.register_intern0 wit_clause_dft_concl intern_clause
+let intern_ident' ist id =
+ let lf = ref Id.Set.empty in
+ (ist, intern_ident lf ist id)
+
let () =
+ Genintern.register_intern0 wit_int_or_var (lift intern_int_or_var);
Genintern.register_intern0 wit_ref (lift intern_global_reference);
+ Genintern.register_intern0 wit_ident intern_ident';
+ Genintern.register_intern0 wit_var (lift intern_hyp);
Genintern.register_intern0 wit_tactic (lift intern_tactic_or_tacarg);
- Genintern.register_intern0 wit_sort (fun ist s -> (ist, s))
-
-let () =
- Genintern.register_intern0 wit_uconstr (fun ist c -> (ist,intern_constr ist c))
+ Genintern.register_intern0 wit_sort (fun ist s -> (ist, s));
+ Genintern.register_intern0 wit_quant_hyp (lift intern_quantified_hypothesis);
+ Genintern.register_intern0 wit_constr (fun ist c -> (ist,intern_constr ist c));
+ Genintern.register_intern0 wit_uconstr (fun ist c -> (ist,intern_constr ist c));
+ Genintern.register_intern0 wit_open_constr (fun ist c -> (ist,intern_constr ist c));
+ Genintern.register_intern0 wit_red_expr (lift intern_red_expr);
+ Genintern.register_intern0 wit_bindings (lift intern_bindings);
+ Genintern.register_intern0 wit_constr_with_bindings (lift intern_constr_with_bindings);
+ Genintern.register_intern0 wit_constr_may_eval (lift intern_constr_may_eval);
+ ()
(***************************************************************************)
(* Backwarding recursive needs of tactic glob/interp/eval functions *)
diff --git a/tactics/tacintern.mli b/tactics/tacintern.mli
index 7901cfeb45..71ca354fa1 100644
--- a/tactics/tacintern.mli
+++ b/tactics/tacintern.mli
@@ -12,7 +12,6 @@ open Tacexpr
open Genarg
open Constrexpr
open Misctypes
-open Nametab
(** Globalization of tactic expressions :
Conversion from [raw_tactic_expr] to [glob_tactic_expr] *)
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 5ecc46d670..6bf0e2aa73 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -23,7 +23,7 @@ open Nametab
open Pfedit
open Proof_type
open Refiner
-open Tacmach
+open Tacmach.New
open Tactic_debug
open Constrexpr
open Term
@@ -40,29 +40,52 @@ open Misctypes
open Locus
open Tacintern
open Taccoerce
+open Sigma.Notations
open Proofview.Notations
+open Context.Named.Declaration
+
+let ltac_trace_info = Tactic_debug.ltac_trace_info
+
+let has_type : type a. Val.t -> a typed_abstract_argument_type -> bool = fun v wit ->
+ let Val.Dyn (t, _) = v in
+ match Val.eq t (val_tag wit) with
+ | None -> false
+ | Some Refl -> true
+
+let prj : type a. a Val.tag -> Val.t -> a option = fun t v ->
+ let Val.Dyn (t', x) = v in
+ match Val.eq t t' with
+ | None -> None
+ | Some Refl -> Some x
+
+let in_gen wit v = Val.Dyn (val_tag wit, v)
+let out_gen wit v = match prj (val_tag wit) v with None -> assert false | Some x -> x
+
+let val_tag wit = val_tag (topwit wit)
+
+let pr_argument_type arg =
+ let Val.Dyn (tag, _) = arg in
+ Val.repr tag
let safe_msgnl s =
Proofview.NonLogical.catch
(Proofview.NonLogical.print_debug (s++fnl()))
(fun _ -> Proofview.NonLogical.print_warning (str "bug in the debugger: an exception is raised while printing debug information"++fnl()))
-type value = tlevel generic_argument
+type value = Val.t
(** Abstract application, to print ltac functions *)
type appl =
| UnnamedAppl (** For generic applications: nothing is printed *)
- | GlbAppl of (Names.kernel_name * typed_generic_argument list) list
+ | GlbAppl of (Names.kernel_name * Val.t list) list
(** For calls to global constants, some may alias other. *)
let push_appl appl args =
match appl with
| UnnamedAppl -> UnnamedAppl
| GlbAppl l -> GlbAppl (List.map (fun (h,vs) -> (h,vs@args)) l)
-let pr_generic arg =
- let pr_gtac _ x = Pptactic.pr_glob_tactic (Global.env()) x in
- try
- Pptactic.pr_top_generic pr_constr pr_lconstr pr_gtac pr_constr_pattern arg
- with e when Errors.noncritical e -> str"<generic>"
+let pr_generic arg = (** FIXME *)
+ let Val.Dyn (tag, _) = arg in
+ str"<" ++ Val.repr tag ++ str ">"
let pr_appl h vs =
Pptactic.pr_ltac_constant h ++ spc () ++
Pp.prlist_with_sep spc pr_generic vs
@@ -85,8 +108,8 @@ type tacvalue =
Id.t option list * glob_tactic_expr
| VRec of value Id.Map.t ref * glob_tactic_expr
-let (wit_tacvalue : (Empty.t, Empty.t, tacvalue) Genarg.genarg_type) =
- Genarg.create_arg None "tacvalue"
+let (wit_tacvalue : (Empty.t, tacvalue, tacvalue) Genarg.genarg_type) =
+ Genarg.create_arg "tacvalue"
let of_tacvalue v = in_gen (topwit wit_tacvalue) v
let to_tacvalue v = out_gen (topwit wit_tacvalue) v
@@ -124,8 +147,59 @@ module Value = struct
let closure = VFun (UnnamedAppl,extract_trace ist, ist.lfun, [], tac) in
of_tacvalue closure
+ let cast_error wit v =
+ let pr_v = mt () in (** FIXME *)
+ let Val.Dyn (tag, _) = v in
+ let tag = Val.repr tag in
+ errorlabstrm "" (str "Type error: value " ++ pr_v ++ str "is a " ++ tag
+ ++ str " while type " ++ Genarg.pr_argument_type (unquote (rawwit wit)) ++ str " was expected.")
+
+ let prj : type a. a Val.tag -> Val.t -> a option = fun t v ->
+ let Val.Dyn (t', x) = v in
+ match Val.eq t t' with
+ | None -> None
+ | Some Refl -> Some x
+
+ let try_prj wit v = match prj (val_tag wit) v with
+ | None -> cast_error wit v
+ | Some x -> x
+
+ let rec val_cast : type a b c. (a, b, c) genarg_type -> Val.t -> c =
+ fun wit v -> match wit with
+ | ExtraArg _ -> try_prj wit v
+ | ListArg t ->
+ let Val.Dyn (tag, v) = v in
+ begin match tag with
+ | Val.List tag ->
+ let map x = val_cast t (Val.Dyn (tag, x)) in
+ List.map map v
+ | _ -> cast_error wit (Val.Dyn (tag, v))
+ end
+ | OptArg t ->
+ let Val.Dyn (tag, v) = v in
+ begin match tag with
+ | Val.Opt tag ->
+ let map x = val_cast t (Val.Dyn (tag, x)) in
+ Option.map map v
+ | _ -> cast_error wit (Val.Dyn (tag, v))
+ end
+ | PairArg (t1, t2) ->
+ let Val.Dyn (tag, v) = v in
+ begin match tag with
+ | Val.Pair (tag1, tag2) ->
+ let (v1, v2) = v in
+ let v1 = Val.Dyn (tag1, v1) in
+ let v2 = Val.Dyn (tag2, v2) in
+ (val_cast t1 v1, val_cast t2 v2)
+ | _ -> cast_error wit (Val.Dyn (tag, v))
+ end
+
+ let cast (Topwit wit) v = val_cast wit v
+
end
+let print_top_val env v = mt () (** FIXME *)
+
let dloc = Loc.ghost
let catching_error call_trace fail (e, info) =
@@ -177,13 +251,13 @@ let pr_value env v =
| Some (env,sigma) -> pr_lconstr_under_binders_env env sigma c
| _ -> str "a term"
else
- str "a value of type" ++ spc () ++ pr_argument_type (genarg_tag v)
+ str "a value of type" ++ spc () ++ pr_argument_type v
let pr_closure env ist body =
let pp_body = Pptactic.pr_glob_tactic env body in
let pr_sep () = fnl () in
let pr_iarg (id, arg) =
- let arg = pr_argument_type (genarg_tag arg) in
+ let arg = pr_argument_type arg in
hov 0 (pr_id id ++ spc () ++ str ":" ++ spc () ++ arg)
in
let pp_iargs = v 0 (prlist_with_sep pr_sep pr_iarg (Id.Map.bindings ist)) in
@@ -200,7 +274,7 @@ let pr_inspect env expr result =
| VRec (ist, body) ->
str "a recursive closure" ++ fnl () ++ pr_closure env !ist body
else
- let pp_type = pr_argument_type (genarg_tag result) in
+ let pp_type = pr_argument_type result in
str "an object of type" ++ spc () ++ pp_type
in
pp_expr ++ fnl() ++ str "this is " ++ pp_result
@@ -209,17 +283,6 @@ let pr_inspect env expr result =
let constr_of_id env id =
Term.mkVar (let _ = Environ.lookup_named id env in id)
-(* To embed tactics *)
-
-let ((tactic_in : (interp_sign -> glob_tactic_expr) -> Dyn.t),
- (tactic_out : Dyn.t -> (interp_sign -> glob_tactic_expr))) =
- Dyn.create "tactic"
-
-let ((value_in : value -> Dyn.t),
- (value_out : Dyn.t -> value)) = Dyn.create "value"
-
-let valueIn t = TacDynamic (Loc.ghost, value_in t)
-
(** Generic arguments : table of interpretation functions *)
let push_trace call ist = match TacStore.get ist.extra f_trace with
@@ -260,9 +323,9 @@ let coerce_to_tactic loc id v =
| _ -> fail ()
else fail ()
+let intro_pattern_of_ident id = (Loc.ghost, IntroNaming (IntroIdentifier id))
let value_of_ident id =
- in_gen (topwit wit_intro_pattern)
- (Loc.ghost, IntroNaming (IntroIdentifier id))
+ in_gen (topwit wit_intro_pattern) (intro_pattern_of_ident id)
let (+++) lfun1 lfun2 = Id.Map.fold Id.Map.add lfun1 lfun2
@@ -337,10 +400,6 @@ let interp_intro_pattern_naming_var loc ist env sigma id =
try try_interp_ltac_var (coerce_to_intro_pattern_naming env) ist (Some (env,sigma)) (loc,id)
with Not_found -> IntroIdentifier id
-let interp_hint_base ist s =
- try try_interp_ltac_var coerce_to_hint_base ist None (dloc,Id.of_string s)
- with Not_found -> s
-
let interp_int ist locid =
try try_interp_ltac_var coerce_to_int ist None locid
with Not_found ->
@@ -388,14 +447,13 @@ let interp_reference ist env sigma = function
try try_interp_ltac_var (coerce_to_reference env) ist (Some (env,sigma)) (loc, id)
with Not_found ->
try
- let (v, _, _) = Environ.lookup_named id env in
- VarRef v
+ VarRef (get_id (Environ.lookup_named id env))
with Not_found -> error_global_not_found_loc loc (qualid_of_ident id)
let try_interp_evaluable env (loc, id) =
let v = Environ.lookup_named id env in
match v with
- | (_, Some _, _) -> EvalVarRef id
+ | LocalDef _ -> EvalVarRef id
| _ -> error_not_evaluable (VarRef id)
let interp_evaluable ist env sigma = function
@@ -455,7 +513,9 @@ let extract_ltac_constr_values ist env =
(* Extract the identifier list from lfun: join all branches (what to do else?)*)
let rec intropattern_ids (loc,pat) = match pat with
| IntroNaming (IntroIdentifier id) -> [id]
- | IntroAction (IntroOrAndPattern ll) ->
+ | IntroAction (IntroOrAndPattern (IntroAndPattern l)) ->
+ List.flatten (List.map intropattern_ids l)
+ | IntroAction (IntroOrAndPattern (IntroOrPattern ll)) ->
List.flatten (List.map intropattern_ids (List.flatten ll))
| IntroAction (IntroInjection l) ->
List.flatten (List.map intropattern_ids l)
@@ -633,10 +693,10 @@ let pf_interp_constr ist gl =
let new_interp_constr ist c k =
let open Proofview in
- Proofview.Goal.enter begin fun gl ->
- let (sigma, c) = interp_constr ist (Goal.env gl) (Goal.sigma gl) c in
- Proofview.tclTHEN (Proofview.Unsafe.tclEVARS sigma) (k c)
- end
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let (sigma, c) = interp_constr ist (Goal.env gl) (project gl) c in
+ Sigma.Unsafe.of_pair (k c, sigma)
+ end }
let interp_constr_in_compound_list inj_fun dest_fun interp_fun ist env sigma l =
let try_expand_ltac_var sigma x =
@@ -659,13 +719,27 @@ let interp_constr_list ist env sigma c =
let interp_open_constr_list =
interp_constr_in_compound_list (fun x -> x) (fun x -> x) interp_open_constr
-let interp_auto_lemmas ist env sigma lems =
- let local_sigma, lems = interp_open_constr_list ist env sigma lems in
- List.map (fun lem -> (local_sigma,lem)) lems
-
(* Interprets a type expression *)
-let pf_interp_type ist gl =
- interp_type ist (pf_env gl) (project gl)
+let pf_interp_type ist env sigma =
+ interp_type ist env sigma
+
+(* Fully evaluate an untyped constr *)
+let type_uconstr ?(flags = constr_flags)
+ ?(expected_type = WithoutTypeConstraint) ist c =
+ { delayed = begin fun env sigma ->
+ let open Pretyping in
+ let { closure; term } = c in
+ let vars = {
+ ltac_constrs = closure.typed;
+ ltac_uconstrs = closure.untyped;
+ ltac_idents = closure.idents;
+ ltac_genargs = ist.lfun;
+ } in
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = understand_ltac flags env sigma vars expected_type term in
+ Sigma.Unsafe.of_pair (c, sigma)
+ end }
+
(* Interprets a reduction expression *)
let interp_unfold ist env sigma (occs,qid) =
@@ -733,14 +807,17 @@ let interp_may_eval f ist env sigma = function
| ConstrEval (r,c) ->
let (sigma,redexp) = interp_red_expr ist env sigma r in
let (sigma,c_interp) = f ist env sigma c in
- (fst (Redexpr.reduction_of_red_expr env redexp) env sigma c_interp)
+ let (redfun, _) = Redexpr.reduction_of_red_expr env redexp in
+ let sigma = Sigma.Unsafe.of_evar_map sigma in
+ let Sigma (c, sigma, _) = redfun.Reductionops.e_redfun env sigma c_interp in
+ (Sigma.to_evar_map sigma, c)
| ConstrContext ((loc,s),c) ->
(try
let (sigma,ic) = f ist env sigma c in
let ctxt = coerce_to_constr_context (Id.Map.find s ist.lfun) in
let evdref = ref sigma in
let c = subst_meta [Constr_matching.special_meta,ic] ctxt in
- let c = Typing.solve_evars env evdref c in
+ let c = Typing.e_solve_evars env evdref c in
!evdref , c
with
| Not_found ->
@@ -785,43 +862,42 @@ let interp_constr_may_eval ist env sigma c =
(** TODO: should use dedicated printers *)
let rec message_of_value v =
let v = Value.normalize v in
- let open Tacmach.New in
let open Ftactic in
if has_type v (topwit wit_tacvalue) then
Ftactic.return (str "<tactic>")
else if has_type v (topwit wit_constr) then
let v = out_gen (topwit wit_constr) v in
- Ftactic.nf_enter begin fun gl -> Ftactic.return (pr_constr_env (pf_env gl) (Proofview.Goal.sigma gl) v) end
+ Ftactic.nf_enter {enter = begin fun gl -> Ftactic.return (pr_constr_env (pf_env gl) (project gl) v) end }
else if has_type v (topwit wit_constr_under_binders) then
let c = out_gen (topwit wit_constr_under_binders) v in
- Ftactic.nf_enter begin fun gl ->
- Ftactic.return (pr_constr_under_binders_env (pf_env gl) (Proofview.Goal.sigma gl) c)
- end
+ Ftactic.nf_enter { enter = begin fun gl ->
+ Ftactic.return (pr_constr_under_binders_env (pf_env gl) (project gl) c)
+ end }
else if has_type v (topwit wit_unit) then
Ftactic.return (str "()")
else if has_type v (topwit wit_int) then
Ftactic.return (int (out_gen (topwit wit_int) v))
else if has_type v (topwit wit_intro_pattern) then
let p = out_gen (topwit wit_intro_pattern) v in
- let print env sigma c = pr_constr_env env sigma (snd (c env Evd.empty)) in
- Ftactic.nf_enter begin fun gl ->
- Ftactic.return (Miscprint.pr_intro_pattern (fun c -> print (pf_env gl) (Proofview.Goal.sigma gl) c) p)
- end
+ let print env sigma c = pr_constr_env env sigma (fst (Tactics.run_delayed env Evd.empty c)) in
+ Ftactic.nf_enter { enter = begin fun gl ->
+ Ftactic.return (Miscprint.pr_intro_pattern (fun c -> print (pf_env gl) (project gl) c) p)
+ end }
else if has_type v (topwit wit_constr_context) then
let c = out_gen (topwit wit_constr_context) v in
- Ftactic.nf_enter begin fun gl -> Ftactic.return (pr_constr_env (pf_env gl) (Proofview.Goal.sigma gl) c) end
+ Ftactic.nf_enter { enter = begin fun gl -> Ftactic.return (pr_constr_env (pf_env gl) (project gl) c) end }
else if has_type v (topwit wit_uconstr) then
let c = out_gen (topwit wit_uconstr) v in
- Ftactic.nf_enter begin fun gl ->
+ Ftactic.nf_enter { enter = begin fun gl ->
Ftactic.return (pr_closed_glob_env (pf_env gl)
- (Proofview.Goal.sigma gl) c)
- end
+ (project gl) c)
+ end }
else match Value.to_list v with
| Some l ->
Ftactic.List.map message_of_value l >>= fun l ->
Ftactic.return (prlist_with_sep spc (fun x -> x) l)
| None ->
- let tag = pr_argument_type (genarg_tag v) in
+ let tag = pr_argument_type v in
Ftactic.return (str "<" ++ tag ++ str ">") (** TODO *)
let interp_message_token ist = function
@@ -838,11 +914,6 @@ let interp_message ist l =
Ftactic.List.map (interp_message_token ist) l >>= fun l ->
Ftactic.return (prlist_with_sep spc (fun x -> x) l)
-let interp_message ist l =
- let open Ftactic in
- Ftactic.List.map (interp_message_token ist) l >>= fun l ->
- Ftactic.return (prlist_with_sep spc (fun x -> x) l)
-
let rec interp_intro_pattern ist env sigma = function
| loc, IntroAction pat ->
let (sigma,pat) = interp_intro_pattern_action ist env sigma pat in
@@ -866,13 +937,22 @@ and interp_intro_pattern_action ist env sigma = function
let sigma,l = interp_intro_pattern_list_as_list ist env sigma l in
sigma, IntroInjection l
| IntroApplyOn (c,ipat) ->
- let c = fun env sigma -> interp_open_constr ist env sigma c in
+ let c = { delayed = fun env sigma ->
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = interp_open_constr ist env sigma c in
+ Sigma.Unsafe.of_pair (c, sigma)
+ } in
let sigma,ipat = interp_intro_pattern ist env sigma ipat in
sigma, IntroApplyOn (c,ipat)
| IntroWildcard | IntroRewrite _ as x -> sigma, x
-and interp_or_and_intro_pattern ist env sigma =
- List.fold_map (interp_intro_pattern_list_as_list ist env) sigma
+and interp_or_and_intro_pattern ist env sigma = function
+ | IntroAndPattern l ->
+ let sigma, l = List.fold_map (interp_intro_pattern ist env) sigma l in
+ sigma, IntroAndPattern l
+ | IntroOrPattern ll ->
+ let sigma, ll = List.fold_map (interp_intro_pattern_list_as_list ist env) sigma ll in
+ sigma, IntroOrPattern ll
and interp_intro_pattern_list_as_list ist env sigma = function
| [loc,IntroNaming (IntroIdentifier id)] as l ->
@@ -947,19 +1027,11 @@ let interp_constr_with_bindings ist env sigma (c,bl) =
let sigma, c = interp_open_constr ist env sigma c in
sigma, (c,bl)
-let interp_constr_with_bindings_arg ist env sigma (keep,c) =
- let sigma, c = interp_constr_with_bindings ist env sigma c in
- sigma, (keep,c)
-
let interp_open_constr_with_bindings ist env sigma (c,bl) =
let sigma, bl = interp_bindings ist env sigma bl in
let sigma, c = interp_open_constr ist env sigma c in
sigma, (c, bl)
-let interp_open_constr_with_bindings_arg ist env sigma (keep,c) =
- let sigma, c = interp_open_constr_with_bindings ist env sigma c in
- sigma,(keep,c)
-
let loc_of_bindings = function
| NoBindings -> Loc.ghost
| ImplicitBindings l -> loc_of_glob_constr (fst (List.last l))
@@ -969,13 +1041,21 @@ let interp_open_constr_with_bindings_loc ist ((c,_),bl as cb) =
let loc1 = loc_of_glob_constr c in
let loc2 = loc_of_bindings bl in
let loc = if Loc.is_ghost loc2 then loc1 else Loc.merge loc1 loc2 in
- let f env sigma = interp_open_constr_with_bindings ist env sigma cb in
+ let f = { delayed = fun env sigma ->
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = interp_open_constr_with_bindings ist env sigma cb in
+ Sigma.Unsafe.of_pair (c, sigma)
+ } in
(loc,f)
let interp_induction_arg ist gl arg =
match arg with
| keep,ElimOnConstr c ->
- keep,ElimOnConstr (fun env sigma -> interp_constr_with_bindings ist env sigma c)
+ keep,ElimOnConstr { delayed = fun env sigma ->
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = interp_constr_with_bindings ist env sigma c in
+ Sigma.Unsafe.of_pair (c, sigma)
+ }
| keep,ElimOnAnonHyp n as x -> x
| keep,ElimOnIdent (loc,id) ->
let error () = user_err_loc (loc, "",
@@ -985,11 +1065,13 @@ let interp_induction_arg ist gl arg =
let try_cast_id id' =
if Tactics.is_quantified_hypothesis id' gl
then keep,ElimOnIdent (loc,id')
- else keep, ElimOnConstr (fun env sigma ->
- try sigma, (constr_of_id env id', NoBindings)
+ else
+ (keep, ElimOnConstr { delayed = begin fun env sigma ->
+ try Sigma.here (constr_of_id env id', NoBindings) sigma
with Not_found ->
user_err_loc (loc, "interp_induction_arg",
- pr_id id ++ strbrk " binds to " ++ pr_id id' ++ strbrk " which is neither a declared nor a quantified hypothesis."))
+ pr_id id ++ strbrk " binds to " ++ pr_id id' ++ strbrk " which is neither a declared nor a quantified hypothesis.")
+ end })
in
try
(** FIXME: should be moved to taccoerce *)
@@ -1007,16 +1089,18 @@ let interp_induction_arg ist gl arg =
keep,ElimOnAnonHyp (out_gen (topwit wit_int) v)
else match Value.to_constr v with
| None -> error ()
- | Some c -> keep,ElimOnConstr (fun env sigma -> sigma,(c,NoBindings))
+ | Some c -> keep,ElimOnConstr { delayed = fun env sigma -> Sigma ((c,NoBindings), sigma, Sigma.refl) }
with Not_found ->
(* We were in non strict (interactive) mode *)
if Tactics.is_quantified_hypothesis id gl then
keep,ElimOnIdent (loc,id)
else
let c = (GVar (loc,id),Some (CRef (Ident (loc,id),None))) in
- let f env sigma =
+ let f = { delayed = fun env sigma ->
+ let sigma = Sigma.to_evar_map sigma in
let (sigma,c) = interp_open_constr ist env sigma c in
- sigma,(c,NoBindings) in
+ Sigma.Unsafe.of_pair ((c,NoBindings), sigma)
+ } in
keep,ElimOnConstr f
(* Associates variables with values and gives the remaining variables and
@@ -1081,20 +1165,17 @@ let rec read_match_rule lfun ist env sigma = function
(* misc *)
-let mk_constr_value ist gl c =
- let (sigma,c_interp) = pf_interp_constr ist gl c in
- sigma, Value.of_constr c_interp
-let mk_open_constr_value ist gl c =
- let (sigma,c_interp) = pf_apply (interp_open_constr ist) gl c in
- sigma, Value.of_constr c_interp
-let mk_hyp_value ist env sigma c =
- Value.of_constr (mkVar (interp_hyp ist env sigma c))
-let mk_int_or_var_value ist c = in_gen (topwit wit_int) (interp_int_or_var ist c)
-
-let pack_sigma (sigma,c) = {it=c;sigma=sigma;}
+let interp_focussed wit f v =
+ Ftactic.nf_enter { enter = begin fun gl ->
+ let v = Genarg.out_gen (glbwit wit) v in
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ let v = in_gen (topwit wit) (f env sigma v) in
+ Ftactic.return v
+ end }
(* Interprets an l-tac expression into a value *)
-let rec val_interp ist ?(appl=UnnamedAppl) (tac:glob_tactic_expr) : typed_generic_argument Ftactic.t =
+let rec val_interp ist ?(appl=UnnamedAppl) (tac:glob_tactic_expr) : Val.t Ftactic.t =
(* The name [appl] of applied top-level Ltac names is ignored in
[value_interp]. It is installed in the second step by a call to
[name_vfun], because it gives more opportunities to detect a
@@ -1121,7 +1202,7 @@ let rec val_interp ist ?(appl=UnnamedAppl) (tac:glob_tactic_expr) : typed_generi
let ist = { ist with extra = TacStore.set ist.extra f_debug v } in
value_interp ist >>= fun v -> return (name_vfun appl v)
in
- Ftactic.debug_prompt lev tac eval
+ Tactic_debug.debug_prompt lev tac eval
| _ -> value_interp ist >>= fun v -> return (name_vfun appl v)
@@ -1159,9 +1240,9 @@ and eval_tactic ist tac : unit Proofview.tactic = match tac with
tclSHOWHYPS (Proofview.V82.of_tactic (interp_tactic ist tac))
end
| TacAbstract (tac,ido) ->
- Proofview.Goal.nf_enter begin fun gl -> Tactics.tclABSTRACT
- (Option.map (Tacmach.New.of_old (pf_interp_ident ist) gl) ido) (interp_tactic ist tac)
- end
+ Proofview.Goal.nf_enter { enter = begin fun gl -> Tactics.tclABSTRACT
+ (Option.map (pf_interp_ident ist gl) ido) (interp_tactic ist tac)
+ end }
| TacThen (t1,t) ->
Tacticals.New.tclTHEN (interp_tactic ist t1) (interp_tactic ist t)
| TacDispatch tl ->
@@ -1204,138 +1285,12 @@ and eval_tactic ist tac : unit Proofview.tactic = match tac with
eval_tactic ist tac
(* For extensions *)
| TacAlias (loc,s,l) ->
- let body = Tacenv.interp_alias s in
- let rec f x = match genarg_tag x with
- | QuantHypArgType | RedExprArgType
- | ConstrWithBindingsArgType
- | BindingsArgType
- | OptArgType _ | PairArgType _ -> (** generic handler *)
- Ftactic.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env gl in
- let concl = Proofview.Goal.concl gl in
- let goal = Proofview.Goal.goal gl in
- let (sigma, arg) = interp_genarg ist env sigma concl goal x in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return arg)
- end
- | _ as tag -> (** Special treatment. TODO: use generic handler *)
- match tag with
- | IntOrVarArgType ->
- Ftactic.enter begin fun _ ->
- Ftactic.return (mk_int_or_var_value ist (out_gen (glbwit wit_int_or_var) x))
- end
- | IdentArgType ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env (Proofview.Goal.assume gl) in
- Ftactic.return (value_of_ident (interp_ident ist env sigma
- (out_gen (glbwit wit_ident) x)))
- end
- | VarArgType ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env (Proofview.Goal.assume gl) in
- Ftactic.return (mk_hyp_value ist env sigma (out_gen (glbwit wit_var) x))
- end
- | GenArgType ->
- Ftactic.enter begin fun _ ->
- f (out_gen (glbwit wit_genarg) x)
- end
- | ConstrArgType ->
- Ftactic.nf_enter begin fun gl ->
- let (sigma,v) =
- Tacmach.New.of_old (fun gl -> mk_constr_value ist gl (out_gen (glbwit wit_constr) x)) gl
- in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return v)
- end
- | OpenConstrArgType ->
- Ftactic.nf_enter begin fun gl ->
- let (sigma,v) =
- Tacmach.New.of_old (fun gl -> mk_open_constr_value ist gl (snd (out_gen (glbwit wit_open_constr) x))) gl in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return v)
- end
- | ConstrMayEvalArgType ->
- Ftactic.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env gl in
- let (sigma,c_interp) =
- interp_constr_may_eval ist env sigma
- (out_gen (glbwit wit_constr_may_eval) x)
- in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return (Value.of_constr c_interp))
- end
- | ListArgType ConstrArgType ->
- Ftactic.nf_enter begin fun gl ->
- let wit = glbwit (wit_list wit_constr) in
- let (sigma,l_interp) = Tacmach.New.of_old begin fun gl ->
- Evd.MonadR.List.map_right
- (fun c sigma -> mk_constr_value ist { gl with sigma=sigma } c)
- (out_gen wit x)
- (project gl)
- end gl in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return (in_gen (topwit (wit_list wit_genarg)) l_interp))
- end
- | ListArgType VarArgType ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env (Proofview.Goal.assume gl) in
- let wit = glbwit (wit_list wit_var) in
- Ftactic.return (
- let ans = List.map (mk_hyp_value ist env sigma) (out_gen wit x) in
- in_gen (topwit (wit_list wit_genarg)) ans
- )
- end
- | ListArgType IntOrVarArgType ->
- Ftactic.enter begin fun _ ->
- let wit = glbwit (wit_list wit_int_or_var) in
- let ans = List.map (mk_int_or_var_value ist) (out_gen wit x) in
- Ftactic.return (in_gen (topwit (wit_list wit_genarg)) ans)
- end
- | ListArgType IdentArgType ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let env = Proofview.Goal.env (Proofview.Goal.assume gl) in
- let wit = glbwit (wit_list wit_ident) in
- let mk_ident x = value_of_ident (interp_ident ist env sigma x) in
- let ans = List.map mk_ident (out_gen wit x) in
- Ftactic.return (in_gen (topwit (wit_list wit_genarg)) ans)
- end
- | ListArgType t ->
- Ftactic.enter begin fun gl ->
- let open Ftactic in
- let list_unpacker wit l =
- let map x =
- f (in_gen (glbwit wit) x) >>= fun v ->
- Ftactic.return (out_gen (topwit wit) v)
- in
- Ftactic.List.map map (glb l) >>= fun l ->
- Ftactic.return (in_gen (topwit (wit_list wit)) l)
- in
- list_unpack { list_unpacker } x
- end
- | ExtraArgType _ ->
- (** Special treatment of tactics *)
- if has_type x (glbwit wit_tactic) then
- Ftactic.enter begin fun _ ->
- let tac = out_gen (glbwit wit_tactic) x in
- val_interp ist tac
- end
- else
- Ftactic.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let goal = Proofview.Goal.goal gl in
- let (newsigma,v) = Geninterp.generic_interp ist {Evd.it=goal;sigma} x in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS newsigma) <*> return v)
- end
- | _ -> assert false
- in
+ let (ids, body) = Tacenv.interp_alias s in
let (>>=) = Ftactic.bind in
- let interp_vars =
- Ftactic.List.map (fun (x,v) -> f v >>= fun v -> Ftactic.return (x,v)) l
- in
- let addvar (x, v) accu = Id.Map.add x v accu in
+ let interp_vars = Ftactic.List.map (fun v -> interp_tacarg ist v) l in
let tac l =
- let lfun = List.fold_right addvar l ist.lfun in
+ let addvar x v accu = Id.Map.add x v accu in
+ let lfun = List.fold_right2 addvar ids l ist.lfun in
let trace = push_trace (loc,LtacNotationCall s) ist in
let ist = {
lfun = lfun;
@@ -1344,52 +1299,35 @@ and eval_tactic ist tac : unit Proofview.tactic = match tac with
Ftactic.lift (tactic_of_value ist v)
in
let tac =
- Ftactic.with_env interp_vars >>= fun (env,l) ->
- let name () = Pptactic.pr_tactic env (TacAlias(loc,s,l)) in
- Proofview.Trace.name_tactic name (tac l)
+ Ftactic.with_env interp_vars >>= fun (env, lr) ->
+ let name () = Pptactic.pr_alias (fun v -> print_top_val env v) 0 s lr in
+ Proofview.Trace.name_tactic name (tac lr)
(* spiwack: this use of name_tactic is not robust to a
change of implementation of [Ftactic]. In such a situation,
some more elaborate solution will have to be used. *)
in
+ let tac =
+ let len1 = List.length ids in
+ let len2 = List.length l in
+ if len1 = len2 then tac
+ else Tacticals.New.tclZEROMSG (str "Arguments length mismatch: \
+ expected " ++ int len1 ++ str ", found " ++ int len2)
+ in
Ftactic.run tac (fun () -> Proofview.tclUNIT ())
- | TacML (loc,opn,l) when List.for_all global_genarg l ->
- let trace = push_trace (loc,LtacMLCall tac) ist in
- let ist = { ist with extra = TacStore.set ist.extra f_trace trace; } in
- (* spiwack: a special case for tactics (from TACTIC EXTEND) when
- every argument can be interpreted without a
- [Proofview.Goal.nf_enter]. *)
- let tac = Tacenv.interp_ml_tactic opn in
- (* dummy values, will be ignored *)
- let env = Environ.empty_env in
- let sigma = Evd.empty in
- let concl = Term.mkRel (-1) in
- let goal = Evar.unsafe_of_int (-1) in
- (* /dummy values *)
- let args = List.map (fun a -> snd(interp_genarg ist env sigma concl goal a)) l in
- let name () = Pptactic.pr_tactic env (TacML(loc,opn,args)) in
- Proofview.Trace.name_tactic name
- (catch_error_tac trace (tac args ist))
| TacML (loc,opn,l) ->
+ let open Ftactic.Notations in
let trace = push_trace (loc,LtacMLCall tac) ist in
let ist = { ist with extra = TacStore.set ist.extra f_trace trace; } in
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let goal_sigma = Proofview.Goal.sigma gl in
- let concl = Proofview.Goal.concl gl in
- let goal = Proofview.Goal.goal gl in
- let tac = Tacenv.interp_ml_tactic opn in
- let (sigma,args) =
- Evd.MonadR.List.map_right
- (fun a sigma -> interp_genarg ist env sigma concl goal a) l goal_sigma
- in
- Proofview.Unsafe.tclEVARS sigma <*>
- let name () = Pptactic.pr_tactic env (TacML(loc,opn,args)) in
- Proofview.Trace.name_tactic name
- (catch_error_tac trace (tac args ist))
- end
+ let tac = Tacenv.interp_ml_tactic opn in
+ let args = Ftactic.List.map_right (fun a -> interp_tacarg ist a) l in
+ let tac args =
+ let name () = Pptactic.pr_extend (fun v -> print_top_val () v) 0 opn args in
+ Proofview.Trace.name_tactic name (catch_error_tac trace (tac args ist))
+ in
+ Ftactic.run args tac
-and force_vrec ist v : typed_generic_argument Ftactic.t =
+and force_vrec ist v : Val.t Ftactic.t =
let v = Value.normalize v in
if has_type v (topwit wit_tacvalue) then
let v = to_tacvalue v in
@@ -1398,7 +1336,7 @@ and force_vrec ist v : typed_generic_argument Ftactic.t =
| v -> Ftactic.return (of_tacvalue v)
else Ftactic.return v
-and interp_ltac_reference loc' mustbetac ist r : typed_generic_argument Ftactic.t =
+and interp_ltac_reference loc' mustbetac ist r : Val.t Ftactic.t =
match r with
| ArgVar (loc,id) ->
let v =
@@ -1418,29 +1356,17 @@ and interp_ltac_reference loc' mustbetac ist r : typed_generic_argument Ftactic.
let appl = GlbAppl[r,[]] in
val_interp ~appl ist (Tacenv.interp_ltac r)
-and interp_tacarg ist arg : typed_generic_argument Ftactic.t =
+and interp_tacarg ist arg : Val.t Ftactic.t =
match arg with
- | TacGeneric arg ->
- Ftactic.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
- let goal = Proofview.Goal.goal gl in
- let (sigma,v) = Geninterp.generic_interp ist {Evd.it=goal;sigma} arg in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return v)
- end
+ | TacGeneric arg -> interp_genarg ist arg
| Reference r -> interp_ltac_reference dloc false ist r
| ConstrMayEval c ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Ftactic.s_enter { s_enter = begin fun gl ->
+ let sigma = project gl in
let env = Proofview.Goal.env gl in
let (sigma,c_interp) = interp_constr_may_eval ist env sigma c in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return (Value.of_constr c_interp))
- end
- | UConstr c ->
- Ftactic.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- Ftactic.return (Value.of_uconstr (interp_uconstr ist env c))
- end
- | MetaIdArg (loc,_,id) -> assert false
+ Sigma.Unsafe.of_pair (Ftactic.return (Value.of_constr c_interp), sigma)
+ end }
| TacCall (loc,r,[]) ->
interp_ltac_reference loc true ist r
| TacCall (loc,f,l) ->
@@ -1449,26 +1375,18 @@ and interp_tacarg ist arg : typed_generic_argument Ftactic.t =
Ftactic.List.map (fun a -> interp_tacarg ist a) l >>= fun largs ->
interp_app loc ist fv largs
| TacFreshId l ->
- Ftactic.enter begin fun gl ->
- let id = interp_fresh_id ist (Tacmach.New.pf_env gl) (Proofview.Goal.sigma gl) l in
+ Ftactic.enter { enter = begin fun gl ->
+ let id = interp_fresh_id ist (pf_env gl) (project gl) l in
Ftactic.return (in_gen (topwit wit_intro_pattern) (dloc, IntroNaming (IntroIdentifier id)))
- end
+ end }
| TacPretype c ->
- Ftactic.enter begin fun gl ->
+ Ftactic.s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
let env = Proofview.Goal.env gl in
- let {closure;term} = interp_uconstr ist env c in
- let vars = {
- Pretyping.ltac_constrs = closure.typed;
- Pretyping.ltac_uconstrs = closure.untyped;
- Pretyping.ltac_idents = closure.idents;
- Pretyping.ltac_genargs = ist.lfun;
- } in
- let (sigma,c_interp) =
- Pretyping.understand_ltac constr_flags env sigma vars WithoutTypeConstraint term
- in
- Ftactic.(lift (Proofview.Unsafe.tclEVARS sigma) <*> return (Value.of_constr c_interp))
- end
+ let c = interp_uconstr ist env c in
+ let Sigma (c, sigma, p) = (type_uconstr ist c).delayed env sigma in
+ Sigma (Ftactic.return (Value.of_constr c), sigma, p)
+ end }
| TacNumgoals ->
Ftactic.lift begin
let open Proofview.Notations in
@@ -1476,20 +1394,9 @@ and interp_tacarg ist arg : typed_generic_argument Ftactic.t =
Proofview.tclUNIT (Value.of_int i)
end
| Tacexp t -> val_interp ist t
- | TacDynamic(_,t) ->
- let tg = (Dyn.tag t) in
- if String.equal tg "tactic" then
- val_interp ist (tactic_out t ist)
- else if String.equal tg "value" then
- Ftactic.return (value_out t)
- else if String.equal tg "constr" then
- Ftactic.return (Value.of_constr (constr_out t))
- else
- Errors.anomaly ~loc:dloc ~label:"Tacinterp.val_interp"
- (str "Unknown dynamic: <" ++ str (Dyn.tag t) ++ str ">")
(* Interprets an application node *)
-and interp_app loc ist fv largs : typed_generic_argument Ftactic.t =
+and interp_app loc ist fv largs : Val.t Ftactic.t =
let (>>=) = Ftactic.bind in
let fail = Tacticals.New.tclZEROMSG (str "Illegal tactic application.") in
let fv = Value.normalize fv in
@@ -1546,7 +1453,7 @@ and tactic_of_value ist vle =
| (VFun _|VRec _) -> Tacticals.New.tclZEROMSG (str "A fully applied tactic is expected.")
else if has_type vle (topwit wit_tactic) then
let tac = out_gen (topwit wit_tactic) vle in
- eval_tactic ist tac
+ tactic_of_value ist tac
else Tacticals.New.tclZEROMSG (str "Expression does not evaluate to a tactic.")
(* Interprets the clauses of a recursive LetIn *)
@@ -1633,141 +1540,84 @@ and interp_match ist lz constr lmr =
Proofview.tclZERO ~info e
end
end >>= fun constr ->
- Ftactic.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Ftactic.enter { enter = begin fun gl ->
+ let sigma = project gl in
let env = Proofview.Goal.env gl in
let ilr = read_match_rule (extract_ltac_constr_values ist env) ist env sigma lmr in
interp_match_successes lz ist (Tactic_matching.match_term env sigma constr ilr)
- end
+ end }
(* Interprets the Match Context expressions *)
and interp_match_goal ist lz lr lmr =
- Ftactic.nf_enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Ftactic.nf_enter { enter = begin fun gl ->
+ let sigma = project gl in
let env = Proofview.Goal.env gl in
let hyps = Proofview.Goal.hyps gl in
let hyps = if lr then List.rev hyps else hyps in
let concl = Proofview.Goal.concl gl in
let ilr = read_match_rule (extract_ltac_constr_values ist env) ist env sigma lmr in
interp_match_successes lz ist (Tactic_matching.match_goal env sigma hyps concl ilr)
- end
+ end }
(* Interprets extended tactic generic arguments *)
-(* spiwack: interp_genarg has an argument [concl] for the case of
- "casted open constr". And [gl] for [Geninterp]. I haven't changed
- the interface for geninterp yet as it is used by ARGUMENT EXTEND
- (in turn used by plugins). At the time I'm writing this comment
- though, the only concerned plugins are the declarative mode (which
- needs the [extra] field of goals to interprete rules) and ssreflect
- (a handful of time). I believe we'd need to address "casted open
- constr" and the declarative mode rules to provide a reasonable
- interface. *)
-and interp_genarg ist env sigma concl gl x =
- let evdref = ref sigma in
- let rec interp_genarg x =
- match genarg_tag x with
- | IntOrVarArgType ->
- in_gen (topwit wit_int_or_var)
- (ArgArg (interp_int_or_var ist (out_gen (glbwit wit_int_or_var) x)))
- | IdentArgType ->
- in_gen (topwit wit_ident)
- (interp_ident ist env sigma (out_gen (glbwit wit_ident) x))
- | VarArgType ->
- in_gen (topwit wit_var) (interp_hyp ist env sigma (out_gen (glbwit wit_var) x))
- | GenArgType ->
- in_gen (topwit wit_genarg) (interp_genarg (out_gen (glbwit wit_genarg) x))
- | ConstrArgType ->
- let (sigma,c_interp) =
- interp_constr ist env !evdref (out_gen (glbwit wit_constr) x)
- in
- evdref := sigma;
- in_gen (topwit wit_constr) c_interp
- | ConstrMayEvalArgType ->
- let (sigma,c_interp) = interp_constr_may_eval ist env !evdref (out_gen (glbwit wit_constr_may_eval) x) in
- evdref := sigma;
- in_gen (topwit wit_constr_may_eval) c_interp
- | QuantHypArgType ->
- in_gen (topwit wit_quant_hyp)
- (interp_declared_or_quantified_hypothesis ist env sigma
- (out_gen (glbwit wit_quant_hyp) x))
- | RedExprArgType ->
- let (sigma,r_interp) =
- interp_red_expr ist env !evdref (out_gen (glbwit wit_red_expr) x)
- in
- evdref := sigma;
- in_gen (topwit wit_red_expr) r_interp
- | OpenConstrArgType ->
- let expected_type = WithoutTypeConstraint in
- in_gen (topwit wit_open_constr)
- (interp_open_constr ~expected_type
- ist env !evdref
- (snd (out_gen (glbwit wit_open_constr) x)))
- | ConstrWithBindingsArgType ->
- in_gen (topwit wit_constr_with_bindings)
- (pack_sigma (interp_constr_with_bindings ist env !evdref
- (out_gen (glbwit wit_constr_with_bindings) x)))
- | BindingsArgType ->
- in_gen (topwit wit_bindings)
- (pack_sigma (interp_bindings ist env !evdref (out_gen (glbwit wit_bindings) x)))
- | ListArgType ConstrArgType ->
- let (sigma,v) = interp_genarg_constr_list ist env !evdref x in
- evdref := sigma;
- v
- | ListArgType VarArgType -> interp_genarg_var_list ist env sigma x
- | ListArgType _ ->
- let list_unpacker wit l =
- let map x =
- out_gen (topwit wit) (interp_genarg (in_gen (glbwit wit) x))
- in
- in_gen (topwit (wit_list wit)) (List.map map (glb l))
+and interp_genarg ist x : Val.t Ftactic.t =
+ let open Ftactic.Notations in
+ (** Ad-hoc handling of some types. *)
+ let tag = genarg_tag x in
+ if argument_type_eq tag (unquote (topwit (wit_list wit_var))) then
+ interp_genarg_var_list ist x
+ else if argument_type_eq tag (unquote (topwit (wit_list wit_constr))) then
+ interp_genarg_constr_list ist x
+ else
+ let GenArg (Glbwit wit, x) = x in
+ match wit with
+ | ListArg wit ->
+ let map x =
+ interp_genarg ist (Genarg.in_gen (glbwit wit) x) >>= fun x ->
+ Ftactic.return (Value.cast (topwit wit) x)
in
- list_unpack { list_unpacker } x
- | OptArgType _ ->
- let opt_unpacker wit o = match glb o with
- | None -> in_gen (topwit (wit_opt wit)) None
+ Ftactic.List.map map x >>= fun l ->
+ Ftactic.return (Value.of_list (val_tag wit) l)
+ | OptArg wit ->
+ let ans = match x with
+ | None -> Ftactic.return (Value.of_option (val_tag wit) None)
| Some x ->
- let x = out_gen (topwit wit) (interp_genarg (in_gen (glbwit wit) x)) in
- in_gen (topwit (wit_opt wit)) (Some x)
- in
- opt_unpack { opt_unpacker } x
- | PairArgType _ ->
- let pair_unpacker wit1 wit2 o =
- let (p, q) = glb o in
- let p = out_gen (topwit wit1) (interp_genarg (in_gen (glbwit wit1) p)) in
- let q = out_gen (topwit wit2) (interp_genarg (in_gen (glbwit wit2) q)) in
- in_gen (topwit (wit_pair wit1 wit2)) (p, q)
+ interp_genarg ist (Genarg.in_gen (glbwit wit) x) >>= fun x ->
+ let x = Value.cast (topwit wit) x in
+ Ftactic.return (Value.of_option (val_tag wit) (Some x))
in
- pair_unpack { pair_unpacker } x
- | ExtraArgType s ->
- let (sigma,v) = Geninterp.generic_interp ist { Evd.it=gl;sigma=(!evdref) } x in
- evdref:=sigma;
- v
- in
- let v = interp_genarg x in
- !evdref , v
-
+ ans
+ | PairArg (wit1, wit2) ->
+ let (p, q) = x in
+ interp_genarg ist (Genarg.in_gen (glbwit wit1) p) >>= fun p ->
+ interp_genarg ist (Genarg.in_gen (glbwit wit2) q) >>= fun q ->
+ let p = Value.cast (topwit wit1) p in
+ let q = Value.cast (topwit wit2) q in
+ Ftactic.return (Val.Dyn (Val.Pair (val_tag wit1, val_tag wit2), (p, q)))
+ | ExtraArg s ->
+ Geninterp.generic_interp ist (Genarg.in_gen (glbwit wit) x)
(** returns [true] for genargs which have the same meaning
independently of goals. *)
-and global_genarg =
- let rec global_tag = function
- | IntOrVarArgType | GenArgType -> true
- | ListArgType t | OptArgType t -> global_tag t
- | PairArgType (t1,t2) -> global_tag t1 && global_tag t2
- | _ -> false
- in
- fun x -> global_tag (genarg_tag x)
-
-and interp_genarg_constr_list ist env sigma x =
- let lc = out_gen (glbwit (wit_list wit_constr)) x in
+and interp_genarg_constr_list ist x =
+ Ftactic.nf_s_enter { s_enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ let lc = Genarg.out_gen (glbwit (wit_list wit_constr)) x in
let (sigma,lc) = interp_constr_list ist env sigma lc in
- sigma , in_gen (topwit (wit_list wit_constr)) lc
+ let lc = Value.of_list (val_tag wit_constr) lc in
+ Sigma.Unsafe.of_pair (Ftactic.return lc, sigma)
+ end }
-and interp_genarg_var_list ist env sigma x =
- let lc = out_gen (glbwit (wit_list wit_var)) x in
+and interp_genarg_var_list ist x =
+ Ftactic.nf_enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ let lc = Genarg.out_gen (glbwit (wit_list wit_var)) x in
let lc = interp_hyp_list ist env sigma lc in
- in_gen (topwit (wit_list wit_var)) lc
+ Ftactic.return (Value.of_list (val_tag wit_var) lc)
+ end }
(* Interprets tactic expressions : returns a "constr" *)
and interp_ltac_constr ist e : constr Ftactic.t =
@@ -1776,7 +1626,7 @@ and interp_ltac_constr ist e : constr Ftactic.t =
(val_interp ist e)
begin function (err, info) -> match err with
| Not_found ->
- Ftactic.enter begin fun gl ->
+ Ftactic.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
Proofview.tclLIFT begin
debugging_step ist (fun () ->
@@ -1784,13 +1634,13 @@ and interp_ltac_constr ist e : constr Ftactic.t =
Pptactic.pr_glob_tactic env e)
end
<*> Proofview.tclZERO Not_found
- end
+ end }
| err -> Proofview.tclZERO ~info err
end
end >>= fun result ->
- Ftactic.enter begin fun gl ->
+ Ftactic.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let result = Value.normalize result in
try
let cresult = coerce_to_closed_constr env result in
@@ -1805,7 +1655,7 @@ and interp_ltac_constr ist e : constr Ftactic.t =
let env = Proofview.Goal.env gl in
Tacticals.New.tclZEROMSG (str "Must evaluate to a closed term" ++ fnl() ++
str "offending expression: " ++ fnl() ++ pr_inspect env e result)
- end
+ end }
(* Interprets tactic expressions : returns a "tactic" *)
@@ -1826,44 +1676,41 @@ and interp_atomic ist tac : unit Proofview.tactic =
match tac with
(* Basic tactics *)
| TacIntroPattern l ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let sigma,l' = interp_intro_pattern_list_as_list ist env sigma l in
Tacticals.New.tclWITHHOLES false
(name_atomic ~env
(TacIntroPattern l)
(* spiwack: print uninterpreted, not sure if it is the
expected behaviour. *)
- (Tactics.intros_patterns l')) sigma
- end
+ (Tactics.intro_patterns l')) sigma
+ end }
| TacIntroMove (ido,hto) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let mloc = interp_move_location ist env sigma hto in
let ido = Option.map (interp_ident ist env sigma) ido in
name_atomic ~env
(TacIntroMove(ido,mloc))
(Tactics.intro_move ido mloc)
- end
+ end }
| TacExact c ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<exact>") begin
- Proofview.V82.tactic begin fun gl ->
- let (sigma,c_interp) = pf_interp_casted_constr ist gl c in
- tclTHEN
- (tclEVARS sigma)
- (Tactics.exact_no_check c_interp)
- gl
- end
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let (sigma, c_interp) = pf_interp_casted_constr ist gl c in
+ Sigma.Unsafe.of_pair (Proofview.V82.tactic (Tactics.exact_no_check c_interp), sigma)
+ end }
end
| TacApply (a,ev,cb,cl) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<apply>") begin
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let l = List.map (fun (k,c) ->
let loc, f = interp_open_constr_with_bindings_loc ist c in
(k,(loc,f))) cb
@@ -1874,12 +1721,12 @@ and interp_atomic ist tac : unit Proofview.tactic =
let sigma,(id,cl) = interp_in_hyp_as ist env sigma cl in
sigma, Tactics.apply_delayed_in a ev id l cl in
Tacticals.New.tclWITHHOLES ev tac sigma
- end
+ end }
end
| TacElim (ev,(keep,cb),cbo) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let sigma, cb = interp_constr_with_bindings ist env sigma cb in
let sigma, cbo = Option.fold_map (interp_constr_with_bindings ist env) sigma cbo in
let named_tac =
@@ -1887,10 +1734,10 @@ and interp_atomic ist tac : unit Proofview.tactic =
name_atomic ~env (TacElim (ev,(keep,cb),cbo)) tac
in
Tacticals.New.tclWITHHOLES ev named_tac sigma
- end
+ end }
| TacCase (ev,(keep,cb)) ->
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = project gl in
let env = Proofview.Goal.env gl in
let sigma, cb = interp_constr_with_bindings ist env sigma cb in
let named_tac =
@@ -1898,63 +1745,41 @@ and interp_atomic ist tac : unit Proofview.tactic =
name_atomic ~env (TacCase(ev,(keep,cb))) tac
in
Tacticals.New.tclWITHHOLES ev named_tac sigma
- end
- | TacFix (idopt,n) ->
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let idopt = Option.map (interp_ident ist env sigma) idopt in
- name_atomic ~env
- (TacFix(idopt,n))
- (Proofview.V82.tactic (Tactics.fix idopt n))
- end
+ end }
| TacMutualFix (id,n,l) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<mutual fix>") begin
- Proofview.V82.tactic begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let env = pf_env gl in
let f sigma (id,n,c) =
- let (sigma,c_interp) = pf_interp_type ist { gl with sigma=sigma } c in
+ let (sigma,c_interp) = pf_interp_type ist env sigma c in
sigma , (interp_ident ist env sigma id,n,c_interp) in
let (sigma,l_interp) =
Evd.MonadR.List.map_right (fun c sigma -> f sigma c) l (project gl)
in
- tclTHEN
- (tclEVARS sigma)
- (Tactics.mutual_fix (interp_ident ist env sigma id) n l_interp 0)
- gl
- end
- end
- | TacCofix idopt ->
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let idopt = Option.map (interp_ident ist env sigma) idopt in
- name_atomic ~env
- (TacCofix (idopt))
- (Proofview.V82.tactic (Tactics.cofix idopt))
+ let tac = Proofview.V82.tactic (Tactics.mutual_fix (interp_ident ist env sigma id) n l_interp 0) in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
end
| TacMutualCofix (id,l) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<mutual cofix>") begin
- Proofview.V82.tactic begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let env = pf_env gl in
let f sigma (id,c) =
- let (sigma,c_interp) = pf_interp_type ist { gl with sigma=sigma } c in
+ let (sigma,c_interp) = pf_interp_type ist env sigma c in
sigma , (interp_ident ist env sigma id,c_interp) in
let (sigma,l_interp) =
Evd.MonadR.List.map_right (fun c sigma -> f sigma c) l (project gl)
in
- tclTHEN
- (tclEVARS sigma)
- (Tactics.mutual_cofix (interp_ident ist env sigma id) l_interp 0)
- gl
- end
+ let tac = Proofview.V82.tactic (Tactics.mutual_cofix (interp_ident ist env sigma id) l_interp 0) in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
end
| TacAssert (b,t,ipat,c) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let (sigma,c) =
(if Option.is_empty t then interp_constr else interp_type) ist env sigma c
in
@@ -1964,35 +1789,27 @@ and interp_atomic ist tac : unit Proofview.tactic =
(name_atomic ~env
(TacAssert(b,t,ipat,c))
(Tactics.forward b tac ipat' c)) sigma
- end
+ end }
| TacGeneralize cl ->
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = project gl in
let env = Proofview.Goal.env gl in
let sigma, cl = interp_constr_with_occurrences_and_name_as_list ist env sigma cl in
Tacticals.New.tclWITHHOLES false
(name_atomic ~env
(TacGeneralize cl)
- (Proofview.V82.tactic (Tactics.Simple.generalize_gen cl))) sigma
- end
- | TacGeneralizeDep c ->
- (new_interp_constr ist c) (fun c ->
- name_atomic (* spiwack: probably needs a goal environment *)
- (TacGeneralizeDep c)
- (Proofview.V82.tactic (Tactics.generalize_dep c))
- )
+ (Proofview.V82.tactic (Tactics.generalize_gen cl))) sigma
+ end }
| TacLetTac (na,c,clp,b,eqpat) ->
Proofview.V82.nf_evar_goals <*>
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let clp = interp_clause ist env sigma clp in
let eqpat = interp_intro_pattern_naming_option ist env sigma eqpat in
if Locusops.is_nowhere clp then
(* We try to fully-typecheck the term *)
- let (sigma,c_interp) =
- Tacmach.New.of_old (fun gl -> pf_interp_constr ist gl c) gl
- in
+ let (sigma,c_interp) = pf_interp_constr ist gl c in
let let_tac b na c cl eqpat =
let id = Option.default (Loc.ghost,IntroAnonymous) eqpat in
let with_eq = if b then None else Some (true,id) in
@@ -2016,58 +1833,22 @@ and interp_atomic ist tac : unit Proofview.tactic =
(Tacticals.New.tclWITHHOLES false (*in hope of a future "eset/epose"*)
(let_pat_tac b (interp_name ist env sigma na)
((sigma,sigma'),c) clp eqpat) sigma')
- end
-
- (* Automation tactics *)
- | TacTrivial (debug,lems,l) ->
- begin if debug == Tacexpr.Info then
- msg_warning
- (strbrk"The \"info_trivial\" tactic" ++ spc ()
- ++strbrk"does not print traces anymore." ++ spc()
- ++strbrk"Use \"Info 1 trivial\", instead.")
- end;
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let lems = interp_auto_lemmas ist env sigma lems in
- name_atomic ~env
- (TacTrivial(debug,List.map snd lems,l))
- (Auto.h_trivial ~debug
- lems
- (Option.map (List.map (interp_hint_base ist)) l))
- end
- | TacAuto (debug,n,lems,l) ->
- begin if debug == Tacexpr.Info then
- msg_warning
- (strbrk"The \"info_auto\" tactic" ++ spc ()
- ++strbrk"does not print traces anymore." ++ spc()
- ++strbrk"Use \"Info 1 auto\", instead.")
- end;
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let lems = interp_auto_lemmas ist env sigma lems in
- name_atomic ~env
- (TacAuto(debug,n,List.map snd lems,l))
- (Auto.h_auto ~debug (Option.map (interp_int_or_var ist) n)
- lems
- (Option.map (List.map (interp_hint_base ist)) l))
- end
+ end }
(* Derived basic tactics *)
| TacInductionDestruct (isrec,ev,(l,el)) ->
(* spiwack: some unknown part of destruct needs the goal to be
prenormalised. *)
Proofview.V82.nf_evar_goals <*>
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let sigma,l =
List.fold_map begin fun sigma (c,(ipato,ipats),cls) ->
(* TODO: move sigma as a side-effect *)
(* spiwack: the [*p] variants are for printing *)
let cp = c in
- let c = Tacmach.New.of_old (fun gl -> interp_induction_arg ist gl c) gl in
+ let c = interp_induction_arg ist gl c in
let ipato = interp_intro_pattern_naming_option ist env sigma ipato in
let ipatsp = ipats in
let sigma,ipats = interp_or_and_intro_pattern_option ist env sigma ipats in
@@ -2078,12 +1859,12 @@ and interp_atomic ist tac : unit Proofview.tactic =
let l,lp = List.split l in
let sigma,el =
Option.fold_map (interp_constr_with_bindings ist env) sigma el in
- name_atomic ~env
+ let tac = name_atomic ~env
(TacInductionDestruct(isrec,ev,(lp,el)))
- (Tacticals.New.tclTHEN
- (Proofview.Unsafe.tclEVARS sigma)
- (Tactics.induction_destruct isrec ev (l,el)))
- end
+ (Tactics.induction_destruct isrec ev (l,el))
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
| TacDoubleInduction (h1,h2) ->
let h1 = interp_quantified_hypothesis ist h1 in
let h2 = interp_quantified_hypothesis ist h2 in
@@ -2091,36 +1872,10 @@ and interp_atomic ist tac : unit Proofview.tactic =
(TacDoubleInduction (h1,h2))
(Elim.h_double_induction h1 h2)
(* Context management *)
- | TacClear (b,l) ->
- Proofview.Goal.enter begin fun gl ->
- let env = Tacmach.New.pf_env gl in
- let sigma = Proofview.Goal.sigma gl in
- let l = interp_hyp_list ist env sigma l in
- if b then name_atomic ~env (TacClear (b, l)) (Tactics.keep l)
- else
- (* spiwack: until the tactic is in the monad *)
- let tac = Proofview.V82.tactic (fun gl -> Tactics.clear l gl) in
- Proofview.Trace.name_tactic (fun () -> Pp.str"<clear>") tac
- end
- | TacClearBody l ->
- Proofview.Goal.enter begin fun gl ->
- let env = Tacmach.New.pf_env gl in
- let sigma = Proofview.Goal.sigma gl in
- let l = interp_hyp_list ist env sigma l in
- name_atomic ~env
- (TacClearBody l)
- (Tactics.clear_body l)
- end
- | TacMove (id1,id2) ->
- Proofview.V82.tactic begin fun gl ->
- Tactics.move_hyp (interp_hyp ist (pf_env gl) (project gl) id1)
- (interp_move_location ist (pf_env gl) (project gl) id2)
- gl
- end
| TacRename l ->
- Proofview.Goal.enter begin fun gl ->
- let env = Tacmach.New.pf_env gl in
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let env = pf_env gl in
+ let sigma = project gl in
let l =
List.map (fun (id1,id2) ->
interp_hyp ist env sigma id1,
@@ -2129,37 +1884,22 @@ and interp_atomic ist tac : unit Proofview.tactic =
name_atomic ~env
(TacRename l)
(Tactics.rename_hyp l)
- end
+ end }
- (* Constructors *)
- | TacSplit (ev,bll) ->
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let sigma, bll = List.fold_map (interp_bindings ist env) sigma bll in
- let named_tac =
- let tac = Tactics.split_with_bindings ev bll in
- name_atomic ~env (TacSplit (ev, bll)) tac
- in
- Tacticals.New.tclWITHHOLES ev named_tac sigma
- end
(* Conversion *)
| TacReduce (r,cl) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<reduce>") begin
- Proofview.V82.tactic begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let (sigma,r_interp) = interp_red_expr ist (pf_env gl) (project gl) r in
- tclTHEN
- (tclEVARS sigma)
- (Tactics.reduce r_interp (interp_clause ist (pf_env gl) (project gl) cl))
- gl
- end
+ Sigma.Unsafe.of_pair (Tactics.reduce r_interp (interp_clause ist (pf_env gl) (project gl) cl), sigma)
+ end }
end
| TacChange (None,c,cl) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<change>") begin
Proofview.V82.nf_evar_goals <*>
- Proofview.V82.tactic begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let is_onhyps = match cl.onhyps with
| None | Some [] -> true
| _ -> false
@@ -2168,65 +1908,65 @@ and interp_atomic ist tac : unit Proofview.tactic =
| AllOccurrences | NoOccurrences -> true
| _ -> false
in
- let c_interp patvars sigma =
+ let c_interp patvars = { Sigma.run = begin fun sigma ->
let lfun' = Id.Map.fold (fun id c lfun ->
Id.Map.add id (Value.of_constr c) lfun)
patvars ist.lfun
in
+ let sigma = Sigma.to_evar_map sigma in
let ist = { ist with lfun = lfun' } in
- if is_onhyps && is_onconcl
- then interp_type ist (pf_env gl) sigma c
- else interp_constr ist (pf_env gl) sigma c
- in
- (Tactics.change None c_interp (interp_clause ist (pf_env gl) (project gl) cl))
- gl
- end
+ let (sigma, c) =
+ if is_onhyps && is_onconcl
+ then interp_type ist (pf_env gl) sigma c
+ else interp_constr ist (pf_env gl) sigma c
+ in
+ Sigma.Unsafe.of_pair (c, sigma)
+ end } in
+ Proofview.V82.tactic (Tactics.change None c_interp (interp_clause ist (pf_env gl) (project gl) cl))
+ end }
end
| TacChange (Some op,c,cl) ->
(* spiwack: until the tactic is in the monad *)
Proofview.Trace.name_tactic (fun () -> Pp.str"<change>") begin
Proofview.V82.nf_evar_goals <*>
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
Proofview.V82.tactic begin fun gl ->
let op = interp_typed_pattern ist env sigma op in
let to_catch = function Not_found -> true | e -> Errors.is_anomaly e in
- let c_interp patvars sigma =
+ let c_interp patvars = { Sigma.run = begin fun sigma ->
let lfun' = Id.Map.fold (fun id c lfun ->
Id.Map.add id (Value.of_constr c) lfun)
patvars ist.lfun
in
let ist = { ist with lfun = lfun' } in
- try interp_constr ist env sigma c
+ try
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = interp_constr ist env sigma c in
+ Sigma.Unsafe.of_pair (c, sigma)
with e when to_catch e (* Hack *) ->
errorlabstrm "" (strbrk "Failed to get enough information from the left-hand side to type the right-hand side.")
- in
+ end } in
(Tactics.change (Some op) c_interp (interp_clause ist env sigma cl))
gl
end
- end
+ end }
end
- (* Equivalence relations *)
- | TacSymmetry c ->
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let cl = interp_clause ist env sigma c in
- name_atomic ~env
- (TacSymmetry cl)
- (Tactics.intros_symmetry cl)
- end
(* Equality and inversion *)
| TacRewrite (ev,l,cl,by) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let l' = List.map (fun (b,m,(keep,c)) ->
- let f env sigma = interp_open_constr_with_bindings ist env sigma c in
+ let f = { delayed = fun env sigma ->
+ let sigma = Sigma.to_evar_map sigma in
+ let (sigma, c) = interp_open_constr_with_bindings ist env sigma c in
+ Sigma.Unsafe.of_pair (c, sigma)
+ } in
(b,m,keep,f)) l in
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let cl = interp_clause ist env sigma cl in
name_atomic ~env
(TacRewrite (ev,l,cl,by))
@@ -2234,18 +1974,16 @@ and interp_atomic ist tac : unit Proofview.tactic =
(Option.map (fun by -> Tacticals.New.tclCOMPLETE (interp_tactic ist by),
Equality.Naive)
by))
- end
+ end }
| TacInversion (DepInversion (k,c,ids),hyp) ->
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let (sigma,c_interp) =
match c with
| None -> sigma , None
| Some c ->
- let (sigma,c_interp) =
- Tacmach.New.of_old (fun gl -> pf_interp_constr ist gl c) gl
- in
+ let (sigma,c_interp) = pf_interp_constr ist gl c in
sigma , Some c_interp
in
let dqhyps = interp_declared_or_quantified_hypothesis ist env sigma hyp in
@@ -2254,11 +1992,11 @@ and interp_atomic ist tac : unit Proofview.tactic =
(name_atomic ~env
(TacInversion(DepInversion(k,c_interp,ids),dqhyps))
(Inv.dinv k c_interp ids_interp dqhyps)) sigma
- end
+ end }
| TacInversion (NonDepInversion (k,idl,ids),hyp) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let hyps = interp_hyp_list ist env sigma idl in
let dqhyps = interp_declared_or_quantified_hypothesis ist env sigma hyp in
let sigma, ids_interp = interp_or_and_intro_pattern_option ist env sigma ids in
@@ -2266,19 +2004,20 @@ and interp_atomic ist tac : unit Proofview.tactic =
(name_atomic ~env
(TacInversion (NonDepInversion (k,hyps,ids),dqhyps))
(Inv.inv_clause k ids_interp hyps dqhyps)) sigma
- end
+ end }
| TacInversion (InversionUsing (c,idl),hyp) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let (sigma,c_interp) = interp_constr ist env sigma c in
let dqhyps = interp_declared_or_quantified_hypothesis ist env sigma hyp in
let hyps = interp_hyp_list ist env sigma idl in
- Proofview.Unsafe.tclEVARS sigma <*>
- name_atomic ~env
+ let tac = name_atomic ~env
(TacInversion (InversionUsing (c_interp,hyps),dqhyps))
(Leminv.lemInv_clause dqhyps c_interp hyps)
- end
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
(* Initial call for interpretation *)
@@ -2299,7 +2038,7 @@ let eval_tactic_ist ist t =
let interp_tac_gen lfun avoid_ids debug t =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let extra = TacStore.set TacStore.empty f_debug debug in
let extra = TacStore.set extra f_avoid_ids avoid_ids in
@@ -2308,7 +2047,7 @@ let interp_tac_gen lfun avoid_ids debug t =
interp_tactic ist
(intern_pure_tactic {
ltacvars; genv = env } t)
- end
+ end }
let interp t = interp_tac_gen Id.Map.empty [] (get_debug()) t
let _ = Proof_global.set_interp_tac interp
@@ -2328,16 +2067,16 @@ let hide_interp global t ot =
Proofview.tclENV >>= fun env ->
hide_interp env
else
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
hide_interp (Proofview.Goal.env gl)
- end
+ end }
(***************************************************************************)
(** Register standard arguments *)
let def_intern ist x = (ist, x)
let def_subst _ x = x
-let def_interp ist gl x = (project gl, x)
+let def_interp ist x = Ftactic.return x
let declare_uniform t =
Genintern.register_intern0 t def_intern;
@@ -2359,27 +2098,55 @@ let () =
let () =
declare_uniform wit_pre_ident
+let lift f = (); fun ist x -> Ftactic.nf_enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ Ftactic.return (f ist env sigma x)
+end }
+
+let lifts f = (); fun ist x -> Ftactic.nf_s_enter { s_enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ let (sigma, v) = f ist env sigma x in
+ Sigma.Unsafe.of_pair (Ftactic.return v, sigma)
+end }
+
+let interp_bindings' ist bl = Ftactic.return { delayed = fun env sigma ->
+ let (sigma, bl) = interp_bindings ist env (Sigma.to_evar_map sigma) bl in
+ Sigma.Unsafe.of_pair (bl, sigma)
+ }
+
+let interp_constr_with_bindings' ist c = Ftactic.return { delayed = fun env sigma ->
+ let (sigma, c) = interp_constr_with_bindings ist env (Sigma.to_evar_map sigma) c in
+ Sigma.Unsafe.of_pair (c, sigma)
+ }
+
let () =
- let interp ist gl ref = (project gl, interp_reference ist (pf_env gl) (project gl) ref) in
- Geninterp.register_interp0 wit_ref interp;
- let interp ist gl pat = interp_intro_pattern ist (pf_env gl) (project gl) pat in
- Geninterp.register_interp0 wit_intro_pattern interp;
- let interp ist gl pat = (project gl, interp_clause ist (pf_env gl) (project gl) pat) in
- Geninterp.register_interp0 wit_clause_dft_concl interp;
- let interp ist gl s = interp_sort (project gl) s in
- Geninterp.register_interp0 wit_sort interp
+ Geninterp.register_interp0 wit_int_or_var (fun ist n -> Ftactic.return (interp_int_or_var ist n));
+ Geninterp.register_interp0 wit_ref (lift interp_reference);
+ Geninterp.register_interp0 wit_ident (lift interp_ident);
+ Geninterp.register_interp0 wit_var (lift interp_hyp);
+ Geninterp.register_interp0 wit_intro_pattern (lifts interp_intro_pattern);
+ Geninterp.register_interp0 wit_clause_dft_concl (lift interp_clause);
+ Geninterp.register_interp0 wit_constr (lifts interp_constr);
+ Geninterp.register_interp0 wit_sort (lifts (fun _ _ evd s -> interp_sort evd s));
+ Geninterp.register_interp0 wit_tacvalue (fun ist v -> Ftactic.return v);
+ Geninterp.register_interp0 wit_red_expr (lifts interp_red_expr);
+ Geninterp.register_interp0 wit_quant_hyp (lift interp_declared_or_quantified_hypothesis);
+ Geninterp.register_interp0 wit_open_constr (lifts interp_open_constr);
+ Geninterp.register_interp0 wit_bindings interp_bindings';
+ Geninterp.register_interp0 wit_constr_with_bindings interp_constr_with_bindings';
+ Geninterp.register_interp0 wit_constr_may_eval (lifts interp_constr_may_eval);
+ ()
let () =
- let interp ist gl tac =
- let f = VFun (UnnamedAppl,extract_trace ist, ist.lfun, [], tac) in
- (project gl, TacArg (dloc, valueIn (of_tacvalue f)))
- in
+ let interp ist tac = Ftactic.return (Value.of_closure ist tac) in
Geninterp.register_interp0 wit_tactic interp
let () =
- Geninterp.register_interp0 wit_uconstr (fun ist gl c ->
- project gl , interp_uconstr ist (pf_env gl) c
- )
+ Geninterp.register_interp0 wit_uconstr (fun ist c -> Ftactic.nf_enter { enter = begin fun gl ->
+ Ftactic.return (interp_uconstr ist (Proofview.Goal.env gl) c)
+ end })
(***************************************************************************)
(* Other entry points *)
@@ -2394,24 +2161,13 @@ let interp_redexp env sigma r =
interp_red_expr ist env sigma (intern_red_expr gist r)
(***************************************************************************)
-(* Embed tactics in raw or glob tactic expr *)
-
-let globTacticIn t = TacArg (dloc,TacDynamic (dloc,tactic_in t))
-let tacticIn t =
- globTacticIn (fun ist ->
- try glob_tactic (t ist)
- with e when Errors.noncritical e -> anomaly ~label:"tacticIn"
- (str "Incorrect tactic expression. Received exception is:" ++
- Errors.print e))
-
-(***************************************************************************)
(* Backwarding recursive needs of tactic glob/interp/eval functions *)
let _ =
let eval ty env sigma lfun arg =
let ist = { lfun = lfun; extra = TacStore.empty; } in
- if has_type arg (glbwit wit_tactic) then
- let tac = out_gen (glbwit wit_tactic) arg in
+ if Genarg.has_type arg (glbwit wit_tactic) then
+ let tac = Genarg.out_gen (glbwit wit_tactic) arg in
let tac = interp_tactic ist tac in
Pfedit.refine_by_tactic env sigma ty tac
else
@@ -2430,9 +2186,9 @@ let _ = Hook.set Auto.extern_interp
let dummy_id = Id.of_string "_"
let lift_constr_tac_to_ml_tac vars tac =
- let tac _ ist = Proofview.Goal.enter begin fun gl ->
+ let tac _ ist = Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = project gl in
let map = function
| None -> None
| Some id ->
@@ -2443,5 +2199,20 @@ let lift_constr_tac_to_ml_tac vars tac =
in
let args = List.map_filter map vars in
tac args ist
- end in
+ end } in
tac
+
+let vernac_debug b =
+ set_debug (if b then Tactic_debug.DebugOn 0 else Tactic_debug.DebugOff)
+
+let _ =
+ let open Goptions in
+ declare_bool_option
+ { optsync = false;
+ optdepr = false;
+ optname = "Ltac debug";
+ optkey = ["Ltac";"Debug"];
+ optread = (fun () -> get_debug () != Tactic_debug.DebugOff);
+ optwrite = vernac_debug }
+
+let () = Hook.set Vernacentries.interp_redexp_hook interp_redexp
diff --git a/tactics/tacinterp.mli b/tactics/tacinterp.mli
index ac7e2149ed..31327873e9 100644
--- a/tactics/tacinterp.mli
+++ b/tactics/tacinterp.mli
@@ -14,15 +14,18 @@ open Genarg
open Redexpr
open Misctypes
+val ltac_trace_info : ltac_trace Exninfo.t
+
module Value :
sig
- type t = tlevel generic_argument
+ type t = Val.t
val of_constr : constr -> t
val to_constr : t -> constr option
val of_int : int -> t
val to_int : t -> int option
val to_list : t -> t list option
val of_closure : Geninterp.interp_sign -> glob_tactic_expr -> t
+ val cast : 'a typed_abstract_argument_type -> Val.t -> 'a
end
(** Values for interpretation *)
@@ -45,14 +48,6 @@ val extract_ltac_constr_values : interp_sign -> Environ.env ->
(** Given an interpretation signature, extract all values which are coercible to
a [constr]. *)
-(** To embed several objects in Coqast.t *)
-val tactic_in : (interp_sign -> glob_tactic_expr) -> Dyn.t
-val tactic_out : Dyn.t -> (interp_sign -> glob_tactic_expr)
-
-val tacticIn : (interp_sign -> raw_tactic_expr) -> raw_tactic_expr
-val globTacticIn : (interp_sign -> glob_tactic_expr) -> raw_tactic_expr
-val valueIn : value -> raw_tactic_arg
-
(** Sets the debugger mode *)
val set_debug : debug_info -> unit
@@ -61,10 +56,7 @@ val get_debug : unit -> debug_info
(** Adds an interpretation function for extra generic arguments *)
-(* spiwack: the [Term.constr] argument is the conclusion of the goal,
- for "casted open constr" *)
-val interp_genarg : interp_sign -> Environ.env -> Evd.evar_map -> Term.constr -> Goal.goal ->
- glob_generic_argument -> Evd.evar_map * typed_generic_argument
+val interp_genarg : interp_sign -> glob_generic_argument -> Value.t Ftactic.t
(** Interprets any expression *)
val val_interp : interp_sign -> glob_tactic_expr -> (value -> unit Proofview.tactic) -> unit Proofview.tactic
@@ -72,6 +64,11 @@ val val_interp : interp_sign -> glob_tactic_expr -> (value -> unit Proofview.tac
(** Interprets an expression that evaluates to a constr *)
val interp_ltac_constr : interp_sign -> glob_tactic_expr -> (constr -> unit Proofview.tactic) -> unit Proofview.tactic
+val type_uconstr :
+ ?flags:Pretyping.inference_flags ->
+ ?expected_type:Pretyping.typing_constraint ->
+ interp_sign -> Glob_term.closed_glob_constr -> constr delayed_open
+
(** Interprets redexp arguments *)
val interp_redexp : Environ.env -> Evd.evar_map -> raw_red_expr -> Evd.evar_map * red_expr
@@ -93,6 +90,8 @@ val eval_tactic : glob_tactic_expr -> unit Proofview.tactic
val eval_tactic_ist : interp_sign -> glob_tactic_expr -> unit Proofview.tactic
(** Same as [eval_tactic], but with the provided [interp_sign]. *)
+val tactic_of_value : interp_sign -> Value.t -> unit Proofview.tactic
+
(** Globalization + interpretation *)
val interp_tac_gen : value Id.Map.t -> Id.t list ->
diff --git a/tactics/tacsubst.ml b/tactics/tacsubst.ml
index cef630da32..55941c1ca6 100644
--- a/tactics/tacsubst.ml
+++ b/tactics/tacsubst.ml
@@ -54,10 +54,16 @@ and subst_intro_pattern_action subst = function
| IntroApplyOn (t,pat) ->
IntroApplyOn (subst_glob_constr subst t,subst_intro_pattern subst pat)
| IntroOrAndPattern l ->
- IntroOrAndPattern (List.map (List.map (subst_intro_pattern subst)) l)
+ IntroOrAndPattern (subst_intro_or_and_pattern subst l)
| IntroInjection l -> IntroInjection (List.map (subst_intro_pattern subst) l)
| IntroWildcard | IntroRewrite _ as x -> x
+and subst_intro_or_and_pattern subst = function
+ | IntroAndPattern l ->
+ IntroAndPattern (List.map (subst_intro_pattern subst) l)
+ | IntroOrPattern ll ->
+ IntroOrPattern (List.map (List.map (subst_intro_pattern subst)) ll)
+
let subst_induction_arg subst = function
| clear,ElimOnConstr c -> clear,ElimOnConstr (subst_glob_with_bindings subst c)
| clear,ElimOnAnonHyp n as x -> x
@@ -140,24 +146,17 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
TacElim (ev,subst_glob_with_bindings_arg subst cb,
Option.map (subst_glob_with_bindings subst) cbo)
| TacCase (ev,cb) -> TacCase (ev,subst_glob_with_bindings_arg subst cb)
- | TacFix (idopt,n) as x -> x
| TacMutualFix (id,n,l) ->
TacMutualFix(id,n,List.map (fun (id,n,c) -> (id,n,subst_glob_constr subst c)) l)
- | TacCofix idopt as x -> x
| TacMutualCofix (id,l) ->
TacMutualCofix (id, List.map (fun (id,c) -> (id,subst_glob_constr subst c)) l)
| TacAssert (b,otac,na,c) ->
TacAssert (b,Option.map (subst_tactic subst) otac,na,subst_glob_constr subst c)
| TacGeneralize cl ->
TacGeneralize (List.map (on_fst (subst_constr_with_occurrences subst))cl)
- | TacGeneralizeDep c -> TacGeneralizeDep (subst_glob_constr subst c)
| TacLetTac (id,c,clp,b,eqpat) ->
TacLetTac (id,subst_glob_constr subst c,clp,b,eqpat)
- (* Automation tactics *)
- | TacTrivial (d,lems,l) -> TacTrivial (d,List.map (subst_glob_constr subst) lems,l)
- | TacAuto (d,n,lems,l) -> TacAuto (d,n,List.map (subst_glob_constr subst) lems,l)
-
(* Derived basic tactics *)
| TacInductionDestruct (isrec,ev,(l,el)) ->
let l' = List.map (fun (c,ids,cls) ->
@@ -167,23 +166,14 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
| TacDoubleInduction (h1,h2) as x -> x
(* Context management *)
- | TacClear _ as x -> x
- | TacClearBody l as x -> x
- | TacMove (id1,id2) as x -> x
| TacRename l as x -> x
- (* Constructors *)
- | TacSplit (ev,bll) -> TacSplit (ev,List.map (subst_bindings subst) bll)
-
(* Conversion *)
| TacReduce (r,cl) -> TacReduce (subst_redexp subst r, cl)
| TacChange (op,c,cl) ->
TacChange (Option.map (subst_glob_constr_or_pattern subst) op,
subst_glob_constr subst c, cl)
- (* Equivalence relations *)
- | TacSymmetry _ as x -> x
-
(* Equality and inversion *)
| TacRewrite (ev,l,cl,by) ->
TacRewrite (ev,
@@ -249,30 +239,21 @@ and subst_tactic subst (t:glob_tactic_expr) = match t with
(* For extensions *)
| TacAlias (_,s,l) ->
let s = subst_kn subst s in
- TacAlias (dloc,s,List.map (fun (id,a) -> (id,subst_genarg subst a)) l)
- | TacML (_loc,opn,l) -> TacML (dloc,opn,List.map (subst_genarg subst) l)
+ TacAlias (dloc,s,List.map (subst_tacarg subst) l)
+ | TacML (_loc,opn,l) -> TacML (dloc,opn,List.map (subst_tacarg subst) l)
and subst_tactic_fun subst (var,body) = (var,subst_tactic subst body)
and subst_tacarg subst = function
| Reference r -> Reference (subst_reference subst r)
| ConstrMayEval c -> ConstrMayEval (subst_raw_may_eval subst c)
- | UConstr c -> UConstr (subst_glob_constr subst c)
- | MetaIdArg (_loc,_,_) -> assert false
| TacCall (_loc,f,l) ->
TacCall (_loc, subst_reference subst f, List.map (subst_tacarg subst) l)
| TacFreshId _ as x -> x
| TacPretype c -> TacPretype (subst_glob_constr subst c)
| TacNumgoals -> TacNumgoals
| Tacexp t -> Tacexp (subst_tactic subst t)
- | TacGeneric arg -> TacGeneric (Genintern.generic_substitute subst arg)
- | TacDynamic(the_loc,t) as x ->
- (match Dyn.tag t with
- | "tactic" | "value" -> x
- | "constr" ->
- TacDynamic(the_loc, constr_in (subst_mps subst (constr_out t)))
- | s -> Errors.anomaly ~loc:dloc ~label:"Tacinterp.val_interp"
- (str "Unknown dynamic: <" ++ str s ++ str ">"))
+ | TacGeneric arg -> TacGeneric (subst_genarg subst arg)
(* Reads the rules of a Match Context or a Match *)
and subst_match_rule subst = function
@@ -285,66 +266,47 @@ and subst_match_rule subst = function
::(subst_match_rule subst tl)
| [] -> []
-and subst_genarg subst (x:glob_generic_argument) =
- match genarg_tag x with
- | IntOrVarArgType -> in_gen (glbwit wit_int_or_var) (out_gen (glbwit wit_int_or_var) x)
- | IdentArgType ->
- in_gen (glbwit wit_ident) (out_gen (glbwit wit_ident) x)
- | VarArgType -> in_gen (glbwit wit_var) (out_gen (glbwit wit_var) x)
- | GenArgType -> in_gen (glbwit wit_genarg) (subst_genarg subst (out_gen (glbwit wit_genarg) x))
- | ConstrArgType ->
- in_gen (glbwit wit_constr) (subst_glob_constr subst (out_gen (glbwit wit_constr) x))
- | ConstrMayEvalArgType ->
- in_gen (glbwit wit_constr_may_eval) (subst_raw_may_eval subst (out_gen (glbwit wit_constr_may_eval) x))
- | QuantHypArgType ->
- in_gen (glbwit wit_quant_hyp)
- (subst_declared_or_quantified_hypothesis subst
- (out_gen (glbwit wit_quant_hyp) x))
- | RedExprArgType ->
- in_gen (glbwit wit_red_expr) (subst_redexp subst (out_gen (glbwit wit_red_expr) x))
- | OpenConstrArgType ->
- in_gen (glbwit wit_open_constr)
- ((),subst_glob_constr subst (snd (out_gen (glbwit wit_open_constr) x)))
- | ConstrWithBindingsArgType ->
- in_gen (glbwit wit_constr_with_bindings)
- (subst_glob_with_bindings subst (out_gen (glbwit wit_constr_with_bindings) x))
- | BindingsArgType ->
- in_gen (glbwit wit_bindings)
- (subst_bindings subst (out_gen (glbwit wit_bindings) x))
- | ListArgType _ ->
- let list_unpacker wit l =
- let map x =
- let ans = subst_genarg subst (in_gen (glbwit wit) x) in
- out_gen (glbwit wit) ans
- in
- in_gen (glbwit (wit_list wit)) (List.map map (glb l))
+and subst_genarg subst (GenArg (Glbwit wit, x)) =
+ match wit with
+ | ListArg wit ->
+ let map x =
+ let ans = subst_genarg subst (in_gen (glbwit wit) x) in
+ out_gen (glbwit wit) ans
in
- list_unpack { list_unpacker } x
- | OptArgType _ ->
- let opt_unpacker wit o = match glb o with
+ in_gen (glbwit (wit_list wit)) (List.map map x)
+ | OptArg wit ->
+ let ans = match x with
| None -> in_gen (glbwit (wit_opt wit)) None
| Some x ->
let s = out_gen (glbwit wit) (subst_genarg subst (in_gen (glbwit wit) x)) in
in_gen (glbwit (wit_opt wit)) (Some s)
in
- opt_unpack { opt_unpacker } x
- | PairArgType _ ->
- let pair_unpacker wit1 wit2 o =
- let p, q = glb o in
- let p = out_gen (glbwit wit1) (subst_genarg subst (in_gen (glbwit wit1) p)) in
- let q = out_gen (glbwit wit2) (subst_genarg subst (in_gen (glbwit wit2) q)) in
- in_gen (glbwit (wit_pair wit1 wit2)) (p, q)
- in
- pair_unpack { pair_unpacker } x
- | ExtraArgType s ->
- Genintern.generic_substitute subst x
+ ans
+ | PairArg (wit1, wit2) ->
+ let p, q = x in
+ let p = out_gen (glbwit wit1) (subst_genarg subst (in_gen (glbwit wit1) p)) in
+ let q = out_gen (glbwit wit2) (subst_genarg subst (in_gen (glbwit wit2) q)) in
+ in_gen (glbwit (wit_pair wit1 wit2)) (p, q)
+ | ExtraArg s ->
+ Genintern.generic_substitute subst (in_gen (glbwit wit) x)
(** Registering *)
let () =
+ Genintern.register_subst0 wit_int_or_var (fun _ v -> v);
Genintern.register_subst0 wit_ref subst_global_reference;
+ Genintern.register_subst0 wit_ident (fun _ v -> v);
+ Genintern.register_subst0 wit_var (fun _ v -> v);
Genintern.register_subst0 wit_intro_pattern (fun _ v -> v);
Genintern.register_subst0 wit_tactic subst_tactic;
+ Genintern.register_subst0 wit_constr subst_glob_constr;
Genintern.register_subst0 wit_sort (fun _ v -> v);
Genintern.register_subst0 wit_clause_dft_concl (fun _ v -> v);
- Genintern.register_subst0 wit_uconstr (fun subst c -> subst_glob_constr subst c)
+ Genintern.register_subst0 wit_uconstr (fun subst c -> subst_glob_constr subst c);
+ Genintern.register_subst0 wit_open_constr (fun subst c -> subst_glob_constr subst c);
+ Genintern.register_subst0 wit_red_expr subst_redexp;
+ Genintern.register_subst0 wit_quant_hyp subst_declared_or_quantified_hypothesis;
+ Genintern.register_subst0 wit_bindings subst_bindings;
+ Genintern.register_subst0 wit_constr_with_bindings subst_glob_with_bindings;
+ Genintern.register_subst0 wit_constr_may_eval subst_raw_may_eval;
+ ()
diff --git a/tactics/tactic_debug.ml b/tactics/tactic_debug.ml
new file mode 100644
index 0000000000..e991eb86dc
--- /dev/null
+++ b/tactics/tactic_debug.ml
@@ -0,0 +1,400 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Util
+open Names
+open Pp
+open Tacexpr
+open Termops
+open Nameops
+open Proofview.Notations
+
+let (ltac_trace_info : ltac_trace Exninfo.t) = Exninfo.make ()
+
+let prtac x =
+ Pptactic.pr_glob_tactic (Global.env()) x
+let prmatchpatt env sigma hyp =
+ Pptactic.pr_match_pattern (Printer.pr_constr_pattern_env env sigma) hyp
+let prmatchrl rl =
+ Pptactic.pr_match_rule false (Pptactic.pr_glob_tactic (Global.env()))
+ (fun (_,p) -> Printer.pr_constr_pattern p) rl
+
+(* This module intends to be a beginning of debugger for tactic expressions.
+ Currently, it is quite simple and we can hope to have, in the future, a more
+ complete panel of commands dedicated to a proof assistant framework *)
+
+(* Debug information *)
+type debug_info =
+ | DebugOn of int
+ | DebugOff
+
+(* An exception handler *)
+let explain_logic_error = ref (fun e -> mt())
+
+let explain_logic_error_no_anomaly = ref (fun e -> mt())
+
+let msg_tac_debug s = Proofview.NonLogical.print_debug (s++fnl())
+let msg_tac_notice s = Proofview.NonLogical.print_notice (s++fnl())
+
+(* Prints the goal *)
+
+let db_pr_goal gl =
+ let env = Proofview.Goal.env gl in
+ let concl = Proofview.Goal.concl gl in
+ let penv = print_named_context env in
+ let pc = print_constr_env env concl in
+ str" " ++ hv 0 (penv ++ fnl () ++
+ str "============================" ++ fnl () ++
+ str" " ++ pc) ++ fnl ()
+
+let db_pr_goal =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let pg = db_pr_goal gl in
+ Proofview.tclLIFT (msg_tac_notice (str "Goal:" ++ fnl () ++ pg))
+ end }
+
+
+(* Prints the commands *)
+let help () =
+ msg_tac_debug (str "Commands: <Enter> = Continue" ++ fnl() ++
+ str " h/? = Help" ++ fnl() ++
+ str " r <num> = Run <num> times" ++ fnl() ++
+ str " r <string> = Run up to next idtac <string>" ++ fnl() ++
+ str " s = Skip" ++ fnl() ++
+ str " x = Exit")
+
+(* Prints the goal and the command to be executed *)
+let goal_com tac =
+ Proofview.tclTHEN
+ db_pr_goal
+ (Proofview.tclLIFT (msg_tac_debug (str "Going to execute:" ++ fnl () ++ prtac tac)))
+
+(* [run (new_ref _)] gives us a ref shared among [NonLogical.t]
+ expressions. It avoids parametrizing everything over a
+ reference. *)
+let skipped = Proofview.NonLogical.run (Proofview.NonLogical.ref 0)
+let skip = Proofview.NonLogical.run (Proofview.NonLogical.ref 0)
+let breakpoint = Proofview.NonLogical.run (Proofview.NonLogical.ref None)
+
+let rec drop_spaces inst i =
+ if String.length inst > i && inst.[i] == ' ' then drop_spaces inst (i+1)
+ else i
+
+let possibly_unquote s =
+ if String.length s >= 2 && s.[0] == '"' && s.[String.length s - 1] == '"' then
+ String.sub s 1 (String.length s - 2)
+ else
+ s
+
+(* (Re-)initialize debugger *)
+let db_initialize =
+ let open Proofview.NonLogical in
+ (skip:=0) >> (skipped:=0) >> (breakpoint:=None)
+
+let int_of_string s =
+ try Proofview.NonLogical.return (int_of_string s)
+ with e -> Proofview.NonLogical.raise e
+
+let string_get s i =
+ try Proofview.NonLogical.return (String.get s i)
+ with e -> Proofview.NonLogical.raise e
+
+(* Gives the number of steps or next breakpoint of a run command *)
+let run_com inst =
+ let open Proofview.NonLogical in
+ string_get inst 0 >>= fun first_char ->
+ if first_char ='r' then
+ let i = drop_spaces inst 1 in
+ if String.length inst > i then
+ let s = String.sub inst i (String.length inst - i) in
+ if inst.[0] >= '0' && inst.[0] <= '9' then
+ int_of_string s >>= fun num ->
+ (if num<0 then invalid_arg "run_com" else return ()) >>
+ (skip:=num) >> (skipped:=0)
+ else
+ breakpoint:=Some (possibly_unquote s)
+ else
+ invalid_arg "run_com"
+ else
+ invalid_arg "run_com"
+
+(* Prints the run counter *)
+let run ini =
+ let open Proofview.NonLogical in
+ if not ini then
+ begin
+ Proofview.NonLogical.print_notice (str"\b\r\b\r") >>
+ !skipped >>= fun skipped ->
+ msg_tac_debug (str "Executed expressions: " ++ int skipped ++ fnl())
+ end >>
+ !skipped >>= fun x ->
+ skipped := x+1
+ else
+ return ()
+
+(* Prints the prompt *)
+let rec prompt level =
+ (* spiwack: avoid overriding by the open below *)
+ let runtrue = run true in
+ begin
+ let open Proofview.NonLogical in
+ Proofview.NonLogical.print_notice (fnl () ++ str "TcDebug (" ++ int level ++ str ") > ") >>
+ let exit = (skip:=0) >> (skipped:=0) >> raise Sys.Break in
+ Proofview.NonLogical.catch Proofview.NonLogical.read_line
+ begin function (e, info) -> match e with
+ | End_of_file -> exit
+ | e -> raise ~info e
+ end
+ >>= fun inst ->
+ match inst with
+ | "" -> return (DebugOn (level+1))
+ | "s" -> return (DebugOff)
+ | "x" -> Proofview.NonLogical.print_char '\b' >> exit
+ | "h"| "?" ->
+ begin
+ help () >>
+ prompt level
+ end
+ | _ ->
+ Proofview.NonLogical.catch (run_com inst >> runtrue >> return (DebugOn (level+1)))
+ begin function (e, info) -> match e with
+ | Failure _ | Invalid_argument _ -> prompt level
+ | e -> raise ~info e
+ end
+ end
+
+(* Prints the state and waits for an instruction *)
+(* spiwack: the only reason why we need to take the continuation [f]
+ as an argument rather than returning the new level directly seems to
+ be that [f] is wrapped in with "explain_logic_error". I don't think
+ it serves any purpose in the current design, so we could just drop
+ that. *)
+let debug_prompt lev tac f =
+ (* spiwack: avoid overriding by the open below *)
+ let runfalse = run false in
+ let open Proofview.NonLogical in
+ let (>=) = Proofview.tclBIND in
+ (* What to print and to do next *)
+ let newlevel =
+ Proofview.tclLIFT !skip >= fun initial_skip ->
+ if Int.equal initial_skip 0 then
+ Proofview.tclLIFT !breakpoint >= fun breakpoint ->
+ if Option.is_empty breakpoint then Proofview.tclTHEN (goal_com tac) (Proofview.tclLIFT (prompt lev))
+ else Proofview.tclLIFT(runfalse >> return (DebugOn (lev+1)))
+ else Proofview.tclLIFT begin
+ (!skip >>= fun s -> skip:=s-1) >>
+ runfalse >>
+ !skip >>= fun new_skip ->
+ (if Int.equal new_skip 0 then skipped:=0 else return ()) >>
+ return (DebugOn (lev+1))
+ end in
+ newlevel >= fun newlevel ->
+ (* What to execute *)
+ Proofview.tclOR
+ (f newlevel)
+ begin fun (reraise, info) ->
+ Proofview.tclTHEN
+ (Proofview.tclLIFT begin
+ (skip:=0) >> (skipped:=0) >>
+ if Logic.catchable_exception reraise then
+ msg_tac_debug (str "Level " ++ int lev ++ str ": " ++ Pervasives.(!) explain_logic_error reraise)
+ else return ()
+ end)
+ (Proofview.tclZERO ~info reraise)
+ end
+
+let is_debug db =
+ let open Proofview.NonLogical in
+ !breakpoint >>= fun breakpoint ->
+ match db, breakpoint with
+ | DebugOff, _ -> return false
+ | _, Some _ -> return false
+ | _ ->
+ !skip >>= fun skip ->
+ return (Int.equal skip 0)
+
+(* Prints a constr *)
+let db_constr debug env c =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "Evaluated term: " ++ print_constr_env env c)
+ else return ()
+
+(* Prints the pattern rule *)
+let db_pattern_rule debug num r =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ begin
+ msg_tac_debug (str "Pattern rule " ++ int num ++ str ":" ++ fnl () ++
+ str "|" ++ spc () ++ prmatchrl r)
+ end
+ else return ()
+
+(* Prints the hypothesis pattern identifier if it exists *)
+let hyp_bound = function
+ | Anonymous -> str " (unbound)"
+ | Name id -> str " (bound to " ++ pr_id id ++ str ")"
+
+(* Prints a matched hypothesis *)
+let db_matched_hyp debug env (id,_,c) ido =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "Hypothesis " ++ pr_id id ++ hyp_bound ido ++
+ str " has been matched: " ++ print_constr_env env c)
+ else return ()
+
+(* Prints the matched conclusion *)
+let db_matched_concl debug env c =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "Conclusion has been matched: " ++ print_constr_env env c)
+ else return ()
+
+(* Prints a success message when the goal has been matched *)
+let db_mc_pattern_success debug =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "The goal has been successfully matched!" ++ fnl() ++
+ str "Let us execute the right-hand side part..." ++ fnl())
+ else return ()
+
+(* Prints a failure message for an hypothesis pattern *)
+let db_hyp_pattern_failure debug env sigma (na,hyp) =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "The pattern hypothesis" ++ hyp_bound na ++
+ str " cannot match: " ++
+ prmatchpatt env sigma hyp)
+ else return ()
+
+(* Prints a matching failure message for a rule *)
+let db_matching_failure debug =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ msg_tac_debug (str "This rule has failed due to matching errors!" ++ fnl() ++
+ str "Let us try the next one...")
+ else return ()
+
+(* Prints an evaluation failure message for a rule *)
+let db_eval_failure debug s =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ let s = str "message \"" ++ s ++ str "\"" in
+ msg_tac_debug
+ (str "This rule has failed due to \"Fail\" tactic (" ++
+ s ++ str ", level 0)!" ++ fnl() ++ str "Let us try the next one...")
+ else return ()
+
+(* Prints a logic failure message for a rule *)
+let db_logic_failure debug err =
+ let open Proofview.NonLogical in
+ is_debug debug >>= fun db ->
+ if db then
+ begin
+ msg_tac_debug (Pervasives.(!) explain_logic_error err) >>
+ msg_tac_debug (str "This rule has failed due to a logic error!" ++ fnl() ++
+ str "Let us try the next one...")
+ end
+ else return ()
+
+let is_breakpoint brkname s = match brkname, s with
+ | Some s, MsgString s'::_ -> String.equal s s'
+ | _ -> false
+
+let db_breakpoint debug s =
+ let open Proofview.NonLogical in
+ !breakpoint >>= fun opt_breakpoint ->
+ match debug with
+ | DebugOn lev when not (CList.is_empty s) && is_breakpoint opt_breakpoint s ->
+ breakpoint:=None
+ | _ ->
+ return ()
+
+(** Extrating traces *)
+
+let is_defined_ltac trace =
+ let rec aux = function
+ | (_, Tacexpr.LtacNameCall f) :: tail ->
+ not (Tacenv.is_ltac_for_ml_tactic f)
+ | (_, Tacexpr.LtacAtomCall _) :: tail ->
+ false
+ | _ :: tail -> aux tail
+ | [] -> false in
+ aux (List.rev trace)
+
+let explain_ltac_call_trace last trace loc =
+ let calls = last :: List.rev_map snd trace in
+ let pr_call ck = match ck with
+ | Tacexpr.LtacNotationCall kn -> quote (KerName.print kn)
+ | Tacexpr.LtacNameCall cst -> quote (Pptactic.pr_ltac_constant cst)
+ | Tacexpr.LtacMLCall t ->
+ quote (Pptactic.pr_glob_tactic (Global.env()) t)
+ | Tacexpr.LtacVarCall (id,t) ->
+ quote (Nameops.pr_id id) ++ strbrk " (bound to " ++
+ Pptactic.pr_glob_tactic (Global.env()) t ++ str ")"
+ | Tacexpr.LtacAtomCall te ->
+ quote (Pptactic.pr_glob_tactic (Global.env())
+ (Tacexpr.TacAtom (Loc.ghost,te)))
+ | Tacexpr.LtacConstrInterp (c, { Pretyping.ltac_constrs = vars }) ->
+ quote (Printer.pr_glob_constr_env (Global.env()) c) ++
+ (if not (Id.Map.is_empty vars) then
+ strbrk " (with " ++
+ prlist_with_sep pr_comma
+ (fun (id,c) ->
+ pr_id id ++ str ":=" ++ Printer.pr_lconstr_under_binders c)
+ (List.rev (Id.Map.bindings vars)) ++ str ")"
+ else mt())
+ in
+ match calls with
+ | [] -> mt ()
+ | _ ->
+ let kind_of_last_call = match List.last calls with
+ | Tacexpr.LtacConstrInterp _ -> ", last term evaluation failed."
+ | _ -> ", last call failed."
+ in
+ hov 0 (str "In nested Ltac calls to " ++
+ pr_enum pr_call calls ++ strbrk kind_of_last_call)
+
+let skip_extensions trace =
+ let rec aux = function
+ | (_,Tacexpr.LtacNameCall f as tac) :: _
+ when Tacenv.is_ltac_for_ml_tactic f -> [tac]
+ | (_,(Tacexpr.LtacNotationCall _ | Tacexpr.LtacMLCall _) as tac)
+ :: _ -> [tac]
+ | t :: tail -> t :: aux tail
+ | [] -> [] in
+ List.rev (aux (List.rev trace))
+
+let extract_ltac_trace trace eloc =
+ let trace = skip_extensions trace in
+ let (loc,c),tail = List.sep_last trace in
+ if is_defined_ltac trace then
+ (* We entered a user-defined tactic,
+ we display the trace with location of the call *)
+ let msg = hov 0 (explain_ltac_call_trace c tail eloc ++ fnl()) in
+ Some msg, loc
+ else
+ (* We entered a primitive tactic, we don't display trace but
+ report on the finest location *)
+ let best_loc =
+ if not (Loc.is_ghost eloc) then eloc else
+ (* trace is with innermost call coming first *)
+ let rec aux = function
+ | (loc,_)::tail when not (Loc.is_ghost loc) -> loc
+ | _::tail -> aux tail
+ | [] -> Loc.ghost in
+ aux trace in
+ None, best_loc
diff --git a/tactics/tactic_debug.mli b/tactics/tactic_debug.mli
new file mode 100644
index 0000000000..523398e75a
--- /dev/null
+++ b/tactics/tactic_debug.mli
@@ -0,0 +1,80 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Environ
+open Pattern
+open Names
+open Tacexpr
+open Term
+open Evd
+
+(** TODO: Move those definitions somewhere sensible *)
+
+val ltac_trace_info : ltac_trace Exninfo.t
+
+(** This module intends to be a beginning of debugger for tactic expressions.
+ Currently, it is quite simple and we can hope to have, in the future, a more
+ complete panel of commands dedicated to a proof assistant framework *)
+
+(** Debug information *)
+type debug_info =
+ | DebugOn of int
+ | DebugOff
+
+(** Prints the state and waits *)
+val debug_prompt :
+ int -> glob_tactic_expr -> (debug_info -> 'a Proofview.tactic) -> 'a Proofview.tactic
+
+(** Initializes debugger *)
+val db_initialize : unit Proofview.NonLogical.t
+
+(** Prints a constr *)
+val db_constr : debug_info -> env -> constr -> unit Proofview.NonLogical.t
+
+(** Prints the pattern rule *)
+val db_pattern_rule :
+ debug_info -> int -> (Tacexpr.glob_constr_and_expr * constr_pattern,glob_tactic_expr) match_rule -> unit Proofview.NonLogical.t
+
+(** Prints a matched hypothesis *)
+val db_matched_hyp :
+ debug_info -> env -> Id.t * constr option * constr -> Name.t -> unit Proofview.NonLogical.t
+
+(** Prints the matched conclusion *)
+val db_matched_concl : debug_info -> env -> constr -> unit Proofview.NonLogical.t
+
+(** Prints a success message when the goal has been matched *)
+val db_mc_pattern_success : debug_info -> unit Proofview.NonLogical.t
+
+(** Prints a failure message for an hypothesis pattern *)
+val db_hyp_pattern_failure :
+ debug_info -> env -> evar_map -> Name.t * constr_pattern match_pattern -> unit Proofview.NonLogical.t
+
+(** Prints a matching failure message for a rule *)
+val db_matching_failure : debug_info -> unit Proofview.NonLogical.t
+
+(** Prints an evaluation failure message for a rule *)
+val db_eval_failure : debug_info -> Pp.std_ppcmds -> unit Proofview.NonLogical.t
+
+(** An exception handler *)
+val explain_logic_error: (exn -> Pp.std_ppcmds) ref
+
+(** For use in the Ltac debugger: some exception that are usually
+ consider anomalies are acceptable because they are caught later in
+ the process that is being debugged. One should not require
+ from users that they report these anomalies. *)
+val explain_logic_error_no_anomaly : (exn -> Pp.std_ppcmds) ref
+
+(** Prints a logic failure message for a rule *)
+val db_logic_failure : debug_info -> exn -> unit Proofview.NonLogical.t
+
+(** Prints a logic failure message for a rule *)
+val db_breakpoint : debug_info ->
+ Id.t Loc.located message_token list -> unit Proofview.NonLogical.t
+
+val extract_ltac_trace :
+ Tacexpr.ltac_trace -> Loc.t -> Pp.std_ppcmds option * Loc.t
diff --git a/tactics/tactic_matching.ml b/tactics/tactic_matching.ml
index 80786058d9..2144b75e74 100644
--- a/tactics/tactic_matching.ml
+++ b/tactics/tactic_matching.ml
@@ -11,6 +11,7 @@
open Names
open Tacexpr
+open Context.Named.Declaration
(** [t] is the type of matching successes. It ultimately contains a
{!Tacexpr.glob_tactic_expr} representing the left-hand side of the
@@ -278,9 +279,10 @@ module PatternMatching (E:StaticEnvironment) = struct
[hyps]. Tries the hypotheses in order. For each success returns
the name of the matched hypothesis. *)
let hyp_match_type hypname pat hyps =
- pick hyps >>= fun (id,b,hyp) ->
- let refresh = not (Option.is_empty b) in
- pattern_match_term refresh pat hyp () <*>
+ pick hyps >>= fun decl ->
+ let id = get_id decl in
+ let refresh = is_local_def decl in
+ pattern_match_term refresh pat (get_type decl) () <*>
put_terms (id_map_try_add_name hypname (Term.mkVar id) empty_term_subst) <*>
return id
@@ -290,12 +292,12 @@ module PatternMatching (E:StaticEnvironment) = struct
success returns the name of the matched hypothesis. *)
let hyp_match_body_and_type hypname bodypat typepat hyps =
pick hyps >>= function
- | (id,Some body,hyp) ->
+ | LocalDef (id,body,hyp) ->
pattern_match_term false bodypat body () <*>
pattern_match_term true typepat hyp () <*>
put_terms (id_map_try_add_name hypname (Term.mkVar id) empty_term_subst) <*>
return id
- | (id,None,hyp) -> fail
+ | LocalAssum (id,hyp) -> fail
(** [hyp_match pat hyps] dispatches to
{!hyp_match_type} or {!hyp_match_body_and_type} depending on whether
@@ -317,7 +319,7 @@ module PatternMatching (E:StaticEnvironment) = struct
(* spiwack: alternatively it is possible to return the list
with the matched hypothesis removed directly in
[hyp_match]. *)
- let select_matched_hyp (id,_,_) = Id.equal id matched_hyp in
+ let select_matched_hyp decl = Id.equal (get_id decl) matched_hyp in
let hyps = CList.remove_first select_matched_hyp hyps in
hyp_pattern_list_match pats hyps lhs
| [] -> return lhs
diff --git a/tactics/tactic_matching.mli b/tactics/tactic_matching.mli
index d8e6dd0ae3..090207bcc3 100644
--- a/tactics/tactic_matching.mli
+++ b/tactics/tactic_matching.mli
@@ -43,7 +43,7 @@ val match_term :
val match_goal:
Environ.env ->
Evd.evar_map ->
- Context.named_context ->
+ Context.Named.t ->
Term.constr ->
(Tacexpr.binding_bound_vars * Pattern.constr_pattern, Tacexpr.glob_tactic_expr) Tacexpr.match_rule list ->
Tacexpr.glob_tactic_expr t Proofview.tactic
diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml
index f59224111b..7f904a561d 100644
--- a/tactics/tacticals.ml
+++ b/tactics/tacticals.ml
@@ -12,10 +12,11 @@ open Util
open Names
open Term
open Termops
-open Context
open Declarations
open Tacmach
open Clenv
+open Sigma.Notations
+open Context.Named.Declaration
(************************************************************************)
(* Tacticals re-exported from the Refiner module *)
@@ -69,7 +70,7 @@ let nthDecl m gl =
try List.nth (pf_hyps gl) (m-1)
with Failure _ -> error "No such assumption."
-let nthHypId m gl = pi1 (nthDecl m gl)
+let nthHypId m gl = nthDecl m gl |> get_id
let nthHyp m gl = mkVar (nthHypId m gl)
let lastDecl gl = nthDecl 1 gl
@@ -80,7 +81,7 @@ let nLastDecls n gl =
try List.firstn n (pf_hyps gl)
with Failure _ -> error "Not enough hypotheses in the goal."
-let nLastHypsId n gl = List.map pi1 (nLastDecls n gl)
+let nLastHypsId n gl = List.map get_id (nLastDecls n gl)
let nLastHyps n gl = List.map mkVar (nLastHypsId n gl)
let onNthDecl m tac gl = tac (nthDecl m gl) gl
@@ -98,7 +99,7 @@ let onNLastHypsId n tac = onHyps (nLastHypsId n) tac
let onNLastHyps n tac = onHyps (nLastHyps n) tac
let afterHyp id gl =
- fst (List.split_when (fun (hyp,_,_) -> Id.equal hyp id) (pf_hyps gl))
+ fst (List.split_when (Id.equal id % get_id) (pf_hyps gl))
(***************************************)
(* Clause Tacticals *)
@@ -147,14 +148,16 @@ type branch_args = {
largs : constr list; (* its arguments *)
branchnum : int; (* the branch number *)
pred : constr; (* the predicate we used *)
- nassums : int; (* the number of assumptions to be introduced *)
+ nassums : int; (* number of assumptions/letin to be introduced *)
branchsign : bool list; (* the signature of the branch.
- true=recursive argument, false=constant *)
+ true=assumption, false=let-in *)
branchnames : Tacexpr.intro_patterns}
type branch_assumptions = {
- ba : branch_args; (* the branch args *)
- assums : named_context} (* the list of assumptions introduced *)
+ ba : branch_args; (* the branch args *)
+ assums : Context.Named.t} (* the list of assumptions introduced *)
+
+open Misctypes
let fix_empty_or_and_pattern nv l =
(* 1- The syntax does not distinguish between "[ ]" for one clause with no
@@ -162,36 +165,78 @@ let fix_empty_or_and_pattern nv l =
(* 2- More generally, we admit "[ ]" for any disjunctive pattern of
arbitrary length *)
match l with
- | [[]] -> List.make nv []
+ | IntroOrPattern [[]] -> IntroOrPattern (List.make nv [])
| _ -> l
-let check_or_and_pattern_size loc names n =
- if not (Int.equal (List.length names) n) then
- if Int.equal n 1 then
- user_err_loc (loc,"",str "Expects a conjunctive pattern.")
- else
- user_err_loc (loc,"",str "Expects a disjunctive pattern with " ++ int n
- ++ str " branches.")
-
-let compute_induction_names n = function
+let check_or_and_pattern_size check_and loc names branchsigns =
+ let n = Array.length branchsigns in
+ let msg p1 p2 = strbrk "a conjunctive pattern made of " ++ int p1 ++ (if p1 == p2 then mt () else str " or " ++ int p2) ++ str " patterns" in
+ let err1 p1 p2 =
+ user_err_loc (loc,"",str "Expects " ++ msg p1 p2 ++ str ".") in
+ let errn n =
+ user_err_loc (loc,"",str "Expects a disjunctive pattern with " ++ int n
+ ++ str " branches.") in
+ let err1' p1 p2 =
+ user_err_loc (loc,"",strbrk "Expects a disjunctive pattern with 1 branch or " ++ msg p1 p2 ++ str ".") in
+ let errforthcoming loc =
+ user_err_loc (loc,"",strbrk "Unexpected non atomic pattern.") in
+ match names with
+ | IntroAndPattern l ->
+ if not (Int.equal n 1) then errn n;
+ let l' = List.filter (function _,IntroForthcoming _ -> true | _,IntroNaming _ | _,IntroAction _ -> false) l in
+ if l' != [] then errforthcoming (fst (List.hd l'));
+ if check_and then
+ let p1 = List.count (fun x -> x) branchsigns.(0) in
+ let p2 = List.length branchsigns.(0) in
+ let p = List.length l in
+ if not (Int.equal p p1 || Int.equal p p2) then err1 p1 p2;
+ if Int.equal p p1 then
+ IntroAndPattern
+ (List.extend branchsigns.(0) (Loc.ghost,IntroNaming IntroAnonymous) l)
+ else
+ names
+ else
+ names
+ | IntroOrPattern ll ->
+ if not (Int.equal n (List.length ll)) then
+ if Int.equal n 1 then
+ let p1 = List.count (fun x -> x) branchsigns.(0) in
+ let p2 = List.length branchsigns.(0) in
+ err1' p1 p2 else errn n;
+ names
+
+let get_and_check_or_and_pattern_gen check_and loc names branchsigns =
+ let names = check_or_and_pattern_size check_and loc names branchsigns in
+ match names with
+ | IntroAndPattern l -> [|l|]
+ | IntroOrPattern l -> Array.of_list l
+
+let get_and_check_or_and_pattern = get_and_check_or_and_pattern_gen true
+
+let compute_induction_names_gen check_and branchletsigns = function
| None ->
- Array.make n []
+ Array.make (Array.length branchletsigns) []
| Some (loc,names) ->
- let names = fix_empty_or_and_pattern n names in
- check_or_and_pattern_size loc names n;
- Array.of_list names
+ let names = fix_empty_or_and_pattern (Array.length branchletsigns) names in
+ get_and_check_or_and_pattern_gen check_and loc names branchletsigns
+
+let compute_induction_names = compute_induction_names_gen true
-let compute_construtor_signatures isrec ((_,k as ity),u) =
+(* Compute the let-in signature of case analysis or standard induction scheme *)
+let compute_constructor_signatures isrec ((_,k as ity),u) =
let rec analrec c recargs =
match kind_of_term c, recargs with
| Prod (_,_,c), recarg::rest ->
- let b = match Declareops.dest_recarg recarg with
- | Norec | Imbr _ -> false
- | Mrec (_,j) -> isrec && Int.equal j k
- in b :: (analrec c rest)
- | LetIn (_,_,_,c), rest -> false :: (analrec c rest)
+ let rest = analrec c rest in
+ begin match Declareops.dest_recarg recarg with
+ | Norec | Imbr _ -> true :: rest
+ | Mrec (_,j) ->
+ if isrec && Int.equal j k then true :: true :: rest
+ else true :: rest
+ end
+ | LetIn (_,_,_,c), rest -> false :: analrec c rest
| _, [] -> []
- | _ -> anomaly (Pp.str "compute_construtor_signatures")
+ | _ -> anomaly (Pp.str "compute_constructor_signatures")
in
let (mib,mip) = Global.lookup_inductive ity in
let n = mib.mind_nparams in
@@ -225,60 +270,28 @@ let gl_make_elim ind gl =
pf_apply Evd.fresh_global gl gr
let gl_make_case_dep ind gl =
- pf_apply Indrec.build_case_analysis_scheme gl ind true
+ let sigma = Sigma.Unsafe.of_evar_map (Tacmach.project gl) in
+ let Sigma (r, sigma, _) = Indrec.build_case_analysis_scheme (pf_env gl) sigma ind true
(elimination_sort_of_goal gl)
+ in
+ (Sigma.to_evar_map sigma, r)
let gl_make_case_nodep ind gl =
- pf_apply Indrec.build_case_analysis_scheme gl ind false
+ let sigma = Sigma.Unsafe.of_evar_map (Tacmach.project gl) in
+ let Sigma (r, sigma, _) = Indrec.build_case_analysis_scheme (pf_env gl) sigma ind false
(elimination_sort_of_goal gl)
+ in
+ (Sigma.to_evar_map sigma, r)
let make_elim_branch_assumptions ba gl =
- let rec makerec (assums,cargs,constargs,recargs,indargs) lb lc =
- match lb,lc with
- | ([], _) ->
- { ba = ba;
- assums = assums}
- | ((true::tl), ((idrec,_,_ as recarg)::(idind,_,_ as indarg)::idtl)) ->
- makerec (recarg::indarg::assums,
- idrec::cargs,
- idrec::recargs,
- constargs,
- idind::indargs) tl idtl
- | ((false::tl), ((id,_,_ as constarg)::idtl)) ->
- makerec (constarg::assums,
- id::cargs,
- id::constargs,
- recargs,
- indargs) tl idtl
- | (_, _) -> anomaly (Pp.str "make_elim_branch_assumptions")
- in
- makerec ([],[],[],[],[]) ba.branchsign
- (try List.firstn ba.nassums (pf_hyps gl)
- with Failure _ -> anomaly (Pp.str "make_elim_branch_assumptions"))
+ let assums =
+ try List.rev (List.firstn ba.nassums (pf_hyps gl))
+ with Failure _ -> anomaly (Pp.str "make_elim_branch_assumptions") in
+ { ba = ba; assums = assums }
let elim_on_ba tac ba gl = tac (make_elim_branch_assumptions ba gl) gl
-let make_case_branch_assumptions ba gl =
- let rec makerec (assums,cargs,constargs,recargs) p_0 p_1 =
- match p_0,p_1 with
- | ([], _) ->
- { ba = ba;
- assums = assums}
- | ((true::tl), ((idrec,_,_ as recarg)::idtl)) ->
- makerec (recarg::assums,
- idrec::cargs,
- idrec::recargs,
- constargs) tl idtl
- | ((false::tl), ((id,_,_ as constarg)::idtl)) ->
- makerec (constarg::assums,
- id::cargs,
- recargs,
- id::constargs) tl idtl
- | (_, _) -> anomaly (Pp.str "make_case_branch_assumptions")
- in
- makerec ([],[],[],[]) ba.branchsign
- (try List.firstn ba.nassums (pf_hyps gl)
- with Failure _ -> anomaly (Pp.str "make_case_branch_assumptions"))
+let make_case_branch_assumptions = make_elim_branch_assumptions
let case_on_ba tac ba gl = tac (make_case_branch_assumptions ba gl) gl
@@ -508,6 +521,14 @@ module New = struct
in
Proofview.Unsafe.tclEVARS sigma <*> tac >>= check_evars_if
+ let tclDELAYEDWITHHOLES check x tac =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Proofview.Goal.sigma gl in
+ let Sigma (x, sigma, _) = x.Tacexpr.delayed env sigma in
+ tclWITHHOLES check (tac x) (Sigma.to_evar_map sigma)
+ end }
+
let tclTIMEOUT n t =
Proofview.tclOR
(Proofview.tclTIMEOUT n t)
@@ -532,72 +553,70 @@ module New = struct
let nthHypId m gl =
(** We only use [id] *)
let gl = Proofview.Goal.assume gl in
- let (id,_,_) = nthDecl m gl in
- id
+ nthDecl m gl |> get_id
let nthHyp m gl =
mkVar (nthHypId m gl)
let onNthHypId m tac =
- Proofview.Goal.enter begin fun gl -> tac (nthHypId m gl) end
+ Proofview.Goal.enter { enter = begin fun gl -> tac (nthHypId m gl) end }
let onNthHyp m tac =
- Proofview.Goal.enter begin fun gl -> tac (nthHyp m gl) end
+ Proofview.Goal.enter { enter = begin fun gl -> tac (nthHyp m gl) end }
let onLastHypId = onNthHypId 1
let onLastHyp = onNthHyp 1
let onNthDecl m tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
Proofview.tclUNIT (nthDecl m gl) >>= tac
- end
+ end }
let onLastDecl = onNthDecl 1
let ifOnHyp pred tac1 tac2 id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let typ = Tacmach.New.pf_get_hyp_typ id gl in
if pred (id,typ) then
tac1 id
else
tac2 id
- end
+ end }
- let onHyps find tac = Proofview.Goal.nf_enter (fun gl -> tac (find gl))
+ let onHyps find tac = Proofview.Goal.nf_enter { enter = begin fun gl -> tac (find.enter gl) end }
let afterHyp id tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let hyps = Proofview.Goal.hyps gl in
- let rem, _ = List.split_when (fun (hyp,_,_) -> Id.equal hyp id) hyps in
+ let rem, _ = List.split_when (Id.equal id % get_id) hyps in
tac rem
- end
+ end }
let fullGoal gl =
let hyps = Tacmach.New.pf_ids_of_hyps gl in
None :: List.map Option.make hyps
let tryAllHyps tac =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let hyps = Tacmach.New.pf_ids_of_hyps gl in
tclFIRST_PROGRESS_ON tac hyps
- end
+ end }
let tryAllHypsAndConcl tac =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
tclFIRST_PROGRESS_ON tac (fullGoal gl)
- end
+ end }
let onClause tac cl =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let hyps = Tacmach.New.pf_ids_of_hyps gl in
tclMAP tac (Locusops.simple_clause_of (fun () -> hyps) cl)
- end
+ end }
(* Find the right elimination suffix corresponding to the sort of the goal *)
(* c should be of type A1->.. An->B with B an inductive definition *)
let general_elim_then_using mk_elim
isrec allnames tac predicate ind (c, t) =
- Proofview.Goal.nf_enter
- begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let sigma, elim = Tacmach.New.of_old (mk_elim ind) gl in
Proofview.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
- (Proofview.Goal.nf_enter begin fun gl ->
+ (Proofview.Goal.nf_enter { enter = begin fun gl ->
let indclause = Tacmach.New.of_old (fun gl -> mk_clenv_from gl (c, t)) gl in
(* applying elimination_scheme just a little modified *)
let elimclause = Tacmach.New.of_old (fun gls -> mk_clenv_from gls (elim,Tacmach.New.pf_unsafe_type_of gl elim)) gl in
@@ -621,8 +640,8 @@ module New = struct
(str "The elimination combinator " ++ str name_elim ++ str " is unknown.")
in
let elimclause' = clenv_fchain ~with_univs:false indmv elimclause indclause in
- let branchsigns = compute_construtor_signatures isrec ind in
- let brnames = compute_induction_names (Array.length branchsigns) allnames in
+ let branchsigns = compute_constructor_signatures isrec ind in
+ let brnames = compute_induction_names_gen false branchsigns allnames in
let flags = Unification.elim_flags () in
let elimclause' =
match predicate with
@@ -634,10 +653,7 @@ module New = struct
let (hd,largs) = decompose_app clenv'.templtyp.Evd.rebus in
let ba = { branchsign = branchsigns.(i);
branchnames = brnames.(i);
- nassums =
- List.fold_left
- (fun acc b -> if b then acc+2 else acc+1)
- 0 branchsigns.(i);
+ nassums = List.length branchsigns.(i);
branchnum = i+1;
ity = ind;
largs = List.map (clenv_nf_meta clenv') largs;
@@ -649,10 +665,10 @@ module New = struct
Proofview.tclTHEN
(Clenvtac.clenv_refine false clenv')
(Proofview.tclEXTEND [] tclIDTAC branchtacs)
- end) end
+ end }) end }
let elimination_then tac c =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let (ind,t) = pf_reduce_to_quantified_ind gl (pf_unsafe_type_of gl c) in
let isrec,mkelim =
match (Global.lookup_mind (fst (fst ind))).mind_record with
@@ -660,7 +676,7 @@ module New = struct
| Some _ -> false,gl_make_case_dep
in
general_elim_then_using mkelim isrec None tac None ind (c, t)
- end
+ end }
let case_then_using =
general_elim_then_using gl_make_case_dep false
@@ -669,16 +685,16 @@ module New = struct
general_elim_then_using gl_make_case_nodep false
let elim_on_ba tac ba =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let branches = Tacmach.New.of_old (make_elim_branch_assumptions ba) gl in
tac branches
- end
+ end }
let case_on_ba tac ba =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let branches = Tacmach.New.of_old (make_case_branch_assumptions ba) gl in
tac branches
- end
+ end }
let elimination_sort_of_goal gl =
(** Retyping will expand evars anyway. *)
@@ -695,11 +711,11 @@ module New = struct
| Some id -> elimination_sort_of_hyp id gl
let pf_constr_of_global ref tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let (sigma, c) = Evd.fresh_global env sigma ref in
Proofview.Unsafe.tclEVARS sigma <*> (tac c)
- end
+ end }
end
diff --git a/tactics/tacticals.mli b/tactics/tacticals.mli
index 1b3b04d9fe..0f926468b9 100644
--- a/tactics/tacticals.mli
+++ b/tactics/tacticals.mli
@@ -9,7 +9,6 @@
open Pp
open Names
open Term
-open Context
open Tacmach
open Proof_type
open Tacexpr
@@ -60,29 +59,29 @@ val tclIFTHENTRYELSEMUST : tactic -> tactic -> tactic
val onNthHypId : int -> (Id.t -> tactic) -> tactic
val onNthHyp : int -> (constr -> tactic) -> tactic
-val onNthDecl : int -> (named_declaration -> tactic) -> tactic
+val onNthDecl : int -> (Context.Named.Declaration.t -> tactic) -> tactic
val onLastHypId : (Id.t -> tactic) -> tactic
val onLastHyp : (constr -> tactic) -> tactic
-val onLastDecl : (named_declaration -> tactic) -> tactic
+val onLastDecl : (Context.Named.Declaration.t -> tactic) -> tactic
val onNLastHypsId : int -> (Id.t list -> tactic) -> tactic
val onNLastHyps : int -> (constr list -> tactic) -> tactic
-val onNLastDecls : int -> (named_context -> tactic) -> tactic
+val onNLastDecls : int -> (Context.Named.t -> tactic) -> tactic
val lastHypId : goal sigma -> Id.t
val lastHyp : goal sigma -> constr
-val lastDecl : goal sigma -> named_declaration
+val lastDecl : goal sigma -> Context.Named.Declaration.t
val nLastHypsId : int -> goal sigma -> Id.t list
val nLastHyps : int -> goal sigma -> constr list
-val nLastDecls : int -> goal sigma -> named_context
+val nLastDecls : int -> goal sigma -> Context.Named.t
-val afterHyp : Id.t -> goal sigma -> named_context
+val afterHyp : Id.t -> goal sigma -> Context.Named.t
val ifOnHyp : (Id.t * types -> bool) ->
(Id.t -> tactic) -> (Id.t -> tactic) ->
Id.t -> tactic
-val onHyps : (goal sigma -> named_context) ->
- (named_context -> tactic) -> tactic
+val onHyps : (goal sigma -> Context.Named.t) ->
+ (Context.Named.t -> tactic) -> tactic
(** {6 Tacticals applying to goal components } *)
@@ -99,32 +98,36 @@ val onClauseLR : (Id.t option -> tactic) -> clause -> tactic
(** {6 Elimination tacticals. } *)
type branch_args = {
- ity : pinductive; (** the type we were eliminating on *)
+ ity : pinductive; (** the type we were eliminating on *)
largs : constr list; (** its arguments *)
branchnum : int; (** the branch number *)
pred : constr; (** the predicate we used *)
- nassums : int; (** the number of assumptions to be introduced *)
+ nassums : int; (** number of assumptions/letin to be introduced *)
branchsign : bool list; (** the signature of the branch.
- true=recursive argument, false=constant *)
+ true=assumption, false=let-in *)
branchnames : intro_patterns}
type branch_assumptions = {
- ba : branch_args; (** the branch args *)
- assums : named_context} (** the list of assumptions introduced *)
+ ba : branch_args; (** the branch args *)
+ assums : Context.Named.t} (** the list of assumptions introduced *)
-(** [check_disjunctive_pattern_size loc pats n] returns an appropriate
- error message if |pats| <> n *)
-val check_or_and_pattern_size :
- Loc.t -> delayed_open_constr or_and_intro_pattern_expr -> int -> unit
+(** [get_and_check_or_and_pattern loc pats branchsign] returns an appropriate
+ error message if |pats| <> |branchsign|; extends them if no pattern is given
+ for let-ins in the case of a conjunctive pattern *)
+val get_and_check_or_and_pattern :
+ Loc.t -> delayed_open_constr or_and_intro_pattern_expr ->
+ bool list array -> intro_patterns array
(** Tolerate "[]" to mean a disjunctive pattern of any length *)
val fix_empty_or_and_pattern : int ->
delayed_open_constr or_and_intro_pattern_expr ->
delayed_open_constr or_and_intro_pattern_expr
+val compute_constructor_signatures : rec_flag -> pinductive -> bool list array
+
(** Useful for [as intro_pattern] modifier *)
val compute_induction_names :
- int -> or_and_intro_pattern option -> intro_patterns array
+ bool list array -> or_and_intro_pattern option -> intro_patterns array
val elimination_sort_of_goal : goal sigma -> sorts_family
val elimination_sort_of_hyp : Id.t -> goal sigma -> sorts_family
@@ -144,7 +147,7 @@ val case_on_ba : (branch_assumptions -> tactic) -> branch_args -> tactic
semantics as the similarly named tacticals in [Proofview]. The
tactical of [Proofview] are used in the definition of the
tacticals of [Tacticals.New], but they are more atomic. In
- particular [Tacticals.New.tclORELSE] sees like of progress as a
+ particular [Tacticals.New.tclORELSE] sees lack of progress as a
failure, whereas [Proofview.tclORELSE] doesn't. Additionally every
tactic which can catch failure ([tclOR], [tclORELSE], [tclTRY],
[tclREPEAt], etc…) are run into each goal independently (failures
@@ -219,11 +222,12 @@ module New : sig
val tclSOLVE : unit tactic list -> unit tactic
val tclPROGRESS : unit tactic -> unit tactic
val tclWITHHOLES : bool -> 'a tactic -> Evd.evar_map -> 'a tactic
+ val tclDELAYEDWITHHOLES : bool -> 'a delayed_open -> ('a -> unit tactic) -> unit tactic
val tclTIMEOUT : int -> unit tactic -> unit tactic
val tclTIME : string option -> 'a tactic -> 'a tactic
- val nLastDecls : [ `NF ] Proofview.Goal.t -> int -> named_context
+ val nLastDecls : ([ `NF ], 'r) Proofview.Goal.t -> int -> Context.Named.t
val ifOnHyp : (identifier * types -> bool) ->
(identifier -> unit Proofview.tactic) -> (identifier -> unit Proofview.tactic) ->
@@ -232,19 +236,19 @@ module New : sig
val onNthHypId : int -> (identifier -> unit tactic) -> unit tactic
val onLastHypId : (identifier -> unit tactic) -> unit tactic
val onLastHyp : (constr -> unit tactic) -> unit tactic
- val onLastDecl : (named_declaration -> unit tactic) -> unit tactic
+ val onLastDecl : (Context.Named.Declaration.t -> unit tactic) -> unit tactic
- val onHyps : ([ `NF ] Proofview.Goal.t -> named_context) ->
- (named_context -> unit tactic) -> unit tactic
- val afterHyp : Id.t -> (named_context -> unit tactic) -> unit tactic
+ val onHyps : ([ `NF ], Context.Named.t) Proofview.Goal.enter ->
+ (Context.Named.t -> unit tactic) -> unit tactic
+ val afterHyp : Id.t -> (Context.Named.t -> unit tactic) -> unit tactic
val tryAllHyps : (identifier -> unit tactic) -> unit tactic
val tryAllHypsAndConcl : (identifier option -> unit tactic) -> unit tactic
val onClause : (identifier option -> unit tactic) -> clause -> unit tactic
- val elimination_sort_of_goal : 'a Proofview.Goal.t -> sorts_family
- val elimination_sort_of_hyp : Id.t -> 'a Proofview.Goal.t -> sorts_family
- val elimination_sort_of_clause : Id.t option -> 'a Proofview.Goal.t -> sorts_family
+ val elimination_sort_of_goal : ('a, 'r) Proofview.Goal.t -> sorts_family
+ val elimination_sort_of_hyp : Id.t -> ('a, 'r) Proofview.Goal.t -> sorts_family
+ val elimination_sort_of_clause : Id.t option -> ('a, 'r) Proofview.Goal.t -> sorts_family
val elimination_then :
(branch_args -> unit Proofview.tactic) ->
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index f23808f6f9..f725a06549 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -13,7 +13,6 @@ open Names
open Nameops
open Term
open Vars
-open Context
open Termops
open Find_subterm
open Namegen
@@ -26,7 +25,7 @@ open Evd
open Pfedit
open Tacred
open Genredexpr
-open Tacmach
+open Tacmach.New
open Logic
open Clenv
open Refiner
@@ -43,21 +42,13 @@ open Locus
open Locusops
open Misctypes
open Proofview.Notations
-
-let nb_prod x =
- let rec count n c =
- match kind_of_term c with
- Prod(_,_,t) -> count (n+1) t
- | LetIn(_,a,_,t) -> count n (subst1 a t)
- | Cast(c,_,_) -> count n c
- | _ -> n
- in count 0 x
+open Sigma.Notations
let inj_with_occurrences e = (AllOccurrences,e)
let dloc = Loc.ghost
-let typ_of = Retyping.get_type_of
+let typ_of env sigma c = Retyping.get_type_of env (Sigma.to_evar_map sigma) c
open Goptions
@@ -126,13 +117,26 @@ let _ =
optread = (fun () -> !universal_lemma_under_conjunctions) ;
optwrite = (fun b -> universal_lemma_under_conjunctions := b) }
+(* Shrinking of abstract proofs. *)
+
+let shrink_abstract = ref false
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "shrinking of abstracted proofs";
+ optkey = ["Shrink"; "Abstract"];
+ optread = (fun () -> !shrink_abstract) ;
+ optwrite = (fun b -> shrink_abstract := b) }
+
(* The following boolean governs what "intros []" do on examples such
as "forall x:nat*nat, x=x"; if true, it behaves as "intros [? ?]";
if false, it behaves as "intro H; case H; clear H" for fresh H.
Kept as false for compatibility.
*)
-let bracketing_last_or_and_intro_pattern = ref false
+let bracketing_last_or_and_intro_pattern = ref true
let use_bracketing_last_or_and_intro_pattern () =
!bracketing_last_or_and_intro_pattern
@@ -144,7 +148,7 @@ let _ =
optdepr = false;
optname = "bracketing last or-and introduction pattern";
optkey = ["Bracketing";"Last";"Introduction";"Pattern"];
- optread = (fun () -> !bracketing_last_or_and_intro_pattern) ;
+ optread = (fun () -> !bracketing_last_or_and_intro_pattern);
optwrite = (fun b -> bracketing_last_or_and_intro_pattern := b) }
(*********************************************)
@@ -157,22 +161,24 @@ let _ =
(** This tactic creates a partial proof realizing the introduction rule, but
does not check anything. *)
-let unsafe_intro env store (id, c, t) b =
- Proofview.Refine.refine ~unsafe:true begin fun sigma ->
+let unsafe_intro env store decl b =
+ let open Context.Named.Declaration in
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
let ctx = named_context_val env in
- let nctx = push_named_context_val (id, c, t) ctx in
- let inst = List.map (fun (id, _, _) -> mkVar id) (named_context env) in
+ let nctx = push_named_context_val decl ctx in
+ let inst = List.map (mkVar % get_id) (named_context env) in
let ninst = mkRel 1 :: inst in
- let nb = subst1 (mkVar id) b in
- let sigma, ev = new_evar_instance nctx sigma nb ~principal:true ~store ninst in
- sigma, mkNamedLambda_or_LetIn (id, c, t) ev
- end
+ let nb = subst1 (mkVar (get_id decl)) b in
+ let Sigma (ev, sigma, p) = new_evar_instance nctx sigma nb ~principal:true ~store ninst in
+ Sigma (mkNamedLambda_or_LetIn decl ev, sigma, p)
+ end }
let introduction ?(check=true) id =
- Proofview.Goal.enter begin fun gl ->
+ let open Context.Named.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
let gl = Proofview.Goal.assume gl in
let concl = Proofview.Goal.concl gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let hyps = Proofview.Goal.hyps gl in
let store = Proofview.Goal.extra gl in
let env = Proofview.Goal.env gl in
@@ -181,47 +187,51 @@ let introduction ?(check=true) id =
(str "Variable " ++ pr_id id ++ str " is already declared.")
in
match kind_of_term (whd_evar sigma concl) with
- | Prod (_, t, b) -> unsafe_intro env store (id, None, t) b
- | LetIn (_, c, t, b) -> unsafe_intro env store (id, Some c, t) b
+ | Prod (_, t, b) -> unsafe_intro env store (LocalAssum (id, t)) b
+ | LetIn (_, c, t, b) -> unsafe_intro env store (LocalDef (id, c, t)) b
| _ -> raise (RefinerError IntroNeedsProduct)
- end
+ end }
let refine = Tacmach.refine
let convert_concl ?(check=true) ty k =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let store = Proofview.Goal.extra gl in
let conclty = Proofview.Goal.raw_concl gl in
- Proofview.Refine.refine ~unsafe:true begin fun sigma ->
- let sigma =
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
+ let Sigma ((), sigma, p) =
if check then begin
+ let sigma = Sigma.to_evar_map sigma in
ignore (Typing.unsafe_type_of env sigma ty);
let sigma,b = Reductionops.infer_conv env sigma ty conclty in
if not b then error "Not convertible.";
- sigma
- end else sigma in
- let (sigma,x) = Evarutil.new_evar env sigma ~principal:true ~store ty in
- (sigma, if k == DEFAULTcast then x else mkCast(x,k,conclty))
- end
- end
+ Sigma.Unsafe.of_pair ((), sigma)
+ end else Sigma.here () sigma in
+ let Sigma (x, sigma, q) = Evarutil.new_evar env sigma ~principal:true ~store ty in
+ let ans = if k == DEFAULTcast then x else mkCast(x,k,conclty) in
+ Sigma (ans, sigma, p +> q)
+ end }
+ end }
let convert_hyp ?(check=true) d =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let ty = Proofview.Goal.raw_concl gl in
let store = Proofview.Goal.extra gl in
let sign = convert_hyp check (named_context_val env) sigma d in
let env = reset_with_named_context sign env in
- Proofview.Refine.refine ~unsafe:true (fun sigma -> Evarutil.new_evar env sigma ~principal:true ~store ty)
- end
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
+ Evarutil.new_evar env sigma ~principal:true ~store ty
+ end }
+ end }
let convert_concl_no_check = convert_concl ~check:false
let convert_hyp_no_check = convert_hyp ~check:false
let convert_gen pb x y =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
try
let sigma, b = Tacmach.New.pf_apply (Reductionops.infer_conv ~pb) gl x y in
if b then Proofview.Unsafe.tclEVARS sigma
@@ -229,7 +239,7 @@ let convert_gen pb x y =
with (* Reduction.NotConvertible *) _ ->
(** FIXME: Sometimes an anomaly is raised from conversion *)
Tacticals.New.tclFAIL 0 (str "Not convertible")
-end
+end }
let convert x y = convert_gen Reduction.CONV x y
let convert_leq x y = convert_gen Reduction.CUMUL x y
@@ -262,7 +272,7 @@ let error_replacing_dependency env sigma id err =
errorlabstrm "" (replacing_dependency_msg env sigma id err)
let thin l gl =
- try thin l gl
+ try Tacmach.thin l gl
with Evarutil.ClearDependencyError (id,err) ->
error_clear_dependency (pf_env gl) (project gl) id err
@@ -287,6 +297,7 @@ let move_hyp id dest gl = Tacmach.move_hyp id dest gl
(* Renaming hypotheses *)
let rename_hyp repl =
+ let open Context.Named.Declaration in
let fold accu (src, dst) = match accu with
| None -> None
| Some (srcs, dsts) ->
@@ -302,13 +313,13 @@ let rename_hyp repl =
match dom with
| None -> Tacticals.New.tclZEROMSG (str "Not a one-to-one name mapping")
| Some (src, dst) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let gl = Proofview.Goal.assume gl in
let hyps = Proofview.Goal.hyps gl in
let concl = Proofview.Goal.concl gl in
let store = Proofview.Goal.extra gl in
(** Check that we do not mess variables *)
- let fold accu (id, _, _) = Id.Set.add id accu in
+ let fold accu decl = Id.Set.add (get_id decl) accu in
let vars = List.fold_left fold Id.Set.empty hyps in
let () =
if not (Id.Set.subset src vars) then
@@ -326,18 +337,18 @@ let rename_hyp repl =
let make_subst (src, dst) = (src, mkVar dst) in
let subst = List.map make_subst repl in
let subst c = Vars.replace_vars subst c in
- let map (id, body, t) =
- let id = try List.assoc_f Id.equal id repl with Not_found -> id in
- (id, Option.map subst body, subst t)
+ let map decl =
+ decl |> map_id (fun id -> try List.assoc_f Id.equal id repl with Not_found -> id)
+ |> map_constr subst
in
let nhyps = List.map map hyps in
let nconcl = subst concl in
let nctx = Environ.val_of_named_context nhyps in
- let instance = List.map (fun (id, _, _) -> mkVar id) hyps in
- Proofview.Refine.refine ~unsafe:true begin fun sigma ->
+ let instance = List.map (mkVar % get_id) hyps in
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
Evarutil.new_evar_instance nctx sigma nconcl ~store instance
- end
- end
+ end }
+ end }
(**************************************************************)
(* Fresh names *)
@@ -359,11 +370,13 @@ let id_of_name_with_default id = function
let default_id_of_sort s =
if Sorts.is_small s then default_small_ident else default_type_ident
-let default_id env sigma = function
- | (name,None,t) ->
+let default_id env sigma decl =
+ let open Context.Rel.Declaration in
+ match decl with
+ | LocalAssum (name,t) ->
let dft = default_id_of_sort (Retyping.get_sort_of env sigma t) in
id_of_name_with_default dft name
- | (name,Some b,_) -> id_of_name_using_hdchar env b name
+ | LocalDef (name,b,_) -> id_of_name_using_hdchar env b name
(* Non primitive introduction tactics are treated by intro_then_gen
There is possibly renaming, with possibly names to avoid and
@@ -382,7 +395,7 @@ let find_name mayrepl decl naming gl = match naming with
| NamingAvoid idl ->
(* this case must be compatible with [find_intro_names] below. *)
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
new_fresh_id idl (default_id env sigma decl) gl
| NamingBasedOn (id,idl) -> new_fresh_id idl id gl
| NamingMustBe (loc,id) ->
@@ -398,16 +411,17 @@ let find_name mayrepl decl naming gl = match naming with
(**************************************************************)
let assert_before_then_gen b naming t tac =
- Proofview.Goal.enter begin fun gl ->
- let id = find_name b (Anonymous,None,t) naming gl in
+ let open Context.Rel.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let id = find_name b (LocalAssum (Anonymous,t)) naming gl in
Tacticals.New.tclTHENLAST
(Proofview.V82.tactic
(fun gl ->
- try internal_cut b id t gl
+ try Tacmach.internal_cut b id t gl
with Evarutil.ClearDependencyError (id,err) ->
error_replacing_dependency (pf_env gl) (project gl) id err))
(tac id)
- end
+ end }
let assert_before_gen b naming t =
assert_before_then_gen b naming t (fun _ -> Proofview.tclUNIT ())
@@ -416,16 +430,17 @@ let assert_before na = assert_before_gen false (naming_of_name na)
let assert_before_replacing id = assert_before_gen true (NamingMustBe (dloc,id))
let assert_after_then_gen b naming t tac =
- Proofview.Goal.enter begin fun gl ->
- let id = find_name b (Anonymous,None,t) naming gl in
+ let open Context.Rel.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let id = find_name b (LocalAssum (Anonymous,t)) naming gl in
Tacticals.New.tclTHENFIRST
(Proofview.V82.tactic
(fun gl ->
- try internal_cut_rev b id t gl
+ try Tacmach.internal_cut_rev b id t gl
with Evarutil.ClearDependencyError (id,err) ->
error_replacing_dependency (pf_env gl) (project gl) id err))
(tac id)
- end
+ end }
let assert_after_gen b naming t =
assert_after_then_gen b naming t (fun _ -> (Proofview.tclUNIT ()))
@@ -461,17 +476,18 @@ let cofix ido gl = match ido with
type tactic_reduction = env -> evar_map -> constr -> constr
-let pf_reduce_decl redfun where (id,c,ty) gl =
- let redfun' = pf_reduce redfun gl in
- match c with
- | None ->
+let pf_reduce_decl redfun where decl gl =
+ let open Context.Named.Declaration in
+ let redfun' = Tacmach.New.pf_apply redfun gl in
+ match decl with
+ | LocalAssum (id,ty) ->
if where == InHypValueOnly then
errorlabstrm "" (pr_id id ++ str " has no value.");
- (id,None,redfun' ty)
- | Some b ->
+ LocalAssum (id,redfun' ty)
+ | LocalDef (id,b,ty) ->
let b' = if where != InHypTypeOnly then redfun' b else b in
let ty' = if where != InHypValueOnly then redfun' ty else ty in
- (id,Some b',ty')
+ LocalDef (id,b',ty')
(* Possibly equip a reduction with the occurrences mentioned in an
occurrence clause *)
@@ -541,12 +557,15 @@ let bind_red_expr_occurrences occs nbcl redexp =
reduction function either to the conclusion or to a
certain hypothesis *)
-let reduct_in_concl (redfun,sty) gl =
- Proofview.V82.of_tactic (convert_concl_no_check (pf_reduce redfun gl (pf_concl gl)) sty) gl
+let reduct_in_concl (redfun,sty) =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ convert_concl_no_check (Tacmach.New.pf_apply redfun gl (Tacmach.New.pf_concl gl)) sty
+ end }
-let reduct_in_hyp ?(check=false) redfun (id,where) gl =
- Proofview.V82.of_tactic (convert_hyp ~check
- (pf_reduce_decl redfun where (pf_get_hyp gl id) gl)) gl
+let reduct_in_hyp ?(check=false) redfun (id,where) =
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ convert_hyp ~check (pf_reduce_decl redfun where (Tacmach.New.pf_get_hyp id gl) gl)
+ end }
let revert_cast (redfun,kind as r) =
if kind == DEFAULTcast then (redfun,REVERTcast) else r
@@ -557,31 +576,33 @@ let reduct_option ?(check=false) redfun = function
(** Tactic reduction modulo evars (for universes essentially) *)
-let pf_e_reduce_decl redfun where (id,c,ty) gl =
- let sigma = project gl in
- let redfun = redfun (pf_env gl) in
- match c with
- | None ->
+let pf_e_reduce_decl redfun where decl gl =
+ let open Context.Named.Declaration in
+ let sigma = Proofview.Goal.sigma gl in
+ let redfun sigma c = redfun.e_redfun (Tacmach.New.pf_env gl) sigma c in
+ match decl with
+ | LocalAssum (id,ty) ->
if where == InHypValueOnly then
errorlabstrm "" (pr_id id ++ str " has no value.");
- let sigma, ty' = redfun sigma ty in
- sigma, (id,None,ty')
- | Some b ->
- let sigma, b' = if where != InHypTypeOnly then redfun sigma b else sigma, b in
- let sigma, ty' = if where != InHypValueOnly then redfun sigma ty else sigma, ty in
- sigma, (id,Some b',ty')
-
-let e_reduct_in_concl (redfun,sty) gl =
- Proofview.V82.of_tactic
- (let sigma, c' = (pf_apply redfun gl (pf_concl gl)) in
- Proofview.Unsafe.tclEVARS sigma <*>
- convert_concl_no_check c' sty) gl
-
-let e_reduct_in_hyp ?(check=false) redfun (id,where) gl =
- Proofview.V82.of_tactic
- (let sigma, decl' = pf_e_reduce_decl redfun where (pf_get_hyp gl id) gl in
- Proofview.Unsafe.tclEVARS sigma <*>
- convert_hyp ~check decl') gl
+ let Sigma (ty', sigma, p) = redfun sigma ty in
+ Sigma (LocalAssum (id, ty'), sigma, p)
+ | LocalDef (id,b,ty) ->
+ let Sigma (b', sigma, p) = if where != InHypTypeOnly then redfun sigma b else Sigma.here b sigma in
+ let Sigma (ty', sigma, q) = if where != InHypValueOnly then redfun sigma ty else Sigma.here ty sigma in
+ Sigma (LocalDef (id, b', ty'), sigma, p +> q)
+
+let e_reduct_in_concl (redfun, sty) =
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let Sigma (c', sigma, p) = redfun.e_redfun (Tacmach.New.pf_env gl) sigma (Tacmach.New.pf_concl gl) in
+ Sigma (convert_concl_no_check c' sty, sigma, p)
+ end }
+
+let e_reduct_in_hyp ?(check=false) redfun (id, where) =
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let Sigma (decl', sigma, p) = pf_e_reduce_decl redfun where (Tacmach.New.pf_get_hyp id gl) gl in
+ Sigma (convert_hyp ~check decl', sigma, p)
+ end }
let e_reduct_option ?(check=false) redfun = function
| Some id -> e_reduct_in_hyp ~check (fst redfun) id
@@ -590,45 +611,42 @@ let e_reduct_option ?(check=false) redfun = function
(** Versions with evars to maintain the unification of universes resulting
from conversions. *)
-let tclWITHEVARS f k =
- Proofview.Goal.enter begin fun gl ->
- let evm, c' = f gl in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS evm) (k c')
- end
-
let e_change_in_concl (redfun,sty) =
- tclWITHEVARS
- (fun gl -> redfun (Proofview.Goal.env gl) (Proofview.Goal.sigma gl)
- (Proofview.Goal.raw_concl gl))
- (fun c -> convert_concl_no_check c sty)
-
-let e_pf_change_decl (redfun : bool -> e_reduction_function) where (id,c,ty) env sigma =
- match c with
- | None ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let Sigma (c, sigma, p) = redfun.e_redfun (Proofview.Goal.env gl) sigma (Proofview.Goal.raw_concl gl) in
+ Sigma (convert_concl_no_check c sty, sigma, p)
+ end }
+
+let e_pf_change_decl (redfun : bool -> e_reduction_function) where decl env sigma =
+ let open Context.Named.Declaration in
+ match decl with
+ | LocalAssum (id,ty) ->
if where == InHypValueOnly then
errorlabstrm "" (pr_id id ++ str " has no value.");
- let sigma',ty' = redfun false env sigma ty in
- sigma', (id,None,ty')
- | Some b ->
- let sigma',b' =
- if where != InHypTypeOnly then redfun true env sigma b else sigma, b
+ let Sigma (ty', sigma, p) = (redfun false).e_redfun env sigma ty in
+ Sigma (LocalAssum (id, ty'), sigma, p)
+ | LocalDef (id,b,ty) ->
+ let Sigma (b', sigma, p) =
+ if where != InHypTypeOnly then (redfun true).e_redfun env sigma b else Sigma.here b sigma
in
- let sigma',ty' =
- if where != InHypValueOnly then redfun false env sigma' ty else sigma', ty
+ let Sigma (ty', sigma, q) =
+ if where != InHypValueOnly then (redfun false).e_redfun env sigma ty else Sigma.here ty sigma
in
- sigma', (id,Some b',ty')
+ Sigma (LocalDef (id,b',ty'), sigma, p +> q)
let e_change_in_hyp redfun (id,where) =
- tclWITHEVARS
- (fun gl -> e_pf_change_decl redfun where
- (Tacmach.New.pf_get_hyp id (Proofview.Goal.assume gl))
- (Proofview.Goal.env gl) (Proofview.Goal.sigma gl))
- convert_hyp
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let hyp = Tacmach.New.pf_get_hyp id (Proofview.Goal.assume gl) in
+ let Sigma (c, sigma, p) = e_pf_change_decl redfun where hyp (Proofview.Goal.env gl) sigma in
+ Sigma (convert_hyp c, sigma, p)
+ end }
-type change_arg = Pattern.patvar_map -> evar_map -> evar_map * constr
+type change_arg = Pattern.patvar_map -> constr Sigma.run
-let make_change_arg c =
- fun pats sigma -> (sigma, replace_vars (Id.Map.bindings pats) c)
+let make_change_arg c pats =
+ { run = fun sigma -> Sigma.here (replace_vars (Id.Map.bindings pats) c) sigma }
let check_types env sigma mayneedglobalcheck deep newc origc =
let t1 = Retyping.get_type_of env sigma newc in
@@ -652,30 +670,33 @@ let check_types env sigma mayneedglobalcheck deep newc origc =
else sigma
(* Now we introduce different instances of the previous tacticals *)
-let change_and_check cv_pb mayneedglobalcheck deep t env sigma c =
- let sigma, t' = t sigma in
+let change_and_check cv_pb mayneedglobalcheck deep t = { e_redfun = begin fun env sigma c ->
+ let Sigma (t', sigma, p) = t.run sigma in
+ let sigma = Sigma.to_evar_map sigma in
let sigma = check_types env sigma mayneedglobalcheck deep t' c in
let sigma, b = infer_conv ~pb:cv_pb env sigma t' c in
if not b then errorlabstrm "convert-check-hyp" (str "Not convertible.");
- sigma, t'
+ Sigma.Unsafe.of_pair (t', sigma)
+end }
(* Use cumulativity only if changing the conclusion not a subterm *)
-let change_on_subterm cv_pb deep t where env sigma c =
+let change_on_subterm cv_pb deep t where = { e_redfun = begin fun env sigma c ->
let mayneedglobalcheck = ref false in
- let sigma,c = match where with
- | None -> change_and_check cv_pb mayneedglobalcheck deep (t Id.Map.empty) env sigma c
+ let Sigma (c, sigma, p) = match where with
+ | None -> (change_and_check cv_pb mayneedglobalcheck deep (t Id.Map.empty)).e_redfun env sigma c
| Some occl ->
- e_contextually false occl
+ (e_contextually false occl
(fun subst ->
- change_and_check Reduction.CONV mayneedglobalcheck true (t subst))
+ change_and_check Reduction.CONV mayneedglobalcheck true (t subst))).e_redfun
env sigma c in
if !mayneedglobalcheck then
begin
- try ignore (Typing.unsafe_type_of env sigma c)
+ try ignore (Typing.unsafe_type_of env (Sigma.to_evar_map sigma) c)
with e when catchable_exception e ->
error "Replacement would lead to an ill-typed term."
end;
- sigma,c
+ Sigma (c, sigma, p)
+end }
let change_in_concl occl t =
e_change_in_concl ((change_on_subterm Reduction.CUMUL false t occl),DEFAULTcast)
@@ -688,7 +709,7 @@ let change_option occl t = function
| None -> change_in_concl occl t
let change chg c cls gl =
- let cls = concrete_clause_of (fun () -> pf_ids_of_hyps gl) cls in
+ let cls = concrete_clause_of (fun () -> Tacmach.pf_ids_of_hyps gl) cls in
Proofview.V82.of_tactic (Tacticals.New.tclMAP (function
| OnHyp (id,occs,where) ->
change_option (bind_change_occurrences occs chg) c (Some (id,where))
@@ -728,14 +749,16 @@ let reduction_clause redexp cl =
| OnConcl occs ->
(None, bind_red_expr_occurrences occs nbcl redexp)) cl
-let reduce redexp cl goal =
- let cl = concrete_clause_of (fun () -> pf_ids_of_hyps goal) cl in
+let reduce redexp cl =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let cl = concrete_clause_of (fun () -> Tacmach.New.pf_ids_of_hyps gl) cl in
let redexps = reduction_clause redexp cl in
let check = match redexp with Fold _ | Pattern _ -> true | _ -> false in
- let tac = tclMAP (fun (where,redexp) ->
+ let tac = Tacticals.New.tclMAP (fun (where,redexp) ->
e_reduct_option ~check
- (Redexpr.reduction_of_red_expr (pf_env goal) redexp) where) redexps in
- if check then with_check tac goal else tac goal
+ (Redexpr.reduction_of_red_expr (Tacmach.New.pf_env gl) redexp) where) redexps in
+ if check then Proofview.V82.tactic (fun gl -> with_check (Proofview.V82.of_tactic tac) gl) else tac (** FIXME *)
+ end }
(* Unfolding occurrences of a constant *)
@@ -756,10 +779,9 @@ let unfold_constr = function
let find_intro_names ctxt gl =
let _, res = List.fold_right
(fun decl acc ->
- let wantedname,x,typdecl = decl in
let env,idl = acc in
let name = fresh_id idl (default_id env gl.sigma decl) gl in
- let newenv = push_rel (wantedname,x,typdecl) env in
+ let newenv = push_rel decl env in
(newenv,(name::idl)))
ctxt (pf_env gl , []) in
List.rev res
@@ -771,15 +793,16 @@ let build_intro_tac id dest tac = match dest with
Proofview.V82.tactic (move_hyp id dest); tac id]
let rec intro_then_gen name_flag move_flag force_flag dep_flag tac =
- Proofview.Goal.enter begin fun gl ->
+ let open Context.Rel.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl (Proofview.Goal.assume gl) in
- let concl = nf_evar (Proofview.Goal.sigma gl) concl in
+ let concl = nf_evar (Tacmach.New.project gl) concl in
match kind_of_term concl with
| Prod (name,t,u) when not dep_flag || (dependent (mkRel 1) u) ->
- let name = find_name false (name,None,t) name_flag gl in
+ let name = find_name false (LocalAssum (name,t)) name_flag gl in
build_intro_tac name move_flag tac
| LetIn (name,b,t,u) when not dep_flag || (dependent (mkRel 1) u) ->
- let name = find_name false (name,Some b,t) name_flag gl in
+ let name = find_name false (LocalDef (name,b,t)) name_flag gl in
build_intro_tac name move_flag tac
| _ ->
begin if not force_flag then Proofview.tclZERO (RefinerError IntroNeedsProduct)
@@ -790,14 +813,14 @@ let rec intro_then_gen name_flag move_flag force_flag dep_flag tac =
else Proofview.tclUNIT ()
end <*>
Proofview.tclORELSE
- (Tacticals.New.tclTHEN (Proofview.V82.tactic hnf_in_concl)
+ (Tacticals.New.tclTHEN hnf_in_concl
(intro_then_gen name_flag move_flag false dep_flag tac))
begin function (e, info) -> match e with
| RefinerError IntroNeedsProduct ->
Tacticals.New.tclZEROMSG (str "No product even after head-reduction.")
| e -> Proofview.tclZERO ~info e
end
- end
+ end }
let intro_gen n m f d = intro_then_gen n m f d (fun _ -> Proofview.tclUNIT ())
let intro_mustbe_force id = intro_gen (NamingMustBe (dloc,id)) MoveLast true false
@@ -842,33 +865,36 @@ let intro_forthcoming_then_gen name_flag move_flag dep_flag n bound tac =
aux n []
let get_next_hyp_position id gl =
+ let open Context.Named.Declaration in
let rec aux = function
| [] -> raise (RefinerError (NoSuchHyp id))
- | (hyp,_,_) :: right ->
- if Id.equal hyp id then
- match right with (id,_,_)::_ -> MoveBefore id | [] -> MoveLast
+ | decl :: right ->
+ if Id.equal (get_id decl) id then
+ match right with decl::_ -> MoveBefore (get_id decl) | [] -> MoveLast
else
aux right
in
aux (Proofview.Goal.hyps (Proofview.Goal.assume gl))
let get_previous_hyp_position id gl =
+ let open Context.Named.Declaration in
let rec aux dest = function
| [] -> raise (RefinerError (NoSuchHyp id))
- | (hyp,_,_) :: right ->
- if Id.equal hyp id then dest else aux (MoveAfter hyp) right
+ | decl :: right ->
+ let hyp = get_id decl in
+ if Id.equal hyp id then dest else aux (MoveAfter hyp) right
in
aux MoveLast (Proofview.Goal.hyps (Proofview.Goal.assume gl))
let intro_replacing id =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let next_hyp = get_next_hyp_position id gl in
Tacticals.New.tclTHENLIST [
Proofview.V82.tactic (thin_for_replacing [id]);
introduction id;
Proofview.V82.tactic (move_hyp id next_hyp);
]
- end
+ end }
(* We have e.g. [x, y, y', x', y'' |- forall y y' y'', G] and want to
reintroduce y, y,' y''. Note that we have to clear y, y' and y''
@@ -880,7 +906,7 @@ let intro_replacing id =
(* the behavior of inversion *)
let intros_possibly_replacing ids =
let suboptimal = true in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let posl = List.map (fun id -> (id, get_next_hyp_position id gl)) ids in
Tacticals.New.tclTHEN
(Tacticals.New.tclMAP (fun id ->
@@ -889,38 +915,38 @@ let intros_possibly_replacing ids =
(Tacticals.New.tclMAP (fun (id,pos) ->
Tacticals.New.tclORELSE (intro_move (Some id) pos) (intro_using id))
posl)
- end
+ end }
(* This version assumes that replacement is actually possible *)
let intros_replacing ids =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let posl = List.map (fun id -> (id, get_next_hyp_position id gl)) ids in
Tacticals.New.tclTHEN
(Proofview.V82.tactic (thin_for_replacing ids))
(Tacticals.New.tclMAP (fun (id,pos) -> intro_move (Some id) pos) posl)
- end
+ end }
(* User-level introduction tactics *)
-let pf_lookup_hypothesis_as_renamed env ccl = function
+let lookup_hypothesis_as_renamed env ccl = function
| AnonHyp n -> Detyping.lookup_index_as_renamed env ccl n
| NamedHyp id -> Detyping.lookup_name_as_displayed env ccl id
-let pf_lookup_hypothesis_as_renamed_gen red h gl =
- let env = pf_env gl in
+let lookup_hypothesis_as_renamed_gen red h gl =
+ let env = Proofview.Goal.env gl in
let rec aux ccl =
- match pf_lookup_hypothesis_as_renamed env ccl h with
+ match lookup_hypothesis_as_renamed env ccl h with
| None when red ->
- aux
- (snd ((fst (Redexpr.reduction_of_red_expr env (Red true)))
- env (project gl) ccl))
+ let (redfun, _) = Redexpr.reduction_of_red_expr env (Red true) in
+ let Sigma (c, _, _) = redfun.e_redfun env (Proofview.Goal.sigma gl) ccl in
+ aux c
| x -> x
in
- try aux (pf_concl gl)
+ try aux (Proofview.Goal.concl gl)
with Redelimination -> None
-let is_quantified_hypothesis id g =
- match pf_lookup_hypothesis_as_renamed_gen false (NamedHyp id) g with
+let is_quantified_hypothesis id gl =
+ match lookup_hypothesis_as_renamed_gen false (NamedHyp id) gl with
| Some _ -> true
| None -> false
@@ -932,7 +958,7 @@ let msg_quantified_hypothesis = function
str " non dependent hypothesis"
let depth_of_quantified_hypothesis red h gl =
- match pf_lookup_hypothesis_as_renamed_gen red h gl with
+ match lookup_hypothesis_as_renamed_gen red h gl with
| Some depth -> depth
| None ->
errorlabstrm "lookup_quantified_hypothesis"
@@ -942,10 +968,10 @@ let depth_of_quantified_hypothesis red h gl =
str".")
let intros_until_gen red h =
- Proofview.Goal.nf_enter begin fun gl ->
- let n = Tacmach.New.of_old (depth_of_quantified_hypothesis red h) gl in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
+ let n = depth_of_quantified_hypothesis red h gl in
Tacticals.New.tclDO n (if red then introf else intro)
- end
+ end }
let intros_until_id id = intros_until_gen false (NamedHyp id)
let intros_until_n_gen red n = intros_until_gen red (AnonHyp n)
@@ -953,7 +979,7 @@ let intros_until_n_gen red n = intros_until_gen red (AnonHyp n)
let intros_until = intros_until_gen true
let intros_until_n = intros_until_n_gen true
-let tclCHECKVAR id gl = ignore (pf_get_hyp gl id); tclIDTAC gl
+let tclCHECKVAR id gl = ignore (Tacmach.pf_get_hyp gl id); tclIDTAC gl
let try_intros_until_id_check id =
Tacticals.New.tclORELSE (intros_until_id id) (Proofview.V82.tactic (tclCHECKVAR id))
@@ -968,12 +994,15 @@ let rec intros_move = function
Tacticals.New.tclTHEN (intro_gen (NamingMustBe (dloc,hyp)) destopt false false)
(intros_move rest)
+let run_delayed env sigma c =
+ Sigma.run sigma { Sigma.run = fun sigma -> c.delayed env sigma }
+
(* Apply a tactic on a quantified hypothesis, an hypothesis in context
or a term with bindings *)
let onOpenInductionArg env sigma tac = function
| clear_flag,ElimOnConstr f ->
- let (sigma',cbl) = f env sigma in
+ let (cbl, sigma') = run_delayed env sigma f in
let pending = (sigma,sigma') in
Tacticals.New.tclTHEN
(Proofview.Unsafe.tclEVARS sigma')
@@ -983,20 +1012,20 @@ let onOpenInductionArg env sigma tac = function
(intros_until_n n)
(Tacticals.New.onLastHyp
(fun c ->
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let pending = (sigma,sigma) in
tac clear_flag (pending,(c,NoBindings))
- end))
+ end }))
| clear_flag,ElimOnIdent (_,id) ->
(* A quantified hypothesis *)
Tacticals.New.tclTHEN
(try_intros_until_id_check id)
- (Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ (Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let pending = (sigma,sigma) in
tac clear_flag (pending,(mkVar id,NoBindings))
- end)
+ end })
let onInductionArg tac = function
| clear_flag,ElimOnConstr cbl ->
@@ -1020,10 +1049,12 @@ let map_induction_arg f = function
(* tactic "cut" (actually modus ponens) *)
(****************************************)
+let normalize_cut = false
+
let cut c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let concl = Tacmach.New.pf_nf_concl gl in
let is_sort =
try
@@ -1038,16 +1069,16 @@ let cut c =
if is_sort then
let id = next_name_away_with_default "H" Anonymous (Tacmach.New.pf_ids_of_hyps gl) in
(** Backward compat: normalize [c]. *)
- let c = local_strong whd_betaiota sigma c in
- Proofview.Refine.refine ~unsafe:true begin fun h ->
- let (h, f) = Evarutil.new_evar ~principal:true env h (mkArrow c (Vars.lift 1 concl)) in
- let (h, x) = Evarutil.new_evar env h c in
- let f = mkLambda (Name id, c, mkApp (Vars.lift 1 f, [|mkRel 1|])) in
- (h, mkApp (f, [|x|]))
- end
+ let c = if normalize_cut then local_strong whd_betaiota sigma c else c in
+ Proofview.Refine.refine ~unsafe:true { run = begin fun h ->
+ let Sigma (f, h, p) = Evarutil.new_evar ~principal:true env h (mkArrow c (Vars.lift 1 concl)) in
+ let Sigma (x, h, q) = Evarutil.new_evar env h c in
+ let f = mkLetIn (Name id, x, c, mkApp (Vars.lift 1 f, [|mkRel 1|])) in
+ Sigma (f, h, p +> q)
+ end }
else
Tacticals.New.tclZEROMSG (str "Not a proposition or a type.")
- end
+ end }
let error_uninstantiated_metas t clenv =
let na = meta_name clenv.evd (List.hd (Metaset.elements (metavars_of t))) in
@@ -1091,7 +1122,7 @@ let clenv_refine_in ?(sidecond_first=false) with_evars ?(with_classes=true)
if not with_evars && occur_meta new_hyp_typ then
error_uninstantiated_metas new_hyp_typ clenv;
let new_hyp_prf = clenv_value clenv in
- let exact_tac = Proofview.V82.tactic (refine_no_check new_hyp_prf) in
+ let exact_tac = Proofview.V82.tactic (Tacmach.refine_no_check new_hyp_prf) in
let naming = NamingMustBe (dloc,targetid) in
let with_clear = do_replace (Some id) naming in
Tacticals.New.tclTHEN
@@ -1130,6 +1161,7 @@ let index_of_ind_arg t =
in aux None 0 t
let enforce_prop_bound_names rename tac =
+ let open Context.Rel.Declaration in
match rename with
| Some (isrec,nn) when Namegen.use_h_based_elimination_names () ->
(* Rename dependent arguments in Prop with name "H" *)
@@ -1149,19 +1181,19 @@ let enforce_prop_bound_names rename tac =
Name (add_suffix Namegen.default_prop_ident s)
else
na in
- mkProd (na,t,aux (push_rel (na,None,t) env) sigma (i-1) t')
+ mkProd (na,t,aux (push_rel (LocalAssum (na,t)) env) sigma (i-1) t')
| Prod (Anonymous,t,t') ->
- mkProd (Anonymous,t,aux (push_rel (Anonymous,None,t) env) sigma (i-1) t')
+ mkProd (Anonymous,t,aux (push_rel (LocalAssum (Anonymous,t)) env) sigma (i-1) t')
| LetIn (na,c,t,t') ->
- mkLetIn (na,c,t,aux (push_rel (na,Some c,t) env) sigma (i-1) t')
+ mkLetIn (na,c,t,aux (push_rel (LocalDef (na,c,t)) env) sigma (i-1) t')
| _ -> print_int i; Pp.msg (print_constr t); assert false in
let rename_branch i =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let t = Proofview.Goal.concl gl in
change_concl (aux env sigma i t)
- end in
+ end } in
(if isrec then Tacticals.New.tclTHENFIRSTn else Tacticals.New.tclTHENLASTn)
tac
(Array.map rename_branch nn)
@@ -1176,9 +1208,9 @@ let rec contract_letin_in_lam_header c =
let elimination_clause_scheme with_evars ?(with_classes=true) ?(flags=elim_flags ())
rename i (elim, elimty, bindings) indclause =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let elim = contract_letin_in_lam_header elim in
let elimclause = make_clenv_binding env sigma (elim, elimty) bindings in
let indmv =
@@ -1189,7 +1221,7 @@ let elimination_clause_scheme with_evars ?(with_classes=true) ?(flags=elim_flags
in
let elimclause' = clenv_fchain ~flags indmv elimclause indclause in
enforce_prop_bound_names rename (Clenvtac.res_pf elimclause' ~with_evars ~with_classes ~flags)
- end
+ end }
(*
* Elimination tactic with bindings and using an arbitrary
@@ -1206,20 +1238,20 @@ type eliminator = {
}
let general_elim_clause_gen elimtac indclause elim =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let (elimc,lbindelimc) = elim.elimbody in
let elimt = Retyping.get_type_of env sigma elimc in
let i =
match elim.elimindex with None -> index_of_ind_arg elimt | Some i -> i in
elimtac elim.elimrename i (elimc, elimt, lbindelimc) indclause
- end
+ end }
let general_elim with_evars clear_flag (c, lbindc) elim =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let ct = Retyping.get_type_of env sigma c in
let t = try snd (reduce_to_quantified_ind env sigma ct) with UserError _ -> ct in
let elimtac = elimination_clause_scheme with_evars in
@@ -1227,28 +1259,30 @@ let general_elim with_evars clear_flag (c, lbindc) elim =
Tacticals.New.tclTHEN
(general_elim_clause_gen elimtac indclause elim)
(apply_clear_request clear_flag (use_clear_hyp_by_default ()) c)
- end
+ end }
(* Case analysis tactics *)
let general_case_analysis_in_context with_evars clear_flag (c,lbindc) =
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
let concl = Proofview.Goal.concl gl in
- let t = Retyping.get_type_of env sigma c in
- let (mind,_) = reduce_to_quantified_ind env sigma t in
+ let t = Retyping.get_type_of env (Sigma.to_evar_map sigma) c in
+ let (mind,_) = reduce_to_quantified_ind env (Sigma.to_evar_map sigma) t in
let sort = Tacticals.New.elimination_sort_of_goal gl in
- let sigma, elim =
+ let Sigma (elim, sigma, p) =
if occur_term c concl then
build_case_analysis_scheme env sigma mind true sort
else
build_case_analysis_scheme_default env sigma mind sort in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS sigma)
+ let tac =
(general_elim with_evars clear_flag (c,lbindc)
{elimindex = None; elimbody = (elim,NoBindings);
elimrename = Some (false, constructors_nrealdecls (fst mind))})
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
let general_case_analysis with_evars clear_flag (c,lbindc as cx) =
match kind_of_term c with
@@ -1281,11 +1315,13 @@ let find_eliminator c gl =
let default_elim with_evars clear_flag (c,_ as cx) =
Proofview.tclORELSE
- (Proofview.Goal.enter begin fun gl ->
- let evd, elim = find_eliminator c gl in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS evd)
+ (Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma, elim = find_eliminator c gl in
+ let tac =
(general_elim with_evars clear_flag cx elim)
- end)
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end })
begin function (e, info) -> match e with
| IsNonrec ->
(* For records, induction principles aren't there by default
@@ -1332,9 +1368,9 @@ let clenv_fchain_in id ?(flags=elim_flags ()) mv elimclause hypclause =
let elimination_in_clause_scheme with_evars ?(flags=elim_flags ())
id rename i (elim, elimty, bindings) indclause =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let elim = contract_letin_in_lam_header elim in
let elimclause = make_clenv_binding env sigma (elim, elimty) bindings in
let indmv = destMeta (nth_arg i elimclause.templval.rebus) in
@@ -1355,7 +1391,7 @@ let elimination_in_clause_scheme with_evars ?(flags=elim_flags ())
(str "Nothing to rewrite in " ++ pr_id id ++ str".");
clenv_refine_in with_evars id id sigma elimclause''
(fun id -> Proofview.tclUNIT ())
- end
+ end }
let general_elim_clause with_evars flags id c e =
let elim = match id with
@@ -1371,11 +1407,13 @@ type conjunction_status =
| NotADefinedRecordUseScheme of constr
let make_projection env sigma params cstr sign elim i n c u =
+ let open Context.Rel.Declaration in
let elim = match elim with
| NotADefinedRecordUseScheme elim ->
(* bugs: goes from right to left when i increases! *)
- let (na,b,t) = List.nth cstr.cs_args i in
- let b = match b with None -> mkRel (i+1) | Some b -> b in
+ let decl = List.nth cstr.cs_args i in
+ let t = get_type decl in
+ let b = match decl with LocalAssum _ -> mkRel (i+1) | LocalDef (_,b,_) -> b in
let branch = it_mkLambda_or_LetIn b cstr.cs_args in
if
(* excludes dependent projection types *)
@@ -1387,7 +1425,7 @@ let make_projection env sigma params cstr sign elim i n c u =
then
let t = lift (i+1-n) t in
let abselim = beta_applist (elim,params@[t;branch]) in
- let c = beta_applist (abselim, [mkApp (c, extended_rel_vect 0 sign)]) in
+ let c = beta_applist (abselim, [mkApp (c, Context.Rel.to_extended_vect 0 sign)]) in
Some (it_mkLambda_or_LetIn c sign, it_mkProd_or_LetIn t sign)
else
None
@@ -1395,7 +1433,7 @@ let make_projection env sigma params cstr sign elim i n c u =
(* goes from left to right when i increases! *)
match List.nth l i with
| Some proj ->
- let args = extended_rel_vect 0 sign in
+ let args = Context.Rel.to_extended_vect 0 sign in
let proj =
if Environ.is_projection proj env then
mkProj (Projection.make proj false, mkApp (c, args))
@@ -1410,9 +1448,9 @@ let make_projection env sigma params cstr sign elim i n c u =
in elim
let descend_in_conjunctions avoid tac (err, info) c =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
try
let t = Retyping.get_type_of env sigma c in
let ((ind,u),t) = reduce_to_quantified_ind env sigma t in
@@ -1427,13 +1465,14 @@ let descend_in_conjunctions avoid tac (err, info) c =
let elim =
try DefinedRecord (Recordops.lookup_projections ind)
with Not_found ->
- let elim = build_case_analysis_scheme env sigma (ind,u) false sort in
- NotADefinedRecordUseScheme (snd elim) in
+ let sigma = Sigma.Unsafe.of_evar_map sigma in
+ let Sigma (elim, _, _) = build_case_analysis_scheme env sigma (ind,u) false sort in
+ NotADefinedRecordUseScheme elim in
Tacticals.New.tclFIRST
(List.init n (fun i ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
match make_projection env sigma params cstr sign elim i n c u with
| None -> Tacticals.New.tclFAIL 0 (mt())
| Some (p,pt) ->
@@ -1442,31 +1481,33 @@ let descend_in_conjunctions avoid tac (err, info) c =
[Proofview.V82.tactic (refine p);
(* Might be ill-typed due to forbidden elimination. *)
Tacticals.New.onLastHypId (tac (not isrec))]
- end))
+ end }))
| None -> Proofview.tclZERO ~info err
with RefinerError _|UserError _ -> Proofview.tclZERO ~info err
- end
+ end }
(****************************************************)
(* Resolution tactics *)
(****************************************************)
let solve_remaining_apply_goals =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
if !apply_solve_class_goals then
try
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let evd = Sigma.to_evar_map sigma in
let concl = Proofview.Goal.concl gl in
- if Typeclasses.is_class_type sigma concl then
- let evd', c' = Typeclasses.resolve_one_typeclass env sigma concl in
- Tacticals.New.tclTHEN
- (Proofview.Unsafe.tclEVARS evd')
- (Proofview.V82.tactic (refine_no_check c'))
- else Proofview.tclUNIT ()
- with Not_found -> Proofview.tclUNIT ()
- else Proofview.tclUNIT ()
- end
+ if Typeclasses.is_class_type evd concl then
+ let evd', c' = Typeclasses.resolve_one_typeclass env evd concl in
+ let tac =
+ (Proofview.V82.tactic (Tacmach.refine_no_check c'))
+ in
+ Sigma.Unsafe.of_pair (tac, evd')
+ else Sigma.here (Proofview.tclUNIT ()) sigma
+ with Not_found -> Sigma.here (Proofview.tclUNIT ()) sigma
+ else Sigma.here (Proofview.tclUNIT ()) sigma
+ end }
let tclORELSEOPT t k =
Proofview.tclORELSE t
@@ -1477,23 +1518,23 @@ let tclORELSEOPT t k =
| Some tac -> tac)
let general_apply with_delta with_destruct with_evars clear_flag (loc,(c,lbind)) =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let concl = Proofview.Goal.concl gl in
let flags =
if with_delta then default_unify_flags () else default_no_delta_unify_flags () in
(* The actual type of the theorem. It will be matched against the
goal. If this fails, then the head constant will be unfolded step by
step. *)
- let concl_nprod = nb_prod concl in
+ let concl_nprod = nb_prod_modulo_zeta concl in
let rec try_main_apply with_destruct c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let thm_ty0 = nf_betaiota sigma (Retyping.get_type_of env sigma c) in
let try_apply thm_ty nprod =
try
- let n = nb_prod thm_ty - nprod in
+ let n = nb_prod_modulo_zeta thm_ty - nprod in
if n<0 then error "Applied theorem has not enough premisses.";
let clause = make_clenv_binding_apply env sigma (Some n) (c,thm_ty) lbind in
Clenvtac.res_pf clause ~with_evars ~flags
@@ -1540,14 +1581,14 @@ let general_apply with_delta with_destruct with_evars clear_flag (loc,(c,lbind))
| PretypeError _|RefinerError _|UserError _|Failure _ ->
Some (try_red_apply thm_ty0 (e, info))
| _ -> None)
- end
+ end }
in
Tacticals.New.tclTHENLIST [
try_main_apply with_destruct c;
solve_remaining_apply_goals;
apply_clear_request clear_flag (use_clear_hyp_by_default ()) c
]
- end
+ end }
let rec apply_with_bindings_gen b e = function
| [] -> Proofview.tclUNIT ()
@@ -1559,13 +1600,13 @@ let rec apply_with_bindings_gen b e = function
let apply_with_delayed_bindings_gen b e l =
let one k (loc, f) =
- Proofview.Goal.enter begin fun gl ->
- let sigma = Proofview.Goal.sigma gl in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let sigma = Tacmach.New.project gl in
let env = Proofview.Goal.env gl in
- let sigma, cb = f env sigma in
+ let (cb, sigma) = run_delayed env sigma f in
Tacticals.New.tclWITHHOLES e
(general_apply b b e k (loc,cb)) sigma
- end
+ end }
in
let rec aux = function
| [] -> Proofview.tclUNIT ()
@@ -1628,18 +1669,19 @@ let apply_in_once_main flags innerclause env sigma (d,lbind) =
let apply_in_once sidecond_first with_delta with_destruct with_evars naming
id (clear_flag,(loc,(d,lbind))) tac =
- Proofview.Goal.nf_enter begin fun gl ->
+ let open Context.Rel.Declaration in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let flags =
if with_delta then default_unify_flags () else default_no_delta_unify_flags () in
let t' = Tacmach.New.pf_get_hyp_typ id gl in
let innerclause = mk_clenv_from_env env sigma (Some 0) (mkVar id,t') in
- let targetid = find_name true (Anonymous,None,t') naming gl in
+ let targetid = find_name true (LocalAssum (Anonymous,t')) naming gl in
let rec aux idstoclear with_destruct c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
try
let clause = apply_in_once_main flags innerclause env sigma (c,lbind) in
clenv_refine_in ~sidecond_first with_evars targetid id sigma clause
@@ -1654,22 +1696,22 @@ let apply_in_once sidecond_first with_delta with_destruct with_evars naming
(descend_in_conjunctions [targetid]
(fun b id -> aux (id::idstoclear) b (mkVar id))
(e, info) c)
- end
+ end }
in
aux [] with_destruct d
- end
+ end }
let apply_in_delayed_once sidecond_first with_delta with_destruct with_evars naming
id (clear_flag,(loc,f)) tac =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
- let sigma, c = f env sigma in
+ let sigma = Tacmach.New.project gl in
+ let (c, sigma) = run_delayed env sigma f in
Tacticals.New.tclWITHHOLES with_evars
(apply_in_once sidecond_first with_delta with_destruct with_evars
naming id (clear_flag,(loc,c)) tac)
sigma
- end
+ end }
(* A useful resolution tactic which, if c:A->B, transforms |- C into
|- B -> C and |- A
@@ -1689,20 +1731,20 @@ let apply_in_delayed_once sidecond_first with_delta with_destruct with_evars nam
*)
let cut_and_apply c =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
match kind_of_term (Tacmach.New.pf_hnf_constr gl (Tacmach.New.pf_unsafe_type_of gl c)) with
| Prod (_,c1,c2) when not (dependent (mkRel 1) c2) ->
let concl = Proofview.Goal.concl gl in
let env = Tacmach.New.pf_env gl in
- Proofview.Refine.refine begin fun sigma ->
+ Proofview.Refine.refine { run = begin fun sigma ->
let typ = mkProd (Anonymous, c2, concl) in
- let (sigma, f) = Evarutil.new_evar env sigma typ in
- let (sigma, x) = Evarutil.new_evar env sigma c1 in
+ let Sigma (f, sigma, p) = Evarutil.new_evar env sigma typ in
+ let Sigma (x, sigma, q) = Evarutil.new_evar env sigma c1 in
let ans = mkApp (f, [|mkApp (c, [|x|])|]) in
- (sigma, ans)
- end
+ Sigma (ans, sigma, p +> q)
+ end }
| _ -> error "lapply needs a non-dependent product."
- end
+ end }
(********************************************************************)
(* Exact tactics *)
@@ -1715,44 +1757,49 @@ let cut_and_apply c =
(* let refine_no_check = Profile.profile2 refine_no_checkkey refine_no_check *)
let new_exact_no_check c =
- Proofview.Refine.refine ~unsafe:true (fun h -> (h, c))
+ Proofview.Refine.refine ~unsafe:true { run = fun h -> Sigma.here c h }
let exact_check c =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
(** We do not need to normalize the goal because we just check convertibility *)
let concl = Proofview.Goal.concl (Proofview.Goal.assume gl) in
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
let sigma, ct = Typing.type_of env sigma c in
- Proofview.Unsafe.tclEVARS sigma <*>
+ let tac =
Tacticals.New.tclTHEN (convert_leq ct concl) (new_exact_no_check c)
- end
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
-let exact_no_check = refine_no_check
+let exact_no_check = Tacmach.refine_no_check
let vm_cast_no_check c gl =
- let concl = pf_concl gl in
- refine_no_check (Term.mkCast(c,Term.VMcast,concl)) gl
+ let concl = Tacmach.pf_concl gl in
+ Tacmach.refine_no_check (Term.mkCast(c,Term.VMcast,concl)) gl
let native_cast_no_check c gl =
- let concl = pf_concl gl in
- refine_no_check (Term.mkCast(c,Term.NATIVEcast,concl)) gl
+ let concl = Tacmach.pf_concl gl in
+ Tacmach.refine_no_check (Term.mkCast(c,Term.NATIVEcast,concl)) gl
let exact_proof c gl =
- let c,ctx = Constrintern.interp_casted_constr (pf_env gl) (project gl) c (pf_concl gl)
- in tclTHEN (tclEVARUNIVCONTEXT ctx) (refine_no_check c) gl
+ let c,ctx = Constrintern.interp_casted_constr (Tacmach.pf_env gl) (Tacmach.project gl) c (Tacmach.pf_concl gl)
+ in tclTHEN (tclEVARUNIVCONTEXT ctx) (Tacmach.refine_no_check c) gl
let assumption =
+ let open Context.Named.Declaration in
let rec arec gl only_eq = function
| [] ->
if only_eq then
let hyps = Proofview.Goal.hyps gl in
arec gl false hyps
else Tacticals.New.tclZEROMSG (str "No such assumption.")
- | (id, c, t)::rest ->
+ | decl::rest ->
+ let t = get_type decl in
let concl = Proofview.Goal.concl gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let (sigma, is_same_type) =
if only_eq then (sigma, Constr.equal t concl)
else
@@ -1761,13 +1808,13 @@ let assumption =
in
if is_same_type then
(Proofview.Unsafe.tclEVARS sigma) <*>
- Proofview.Refine.refine ~unsafe:true (fun h -> (h, mkVar id))
+ Proofview.Refine.refine ~unsafe:true { run = fun h -> Sigma.here (mkVar (get_id decl)) h }
else arec gl only_eq rest
in
- let assumption_tac gl =
+ let assumption_tac = { enter = begin fun gl ->
let hyps = Proofview.Goal.hyps gl in
arec gl true hyps
- in
+ end } in
Proofview.Goal.nf_enter assumption_tac
(*****************************************************************)
@@ -1791,45 +1838,48 @@ let check_is_type env ty msg =
Proofview.tclEVARMAP >>= fun sigma ->
let evdref = ref sigma in
try
- let _ = Typing.sort_of env evdref ty in
+ let _ = Typing.e_sort_of env evdref ty in
Proofview.Unsafe.tclEVARS !evdref
with e when Errors.noncritical e ->
msg e
-let check_decl env (_, c, ty) msg =
+let check_decl env decl msg =
+ let open Context.Named.Declaration in
+ let ty = get_type decl in
Proofview.tclEVARMAP >>= fun sigma ->
let evdref = ref sigma in
try
- let _ = Typing.sort_of env evdref ty in
- let _ = match c with
- | None -> ()
- | Some c -> Typing.check env evdref c ty
+ let _ = Typing.e_sort_of env evdref ty in
+ let _ = match decl with
+ | LocalAssum _ -> ()
+ | LocalDef (_,c,_) -> Typing.e_check env evdref c ty
in
Proofview.Unsafe.tclEVARS !evdref
with e when Errors.noncritical e ->
msg e
let clear_body ids =
- Proofview.Goal.enter begin fun gl ->
+ let open Context.Named.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let concl = Proofview.Goal.concl (Proofview.Goal.assume gl) in
let ctx = named_context env in
- let map (id, body, t as decl) = match body with
- | None ->
+ let map = function
+ | LocalAssum (id,t) as decl ->
let () = if List.mem_f Id.equal id ids then
errorlabstrm "" (str "Hypothesis " ++ pr_id id ++ str " is not a local definition")
in
decl
- | Some _ ->
- if List.mem_f Id.equal id ids then (id, None, t) else decl
+ | LocalDef (id,_,t) as decl ->
+ if List.mem_f Id.equal id ids then LocalAssum (id, t) else decl
in
let ctx = List.map map ctx in
let base_env = reset_context env in
let env = push_named_context ctx base_env in
let check_hyps =
- let check env (id, _, _ as decl) =
+ let check env decl =
let msg _ = Tacticals.New.tclZEROMSG
- (str "Hypothesis " ++ pr_id id ++ on_the_bodies ids)
+ (str "Hypothesis " ++ pr_id (get_id decl) ++ on_the_bodies ids)
in
check_decl env decl msg <*> Proofview.tclUNIT (push_named decl env)
in
@@ -1843,10 +1893,10 @@ let clear_body ids =
check_is_type env concl msg
in
check_hyps <*> check_concl <*>
- Proofview.Refine.refine ~unsafe:true begin fun sigma ->
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
Evarutil.new_evar env sigma ~principal:true concl
- end
- end
+ end }
+ end }
let clear_wildcards ids =
Proofview.V82.tactic (tclMAP (fun (loc,id) gl ->
@@ -1868,49 +1918,16 @@ let rec intros_clearing = function
Tacticals.New.tclTHENLIST
[ intro; Tacticals.New.onLastHypId (fun id -> Proofview.V82.tactic (clear [id])); intros_clearing tl]
-(* Modifying/Adding an hypothesis *)
-
-let specialize (c,lbind) g =
- let tac, term =
- if lbind == NoBindings then
- let evd = Typeclasses.resolve_typeclasses (pf_env g) (project g) in
- tclEVARS evd, nf_evar evd c
- else
- let clause = pf_apply make_clenv_binding g (c,pf_unsafe_type_of g c) lbind in
- let flags = { (default_unify_flags ()) with resolve_evars = true } in
- let clause = clenv_unify_meta_types ~flags clause in
- let (thd,tstack) = whd_nored_stack clause.evd (clenv_value clause) in
- let rec chk = function
- | [] -> []
- | t::l -> if occur_meta t then [] else t :: chk l
- in
- let tstack = chk tstack in
- let term = applist(thd,List.map (nf_evar clause.evd) tstack) in
- if occur_meta term then
- errorlabstrm "" (str "Cannot infer an instance for " ++
- pr_name (meta_name clause.evd (List.hd (collect_metas term))) ++
- str ".");
- tclEVARS clause.evd, term
- in
- match kind_of_term (fst(decompose_app (snd(decompose_lam_assum c)))) with
- | Var id when Id.List.mem id (pf_ids_of_hyps g) ->
- tclTHEN tac
- (tclTHENFIRST
- (fun g -> Proofview.V82.of_tactic (assert_before_replacing id (pf_unsafe_type_of g term)) g)
- (exact_no_check term)) g
- | _ -> tclTHEN tac
- (tclTHENLAST
- (fun g -> Proofview.V82.of_tactic (cut (pf_unsafe_type_of g term)) g)
- (exact_no_check term)) g
-
(* Keeping only a few hypotheses *)
let keep hyps =
- Proofview.Goal.nf_enter begin fun gl ->
+ let open Context.Named.Declaration in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
Proofview.tclENV >>= fun env ->
let ccl = Proofview.Goal.concl gl in
let cl,_ =
- fold_named_context_reverse (fun (clear,keep) (hyp,_,_ as decl) ->
+ fold_named_context_reverse (fun (clear,keep) decl ->
+ let hyp = get_id decl in
if Id.List.mem hyp hyps
|| List.exists (occur_var_in_decl env hyp) keep
|| occur_var env hyp ccl
@@ -1919,7 +1936,54 @@ let keep hyps =
~init:([],[]) (Proofview.Goal.env gl)
in
Proofview.V82.tactic (fun gl -> thin cl gl)
- end
+ end }
+
+(*********************************)
+(* Basic generalization tactics *)
+(*********************************)
+
+(* Given a type [T] convertible to [forall x1..xn:A1..An(x1..xn-1), G(x1..xn)]
+ and [a1..an:A1..An(a1..an-1)] such that the goal is [G(a1..an)],
+ this generalizes [hyps |- goal] into [hyps |- T] *)
+
+let apply_type newcl args =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let store = Proofview.Goal.extra gl in
+ Proofview.Refine.refine { run = begin fun sigma ->
+ let newcl = nf_betaiota (Sigma.to_evar_map sigma) newcl (* As in former Logic.refine *) in
+ let Sigma (ev, sigma, p) =
+ Evarutil.new_evar env sigma ~principal:true ~store newcl in
+ Sigma (applist (ev, args), sigma, p)
+ end }
+ end }
+
+(* Given a context [hyps] with domain [x1..xn], possibly with let-ins,
+ and well-typed in the current goal, [bring_hyps hyps] generalizes
+ [ctxt |- G(x1..xn] into [ctxt |- forall hyps, G(x1..xn)] *)
+
+let bring_hyps hyps =
+ if List.is_empty hyps then Tacticals.New.tclIDTAC
+ else
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let store = Proofview.Goal.extra gl in
+ let concl = Tacmach.New.pf_nf_concl gl in
+ let newcl = List.fold_right mkNamedProd_or_LetIn hyps concl in
+ let args = Array.of_list (Context.Named.to_instance hyps) in
+ Proofview.Refine.refine { run = begin fun sigma ->
+ let Sigma (ev, sigma, p) =
+ Evarutil.new_evar env sigma ~principal:true ~store newcl in
+ Sigma (mkApp (ev, args), sigma, p)
+ end }
+ end }
+
+let revert hyps =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let gl = Proofview.Goal.assume gl in
+ let ctx = List.map (fun id -> Tacmach.New.pf_get_hyp id gl) hyps in
+ (bring_hyps ctx) <*> (Proofview.V82.tactic (clear hyps))
+ end }
(************************)
(* Introduction tactics *)
@@ -1936,7 +2000,8 @@ let check_number_of_constructors expctdnumopt i nconstr =
if i > nconstr then error "Not enough constructors."
let constructor_tac with_evars expctdnumopt i lbind =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
let cl = Tacmach.New.pf_nf_concl gl in
let reduce_to_quantified_ind =
Tacmach.New.pf_apply Tacred.reduce_to_quantified_ind gl
@@ -1946,16 +2011,19 @@ let constructor_tac with_evars expctdnumopt i lbind =
Array.length (snd (Global.lookup_inductive (fst mind))).mind_consnames in
check_number_of_constructors expctdnumopt i nconstr;
- let sigma, cons = Evd.fresh_constructor_instance
- (Proofview.Goal.env gl) (Proofview.Goal.sigma gl) (fst mind, i) in
+ let Sigma (cons, sigma, p) = Sigma.fresh_constructor_instance
+ (Proofview.Goal.env gl) sigma (fst mind, i) in
let cons = mkConstructU cons in
let apply_tac = general_apply true false with_evars None (dloc,(cons,lbind)) in
+ let tac =
(Tacticals.New.tclTHENLIST
- [Proofview.Unsafe.tclEVARS sigma;
+ [
convert_concl_no_check redcl DEFAULTcast;
intros; apply_tac])
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
let one_constructor i lbind = constructor_tac false None i lbind
@@ -1972,7 +2040,7 @@ let rec tclANY tac = function
let any_constructor with_evars tacopt =
let t = match tacopt with None -> Proofview.tclUNIT () | Some t -> t in
let tac i = Tacticals.New.tclTHEN (constructor_tac with_evars None i NoBindings) t in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let cl = Tacmach.New.pf_nf_concl gl in
let reduce_to_quantified_ind =
Tacmach.New.pf_apply Tacred.reduce_to_quantified_ind gl
@@ -1982,7 +2050,7 @@ let any_constructor with_evars tacopt =
Array.length (snd (Global.lookup_inductive (fst mind))).mind_consnames in
if Int.equal nconstr 0 then error "The type has no constructors.";
tclANY tac (List.interval 1 nconstr)
- end
+ end }
let left_with_bindings with_evars = constructor_tac with_evars (Some 2) 1
let right_with_bindings with_evars = constructor_tac with_evars (Some 2) 2
@@ -2033,7 +2101,7 @@ let my_find_eq_data_decompose gl t =
| Constr_matching.PatternMatchingFailure -> None
let intro_decomp_eq loc l thin tac id =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let c = mkVar id in
let t = Tacmach.New.pf_unsafe_type_of gl c in
let _,t = Tacmach.New.pf_reduce_to_quantified_ind gl t in
@@ -2044,53 +2112,65 @@ let intro_decomp_eq loc l thin tac id =
(eq,t,eq_args) (c, t)
| None ->
Tacticals.New.tclZEROMSG (str "Not a primitive equality here.")
- end
+ end }
let intro_or_and_pattern loc bracketed ll thin tac id =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let c = mkVar id in
let t = Tacmach.New.pf_unsafe_type_of gl c in
- let ((ind,u),t) = Tacmach.New.pf_reduce_to_quantified_ind gl t in
- let nv = constructors_nrealargs ind in
- let ll = fix_empty_or_and_pattern (Array.length nv) ll in
- check_or_and_pattern_size loc ll (Array.length nv);
+ let (ind,t) = Tacmach.New.pf_reduce_to_quantified_ind gl t in
+ let branchsigns = compute_constructor_signatures false ind in
+ let nv_with_let = Array.map List.length branchsigns in
+ let ll = fix_empty_or_and_pattern (Array.length branchsigns) ll in
+ let ll = get_and_check_or_and_pattern loc ll branchsigns in
Tacticals.New.tclTHENLASTn
(Tacticals.New.tclTHEN (simplest_case c) (Proofview.V82.tactic (clear [id])))
(Array.map2 (fun n l -> tac thin (Some (bracketed,n)) l)
- nv (Array.of_list ll))
- end
+ nv_with_let ll)
+ end }
-let rewrite_hyp assert_style l2r id =
+let rewrite_hyp_then assert_style thin l2r id tac =
let rew_on l2r =
Hook.get forward_general_rewrite_clause l2r false (mkVar id,NoBindings) in
let subst_on l2r x rhs =
Hook.get forward_subst_one true x (id,rhs,l2r) in
- let clear_var_and_eq c = tclTHEN (clear [id]) (clear [destVar c]) in
- Proofview.Goal.enter begin fun gl ->
+ let clear_var_and_eq id' = clear [id';id] in
+ let early_clear id' thin =
+ List.filter (fun (_,id) -> not (Id.equal id id')) thin in
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let type_of = Tacmach.New.pf_unsafe_type_of gl in
let whd_betadeltaiota = Tacmach.New.pf_apply whd_betadeltaiota gl in
let t = whd_betadeltaiota (type_of (mkVar id)) in
- match match_with_equality_type t with
+ let eqtac, thin = match match_with_equality_type t with
| Some (hdcncl,[_;lhs;rhs]) ->
if l2r && isVar lhs && not (occur_var env (destVar lhs) rhs) then
- subst_on l2r (destVar lhs) rhs
+ let id' = destVar lhs in
+ subst_on l2r id' rhs, early_clear id' thin
else if not l2r && isVar rhs && not (occur_var env (destVar rhs) lhs) then
- subst_on l2r (destVar rhs) lhs
+ let id' = destVar rhs in
+ subst_on l2r id' lhs, early_clear id' thin
else
- Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id]))
+ Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id])),
+ thin
| Some (hdcncl,[c]) ->
let l2r = not l2r in (* equality of the form eq_true *)
if isVar c then
+ let id' = destVar c in
Tacticals.New.tclTHEN (rew_on l2r allHypsAndConcl)
- (Proofview.V82.tactic (clear_var_and_eq c))
+ (Proofview.V82.tactic (clear_var_and_eq id')),
+ early_clear id' thin
else
- Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id]))
+ Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id])),
+ thin
| _ ->
- Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id]))
- end
+ Tacticals.New.tclTHEN (rew_on l2r onConcl) (Proofview.V82.tactic (clear [id])),
+ thin in
+ (* Skip the side conditions of the rewriting step *)
+ Tacticals.New.tclTHENFIRST eqtac (tac thin)
+ end }
-let rec prepare_naming loc = function
+let prepare_naming loc = function
| IntroIdentifier id -> NamingMustBe (loc,id)
| IntroAnonymous -> NamingAvoid []
| IntroFresh id -> NamingBasedOn (id,[])
@@ -2098,7 +2178,8 @@ let rec prepare_naming loc = function
let rec explicit_intro_names = function
| (_, IntroForthcoming _) :: l -> explicit_intro_names l
| (_, IntroNaming (IntroIdentifier id)) :: l -> id :: explicit_intro_names l
-| (_, IntroAction (IntroOrAndPattern ll)) :: l' ->
+| (_, IntroAction (IntroOrAndPattern l)) :: l' ->
+ let ll = match l with IntroAndPattern l -> [l] | IntroOrPattern ll -> ll in
List.flatten (List.map (fun l -> explicit_intro_names (l@l')) ll)
| (_, IntroAction (IntroInjection l)) :: l' ->
explicit_intro_names (l@l')
@@ -2212,10 +2293,7 @@ and intro_pattern_action loc b style pat thin destopt tac id = match pat with
| IntroInjection l' ->
intro_decomp_eq loc l' thin tac id
| IntroRewrite l2r ->
- Tacticals.New.tclTHENLAST
- (* Skip the side conditions of the rewriting step *)
- (rewrite_hyp style l2r id)
- (tac thin None [])
+ rewrite_hyp_then style thin l2r id (fun thin -> tac thin None [])
| IntroApplyOn (f,(loc,pat)) ->
let naming,tac_ipat =
prepare_intros_loc loc (IntroIdentifier id) destopt pat in
@@ -2224,7 +2302,10 @@ and intro_pattern_action loc b style pat thin destopt tac id = match pat with
Proofview.tclUNIT () (* apply_in_once do a replacement *)
else
Proofview.V82.tactic (clear [id]) in
- let f env sigma = let (sigma,c) = f env sigma in (sigma,(c,NoBindings)) in
+ let f = { delayed = fun env sigma ->
+ let Sigma (c, sigma, p) = f.delayed env sigma in
+ Sigma ((c, NoBindings), sigma, p)
+ } in
apply_in_delayed_once false true true true naming id (None,(loc,f))
(fun id -> Tacticals.New.tclTHENLIST [doclear; tac_ipat id; tac thin None []])
@@ -2289,7 +2370,7 @@ let general_apply_in sidecond_first with_delta with_destruct with_evars
let tac (naming,lemma) tac id =
apply_in_delayed_once sidecond_first with_delta with_destruct with_evars
naming id lemma tac in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let destopt =
if with_evars then MoveLast (* evars would depend on the whole context *)
else get_previous_hyp_position id gl in
@@ -2300,7 +2381,7 @@ let general_apply_in sidecond_first with_delta with_destruct with_evars
in
(* We chain apply_in_once, ending with an intro pattern *)
List.fold_right tac lemmas_target (tac last_lemma_target ipat_tac) id
- end
+ end }
(*
if sidecond_first then
@@ -2311,7 +2392,7 @@ let general_apply_in sidecond_first with_delta with_destruct with_evars
*)
let apply_in simple with_evars id lemmas ipat =
- let lemmas = List.map (fun (k,(loc,l)) -> k, (loc, fun _ sigma -> sigma, l)) lemmas in
+ let lemmas = List.map (fun (k,(loc,l)) -> k, (loc, { delayed = fun _ sigma -> Sigma.here l sigma })) lemmas in
general_apply_in false simple simple with_evars id lemmas ipat
let apply_delayed_in simple with_evars id lemmas ipat =
@@ -2342,16 +2423,17 @@ let decode_hyp = function
*)
let letin_tac_gen with_eq (id,depdecls,lastlhyp,ccl,c) ty =
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
- let (sigma, t) = match ty with
- | Some t -> (sigma, t)
+ let env = Proofview.Goal.env gl in
+ let Sigma (t, sigma, p) = match ty with
+ | Some t -> Sigma.here t sigma
| None ->
let t = typ_of env sigma c in
- Evarsolve.refresh_universes ~onlyalg:true (Some false) env sigma t
+ let sigma, c = Evarsolve.refresh_universes ~onlyalg:true (Some false) env (Sigma.to_evar_map sigma) t in
+ Sigma.Unsafe.of_pair (c, sigma)
in
- let eq_tac gl = match with_eq with
+ let Sigma ((newcl, eq_tac), sigma, q) = match with_eq with
| Some (lr,(loc,ido)) ->
let heq = match ido with
| IntroAnonymous -> new_fresh_id [id] (add_prefix "Heq" id) gl
@@ -2359,42 +2441,51 @@ let letin_tac_gen with_eq (id,depdecls,lastlhyp,ccl,c) ty =
| IntroIdentifier id -> id in
let eqdata = build_coq_eq_data () in
let args = if lr then [t;mkVar id;c] else [t;c;mkVar id]in
- let sigma, eq = Evd.fresh_global env sigma eqdata.eq in
- let sigma, refl = Evd.fresh_global env sigma eqdata.refl in
+ let Sigma (eq, sigma, p) = Sigma.fresh_global env sigma eqdata.eq in
+ let Sigma (refl, sigma, q) = Sigma.fresh_global env sigma eqdata.refl in
let eq = applist (eq,args) in
let refl = applist (refl, [t;mkVar id]) in
let term = mkNamedLetIn id c t (mkLetIn (Name heq, refl, eq, ccl)) in
+ let sigma = Sigma.to_evar_map sigma in
let sigma, _ = Typing.type_of env sigma term in
- sigma, term,
+ let ans = term,
Tacticals.New.tclTHEN
(intro_gen (NamingMustBe (loc,heq)) (decode_hyp lastlhyp) true false)
(clear_body [heq;id])
+ in
+ Sigma.Unsafe.of_pair (ans, sigma)
| None ->
- (sigma, mkNamedLetIn id c t ccl, Proofview.tclUNIT ()) in
- let (sigma,newcl,eq_tac) = eq_tac gl in
- Tacticals.New.tclTHENLIST
- [ Proofview.Unsafe.tclEVARS sigma;
- convert_concl_no_check newcl DEFAULTcast;
+ Sigma.here (mkNamedLetIn id c t ccl, Proofview.tclUNIT ()) sigma
+ in
+ let tac =
+ Tacticals.New.tclTHENLIST
+ [ convert_concl_no_check newcl DEFAULTcast;
intro_gen (NamingMustBe (dloc,id)) (decode_hyp lastlhyp) true false;
Tacticals.New.tclMAP convert_hyp_no_check depdecls;
eq_tac ]
- end
+ in
+ Sigma (tac, sigma, p +> q)
+ end }
let insert_before decls lasthyp env =
+ let open Context.Named.Declaration in
match lasthyp with
| None -> push_named_context decls env
| Some id ->
Environ.fold_named_context
- (fun _ (id',_,_ as d) env ->
- let env = if Id.equal id id' then push_named_context decls env else env in
+ (fun _ d env ->
+ let env = if Id.equal id (get_id d) then push_named_context decls env else env in
push_named d env)
~init:(reset_context env) env
(* unsafe *)
let mkletin_goal env sigma store with_eq dep (id,lastlhyp,ccl,c) ty =
- let body = if dep then Some c else None in
+ let open Context.Named.Declaration in
let t = match ty with Some t -> t | _ -> typ_of env sigma c in
+ let decl = if dep then LocalDef (id,c,t)
+ else LocalAssum (id,t)
+ in
match with_eq with
| Some (lr,(loc,ido)) ->
let heq = match ido with
@@ -2406,55 +2497,57 @@ let mkletin_goal env sigma store with_eq dep (id,lastlhyp,ccl,c) ty =
id in
let eqdata = build_coq_eq_data () in
let args = if lr then [t;mkVar id;c] else [t;c;mkVar id]in
- let sigma, eq = Evd.fresh_global env sigma eqdata.eq in
- let sigma, refl = Evd.fresh_global env sigma eqdata.refl in
+ let Sigma (eq, sigma, p) = Sigma.fresh_global env sigma eqdata.eq in
+ let Sigma (refl, sigma, q) = Sigma.fresh_global env sigma eqdata.refl in
let eq = applist (eq,args) in
let refl = applist (refl, [t;mkVar id]) in
- let newenv = insert_before [heq,None,eq;id,body,t] lastlhyp env in
- let (sigma,x) = new_evar newenv sigma ~principal:true ~store ccl in
- (sigma,mkNamedLetIn id c t (mkNamedLetIn heq refl eq x))
+ let newenv = insert_before [LocalAssum (heq,eq); decl] lastlhyp env in
+ let Sigma (x, sigma, r) = new_evar newenv sigma ~principal:true ~store ccl in
+ Sigma (mkNamedLetIn id c t (mkNamedLetIn heq refl eq x), sigma, p +> q +> r)
| None ->
- let newenv = insert_before [id,body,t] lastlhyp env in
- let (sigma,x) = new_evar newenv sigma ~principal:true ~store ccl in
- (sigma,mkNamedLetIn id c t x)
+ let newenv = insert_before [decl] lastlhyp env in
+ let Sigma (x, sigma, p) = new_evar newenv sigma ~principal:true ~store ccl in
+ Sigma (mkNamedLetIn id c t x, sigma, p)
let letin_tac with_eq id c ty occs =
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
let ccl = Proofview.Goal.concl gl in
let abs = AbstractExact (id,c,ty,occs,true) in
let (id,_,depdecls,lastlhyp,ccl,_) = make_abstraction env sigma ccl abs in
(* We keep the original term to match *)
- letin_tac_gen with_eq (id,depdecls,lastlhyp,ccl,c) ty
- end
+ let tac = letin_tac_gen with_eq (id,depdecls,lastlhyp,ccl,c) ty in
+ Sigma.here tac sigma
+ end }
let letin_pat_tac with_eq id c occs =
- Proofview.Goal.nf_enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
let ccl = Proofview.Goal.concl gl in
let check t = true in
let abs = AbstractPattern (false,check,id,c,occs,false) in
let (id,_,depdecls,lastlhyp,ccl,res) = make_abstraction env sigma ccl abs in
- let sigma,c = match res with
+ let Sigma (c, sigma, p) = match res with
| None -> finish_evar_resolution ~flags:(tactic_infer_flags false) env sigma c
- | Some (sigma,c) -> (sigma,c) in
- Tacticals.New.tclTHEN
- (Proofview.Unsafe.tclEVARS sigma)
+ | Some res -> res in
+ let tac =
(letin_tac_gen with_eq (id,depdecls,lastlhyp,ccl,c) None)
- end
+ in
+ Sigma (tac, sigma, p)
+ end }
(* Tactics "pose proof" (usetac=None) and "assert"/"enough" (otherwise) *)
let forward b usetac ipat c =
match usetac with
| None ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let t = Tacmach.New.pf_unsafe_type_of gl c in
let hd = head_ident c in
Tacticals.New.tclTHENFIRST (assert_as true hd ipat t)
(Proofview.V82.tactic (exact_no_check c))
- end
+ end }
| Some tac ->
if b then
Tacticals.New.tclTHENFIRST (assert_as b None ipat c) tac
@@ -2470,40 +2563,6 @@ let enough_by na t tac = forward false (Some tac) (ipat_of_name na) t
(* Generalization tactics *)
(***************************)
-(* Given a type [T] convertible to [forall x1..xn:A1..An(x1..xn-1), G(x1..xn)]
- and [a1..an:A1..An(a1..an-1)] such that the goal is [G(a1..an)],
- this generalizes [hyps |- goal] into [hyps |- T] *)
-
-let apply_type hdcty argl gl =
- refine (applist (mkCast (Evarutil.mk_new_meta(),DEFAULTcast, hdcty),argl)) gl
-
-(* Given a context [hyps] with domain [x1..xn], possibly with let-ins,
- and well-typed in the current goal, [bring_hyps hyps] generalizes
- [ctxt |- G(x1..xn] into [ctxt |- forall hyps, G(x1..xn)] *)
-
-let bring_hyps hyps =
- if List.is_empty hyps then Tacticals.New.tclIDTAC
- else
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
- let store = Proofview.Goal.extra gl in
- let concl = Tacmach.New.pf_nf_concl gl in
- let newcl = List.fold_right mkNamedProd_or_LetIn hyps concl in
- let args = Array.of_list (instance_from_named_context hyps) in
- Proofview.Refine.refine begin fun sigma ->
- let (sigma, ev) =
- Evarutil.new_evar env sigma ~principal:true ~store newcl in
- (sigma, (mkApp (ev, args)))
- end
- end
-
-let revert hyps =
- Proofview.Goal.enter begin fun gl ->
- let gl = Proofview.Goal.assume gl in
- let ctx = List.map (fun id -> Tacmach.New.pf_get_hyp id gl) hyps in
- (bring_hyps ctx) <*> (Proofview.V82.tactic (clear hyps))
- end
-
(* Compute a name for a generalization *)
let generalized_name c t ids cl = function
@@ -2527,32 +2586,39 @@ let generalized_name c t ids cl = function
[forall x, x1:A1(x1), .., xi:Ai(x). T(x)] with all [c] abtracted in [Ai]
but only those at [occs] in [T] *)
-let generalize_goal_gen env ids i ((occs,c,b),na) t (cl,evd) =
+let generalize_goal_gen env sigma ids i ((occs,c,b),na) t cl =
+ let open Context.Rel.Declaration in
let decls,cl = decompose_prod_n_assum i cl in
let dummy_prod = it_mkProd_or_LetIn mkProp decls in
let newdecls,_ = decompose_prod_n_assum i (subst_term_gen eq_constr_nounivs c dummy_prod) in
- let cl',evd' = subst_closed_term_occ env evd (AtOccs occs) c (it_mkProd_or_LetIn cl newdecls) in
+ let cl',sigma' = subst_closed_term_occ env sigma (AtOccs occs) c (it_mkProd_or_LetIn cl newdecls) in
let na = generalized_name c t ids cl' na in
- mkProd_or_LetIn (na,b,t) cl', evd'
+ let decl = match b with
+ | None -> LocalAssum (na,t)
+ | Some b -> LocalDef (na,b,t)
+ in
+ mkProd_or_LetIn decl cl', sigma'
-let generalize_goal gl i ((occs,c,b),na as o) cl =
- let t = pf_unsafe_type_of gl c in
- let env = pf_env gl in
- generalize_goal_gen env (pf_ids_of_hyps gl) i o t cl
+let generalize_goal gl i ((occs,c,b),na as o) (cl,sigma) =
+ let env = Tacmach.pf_env gl in
+ let ids = Tacmach.pf_ids_of_hyps gl in
+ let sigma, t = Typing.type_of env sigma c in
+ generalize_goal_gen env sigma ids i o t cl
let generalize_dep ?(with_let=false) c gl =
+ let open Context.Named.Declaration in
let env = pf_env gl in
let sign = pf_hyps gl in
let init_ids = ids_of_named_context (Global.named_context()) in
- let seek d toquant =
- if List.exists (fun (id,_,_) -> occur_var_in_decl env id d) toquant
+ let seek (d:Context.Named.Declaration.t) (toquant:Context.Named.t) =
+ if List.exists (fun d' -> occur_var_in_decl env (get_id d') d) toquant
|| dependent_in_decl c d then
d::toquant
else
toquant in
- let to_quantify = Context.fold_named_context seek sign ~init:[] in
+ let to_quantify = Context.Named.fold_outside seek sign ~init:[] in
let to_quantify_rev = List.rev to_quantify in
- let qhyps = List.map (fun (id,_,_) -> id) to_quantify_rev in
+ let qhyps = List.map get_id to_quantify_rev in
let tothin = List.filter (fun id -> not (Id.List.mem id init_ids)) qhyps in
let tothin' =
match kind_of_term c with
@@ -2560,20 +2626,20 @@ let generalize_dep ?(with_let=false) c gl =
-> id::tothin
| _ -> tothin
in
- let cl' = it_mkNamedProd_or_LetIn (pf_concl gl) to_quantify in
+ let cl' = it_mkNamedProd_or_LetIn (Tacmach.pf_concl gl) to_quantify in
let body =
if with_let then
match kind_of_term c with
- | Var id -> pi2 (pf_get_hyp gl id)
+ | Var id -> Tacmach.pf_get_hyp gl id |> get_value
| _ -> None
else None
in
let cl'',evd = generalize_goal gl 0 ((AllOccurrences,c,body),Anonymous)
(cl',project gl) in
- let args = instance_from_named_context to_quantify_rev in
+ let args = Context.Named.to_instance to_quantify_rev in
tclTHENLIST
[tclEVARS evd;
- apply_type cl'' (if Option.is_empty body then c::args else args);
+ Proofview.V82.of_tactic (apply_type cl'' (if Option.is_empty body then c::args else args));
thin (List.rev tothin')]
gl
@@ -2581,36 +2647,41 @@ let generalize_dep ?(with_let=false) c gl =
let generalize_gen_let lconstr gl =
let newcl, evd =
List.fold_right_i (generalize_goal gl) 0 lconstr
- (pf_concl gl,project gl)
+ (Tacmach.pf_concl gl,Tacmach.project gl)
in
- tclTHEN (tclEVARS evd)
+ Proofview.V82.of_tactic (Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS evd)
(apply_type newcl (List.map_filter (fun ((_,c,b),_) ->
- if Option.is_empty b then Some c else None) lconstr)) gl
+ if Option.is_empty b then Some c else None) lconstr))) gl
let new_generalize_gen_let lconstr =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
let gl = Proofview.Goal.assume gl in
let concl = Proofview.Goal.concl gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Sigma.to_evar_map sigma in
let env = Proofview.Goal.env gl in
let ids = Tacmach.New.pf_ids_of_hyps gl in
- let (newcl, sigma), args =
+ let newcl, sigma, args =
List.fold_right_i
- (fun i ((_,c,b),_ as o) (cl, args) ->
- let t = Tacmach.New.pf_unsafe_type_of gl c in
+ (fun i ((_,c,b),_ as o) (cl, sigma, args) ->
+ let sigma, t = Typing.type_of env sigma c in
let args = if Option.is_empty b then c :: args else args in
- generalize_goal_gen env ids i o t cl, args)
- 0 lconstr ((concl, sigma), [])
+ let cl, sigma = generalize_goal_gen env sigma ids i o t cl in
+ (cl, sigma, args))
+ 0 lconstr (concl, sigma, [])
in
- Proofview.Unsafe.tclEVARS sigma <*>
- Proofview.Refine.refine begin fun sigma ->
- let (sigma, ev) = Evarutil.new_evar env sigma ~principal:true newcl in
- (sigma, (applist (ev, args)))
- end
- end
+ let tac =
+ Proofview.Refine.refine { run = begin fun sigma ->
+ let Sigma (ev, sigma, p) = Evarutil.new_evar env sigma ~principal:true newcl in
+ Sigma ((applist (ev, args)), sigma, p)
+ end }
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
let generalize_gen lconstr =
- generalize_gen_let (List.map (fun ((occs,c),na) ->
+ generalize_gen_let (List.map (fun (occs_c,na) ->
+ let (occs,c) = Redexpr.out_with_occurrences occs_c in
(occs,c,None),na) lconstr)
let new_generalize_gen lconstr =
@@ -2635,29 +2706,77 @@ let quantify lconstr =
tclIDTAC
*)
+(* Modifying/Adding an hypothesis *)
+
+let specialize (c,lbind) =
+ Proofview.Goal.enter { enter = begin fun gl ->
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map (Proofview.Goal.sigma gl) in
+ let sigma, term =
+ if lbind == NoBindings then
+ let sigma = Typeclasses.resolve_typeclasses env sigma in
+ sigma, nf_evar sigma c
+ else
+ let clause = make_clenv_binding env sigma (c,Retyping.get_type_of env sigma c) lbind in
+ let flags = { (default_unify_flags ()) with resolve_evars = true } in
+ let clause = clenv_unify_meta_types ~flags clause in
+ let (thd,tstack) = whd_nored_stack clause.evd (clenv_value clause) in
+ let rec chk = function
+ | [] -> []
+ | t::l -> if occur_meta t then [] else t :: chk l
+ in
+ let tstack = chk tstack in
+ let term = applist(thd,List.map (nf_evar clause.evd) tstack) in
+ if occur_meta term then
+ errorlabstrm "" (str "Cannot infer an instance for " ++
+ pr_name (meta_name clause.evd (List.hd (collect_metas term))) ++
+ str ".");
+ clause.evd, term in
+ let typ = Retyping.get_type_of env sigma term in
+ match kind_of_term (fst(decompose_app (snd(decompose_lam_assum c)))) with
+ | Var id when Id.List.mem id (Tacmach.New.pf_ids_of_hyps gl) ->
+ Tacticals.New.tclTHEN
+ (Proofview.Unsafe.tclEVARS sigma)
+ (Tacticals.New.tclTHENFIRST
+ (assert_before_replacing id typ)
+ (new_exact_no_check term))
+ | _ ->
+ (* To deprecate in favor of generalize? *)
+ Tacticals.New.tclTHEN
+ (Proofview.Unsafe.tclEVARS sigma)
+ (Tacticals.New.tclTHENLAST
+ (cut typ)
+ (new_exact_no_check term))
+ end }
+
(*****************************)
(* Ad hoc unfold *)
(*****************************)
(* The two following functions should already exist, but found nowhere *)
(* Unfolds x by its definition everywhere *)
-let unfold_body x gl =
- let hyps = pf_hyps gl in
- let xval =
- match Context.lookup_named x hyps with
- (_,Some xval,_) -> xval
- | _ -> errorlabstrm "unfold_body"
- (pr_id x ++ str" is not a defined hypothesis.") in
- let aft = afterHyp x gl in
- let hl = List.fold_right (fun (y,yval,_) cl -> (y,InHyp) :: cl) aft [] in
+let unfold_body x =
+ let open Context.Named.Declaration in
+ Proofview.Goal.enter { enter = begin fun gl ->
+ (** We normalize the given hypothesis immediately. *)
+ let hyps = Proofview.Goal.hyps (Proofview.Goal.assume gl) in
+ let xval = match Context.Named.lookup x hyps with
+ | LocalAssum _ -> errorlabstrm "unfold_body"
+ (pr_id x ++ str" is not a defined hypothesis.")
+ | LocalDef (_,xval,_) -> pf_nf_evar gl xval
+ in
+ Tacticals.New.afterHyp x begin fun aft ->
+ let hl = List.fold_right (fun decl cl -> (get_id decl, InHyp) :: cl) aft [] in
let xvar = mkVar x in
let rfun _ _ c = replace_term xvar xval c in
- tclTHENLIST
- [tclMAP (fun h -> reduct_in_hyp rfun h) hl;
- reduct_in_concl (rfun,DEFAULTcast)] gl
+ let reducth h = reduct_in_hyp rfun h in
+ let reductc = reduct_in_concl (rfun, DEFAULTcast) in
+ Tacticals.New.tclTHENLIST [Tacticals.New.tclMAP reducth hl; reductc]
+ end
+ end }
(* Either unfold and clear if defined or simply clear if not a definition *)
-let expand_hyp id = tclTHEN (tclTRY (unfold_body id)) (clear [id])
+let expand_hyp id = Tacticals.New.tclTHEN (Tacticals.New.tclTRY (unfold_body id)) (Proofview.V82.tactic (clear [id]))
(*****************************)
(* High-level induction *)
@@ -2670,8 +2789,6 @@ let expand_hyp id = tclTHEN (tclTRY (unfold_body id)) (clear [id])
- [hyp0] is the induction hypothesis
- we extract from [args] the variables which are not rigid parameters
of the inductive type, this is [indvars] (other terms are forgotten);
- [indhyps] are the ones which actually are declared in context
- (done in [find_atomic_param_of_ind])
- we look for all hyps depending of [hyp0] or one of [indvars]:
this is [dephyps] of types [deptyps] respectively
- [statuslist] tells for each hyps in [dephyps] after which other hyp
@@ -2683,7 +2800,7 @@ let expand_hyp id = tclTHEN (tclTRY (unfold_body id)) (clear [id])
Strategy: (cf in [induction_with_atomization_of_ind_arg])
- requantify and clear all [dephyps]
- apply induction on [hyp0]
- - clear [indhyps] and [hyp0]
+ - clear those of [indvars] that are variables and [hyp0]
- in the i-th subgoal, intro the arguments of the i-th constructor
of the inductive type after [hyp0succ] (done in
[induct_discharge]) let the induction hypotheses on top of the
@@ -2701,7 +2818,7 @@ let check_unused_names names =
(str"Unused introduction " ++ str (String.plural (List.length names) "pattern")
++ str": " ++ prlist_with_sep spc
(Miscprint.pr_intro_pattern
- (fun c -> Printer.pr_constr (snd (c (Global.env()) Evd.empty)))) names)
+ (fun c -> Printer.pr_constr (fst (run_delayed (Global.env()) Evd.empty c)))) names)
let intropattern_of_name gl avoid = function
| Anonymous -> IntroNaming IntroAnonymous
@@ -2779,9 +2896,9 @@ let induct_discharge dests avoid' tac (avoid,ra) names =
let avoid = avoid @ avoid' in
let rec peel_tac ra dests names thin =
match ra with
- | (RecArg,deprec,recvarname) ::
- (IndArg,depind,hyprecname) :: ra' ->
- Proofview.Goal.enter begin fun gl ->
+ | (RecArg,_,deprec,recvarname) ::
+ (IndArg,_,depind,hyprecname) :: ra' ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let (recpat,names) = match names with
| [loc,IntroNaming (IntroIdentifier id) as pat] ->
let id' = next_ident_away (add_prefix "IH" id) avoid in
@@ -2789,37 +2906,37 @@ let induct_discharge dests avoid' tac (avoid,ra) names =
| _ -> consume_pattern avoid (Name recvarname) deprec gl names in
let dest = get_recarg_dest dests in
dest_intro_patterns avoid thin dest [recpat] (fun ids thin ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let (hyprec,names) =
consume_pattern avoid (Name hyprecname) depind gl names
in
dest_intro_patterns avoid thin MoveLast [hyprec] (fun ids' thin ->
peel_tac ra' (update_dest dests ids') names thin)
- end)
- end
- | (IndArg,dep,hyprecname) :: ra' ->
- Proofview.Goal.enter begin fun gl ->
+ end })
+ end }
+ | (IndArg,_,dep,hyprecname) :: ra' ->
+ Proofview.Goal.enter { enter = begin fun gl ->
(* Rem: does not happen in Coq schemes, only in user-defined schemes *)
let pat,names =
consume_pattern avoid (Name hyprecname) dep gl names in
dest_intro_patterns avoid thin MoveLast [pat] (fun ids thin ->
peel_tac ra' (update_dest dests ids) names thin)
- end
- | (RecArg,dep,recvarname) :: ra' ->
- Proofview.Goal.enter begin fun gl ->
+ end }
+ | (RecArg,_,dep,recvarname) :: ra' ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let (pat,names) =
consume_pattern avoid (Name recvarname) dep gl names in
let dest = get_recarg_dest dests in
dest_intro_patterns avoid thin dest [pat] (fun ids thin ->
peel_tac ra' dests names thin)
- end
- | (OtherArg,dep,_) :: ra' ->
- Proofview.Goal.enter begin fun gl ->
+ end }
+ | (OtherArg,_,dep,_) :: ra' ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let (pat,names) = consume_pattern avoid Anonymous dep gl names in
let dest = get_recarg_dest dests in
safe_dest_intro_patterns avoid thin dest [pat] (fun ids thin ->
peel_tac ra' dests names thin)
- end
+ end }
| [] ->
check_unused_names names;
Tacticals.New.tclTHEN (clear_wildcards thin) (tac dests)
@@ -2831,6 +2948,7 @@ let induct_discharge dests avoid' tac (avoid,ra) names =
substitutions aussi sur l'argument voisin *)
let expand_projections env sigma c =
+ let sigma = Sigma.to_evar_map sigma in
let rec aux env c =
match kind_of_term c with
| Proj (p, c) -> Retyping.expand_projection env sigma p (aux env c) []
@@ -2841,7 +2959,7 @@ let expand_projections env sigma c =
(* Marche pas... faut prendre en compte l'occurrence précise... *)
let atomize_param_of_ind_then (indref,nparams,_) hyp0 tac =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let tmptyp0 = Tacmach.New.pf_get_hyp_typ hyp0 (Proofview.Goal.assume gl) in
let reduce_to_quantified_ref = Tacmach.New.pf_apply reduce_to_quantified_ref gl in
@@ -2894,7 +3012,7 @@ let atomize_param_of_ind_then (indref,nparams,_) hyp0 tac =
(atomize_one (i-1) (mkVar x::args) (mkVar x::args') (x::avoid))
in
atomize_one (List.length argl) [] [] []
- end
+ end }
(* [cook_sign] builds the lists [beforetoclear] (preceding the
ind. var.) and [aftertoclear] (coming after the ind. var.) of hyps
@@ -2918,7 +3036,6 @@ let atomize_param_of_ind_then (indref,nparams,_) hyp0 tac =
Induction hypothesis is H4 ([hyp0])
Variable parameters of (le O n) is the singleton list with "n" ([indvars])
- Part of [indvars] really in context is the same ([indhyps])
The dependent hyps are H3 and H6 ([dephyps])
For H3 the memorized places are H5 ([lhyp]) and H2 ([rhyp])
because these names are among the hyp which are fixed through the induction
@@ -2963,8 +3080,9 @@ let atomize_param_of_ind_then (indref,nparams,_) hyp0 tac =
exception Shunt of Id.t move_location
let cook_sign hyp0_opt inhyps indvars env =
- (* First phase from L to R: get [indhyps], [decldep] and [statuslist]
+ (* First phase from L to R: get [toclear], [decldep] and [statuslist]
for the hypotheses before (= more ancient than) hyp0 (see above) *)
+ let open Context.Named.Declaration in
let toclear = ref [] in
let avoid = ref [] in
let decldeps = ref [] in
@@ -2973,7 +3091,8 @@ let cook_sign hyp0_opt inhyps indvars env =
let lstatus = ref [] in
let before = ref true in
let maindep = ref false in
- let seek_deps env (hyp,_,_ as decl) rhyp =
+ let seek_deps env decl rhyp =
+ let hyp = get_id decl in
if (match hyp0_opt with Some hyp0 -> Id.equal hyp hyp0 | _ -> false)
then begin
before:=false;
@@ -2992,7 +3111,7 @@ let cook_sign hyp0_opt inhyps indvars env =
in
let depother = List.is_empty inhyps &&
(List.exists (fun id -> occur_var_in_decl env id decl) indvars ||
- List.exists (fun (id,_,_) -> occur_var_in_decl env id decl) !decldeps)
+ List.exists (fun decl' -> occur_var_in_decl env (get_id decl') decl) !decldeps)
in
if not (List.is_empty inhyps) && Id.List.mem hyp inhyps
|| dephyp0 || depother
@@ -3014,7 +3133,8 @@ let cook_sign hyp0_opt inhyps indvars env =
in
let _ = fold_named_context seek_deps env ~init:MoveFirst in
(* 2nd phase from R to L: get left hyp of [hyp0] and [lhyps] *)
- let compute_lstatus lhyp (hyp,_,_) =
+ let compute_lstatus lhyp decl =
+ let hyp = get_id decl in
if (match hyp0_opt with Some hyp0 -> Id.equal hyp hyp0 | _ -> false) then
raise (Shunt lhyp);
if Id.List.mem hyp !ldeps then begin
@@ -3064,20 +3184,20 @@ type elim_scheme = {
elimc: constr with_bindings option;
elimt: types;
indref: global_reference option;
- params: rel_context; (* (prm1,tprm1);(prm2,tprm2)...(prmp,tprmp) *)
- nparams: int; (* number of parameters *)
- predicates: rel_context; (* (Qq, (Tq_1 -> Tq_2 ->...-> Tq_nq)), (Q1,...) *)
- npredicates: int; (* Number of predicates *)
- branches: rel_context; (* branchr,...,branch1 *)
- nbranches: int; (* Number of branches *)
- args: rel_context; (* (xni, Ti_ni) ... (x1, Ti_1) *)
- nargs: int; (* number of arguments *)
- indarg: rel_declaration option; (* Some (H,I prm1..prmp x1...xni)
- if HI is in premisses, None otherwise *)
- concl: types; (* Qi x1...xni HI (f...), HI and (f...)
- are optional and mutually exclusive *)
- indarg_in_concl: bool; (* true if HI appears at the end of conclusion *)
- farg_in_concl: bool; (* true if (f...) appears at the end of conclusion *)
+ params: Context.Rel.t; (* (prm1,tprm1);(prm2,tprm2)...(prmp,tprmp) *)
+ nparams: int; (* number of parameters *)
+ predicates: Context.Rel.t; (* (Qq, (Tq_1 -> Tq_2 ->...-> Tq_nq)), (Q1,...) *)
+ npredicates: int; (* Number of predicates *)
+ branches: Context.Rel.t; (* branchr,...,branch1 *)
+ nbranches: int; (* Number of branches *)
+ args: Context.Rel.t; (* (xni, Ti_ni) ... (x1, Ti_1) *)
+ nargs: int; (* number of arguments *)
+ indarg: Context.Rel.Declaration.t option; (* Some (H,I prm1..prmp x1...xni)
+ if HI is in premisses, None otherwise *)
+ concl: types; (* Qi x1...xni HI (f...), HI and (f...)
+ are optional and mutually exclusive *)
+ indarg_in_concl: bool; (* true if HI appears at the end of conclusion *)
+ farg_in_concl: bool; (* true if (f...) appears at the end of conclusion *)
}
let empty_scheme =
@@ -3197,31 +3317,36 @@ let decompose_indapp f args =
| _ -> f, args
let mk_term_eq env sigma ty t ty' t' =
+ let sigma = Sigma.to_evar_map sigma in
if Reductionops.is_conv env sigma ty ty' then
mkEq ty t t', mkRefl ty' t'
else
mkHEq ty t ty' t', mkHRefl ty' t'
-let make_abstract_generalize gl id concl dep ctx body c eqs args refls =
- let meta = Evarutil.new_meta() in
+let make_abstract_generalize env id typ concl dep ctx body c eqs args refls =
+ let open Context.Rel.Declaration in
+ Proofview.Refine.refine { run = begin fun sigma ->
let eqslen = List.length eqs in
- let term, typ = mkVar id, pf_get_hyp_typ gl id in
(* Abstract by the "generalized" hypothesis equality proof if necessary. *)
let abshypeq, abshypt =
if dep then
- let eq, refl = mk_term_eq (push_rel_context ctx (pf_env gl)) (project gl) (lift 1 c) (mkRel 1) typ term in
+ let eq, refl = mk_term_eq (push_rel_context ctx env) sigma (lift 1 c) (mkRel 1) typ (mkVar id) in
mkProd (Anonymous, eq, lift 1 concl), [| refl |]
else concl, [||]
in
(* Abstract by equalities *)
let eqs = lift_togethern 1 eqs in (* lift together and past genarg *)
- let abseqs = it_mkProd_or_LetIn (lift eqslen abshypeq) (List.map (fun x -> (Anonymous, None, x)) eqs) in
+ let abseqs = it_mkProd_or_LetIn (lift eqslen abshypeq) (List.map (fun x -> LocalAssum (Anonymous, x)) eqs) in
+ let decl = match body with
+ | None -> LocalAssum (Name id, c)
+ | Some body -> LocalDef (Name id, body, c)
+ in
(* Abstract by the "generalized" hypothesis. *)
- let genarg = mkProd_or_LetIn (Name id, body, c) abseqs in
+ let genarg = mkProd_or_LetIn decl abseqs in
(* Abstract by the extension of the context *)
let genctyp = it_mkProd_or_LetIn genarg ctx in
(* The goal will become this product. *)
- let genc = mkCast (mkMeta meta, DEFAULTcast, genctyp) in
+ let Sigma (genc, sigma, p) = Evarutil.new_evar env sigma ~principal:true genctyp in
(* Apply the old arguments giving the proper instantiation of the hyp *)
let instc = mkApp (genc, Array.of_list args) in
(* Then apply to the original instantiated hyp. *)
@@ -3229,14 +3354,17 @@ let make_abstract_generalize gl id concl dep ctx body c eqs args refls =
(* Apply the reflexivity proofs on the indices. *)
let appeqs = mkApp (instc, Array.of_list refls) in
(* Finally, apply the reflexivity proof for the original hyp, to get a term of type gl again. *)
- mkApp (appeqs, abshypt)
+ Sigma (mkApp (appeqs, abshypt), sigma, p)
+ end }
let hyps_of_vars env sign nogen hyps =
+ let open Context.Named.Declaration in
if Id.Set.is_empty hyps then []
else
let (_,lh) =
- Context.fold_named_context_reverse
- (fun (hs,hl) (x,_,_ as d) ->
+ Context.Named.fold_inside
+ (fun (hs,hl) d ->
+ let x = get_id d in
if Id.Set.mem x nogen then (hs,hl)
else if Id.Set.mem x hs then (hs,x::hl)
else
@@ -3265,14 +3393,15 @@ let linear vars args =
true
with Seen -> false
-let is_defined_variable env id = match lookup_named id env with
-| (_, None, _) -> false
-| (_, Some _, _) -> true
+let is_defined_variable env id =
+ let open Context.Named.Declaration in
+ lookup_named id env |> is_local_def
let abstract_args gl generalize_vars dep id defined f args =
- let sigma = ref (project gl) in
- let env = pf_env gl in
- let concl = pf_concl gl in
+ let open Context.Rel.Declaration in
+ let sigma = ref (Tacmach.project gl) in
+ let env = Tacmach.pf_env gl in
+ let concl = Tacmach.pf_concl gl in
let dep = dep || dependent (mkVar id) concl in
let avoid = ref [] in
let get_id name =
@@ -3286,11 +3415,12 @@ let abstract_args gl generalize_vars dep id defined f args =
eqs are not lifted w.r.t. each other yet. (* will be needed when going to dependent indexes *)
*)
let aux (prod, ctx, ctxenv, c, args, eqs, refls, nongenvars, vars, env) arg =
- let (name, _, ty), arity =
+ let name, ty, arity =
let rel, c = Reductionops.splay_prod_n env !sigma 1 prod in
- List.hd rel, c
+ let decl = List.hd rel in
+ get_name decl, get_type decl, c
in
- let argty = pf_unsafe_type_of gl arg in
+ let argty = Tacmach.pf_unsafe_type_of gl arg in
let sigma', ty = Evarsolve.refresh_universes (Some true) env !sigma ty in
let () = sigma := sigma' in
let lenctx = List.length ctx in
@@ -3302,7 +3432,7 @@ let abstract_args gl generalize_vars dep id defined f args =
Id.Set.add id nongenvars, Id.Set.remove id vars, env)
| _ ->
let name = get_id name in
- let decl = (Name name, None, ty) in
+ let decl = LocalAssum (Name name, ty) in
let ctx = decl :: ctx in
let c' = mkApp (lift 1 c, [|mkRel 1|]) in
let args = arg :: args in
@@ -3331,7 +3461,7 @@ let abstract_args gl generalize_vars dep id defined f args =
true, mkApp (f', before), after
in
if dogen then
- let tyf' = pf_unsafe_type_of gl f' in
+ let tyf' = Tacmach.pf_unsafe_type_of gl f' in
let arity, ctx, ctxenv, c', args, eqs, refls, nogen, vars, env =
Array.fold_left aux (tyf',[],env,f',[],[],[],Id.Set.empty,Id.Set.empty,env) args'
in
@@ -3343,23 +3473,25 @@ let abstract_args gl generalize_vars dep id defined f args =
else []
in
let body, c' =
- if defined then Some c', typ_of ctxenv !sigma c'
+ if defined then Some c', Retyping.get_type_of ctxenv !sigma c'
else None, c'
in
- let term = make_abstract_generalize {gl with sigma = !sigma} id concl dep ctx body c' eqs args refls in
- Some (term, !sigma, dep, succ (List.length ctx), vars)
+ let typ = Tacmach.pf_get_hyp_typ gl id in
+ let tac = make_abstract_generalize (pf_env gl) id typ concl dep ctx body c' eqs args refls in
+ let tac = Proofview.Unsafe.tclEVARS !sigma <*> tac in
+ Some (tac, dep, succ (List.length ctx), vars)
else None
let abstract_generalize ?(generalize_vars=true) ?(force_dep=false) id =
- Proofview.Goal.nf_enter begin fun gl ->
+ let open Context.Named.Declaration in
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
Coqlib.check_required_library Coqlib.jmeq_module_name;
let (f, args, def, id, oldid) =
let oldid = Tacmach.New.pf_get_new_id id gl in
- let (_, b, t) = Tacmach.New.pf_get_hyp id gl in
- match b with
- | None -> let f, args = decompose_app t in
+ match Tacmach.New.pf_get_hyp id gl with
+ | LocalAssum (_,t) -> let f, args = decompose_app t in
(f, args, false, id, oldid)
- | Some t ->
+ | LocalDef (_,t,_) ->
let f, args = decompose_app t in
(f, args, true, id, oldid)
in
@@ -3369,17 +3501,15 @@ let abstract_generalize ?(generalize_vars=true) ?(force_dep=false) id =
let newc = Tacmach.New.of_old (fun gl -> abstract_args gl generalize_vars force_dep id def f args) gl in
match newc with
| None -> Proofview.tclUNIT ()
- | Some (newc, sigma, dep, n, vars) ->
+ | Some (tac, dep, n, vars) ->
let tac =
if dep then
- Tacticals.New.tclTHENLIST
- [Proofview.Unsafe.tclEVARS sigma;
- Proofview.V82.tactic (refine newc);
+ Tacticals.New.tclTHENLIST [
+ tac;
rename_hyp [(id, oldid)]; Tacticals.New.tclDO n intro;
Proofview.V82.tactic (generalize_dep ~with_let:true (mkVar oldid))]
- else Tacticals.New.tclTHENLIST
- [Proofview.Unsafe.tclEVARS sigma;
- Proofview.V82.tactic (refine newc);
+ else Tacticals.New.tclTHENLIST [
+ tac;
Proofview.V82.tactic (clear [id]);
Tacticals.New.tclDO n intro]
in
@@ -3389,15 +3519,16 @@ let abstract_generalize ?(generalize_vars=true) ?(force_dep=false) id =
[revert vars ;
Proofview.V82.tactic (fun gl -> tclMAP (fun id ->
tclTRY (generalize_dep ~with_let:true (mkVar id))) vars gl)])
- end
+ end }
let rec compare_upto_variables x y =
if (isVar x || isRel x) && (isVar y || isRel y) then true
else compare_constr compare_upto_variables x y
let specialize_eqs id gl =
- let env = pf_env gl in
- let ty = pf_get_hyp_typ gl id in
+ let open Context.Rel.Declaration in
+ let env = Tacmach.pf_env gl in
+ let ty = Tacmach.pf_get_hyp_typ gl id in
let evars = ref (project gl) in
let unif env evars c1 c2 =
compare_upto_variables c1 c2 && Evarconv.e_conv env evars c1 c2
@@ -3424,15 +3555,14 @@ let specialize_eqs id gl =
if in_eqs then acc, in_eqs, ctx, ty
else
let e = e_new_evar (push_rel_context ctx env) evars t in
- aux false ((na, Some e, t) :: ctx) (mkApp (lift 1 acc, [| mkRel 1 |])) b)
+ aux false (LocalDef (na,e,t) :: ctx) (mkApp (lift 1 acc, [| mkRel 1 |])) b)
| t -> acc, in_eqs, ctx, ty
in
let acc, worked, ctx, ty = aux false [] (mkVar id) ty in
let ctx' = nf_rel_context_evar !evars ctx in
- let ctx'' = List.map (fun (n,b,t as decl) ->
- match b with
- | Some k when isEvar k -> (n,None,t)
- | b -> decl) ctx'
+ let ctx'' = List.map (function
+ | LocalDef (n,k,t) when isEvar k -> LocalAssum (n,t)
+ | decl -> decl) ctx'
in
let ty' = it_mkProd_or_LetIn ty ctx'' in
let acc' = it_mkLambda_or_LetIn acc ctx'' in
@@ -3466,18 +3596,19 @@ let occur_rel n c =
We also return the conclusion.
*)
let decompose_paramspred_branch_args elimt =
- let rec cut_noccur elimt acc2 : rel_context * rel_context * types =
+ let open Context.Rel.Declaration in
+ let rec cut_noccur elimt acc2 =
match kind_of_term elimt with
| Prod(nme,tpe,elimt') ->
let hd_tpe,_ = decompose_app ((strip_prod_assum tpe)) in
if not (occur_rel 1 elimt') && isRel hd_tpe
- then cut_noccur elimt' ((nme,None,tpe)::acc2)
+ then cut_noccur elimt' (LocalAssum (nme,tpe)::acc2)
else let acc3,ccl = decompose_prod_assum elimt in acc2 , acc3 , ccl
| App(_, _) | Rel _ -> acc2 , [] , elimt
| _ -> error_ind_scheme "" in
- let rec cut_occur elimt acc1 : rel_context * rel_context * rel_context * types =
+ let rec cut_occur elimt acc1 =
match kind_of_term elimt with
- | Prod(nme,tpe,c) when occur_rel 1 c -> cut_occur c ((nme,None,tpe)::acc1)
+ | Prod(nme,tpe,c) when occur_rel 1 c -> cut_occur c (LocalAssum (nme,tpe)::acc1)
| Prod(nme,tpe,c) -> let acc2,acc3,ccl = cut_noccur elimt [] in acc1,acc2,acc3,ccl
| App(_, _) | Rel _ -> acc1,[],[],elimt
| _ -> error_ind_scheme "" in
@@ -3519,6 +3650,7 @@ let exchange_hd_app subst_hd t =
- finish to fill in the elim_scheme: indarg/farg/args and finally indref. *)
let compute_elim_sig ?elimc elimt =
+ let open Context.Rel.Declaration in
let params_preds,branches,args_indargs,conclusion =
decompose_paramspred_branch_args elimt in
@@ -3552,8 +3684,8 @@ let compute_elim_sig ?elimc elimt =
(* 3- Look at last arg: is it the indarg? *)
ignore (
match List.hd args_indargs with
- | hiname,Some _,hi -> error_ind_scheme ""
- | hiname,None,hi ->
+ | LocalDef (hiname,_,hi) -> error_ind_scheme ""
+ | LocalAssum (hiname,hi) ->
let hi_ind, hi_args = decompose_app hi in
let hi_is_ind = (* hi est d'un type globalisable *)
match kind_of_term hi_ind with
@@ -3577,24 +3709,25 @@ let compute_elim_sig ?elimc elimt =
with Exit -> (* Ending by computing indref: *)
match !res.indarg with
| None -> !res (* No indref *)
- | Some ( _,Some _,_) -> error_ind_scheme ""
- | Some ( _,None,ind) ->
+ | Some (LocalDef _) -> error_ind_scheme ""
+ | Some (LocalAssum (_,ind)) ->
let indhd,indargs = decompose_app ind in
try {!res with indref = Some (global_of_constr indhd) }
with e when Errors.noncritical e ->
error "Cannot find the inductive type of the inductive scheme."
let compute_scheme_signature scheme names_info ind_type_guess =
+ let open Context.Rel.Declaration in
let f,l = decompose_app scheme.concl in
(* Vérifier que les arguments de Qi sont bien les xi. *)
let cond, check_concl =
match scheme.indarg with
- | Some (_,Some _,_) ->
+ | Some (LocalDef _) ->
error "Strange letin, cannot recognize an induction scheme."
| None -> (* Non standard scheme *)
let cond hd = Term.eq_constr hd ind_type_guess && not scheme.farg_in_concl
in (cond, fun _ _ -> ())
- | Some ( _,None,ind) -> (* Standard scheme from an inductive type *)
+ | Some (LocalAssum (_,ind)) -> (* Standard scheme from an inductive type *)
let indhd,indargs = decompose_app ind in
let cond hd = Term.eq_constr hd indhd in
let check_concl is_pred p =
@@ -3603,7 +3736,7 @@ let compute_scheme_signature scheme names_info ind_type_guess =
let ind_is_ok =
List.equal Term.eq_constr
(List.lastn scheme.nargs indargs)
- (extended_rel_list 0 scheme.args) in
+ (Context.Rel.to_extended_list 0 scheme.args) in
if not (ccl_arg_ok && ind_is_ok) then
error_ind_scheme "the conclusion of"
in (cond, check_concl)
@@ -3618,28 +3751,28 @@ let compute_scheme_signature scheme names_info ind_type_guess =
let rec check_branch p c =
match kind_of_term c with
| Prod (_,t,c) ->
- (is_pred p t, dependent (mkRel 1) c) :: check_branch (p+1) c
+ (is_pred p t, true, dependent (mkRel 1) c) :: check_branch (p+1) c
| LetIn (_,_,_,c) ->
- (OtherArg, dependent (mkRel 1) c) :: check_branch (p+1) c
+ (OtherArg, false, dependent (mkRel 1) c) :: check_branch (p+1) c
| _ when is_pred p c == IndArg -> []
| _ -> raise Exit
in
let rec find_branches p lbrch =
match lbrch with
- | (_,None,t)::brs ->
+ | LocalAssum (_,t) :: brs ->
(try
let lchck_brch = check_branch p t in
let n = List.fold_left
- (fun n (b,_) -> if b == RecArg then n+1 else n) 0 lchck_brch in
+ (fun n (b,_,_) -> if b == RecArg then n+1 else n) 0 lchck_brch in
let recvarname, hyprecname, avoid =
make_up_names n scheme.indref names_info in
let namesign =
- List.map (fun (b,dep) ->
- (b, dep, if b == IndArg then hyprecname else recvarname))
+ List.map (fun (b,is_assum,dep) ->
+ (b,is_assum,dep,if b == IndArg then hyprecname else recvarname))
lchck_brch in
(avoid,namesign) :: find_branches (p+1) brs
with Exit-> error_ind_scheme "the branches of")
- | (_,Some _,_)::_ -> error_ind_scheme "the branches of"
+ | LocalDef _ :: _ -> error_ind_scheme "the branches of"
| [] -> check_concl is_pred p; []
in
Array.of_list (find_branches 0 (List.rev scheme.branches))
@@ -3661,21 +3794,26 @@ let guess_elim isrec dep s hyp0 gl =
let evd, elimc =
if isrec && not (is_nonrec (fst mind)) then find_ind_eliminator (fst mind) s gl
else
+ let env = Tacmach.New.pf_env gl in
+ let sigma = Sigma.Unsafe.of_evar_map (Tacmach.New.project gl) in
if use_dependent_propositions_elimination () && dep
then
- Tacmach.New.pf_apply build_case_analysis_scheme gl mind true s
+ let Sigma (ind, sigma, _) = build_case_analysis_scheme env sigma mind true s in
+ (Sigma.to_evar_map sigma, ind)
else
- Tacmach.New.pf_apply build_case_analysis_scheme_default gl mind s in
+ let Sigma (ind, sigma, _) = build_case_analysis_scheme_default env sigma mind s in
+ (Sigma.to_evar_map sigma, ind)
+ in
let elimt = Tacmach.New.pf_unsafe_type_of gl elimc in
evd, ((elimc, NoBindings), elimt), mkIndU mind
let given_elim hyp0 (elimc,lbind as e) gl =
let tmptyp0 = Tacmach.New.pf_get_hyp_typ hyp0 gl in
let ind_type_guess,_ = decompose_app ((strip_prod tmptyp0)) in
- Proofview.Goal.sigma gl, (e, Tacmach.New.pf_unsafe_type_of gl elimc), ind_type_guess
+ Tacmach.New.project gl, (e, Tacmach.New.pf_unsafe_type_of gl elimc), ind_type_guess
type scheme_signature =
- (Id.t list * (elim_arg_kind * bool * Id.t) list) array
+ (Id.t list * (elim_arg_kind * bool * bool * Id.t) list) array
type eliminator_source =
| ElimUsing of (eliminator * types) * scheme_signature
@@ -3715,13 +3853,15 @@ let is_functional_induction elimc gl =
(* Wait the last moment to guess the eliminator so as to know if we
need a dependent one or not *)
-let get_eliminator elim dep s gl = match elim with
+let get_eliminator elim dep s gl =
+ let open Context.Rel.Declaration in
+ match elim with
| ElimUsing (elim,indsign) ->
- Proofview.Goal.sigma gl, (* bugged, should be computed *) true, elim, indsign
+ Tacmach.New.project gl, (* bugged, should be computed *) true, elim, indsign
| ElimOver (isrec,id) ->
let evd, (elimc,elimt),_ as elims = guess_elim isrec dep s id gl in
let _, (l, s) = compute_elim_signature elims id in
- let branchlengthes = List.map (fun (_,b,c) -> assert (b=None); pi1 (decompose_prod_letin c)) (List.rev s.branches) in
+ let branchlengthes = List.map (fun d -> assert (is_local_assum d); pi1 (decompose_prod_letin (get_type d))) (List.rev s.branches) in
evd, isrec, ({elimindex = None; elimbody = elimc; elimrename = Some (isrec,Array.of_list branchlengthes)}, elimt), l
(* Instantiate all meta variables of elimclause using lid, some elts
@@ -3740,10 +3880,10 @@ let recolle_clenv i params args elimclause gl =
let k = match i with -1 -> Array.length lindmv - List.length args | _ -> i in
(* parameters correspond to first elts of lid. *)
let clauses_params =
- List.map_i (fun i id -> mkVar id , pf_get_hyp_typ gl id , lindmv.(i))
+ List.map_i (fun i id -> mkVar id , Tacmach.pf_get_hyp_typ gl id , lindmv.(i))
0 params in
let clauses_args =
- List.map_i (fun i id -> mkVar id , pf_get_hyp_typ gl id , lindmv.(k+i))
+ List.map_i (fun i id -> mkVar id , Tacmach.pf_get_hyp_typ gl id , lindmv.(k+i))
0 args in
let clauses = clauses_params@clauses_args in
(* iteration of clenv_fchain with all infos we have. *)
@@ -3770,7 +3910,7 @@ let induction_tac with_evars params indvars elim gl =
let elimc = contract_letin_in_lam_header elimc in
let elimc = mkCast (elimc, DEFAULTcast, elimt) in
let elimclause =
- pf_apply make_clenv_binding gl (elimc,elimt) lbindelimc in
+ Tacmach.pf_apply make_clenv_binding gl (elimc,elimt) lbindelimc in
(* elimclause' is built from elimclause by instanciating all args and params. *)
let elimclause' = recolle_clenv i params indvars elimclause gl in
(* one last resolution (useless?) *)
@@ -3782,40 +3922,48 @@ let induction_tac with_evars params indvars elim gl =
induction applies with the induction hypotheses *)
let apply_induction_in_context hyp0 inhyps elim indvars names induct_tac =
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ let open Context.Named.Declaration in
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
+ let sigma = Sigma.to_evar_map sigma in
let concl = Tacmach.New.pf_nf_concl gl in
- let statuslists,lhyp0,toclear,deps,avoid,dep = cook_sign hyp0 inhyps indvars env in
- let dep = dep || Option.cata (fun id -> occur_var env id concl) false hyp0 in
+ let statuslists,lhyp0,toclear,deps,avoid,dep_in_hyps = cook_sign hyp0 inhyps indvars env in
+ let dep_in_concl = Option.cata (fun id -> occur_var env id concl) false hyp0 in
+ let dep = dep_in_hyps || dep_in_concl in
let tmpcl = it_mkNamedProd_or_LetIn concl deps in
let s = Retyping.get_sort_family_of env sigma tmpcl in
let deps_cstr =
List.fold_left
- (fun a (id,b,_) -> if Option.is_empty b then (mkVar id)::a else a) [] deps in
+ (fun a decl -> if is_local_assum decl then (mkVar (get_id decl))::a else a) [] deps in
let (sigma, isrec, elim, indsign) = get_eliminator elim dep s (Proofview.Goal.assume gl) in
- let names = compute_induction_names (Array.length indsign) names in
+ let branchletsigns =
+ let f (_,is_not_let,_,_) = is_not_let in
+ Array.map (fun (_,l) -> List.map f l) indsign in
+ let names = compute_induction_names branchletsigns names in
+ let tac =
(if isrec then Tacticals.New.tclTHENFIRSTn else Tacticals.New.tclTHENLASTn)
(Tacticals.New.tclTHENLIST [
- Proofview.Unsafe.tclEVARS sigma;
(* Generalize dependent hyps (but not args) *)
- if deps = [] then Proofview.tclUNIT () else Proofview.V82.tactic (apply_type tmpcl deps_cstr);
+ if deps = [] then Proofview.tclUNIT () else apply_type tmpcl deps_cstr;
(* side-conditions in elim (resp case) schemes come last (resp first) *)
induct_tac elim;
- Proofview.V82.tactic (tclMAP expand_hyp toclear)
+ Tacticals.New.tclMAP expand_hyp toclear;
])
(Array.map2
(induct_discharge lhyp0 avoid (re_intro_dependent_hypotheses statuslists))
indsign names)
- end
+ in
+ Sigma.Unsafe.of_pair (tac, sigma)
+ end }
let induction_with_atomization_of_ind_arg isrec with_evars elim names hyp0 inhyps =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let elim_info = find_induction_type isrec elim hyp0 (Proofview.Goal.assume gl) in
atomize_param_of_ind_then elim_info hyp0 (fun indvars ->
apply_induction_in_context (Some hyp0) inhyps (pi3 elim_info) indvars names
(fun elim -> Proofview.V82.tactic (induction_tac with_evars [] [hyp0] elim)))
- end
+ end }
let msg_not_right_number_induction_arguments scheme =
str"Not the right number of induction arguments (expected " ++
@@ -3832,7 +3980,7 @@ let msg_not_right_number_induction_arguments scheme =
must be given, so we help a bit the unifier by making the "pattern"
by hand before calling induction_tac *)
let induction_without_atomization isrec with_evars elim names lid =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let sigma, (indsign,scheme) = get_elim_signature elim (List.hd lid) gl in
let nargs_indarg_farg =
scheme.nargs + (if scheme.farg_in_concl then 1 else 0) in
@@ -3854,7 +4002,7 @@ let induction_without_atomization isrec with_evars elim names lid =
if indvars = [] then [List.hd lid_params] else indvars in
let induct_tac elim = Proofview.V82.tactic (tclTHENLIST [
(* pattern to make the predicate appear. *)
- reduce (Pattern (List.map inj_with_occurrences lidcstr)) onConcl;
+ Proofview.V82.of_tactic (reduce (Pattern (List.map inj_with_occurrences lidcstr)) onConcl);
(* Induction by "refine (indscheme ?i ?j ?k...)" + resolution of all
possible holes using arguments given by the user (but the
functional one). *)
@@ -3863,18 +4011,20 @@ let induction_without_atomization isrec with_evars elim names lid =
]) in
let elim = ElimUsing (({elimindex = Some (-1); elimbody = Option.get scheme.elimc; elimrename = None}, scheme.elimt), indsign) in
apply_induction_in_context None [] elim indvars names induct_tac
- end
+ end }
(* assume that no occurrences are selected *)
let clear_unselected_context id inhyps cls gl =
- if occur_var (pf_env gl) id (pf_concl gl) &&
+ let open Context.Named.Declaration in
+ if occur_var (Tacmach.pf_env gl) id (Tacmach.pf_concl gl) &&
cls.concl_occs == NoOccurrences
then errorlabstrm ""
(str "Conclusion must be mentioned: it depends on " ++ pr_id id
++ str ".");
match cls.onhyps with
| Some hyps ->
- let to_erase (id',_,_ as d) =
+ let to_erase d =
+ let id' = get_id d in
if Id.List.mem id' inhyps then (* if selected, do not erase *) None
else
(* erase if not selected and dependent on id or selected hyps *)
@@ -3885,6 +4035,7 @@ let clear_unselected_context id inhyps cls gl =
| None -> tclIDTAC gl
let use_bindings env sigma elim must_be_closed (c,lbind) typ =
+ let sigma = Sigma.to_evar_map sigma in
let typ =
if elim == None then
(* w/o an scheme, the term has to be applied at least until
@@ -3906,7 +4057,8 @@ let use_bindings env sigma elim must_be_closed (c,lbind) typ =
if must_be_closed && occur_meta (clenv_value indclause) then
error "Need a fully applied argument.";
(* We lose the possibility of coercions in with-bindings *)
- pose_all_metas_as_evars env indclause.evd (clenv_value indclause)
+ let (sigma, c) = pose_all_metas_as_evars env indclause.evd (clenv_value indclause) in
+ Sigma.Unsafe.of_pair (c, sigma)
with e when catchable_exception e ->
try find_clause (try_red_product env sigma typ)
with Redelimination -> raise e in
@@ -3924,6 +4076,7 @@ let check_expected_type env sigma (elimc,bl) elimt =
fun t -> Evarconv.e_cumul env (ref sigma) t u
let check_enough_applied env sigma elim =
+ let sigma = Sigma.to_evar_map sigma in
(* A heuristic to decide whether the induction arg is enough applied *)
match elim with
| None ->
@@ -3931,7 +4084,7 @@ let check_enough_applied env sigma elim =
fun u ->
let t,_ = decompose_app (whd_betadeltaiota env sigma u) in isInd t
| Some elimc ->
- let elimt = typ_of env sigma (fst elimc) in
+ let elimt = Retyping.get_type_of env sigma (fst elimc) in
let scheme = compute_elim_sig ~elimc elimt in
match scheme.indref with
| None ->
@@ -3944,13 +4097,13 @@ let check_enough_applied env sigma elim =
let pose_induction_arg_then isrec with_evars (is_arg_pure_hyp,from_prefix) elim
id ((pending,(c0,lbind)),(eqname,names)) t0 inhyps cls tac =
- Proofview.Goal.enter begin fun gl ->
- let env = Proofview.Goal.env gl in
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let sigma = Proofview.Goal.sigma gl in
+ let env = Proofview.Goal.env gl in
let ccl = Proofview.Goal.raw_concl gl in
let store = Proofview.Goal.extra gl in
let check = check_enough_applied env sigma elim in
- let (sigma',c) = use_bindings env sigma elim false (c0,lbind) t0 in
+ let Sigma (c, sigma', p) = use_bindings env sigma elim false (c0,lbind) t0 in
let abs = AbstractPattern (from_prefix,check,Name id,(pending,c),cls,false) in
let (id,sign,_,lastlhyp,ccl,res) = make_abstraction env sigma' ccl abs in
match res with
@@ -3960,7 +4113,8 @@ let pose_induction_arg_then isrec with_evars (is_arg_pure_hyp,from_prefix) elim
(* we restart using bindings after having tried type-class
resolution etc. on the term given by the user *)
let flags = tactic_infer_flags (with_evars && (* do not give a success semantics to edestruct on an open term yet *) false) in
- let (sigma,c0) = finish_evar_resolution ~flags env sigma (pending,c0) in
+ let Sigma (c0, sigma, q) = finish_evar_resolution ~flags env sigma (pending,c0) in
+ let tac =
(if isrec then
(* Historically, induction has side conditions last *)
Tacticals.New.tclTHENFIRST
@@ -3968,12 +4122,13 @@ let pose_induction_arg_then isrec with_evars (is_arg_pure_hyp,from_prefix) elim
(* and destruct has side conditions first *)
Tacticals.New.tclTHENLAST)
(Tacticals.New.tclTHENLIST [
- Proofview.Unsafe.tclEVARS sigma;
- Proofview.Refine.refine ~unsafe:true (fun sigma ->
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
let b = not with_evars && with_eq != None in
- let (sigma,c) = use_bindings env sigma elim b (c0,lbind) t0 in
- let t = Retyping.get_type_of env sigma c in
- mkletin_goal env sigma store with_eq false (id,lastlhyp,ccl,c) (Some t));
+ let Sigma (c, sigma, p) = use_bindings env sigma elim b (c0,lbind) t0 in
+ let t = Retyping.get_type_of env (Sigma.to_evar_map sigma) c in
+ let Sigma (ans, sigma, q) = mkletin_goal env sigma store with_eq false (id,lastlhyp,ccl,c) (Some t) in
+ Sigma (ans, sigma, p +> q)
+ end };
Proofview.(if with_evars then shelve_unifiable else guard_no_unifiable);
if is_arg_pure_hyp
then Tacticals.New.tclTRY (Proofview.V82.tactic (thin [destVar c0]))
@@ -3981,19 +4136,24 @@ let pose_induction_arg_then isrec with_evars (is_arg_pure_hyp,from_prefix) elim
if isrec then Proofview.cycle (-1) else Proofview.tclUNIT ()
])
tac
+ in
+ Sigma (tac, sigma, q)
- | Some (sigma',c) ->
+ | Some (Sigma (c, sigma', q)) ->
(* pattern found *)
let with_eq = Option.map (fun eq -> (false,eq)) eqname in
(* TODO: if ind has predicate parameters, use JMeq instead of eq *)
let env = reset_with_named_context sign env in
+ let tac =
Tacticals.New.tclTHENLIST [
- Proofview.Unsafe.tclEVARS sigma';
- Proofview.Refine.refine ~unsafe:true (fun sigma ->
- mkletin_goal env sigma store with_eq true (id,lastlhyp,ccl,c) None);
+ Proofview.Refine.refine ~unsafe:true { run = begin fun sigma ->
+ mkletin_goal env sigma store with_eq true (id,lastlhyp,ccl,c) None
+ end };
tac
]
- end
+ in
+ Sigma (tac, sigma', p +> q)
+ end }
let has_generic_occurrences_but_goal cls id env ccl =
clause_with_generic_context_selection cls &&
@@ -4005,7 +4165,7 @@ let induction_gen clear_flag isrec with_evars elim
let inhyps = match cls with
| Some {onhyps=Some hyps} -> List.map (fun ((_,id),_) -> id) hyps
| _ -> [] in
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
let sigma = Proofview.Goal.sigma gl in
let ccl = Proofview.Goal.raw_concl gl in
@@ -4040,7 +4200,7 @@ let induction_gen clear_flag isrec with_evars elim
isrec with_evars info_arg elim id arg t inhyps cls
(induction_with_atomization_of_ind_arg
isrec with_evars elim names id inhyps)
- end
+ end }
(* Induction on a list of arguments. First make induction arguments
atomic (using letins), then do induction. The specificity here is
@@ -4065,7 +4225,7 @@ let induction_gen_l isrec with_evars elim names lc =
atomize_list l'
| _ ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let type_of = Tacmach.New.pf_unsafe_type_of gl in
let x =
id_of_name_using_hdchar (Global.env()) (type_of c) Anonymous in
@@ -4076,7 +4236,7 @@ let induction_gen_l isrec with_evars elim names lc =
Tacticals.New.tclTHEN
(letin_tac None (Name id) c None allHypsAndConcl)
(atomize_list newl')
- end in
+ end } in
Tacticals.New.tclTHENLIST
[
(atomize_list lc);
@@ -4093,18 +4253,21 @@ let induction_destruct isrec with_evars (lc,elim) =
match lc with
| [] -> assert false (* ensured by syntax, but if called inside caml? *)
| [c,(eqname,names as allnames),cls] ->
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
match elim with
| Some elim when is_functional_induction elim gl ->
(* Standard induction on non-standard induction schemes *)
(* will be removable when is_functional_induction will be more clever *)
if not (Option.is_empty cls) then error "'in' clause not supported here.";
let finish_evar_resolution f =
- let (sigma',(c,lbind)) = f env sigma in
+ let ((c, lbind), sigma') = run_delayed env sigma f in
let pending = (sigma,sigma') in
- snd (finish_evar_resolution env sigma' (pending,c)),lbind in
+ let sigma' = Sigma.Unsafe.of_evar_map sigma' in
+ let Sigma (c, _, _) = finish_evar_resolution env sigma' (pending,c) in
+ (c, lbind)
+ in
let c = map_induction_arg finish_evar_resolution c in
onInductionArg
(fun _clear_flag (c,lbind) ->
@@ -4115,11 +4278,11 @@ let induction_destruct isrec with_evars (lc,elim) =
(* standard induction *)
onOpenInductionArg env sigma
(fun clear_flag c -> induction_gen clear_flag isrec with_evars elim (c,allnames) cls) c
- end
+ end }
| _ ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
match elim with
| None ->
(* Several arguments, without "using" clause *)
@@ -4133,20 +4296,23 @@ let induction_destruct isrec with_evars (lc,elim) =
(onOpenInductionArg env sigma (fun clear_flag a ->
induction_gen clear_flag isrec with_evars None (a,b) cl) a)
(Tacticals.New.tclMAP (fun (a,b,cl) ->
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
onOpenInductionArg env sigma (fun clear_flag a ->
induction_gen clear_flag false with_evars None (a,b) cl) a
- end) l)
+ end }) l)
| Some elim ->
(* Several induction hyps with induction scheme *)
let finish_evar_resolution f =
- let (sigma',(c,lbind)) = f env sigma in
+ let ((c, lbind), sigma') = run_delayed env sigma f in
let pending = (sigma,sigma') in
if lbind != NoBindings then
error "'with' clause not supported here.";
- snd (finish_evar_resolution env sigma' (pending,c)) in
+ let sigma' = Sigma.Unsafe.of_evar_map sigma' in
+ let Sigma (c, _, _) = finish_evar_resolution env sigma' (pending,c) in
+ c
+ in
let lc = List.map (on_pi1 (map_induction_arg finish_evar_resolution)) lc in
let newlc =
List.map (fun (x,(eqn,names),cls) ->
@@ -4163,7 +4329,7 @@ let induction_destruct isrec with_evars (lc,elim) =
error "'as' clause with multiple arguments and 'using' clause can only occur last.";
let newlc = List.map (fun (x,_) -> (x,None)) newlc in
induction_gen_l isrec with_evars elim names newlc
- end
+ end }
let induction ev clr c l e =
induction_gen clr true ev e
@@ -4205,7 +4371,7 @@ let simple_destruct = function
*)
let elim_scheme_type elim t =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_enter { enter = begin fun gl ->
let clause = Tacmach.New.of_old (fun gl -> mk_clenv_type_of gl elim) gl in
match kind_of_term (last_arg clause.templval.rebus) with
| Meta mv ->
@@ -4215,23 +4381,24 @@ let elim_scheme_type elim t =
(clenv_meta_type clause mv) clause in
Clenvtac.res_pf clause' ~flags:(elim_flags ()) ~with_evars:false
| _ -> anomaly (Pp.str "elim_scheme_type")
- end
+ end }
let elim_type t =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
let (ind,t) = Tacmach.New.pf_apply reduce_to_atomic_ind gl t in
let evd, elimc = find_ind_eliminator (fst ind) (Tacticals.New.elimination_sort_of_goal gl) gl in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS evd) (elim_scheme_type elimc t)
- end
+ Sigma.Unsafe.of_pair (elim_scheme_type elimc t, evd)
+ end }
let case_type t =
- Proofview.Goal.enter begin fun gl ->
- let (ind,t) = Tacmach.New.pf_apply reduce_to_atomic_ind gl t in
- let evd, elimc =
- Tacmach.New.pf_apply build_case_analysis_scheme_default gl ind (Tacticals.New.elimination_sort_of_goal gl)
- in
- Tacticals.New.tclTHEN (Proofview.Unsafe.tclEVARS evd) (elim_scheme_type elimc t)
- end
+ Proofview.Goal.s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
+ let env = Tacmach.New.pf_env gl in
+ let (ind,t) = reduce_to_atomic_ind env (Sigma.to_evar_map sigma) t in
+ let s = Tacticals.New.elimination_sort_of_goal gl in
+ let Sigma (elimc, evd, p) = build_case_analysis_scheme_default env sigma ind s in
+ Sigma (elim_scheme_type elimc t, evd, p)
+ end }
(************************************************)
@@ -4244,14 +4411,14 @@ let (forward_setoid_reflexivity, setoid_reflexivity) = Hook.make ()
let maybe_betadeltaiota_concl allowred gl =
let concl = Tacmach.New.pf_nf_concl gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
if not allowred then concl
else
let env = Proofview.Goal.env gl in
whd_betadeltaiota env sigma concl
let reflexivity_red allowred =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
(* PL: usual reflexivity don't perform any reduction when searching
for an equality, but we may need to do some when called back from
inside setoid_reflexivity (see Optimize cases in setoid_replace.ml). *)
@@ -4259,7 +4426,7 @@ let reflexivity_red allowred =
match match_with_equality_type concl with
| None -> Proofview.tclZERO NoEquationFound
| Some _ -> one_constructor 1 NoBindings
- end
+ end }
let reflexivity =
Proofview.tclORELSE
@@ -4301,7 +4468,7 @@ let match_with_equation c =
Proofview.tclZERO NoEquationFound
let symmetry_red allowred =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
(* PL: usual symmetry don't perform any reduction when searching
for an equality, but we may need to do some when called back from
inside setoid_reflexivity (see Optimize cases in setoid_replace.ml). *)
@@ -4313,7 +4480,7 @@ let symmetry_red allowred =
(convert_concl_no_check concl DEFAULTcast)
(Tacticals.New.pf_constr_of_global eq_data.sym apply)
| None,eq,eq_kind -> prove_symmetry eq eq_kind
- end
+ end }
let symmetry =
Proofview.tclORELSE
@@ -4327,7 +4494,7 @@ let (forward_setoid_symmetry_in, setoid_symmetry_in) = Hook.make ()
let symmetry_in id =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let ctype = Tacmach.New.pf_unsafe_type_of gl (mkVar id) in
let sign,t = decompose_prod_assum ctype in
Proofview.tclORELSE
@@ -4345,7 +4512,7 @@ let symmetry_in id =
| NoEquationFound -> Hook.get forward_setoid_symmetry_in id
| e -> Proofview.tclZERO ~info e
end
- end
+ end }
let intros_symmetry =
Tacticals.New.onClause
@@ -4370,7 +4537,7 @@ let (forward_setoid_transitivity, setoid_transitivity) = Hook.make ()
(* This is probably not very useful any longer *)
let prove_transitivity hdcncl eq_kind t =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
let (eq1,eq2) = match eq_kind with
| MonomorphicLeibnizEq (c1,c2) ->
mkApp (hdcncl, [| c1; t|]), mkApp (hdcncl, [| t; c2 |])
@@ -4378,7 +4545,7 @@ let prove_transitivity hdcncl eq_kind t =
mkApp (hdcncl, [| typ; c1; t |]), mkApp (hdcncl, [| typ; t; c2 |])
| HeterogenousEq (typ1,c1,typ2,c2) ->
let env = Proofview.Goal.env gl in
- let sigma = Proofview.Goal.sigma gl in
+ let sigma = Tacmach.New.project gl in
let type_of = Typing.unsafe_type_of env sigma in
let typt = type_of t in
(mkApp(hdcncl, [| typ1; c1; typt ;t |]),
@@ -4390,10 +4557,10 @@ let prove_transitivity hdcncl eq_kind t =
[ Tacticals.New.tclDO 2 intro;
Tacticals.New.onLastHyp simplest_case;
assumption ]))
- end
+ end }
let transitivity_red allowred t =
- Proofview.Goal.enter begin fun gl ->
+ Proofview.Goal.enter { enter = begin fun gl ->
(* PL: usual transitivity don't perform any reduction when searching
for an equality, but we may need to do some when called back from
inside setoid_reflexivity (see Optimize cases in setoid_replace.ml). *)
@@ -4410,7 +4577,7 @@ let transitivity_red allowred t =
match t with
| None -> Tacticals.New.tclZEROMSG (str"etransitivity not supported for this relation.")
| Some t -> prove_transitivity eq eq_kind t
- end
+ end }
let transitivity_gen t =
Proofview.tclORELSE
@@ -4430,28 +4597,81 @@ let intros_transitivity n = Tacticals.New.tclTHEN intros (transitivity_gen n)
is solved by tac *)
(** d1 is the section variable in the global context, d2 in the goal context *)
-let interpretable_as_section_decl evd d1 d2 = match d2,d1 with
- | (_,Some _,_), (_,None,_) -> false
- | (_,Some b1,t1), (_,Some b2,t2) ->
+let interpretable_as_section_decl evd d1 d2 =
+ let open Context.Named.Declaration in
+ match d2, d1 with
+ | LocalDef _, LocalAssum _ -> false
+ | LocalDef (_,b1,t1), LocalDef (_,b2,t2) ->
e_eq_constr_univs evd b1 b2 && e_eq_constr_univs evd t1 t2
- | (_,None,t1), (_,_,t2) -> e_eq_constr_univs evd t1 t2
+ | LocalAssum (_,t1), d2 -> e_eq_constr_univs evd t1 (get_type d2)
+
+let rec decompose len c t accu =
+ let open Context.Rel.Declaration in
+ if len = 0 then (c, t, accu)
+ else match kind_of_term c, kind_of_term t with
+ | Lambda (na, u, c), Prod (_, _, t) ->
+ decompose (pred len) c t (LocalAssum (na, u) :: accu)
+ | LetIn (na, b, u, c), LetIn (_, _, _, t) ->
+ decompose (pred len) c t (LocalDef (na, b, u) :: accu)
+ | _ -> assert false
+
+let rec shrink ctx sign c t accu =
+ let open Context.Rel.Declaration in
+ match ctx, sign with
+ | [], [] -> (c, t, accu)
+ | p :: ctx, decl :: sign ->
+ if noccurn 1 c then
+ let c = subst1 mkProp c in
+ let t = subst1 mkProp t in
+ shrink ctx sign c t accu
+ else
+ let c = mkLambda_or_LetIn p c in
+ let t = mkProd_or_LetIn p t in
+ let accu = if is_local_assum p then let open Context.Named.Declaration in
+ mkVar (get_id decl) :: accu
+ else accu
+ in
+ shrink ctx sign c t accu
+| _ -> assert false
+
+let shrink_entry sign const =
+ let open Context.Named.Declaration in
+ let open Entries in
+ let typ = match const.const_entry_type with
+ | None -> assert false
+ | Some t -> t
+ in
+ (** The body has been forced by the call to [build_constant_by_tactic] *)
+ let () = assert (Future.is_over const.const_entry_body) in
+ let ((body, uctx), eff) = Future.force const.const_entry_body in
+ let (body, typ, ctx) = decompose (List.length sign) body typ [] in
+ let (body, typ, args) = shrink ctx sign body typ [] in
+ let const = { const with
+ const_entry_body = Future.from_val ((body, uctx), eff);
+ const_entry_type = Some typ;
+ } in
+ (const, args)
let abstract_subproof id gk tac =
let open Tacticals.New in
let open Tacmach.New in
let open Proofview.Notations in
- Proofview.Goal.nf_enter begin fun gl ->
+ let open Context.Named.Declaration in
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
let current_sign = Global.named_context()
and global_sign = Proofview.Goal.hyps gl in
- let evdref = ref (Proofview.Goal.sigma gl) in
+ let sigma = Sigma.to_evar_map sigma in
+ let evdref = ref sigma in
let sign,secsign =
List.fold_right
- (fun (id,_,_ as d) (s1,s2) ->
+ (fun d (s1,s2) ->
+ let id = get_id d in
if mem_named_context id current_sign &&
- interpretable_as_section_decl evdref (Context.lookup_named id current_sign) d
+ interpretable_as_section_decl evdref (Context.Named.lookup id current_sign) d
then (s1,push_named_context_val d s2)
- else (add_named_decl d s1,s2))
- global_sign (empty_named_context,empty_named_context_val) in
+ else (Context.Named.add d s1,s2))
+ global_sign (Context.Named.empty, empty_named_context_val) in
let id = next_global_ident_away id (pf_ids_of_hyps gl) in
let concl = it_mkNamedProd_or_LetIn (Proofview.Goal.concl gl) sign in
let concl =
@@ -4477,6 +4697,10 @@ let abstract_subproof id gk tac =
let (_, info) = Errors.push src in
iraise (e, info)
in
+ let const, args =
+ if !shrink_abstract then shrink_entry sign const
+ else (const, List.rev (Context.Named.to_instance sign))
+ in
let cd = Entries.DefinitionEntry const in
let decl = (cd, IsProof Lemma) in
(** ppedrot: seems legit to have abstracted subproofs as local*)
@@ -4488,14 +4712,13 @@ let abstract_subproof id gk tac =
let eff = private_con_of_con (Global.safe_env ()) cst in
let effs = add_private eff
Entries.(snd (Future.force const.const_entry_body)) in
- let args = List.rev (instance_from_named_context sign) in
let solve =
- Proofview.Unsafe.tclEVARS evd <*>
Proofview.tclEFFECTS effs <*>
new_exact_no_check (applist (lem, args))
in
- if not safe then Proofview.mark_as_unsafe <*> solve else solve
- end
+ let tac = if not safe then Proofview.mark_as_unsafe <*> solve else solve in
+ Sigma.Unsafe.of_pair (tac, evd)
+ end }
let anon_id = Id.of_string "anonymous"
@@ -4515,7 +4738,8 @@ let tclABSTRACT name_op tac =
abstract_subproof s gk tac
let unify ?(state=full_transparent_state) x y =
- Proofview.Goal.nf_enter begin fun gl ->
+ Proofview.Goal.nf_s_enter { s_enter = begin fun gl ->
+ let sigma = Proofview.Goal.sigma gl in
try
let core_flags =
{ (default_unify_flags ()).core_unify_flags with
@@ -4527,22 +4751,18 @@ let unify ?(state=full_transparent_state) x y =
merge_unify_flags = core_flags;
subterm_unify_flags = { core_flags with modulo_delta = empty_transparent_state } }
in
- let evd = w_unify (Tacmach.New.pf_env gl) (Proofview.Goal.sigma gl) Reduction.CONV ~flags x y
- in Proofview.Unsafe.tclEVARS evd
- with e when Errors.noncritical e -> Tacticals.New.tclFAIL 0 (str"Not unifiable")
- end
+ let sigma = Sigma.to_evar_map sigma in
+ let sigma = w_unify (Tacmach.New.pf_env gl) sigma Reduction.CONV ~flags x y in
+ Sigma.Unsafe.of_pair (Proofview.tclUNIT (), sigma)
+ with e when Errors.noncritical e ->
+ Sigma.here (Tacticals.New.tclFAIL 0 (str"Not unifiable")) sigma
+ end }
module Simple = struct
(** Simplified version of some of the above tactics *)
let intro x = intro_move (Some x) MoveLast
- let generalize_gen cl =
- generalize_gen (List.map (on_fst Redexpr.out_with_occurrences) cl)
- let generalize cl =
- generalize_gen (List.map (fun c -> ((AllOccurrences,c),Names.Anonymous))
- cl)
-
let apply c =
apply_with_bindings_gen false false [None,(Loc.ghost,(c,NoBindings))]
let eapply c =
@@ -4566,9 +4786,9 @@ module New = struct
open Locus
let reduce_after_refine =
- Proofview.V82.tactic (reduce
+ reduce
(Lazy {rBeta=true;rIota=true;rZeta=false;rDelta=false;rConst=[]})
- {onhyps=None; concl_occs=AllOccurrences })
+ {onhyps=None; concl_occs=AllOccurrences }
let refine ?unsafe c =
Proofview.Refine.refine ?unsafe c <*>
diff --git a/tactics/tactics.mli b/tactics/tactics.mli
index c28cb521e7..26ea017696 100644
--- a/tactics/tactics.mli
+++ b/tactics/tactics.mli
@@ -9,7 +9,6 @@
open Loc
open Names
open Term
-open Context
open Environ
open Proof_type
open Evd
@@ -26,16 +25,16 @@ open Locus
(** {6 General functions. } *)
-val is_quantified_hypothesis : Id.t -> goal sigma -> bool
+val is_quantified_hypothesis : Id.t -> ([`NF],'b) Proofview.Goal.t -> bool
(** {6 Primitive tactics. } *)
val introduction : ?check:bool -> Id.t -> unit Proofview.tactic
val refine : constr -> tactic
val convert_concl : ?check:bool -> types -> cast_kind -> unit Proofview.tactic
-val convert_hyp : ?check:bool -> named_declaration -> unit Proofview.tactic
+val convert_hyp : ?check:bool -> Context.Named.Declaration.t -> unit Proofview.tactic
val convert_concl_no_check : types -> cast_kind -> unit Proofview.tactic
-val convert_hyp_no_check : named_declaration -> unit Proofview.tactic
+val convert_hyp_no_check : Context.Named.Declaration.t -> unit Proofview.tactic
val thin : Id.t list -> tactic
val mutual_fix :
Id.t -> int -> (Id.t * int * constr) list -> int -> tactic
@@ -50,7 +49,7 @@ val convert_leq : constr -> constr -> unit Proofview.tactic
val fresh_id_in_env : Id.t list -> Id.t -> env -> Id.t
val fresh_id : Id.t list -> Id.t -> goal sigma -> Id.t
-val find_intro_names : rel_context -> goal sigma -> Id.t list
+val find_intro_names : Context.Rel.t -> goal sigma -> Id.t list
val intro : unit Proofview.tactic
val introf : unit Proofview.tactic
@@ -74,7 +73,7 @@ val intros : unit Proofview.tactic
(** [depth_of_quantified_hypothesis b h g] returns the index of [h] in
the conclusion of goal [g], up to head-reduction if [b] is [true] *)
val depth_of_quantified_hypothesis :
- bool -> quantified_hypothesis -> goal sigma -> int
+ bool -> quantified_hypothesis -> ([`NF],'b) Proofview.Goal.t -> int
val intros_until : quantified_hypothesis -> unit Proofview.tactic
@@ -126,51 +125,51 @@ val exact_proof : Constrexpr.constr_expr -> tactic
type tactic_reduction = env -> evar_map -> constr -> constr
-type change_arg = patvar_map -> evar_map -> evar_map * constr
+type change_arg = patvar_map -> constr Sigma.run
val make_change_arg : constr -> change_arg
-val reduct_in_hyp : ?check:bool -> tactic_reduction -> hyp_location -> tactic
-val reduct_option : ?check:bool -> tactic_reduction * cast_kind -> goal_location -> tactic
-val reduct_in_concl : tactic_reduction * cast_kind -> tactic
+val reduct_in_hyp : ?check:bool -> tactic_reduction -> hyp_location -> unit Proofview.tactic
+val reduct_option : ?check:bool -> tactic_reduction * cast_kind -> goal_location -> unit Proofview.tactic
+val reduct_in_concl : tactic_reduction * cast_kind -> unit Proofview.tactic
val change_in_concl : (occurrences * constr_pattern) option -> change_arg -> unit Proofview.tactic
val change_concl : constr -> unit Proofview.tactic
val change_in_hyp : (occurrences * constr_pattern) option -> change_arg ->
hyp_location -> unit Proofview.tactic
-val red_in_concl : tactic
-val red_in_hyp : hyp_location -> tactic
-val red_option : goal_location -> tactic
-val hnf_in_concl : tactic
-val hnf_in_hyp : hyp_location -> tactic
-val hnf_option : goal_location -> tactic
-val simpl_in_concl : tactic
-val simpl_in_hyp : hyp_location -> tactic
-val simpl_option : goal_location -> tactic
-val normalise_in_concl : tactic
-val normalise_in_hyp : hyp_location -> tactic
-val normalise_option : goal_location -> tactic
-val normalise_vm_in_concl : tactic
+val red_in_concl : unit Proofview.tactic
+val red_in_hyp : hyp_location -> unit Proofview.tactic
+val red_option : goal_location -> unit Proofview.tactic
+val hnf_in_concl : unit Proofview.tactic
+val hnf_in_hyp : hyp_location -> unit Proofview.tactic
+val hnf_option : goal_location -> unit Proofview.tactic
+val simpl_in_concl : unit Proofview.tactic
+val simpl_in_hyp : hyp_location -> unit Proofview.tactic
+val simpl_option : goal_location -> unit Proofview.tactic
+val normalise_in_concl : unit Proofview.tactic
+val normalise_in_hyp : hyp_location -> unit Proofview.tactic
+val normalise_option : goal_location -> unit Proofview.tactic
+val normalise_vm_in_concl : unit Proofview.tactic
val unfold_in_concl :
- (occurrences * evaluable_global_reference) list -> tactic
+ (occurrences * evaluable_global_reference) list -> unit Proofview.tactic
val unfold_in_hyp :
- (occurrences * evaluable_global_reference) list -> hyp_location -> tactic
+ (occurrences * evaluable_global_reference) list -> hyp_location -> unit Proofview.tactic
val unfold_option :
- (occurrences * evaluable_global_reference) list -> goal_location -> tactic
+ (occurrences * evaluable_global_reference) list -> goal_location -> unit Proofview.tactic
val change :
constr_pattern option -> change_arg -> clause -> tactic
val pattern_option :
- (occurrences * constr) list -> goal_location -> tactic
-val reduce : red_expr -> clause -> tactic
-val unfold_constr : global_reference -> tactic
+ (occurrences * constr) list -> goal_location -> unit Proofview.tactic
+val reduce : red_expr -> clause -> unit Proofview.tactic
+val unfold_constr : global_reference -> unit Proofview.tactic
(** {6 Modification of the local context. } *)
val clear : Id.t list -> tactic
val clear_body : Id.t list -> unit Proofview.tactic
-val unfold_body : Id.t -> tactic
+val unfold_body : Id.t -> unit Proofview.tactic
val keep : Id.t list -> unit Proofview.tactic
val apply_clear_request : clear_flag -> bool -> constr -> unit Proofview.tactic
-val specialize : constr with_bindings -> tactic
+val specialize : constr with_bindings -> unit Proofview.tactic
val move_hyp : Id.t -> Id.t move_location -> tactic
val rename_hyp : (Id.t * Id.t) list -> unit Proofview.tactic
@@ -179,8 +178,8 @@ val revert : Id.t list -> unit Proofview.tactic
(** {6 Resolution tactics. } *)
-val apply_type : constr -> constr list -> tactic
-val bring_hyps : named_context -> unit Proofview.tactic
+val apply_type : constr -> constr list -> unit Proofview.tactic
+val bring_hyps : Context.Named.t -> unit Proofview.tactic
val apply : constr -> unit Proofview.tactic
val eapply : constr -> unit Proofview.tactic
@@ -206,6 +205,8 @@ val apply_delayed_in :
(clear_flag * delayed_open_constr_with_bindings located) list ->
intro_pattern option -> unit Proofview.tactic
+val run_delayed : Environ.env -> evar_map -> 'a delayed_open -> 'a * evar_map
+
(** {6 Elimination tactics. } *)
(*
@@ -237,20 +238,20 @@ type elim_scheme = {
elimc: constr with_bindings option;
elimt: types;
indref: global_reference option;
- params: rel_context; (** (prm1,tprm1);(prm2,tprm2)...(prmp,tprmp) *)
- nparams: int; (** number of parameters *)
- predicates: rel_context; (** (Qq, (Tq_1 -> Tq_2 ->...-> Tq_nq)), (Q1,...) *)
- npredicates: int; (** Number of predicates *)
- branches: rel_context; (** branchr,...,branch1 *)
- nbranches: int; (** Number of branches *)
- args: rel_context; (** (xni, Ti_ni) ... (x1, Ti_1) *)
- nargs: int; (** number of arguments *)
- indarg: rel_declaration option; (** Some (H,I prm1..prmp x1...xni)
- if HI is in premisses, None otherwise *)
- concl: types; (** Qi x1...xni HI (f...), HI and (f...)
- are optional and mutually exclusive *)
- indarg_in_concl: bool; (** true if HI appears at the end of conclusion *)
- farg_in_concl: bool; (** true if (f...) appears at the end of conclusion *)
+ params: Context.Rel.t; (** (prm1,tprm1);(prm2,tprm2)...(prmp,tprmp) *)
+ nparams: int; (** number of parameters *)
+ predicates: Context.Rel.t; (** (Qq, (Tq_1 -> Tq_2 ->...-> Tq_nq)), (Q1,...) *)
+ npredicates: int; (** Number of predicates *)
+ branches: Context.Rel.t; (** branchr,...,branch1 *)
+ nbranches: int; (** Number of branches *)
+ args: Context.Rel.t; (** (xni, Ti_ni) ... (x1, Ti_1) *)
+ nargs: int; (** number of arguments *)
+ indarg: Context.Rel.Declaration.t option; (** Some (H,I prm1..prmp x1...xni)
+ if HI is in premisses, None otherwise *)
+ concl: types; (** Qi x1...xni HI (f...), HI and (f...)
+ are optional and mutually exclusive *)
+ indarg_in_concl: bool; (** true if HI appears at the end of conclusion *)
+ farg_in_concl: bool; (** true if (f...) appears at the end of conclusion *)
}
val compute_elim_sig : ?elimc: constr with_bindings -> types -> elim_scheme
@@ -384,7 +385,8 @@ val letin_pat_tac : (bool * intro_pattern_naming) option ->
(** {6 Generalize tactics. } *)
val generalize : constr list -> tactic
-val generalize_gen : ((occurrences * constr) * Name.t) list -> tactic
+val generalize_gen : (constr Locus.with_occurrences * Name.t) list -> tactic
+
val new_generalize : constr list -> unit Proofview.tactic
val new_generalize_gen : ((occurrences * constr) * Name.t) list -> unit Proofview.tactic
@@ -416,9 +418,6 @@ module Simple : sig
(** Simplified version of some of the above tactics *)
val intro : Id.t -> unit Proofview.tactic
- val generalize : constr list -> tactic
- val generalize_gen : (constr Locus.with_occurrences * Name.t) list -> tactic
-
val apply : constr -> unit Proofview.tactic
val eapply : constr -> unit Proofview.tactic
val elim : constr -> unit Proofview.tactic
@@ -431,7 +430,7 @@ end
module New : sig
- val refine : ?unsafe:bool -> (Evd.evar_map -> Evd.evar_map*constr) -> unit Proofview.tactic
+ val refine : ?unsafe:bool -> constr Sigma.run -> unit Proofview.tactic
(** [refine ?unsafe c] is [Proofview.Refine.refine ?unsafe c]
followed by beta-iota-reduction of the conclusion. *)
diff --git a/tactics/tactics.mllib b/tactics/tactics.mllib
index 2c5edc20ed..b495a885f8 100644
--- a/tactics/tactics.mllib
+++ b/tactics/tactics.mllib
@@ -19,10 +19,6 @@ Taccoerce
Tacenv
Hints
Auto
-Tacintern
Tactic_matching
-Tacinterp
-Evar_tactics
+Tactic_debug
Term_dnet
-Autorewrite
-Tactic_option
diff --git a/tactics/tauto.ml b/tactics/tauto.ml
new file mode 100644
index 0000000000..a86fdb98a9
--- /dev/null
+++ b/tactics/tauto.ml
@@ -0,0 +1,282 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+open Term
+open Hipattern
+open Names
+open Pp
+open Genarg
+open Stdarg
+open Misctypes
+open Tacexpr
+open Tacinterp
+open Tactics
+open Errors
+open Util
+open Tacticals.New
+open Proofview.Notations
+
+let tauto_plugin = "tauto"
+let () = Mltop.add_known_module tauto_plugin
+
+let assoc_var s ist =
+ let v = Id.Map.find (Names.Id.of_string s) ist.lfun in
+ match Value.to_constr v with
+ | Some c -> c
+ | None -> failwith "tauto: anomaly"
+
+(** Parametrization of tauto *)
+
+type tauto_flags = {
+
+(* Whether conjunction and disjunction are restricted to binary connectives *)
+ binary_mode : bool;
+
+(* Whether compatibility for buggy detection of binary connective is on *)
+ binary_mode_bugged_detection : bool;
+
+(* Whether conjunction and disjunction are restricted to the connectives *)
+(* having the structure of "and" and "or" (up to the choice of sorts) in *)
+(* contravariant position in an hypothesis *)
+ strict_in_contravariant_hyp : bool;
+
+(* Whether conjunction and disjunction are restricted to the connectives *)
+(* having the structure of "and" and "or" (up to the choice of sorts) in *)
+(* an hypothesis and in the conclusion *)
+ strict_in_hyp_and_ccl : bool;
+
+(* Whether unit type includes equality types *)
+ strict_unit : bool;
+}
+
+let wit_tauto_flags : tauto_flags uniform_genarg_type =
+ Genarg.create_arg "tauto_flags"
+
+let assoc_flags ist =
+ let v = Id.Map.find (Names.Id.of_string "tauto_flags") ist.lfun in
+ try Value.cast (topwit wit_tauto_flags) v with _ -> assert false
+
+(* Whether inner not are unfolded *)
+let negation_unfolding = ref true
+
+(* Whether inner iff are unfolded *)
+let iff_unfolding = ref false
+
+let unfold_iff () = !iff_unfolding || Flags.version_less_or_equal Flags.V8_2
+
+open Goptions
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "unfolding of not in intuition";
+ optkey = ["Intuition";"Negation";"Unfolding"];
+ optread = (fun () -> !negation_unfolding);
+ optwrite = (:=) negation_unfolding }
+
+let _ =
+ declare_bool_option
+ { optsync = true;
+ optdepr = false;
+ optname = "unfolding of iff in intuition";
+ optkey = ["Intuition";"Iff";"Unfolding"];
+ optread = (fun () -> !iff_unfolding);
+ optwrite = (:=) iff_unfolding }
+
+(** Base tactics *)
+
+let loc = Loc.ghost
+let idtac = Proofview.tclUNIT ()
+let fail = Proofview.tclINDEPENDENT (tclFAIL 0 (Pp.mt ()))
+
+let intro = Tactics.intro
+
+let assert_ ?by c =
+ let tac = match by with
+ | None -> None
+ | Some tac -> Some (tclCOMPLETE tac)
+ in
+ Proofview.tclINDEPENDENT (Tactics.forward true tac None c)
+
+let apply c = Tactics.apply c
+
+let clear id = Proofview.V82.tactic (fun gl -> Tactics.clear [id] gl)
+
+let assumption = Tactics.assumption
+
+let split = Tactics.split_with_bindings false [Misctypes.NoBindings]
+
+(** Test *)
+
+let is_empty _ ist =
+ if is_empty_type (assoc_var "X1" ist) then idtac else fail
+
+(* Strictly speaking, this exceeds the propositional fragment as it
+ matches also equality types (and solves them if a reflexivity) *)
+let is_unit_or_eq _ ist =
+ let flags = assoc_flags ist in
+ let test = if flags.strict_unit then is_unit_type else is_unit_or_eq_type in
+ if test (assoc_var "X1" ist) then idtac else fail
+
+let bugged_is_binary t =
+ isApp t &&
+ let (hdapp,args) = decompose_app t in
+ match (kind_of_term hdapp) with
+ | Ind (ind,u) ->
+ let (mib,mip) = Global.lookup_inductive ind in
+ Int.equal mib.Declarations.mind_nparams 2
+ | _ -> false
+
+(** Dealing with conjunction *)
+
+let is_conj _ ist =
+ let flags = assoc_flags ist in
+ let ind = assoc_var "X1" ist in
+ if (not flags.binary_mode_bugged_detection || bugged_is_binary ind) &&
+ is_conjunction
+ ~strict:flags.strict_in_hyp_and_ccl
+ ~onlybinary:flags.binary_mode ind
+ then idtac
+ else fail
+
+let flatten_contravariant_conj _ ist =
+ let flags = assoc_flags ist in
+ let typ = assoc_var "X1" ist in
+ let c = assoc_var "X2" ist in
+ let hyp = assoc_var "id" ist in
+ match match_with_conjunction
+ ~strict:flags.strict_in_contravariant_hyp
+ ~onlybinary:flags.binary_mode typ
+ with
+ | Some (_,args) ->
+ let newtyp = List.fold_right mkArrow args c in
+ let intros = tclMAP (fun _ -> intro) args in
+ let by = tclTHENLIST [intros; apply hyp; split; assumption] in
+ tclTHENLIST [assert_ ~by newtyp; clear (destVar hyp)]
+ | _ -> fail
+
+(** Dealing with disjunction *)
+
+let is_disj _ ist =
+ let flags = assoc_flags ist in
+ let t = assoc_var "X1" ist in
+ if (not flags.binary_mode_bugged_detection || bugged_is_binary t) &&
+ is_disjunction
+ ~strict:flags.strict_in_hyp_and_ccl
+ ~onlybinary:flags.binary_mode t
+ then idtac
+ else fail
+
+let flatten_contravariant_disj _ ist =
+ let flags = assoc_flags ist in
+ let typ = assoc_var "X1" ist in
+ let c = assoc_var "X2" ist in
+ let hyp = assoc_var "id" ist in
+ match match_with_disjunction
+ ~strict:flags.strict_in_contravariant_hyp
+ ~onlybinary:flags.binary_mode
+ typ with
+ | Some (_,args) ->
+ let map i arg =
+ let typ = mkArrow arg c in
+ let ci = Tactics.constructor_tac false None (succ i) Misctypes.NoBindings in
+ let by = tclTHENLIST [intro; apply hyp; ci; assumption] in
+ assert_ ~by typ
+ in
+ let tacs = List.mapi map args in
+ let tac0 = clear (destVar hyp) in
+ tclTHEN (tclTHENLIST tacs) tac0
+ | _ -> fail
+
+let make_unfold name =
+ let dir = DirPath.make (List.map Id.of_string ["Logic"; "Init"; "Coq"]) in
+ let const = Constant.make2 (MPfile dir) (Label.make name) in
+ (Locus.AllOccurrences, ArgArg (EvalConstRef const, None))
+
+let u_iff = make_unfold "iff"
+let u_not = make_unfold "not"
+
+let reduction_not_iff _ ist =
+ let make_reduce c = TacAtom (loc, TacReduce (Genredexpr.Unfold c, Locusops.allHypsAndConcl)) in
+ let tac = match !negation_unfolding, unfold_iff () with
+ | true, true -> make_reduce [u_not; u_iff]
+ | true, false -> make_reduce [u_not]
+ | false, true -> make_reduce [u_iff]
+ | false, false -> TacId []
+ in
+ eval_tactic_ist ist tac
+
+let coq_nnpp_path =
+ let dir = List.map Id.of_string ["Classical_Prop";"Logic";"Coq"] in
+ Libnames.make_path (DirPath.make dir) (Id.of_string "NNPP")
+
+let apply_nnpp _ ist =
+ Proofview.tclBIND
+ (Proofview.tclUNIT ())
+ begin fun () -> try
+ let nnpp = Universes.constr_of_global (Nametab.global_of_path coq_nnpp_path) in
+ apply nnpp
+ with Not_found -> tclFAIL 0 (Pp.mt ())
+ end
+
+(* This is the uniform mode dealing with ->, not, iff and types isomorphic to
+ /\ and *, \/ and +, False and Empty_set, True and unit, _and_ eq-like types.
+ For the moment not and iff are still always unfolded. *)
+let tauto_uniform_unit_flags = {
+ binary_mode = true;
+ binary_mode_bugged_detection = false;
+ strict_in_contravariant_hyp = true;
+ strict_in_hyp_and_ccl = true;
+ strict_unit = false
+}
+
+(* This is the compatibility mode (not used) *)
+let tauto_legacy_flags = {
+ binary_mode = true;
+ binary_mode_bugged_detection = true;
+ strict_in_contravariant_hyp = true;
+ strict_in_hyp_and_ccl = false;
+ strict_unit = false
+}
+
+(* This is the improved mode *)
+let tauto_power_flags = {
+ binary_mode = false; (* support n-ary connectives *)
+ binary_mode_bugged_detection = false;
+ strict_in_contravariant_hyp = false; (* supports non-regular connectives *)
+ strict_in_hyp_and_ccl = false;
+ strict_unit = false
+}
+
+let with_flags flags _ ist =
+ let f = (loc, Id.of_string "f") in
+ let x = (loc, Id.of_string "x") in
+ let arg = Val.Dyn (val_tag (topwit wit_tauto_flags), flags) in
+ let ist = { ist with lfun = Id.Map.add (snd x) arg ist.lfun } in
+ eval_tactic_ist ist (TacArg (loc, TacCall (loc, ArgVar f, [Reference (ArgVar x)])))
+
+let register_tauto_tactic tac name0 args =
+ let ids = List.map (fun id -> Id.of_string id) args in
+ let ids = List.map (fun id -> Some id) ids in
+ let name = { mltac_plugin = tauto_plugin; mltac_tactic = name0; } in
+ let entry = { mltac_name = name; mltac_index = 0 } in
+ let () = Tacenv.register_ml_tactic name [| tac |] in
+ let tac = TacFun (ids, TacML (loc, entry, [])) in
+ let obj () = Tacenv.register_ltac true true (Id.of_string name0) tac in
+ Mltop.declare_cache_obj obj tauto_plugin
+
+let () = register_tauto_tactic is_empty "is_empty" ["tauto_flags"; "X1"]
+let () = register_tauto_tactic is_unit_or_eq "is_unit_or_eq" ["tauto_flags"; "X1"]
+let () = register_tauto_tactic is_disj "is_disj" ["tauto_flags"; "X1"]
+let () = register_tauto_tactic is_conj "is_conj" ["tauto_flags"; "X1"]
+let () = register_tauto_tactic flatten_contravariant_disj "flatten_contravariant_disj" ["tauto_flags"; "X1"; "X2"; "id"]
+let () = register_tauto_tactic flatten_contravariant_conj "flatten_contravariant_conj" ["tauto_flags"; "X1"; "X2"; "id"]
+let () = register_tauto_tactic apply_nnpp "apply_nnpp" []
+let () = register_tauto_tactic reduction_not_iff "reduction_not_iff" []
+let () = register_tauto_tactic (with_flags tauto_uniform_unit_flags) "with_uniform_flags" ["f"]
+let () = register_tauto_tactic (with_flags tauto_power_flags) "with_power_flags" ["f"]
diff --git a/tactics/tauto.ml4 b/tactics/tauto.ml4
deleted file mode 100644
index f41fac5478..0000000000
--- a/tactics/tauto.ml4
+++ /dev/null
@@ -1,398 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2016 *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-(*i camlp4deps: "grammar/grammar.cma" i*)
-
-open Term
-open Hipattern
-open Names
-open Pp
-open Genarg
-open Stdarg
-open Tacinterp
-open Tactics
-open Errors
-open Util
-
-DECLARE PLUGIN "tauto"
-
-let assoc_var s ist =
- let v = Id.Map.find (Names.Id.of_string s) ist.lfun in
- match Value.to_constr v with
- | Some c -> c
- | None -> failwith "tauto: anomaly"
-
-(** Parametrization of tauto *)
-
-type tauto_flags = {
-
-(* Whether conjunction and disjunction are restricted to binary connectives *)
- binary_mode : bool;
-
-(* Whether compatibility for buggy detection of binary connective is on *)
- binary_mode_bugged_detection : bool;
-
-(* Whether conjunction and disjunction are restricted to the connectives *)
-(* having the structure of "and" and "or" (up to the choice of sorts) in *)
-(* contravariant position in an hypothesis *)
- strict_in_contravariant_hyp : bool;
-
-(* Whether conjunction and disjunction are restricted to the connectives *)
-(* having the structure of "and" and "or" (up to the choice of sorts) in *)
-(* an hypothesis and in the conclusion *)
- strict_in_hyp_and_ccl : bool;
-
-(* Whether unit type includes equality types *)
- strict_unit : bool;
-}
-
-(* Whether inner not are unfolded *)
-let negation_unfolding = ref true
-
-(* Whether inner iff are unfolded *)
-let iff_unfolding = ref false
-
-let unfold_iff () = !iff_unfolding || Flags.version_less_or_equal Flags.V8_2
-
-open Goptions
-let _ =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "unfolding of not in intuition";
- optkey = ["Intuition";"Negation";"Unfolding"];
- optread = (fun () -> !negation_unfolding);
- optwrite = (:=) negation_unfolding }
-
-let _ =
- declare_bool_option
- { optsync = true;
- optdepr = false;
- optname = "unfolding of iff in intuition";
- optkey = ["Intuition";"Iff";"Unfolding"];
- optread = (fun () -> !iff_unfolding);
- optwrite = (:=) iff_unfolding }
-
-(** Test *)
-
-let make_lfun l =
- let fold accu (id, v) = Id.Map.add (Id.of_string id) v accu in
- List.fold_left fold Id.Map.empty l
-
-let is_empty ist =
- if is_empty_type (assoc_var "X1" ist) then
- <:tactic<idtac>>
- else
- <:tactic<fail>>
-
-(* Strictly speaking, this exceeds the propositional fragment as it
- matches also equality types (and solves them if a reflexivity) *)
-let is_unit_or_eq flags ist =
- let test = if flags.strict_unit then is_unit_type else is_unit_or_eq_type in
- if test (assoc_var "X1" ist) then
- <:tactic<idtac>>
- else
- <:tactic<fail>>
-
-let is_record t =
- let (hdapp,args) = decompose_app t in
- match (kind_of_term hdapp) with
- | Ind (ind,u) ->
- let (mib,mip) = Global.lookup_inductive ind in
- mib.Declarations.mind_record <> None
- | _ -> false
-
-let bugged_is_binary t =
- isApp t &&
- let (hdapp,args) = decompose_app t in
- match (kind_of_term hdapp) with
- | Ind (ind,u) ->
- let (mib,mip) = Global.lookup_inductive ind in
- Int.equal mib.Declarations.mind_nparams 2
- | _ -> false
-
-let iter_tac tacl =
- List.fold_right (fun tac tacs -> <:tactic< $tac; $tacs >>) tacl
-
-(** Dealing with conjunction *)
-
-let is_conj flags ist =
- let ind = assoc_var "X1" ist in
- if (not flags.binary_mode_bugged_detection || bugged_is_binary ind) &&
- is_conjunction
- ~strict:flags.strict_in_hyp_and_ccl
- ~onlybinary:flags.binary_mode ind
- then
- <:tactic<idtac>>
- else
- <:tactic<fail>>
-
-let flatten_contravariant_conj flags ist =
- let typ = assoc_var "X1" ist in
- let c = assoc_var "X2" ist in
- let hyp = assoc_var "id" ist in
- match match_with_conjunction
- ~strict:flags.strict_in_contravariant_hyp
- ~onlybinary:flags.binary_mode typ
- with
- | Some (_,args) ->
- let newtyp = valueIn (Value.of_constr (List.fold_right mkArrow args c)) in
- let hyp = valueIn (Value.of_constr hyp) in
- let intros =
- iter_tac (List.map (fun _ -> <:tactic< intro >>) args)
- <:tactic< idtac >> in
- <:tactic<
- let newtyp := $newtyp in
- let hyp := $hyp in
- assert newtyp by ($intros; apply hyp; split; assumption);
- clear hyp
- >>
- | _ ->
- <:tactic<fail>>
-
-(** Dealing with disjunction *)
-
-let constructor i =
- let name = { Tacexpr.mltac_plugin = "coretactics"; mltac_tactic = "constructor" } in
- let i = in_gen (rawwit Constrarg.wit_int_or_var) (Misctypes.ArgArg i) in
- Tacexpr.TacML (Loc.ghost, name, [i])
-
-let is_disj flags ist =
- let t = assoc_var "X1" ist in
- if (not flags.binary_mode_bugged_detection || bugged_is_binary t) &&
- is_disjunction
- ~strict:flags.strict_in_hyp_and_ccl
- ~onlybinary:flags.binary_mode t
- then
- <:tactic<idtac>>
- else
- <:tactic<fail>>
-
-let flatten_contravariant_disj flags ist =
- let typ = assoc_var "X1" ist in
- let c = assoc_var "X2" ist in
- let hyp = assoc_var "id" ist in
- match match_with_disjunction
- ~strict:flags.strict_in_contravariant_hyp
- ~onlybinary:flags.binary_mode
- typ with
- | Some (_,args) ->
- let hyp = valueIn (Value.of_constr hyp) in
- iter_tac (List.map_i (fun i arg ->
- let typ = valueIn (Value.of_constr (mkArrow arg c)) in
- let ci = constructor i in
- <:tactic<
- let typ := $typ in
- let hyp := $hyp in
- assert typ by (intro; apply hyp; $ci; assumption)
- >>) 1 args) <:tactic< let hyp := $hyp in clear hyp >>
- | _ ->
- <:tactic<fail>>
-
-
-(** Main tactic *)
-
-let not_dep_intros ist =
- <:tactic<
- repeat match goal with
- | |- (forall (_: ?X1), ?X2) => intro
- | |- (Coq.Init.Logic.not _) => unfold Coq.Init.Logic.not at 1; intro
- end >>
-
-let axioms flags ist =
- let t_is_unit_or_eq = tacticIn (is_unit_or_eq flags)
- and t_is_empty = tacticIn is_empty in
- let c1 = constructor 1 in
- <:tactic<
- match reverse goal with
- | |- ?X1 => $t_is_unit_or_eq; $c1
- | _:?X1 |- _ => $t_is_empty; elimtype X1; assumption
- | _:?X1 |- ?X1 => assumption
- end >>
-
-
-let simplif flags ist =
- let t_is_unit_or_eq = tacticIn (is_unit_or_eq flags)
- and t_is_conj = tacticIn (is_conj flags)
- and t_flatten_contravariant_conj = tacticIn (flatten_contravariant_conj flags)
- and t_flatten_contravariant_disj = tacticIn (flatten_contravariant_disj flags)
- and t_is_disj = tacticIn (is_disj flags)
- and t_not_dep_intros = tacticIn not_dep_intros in
- let c1 = constructor 1 in
- <:tactic<
- $t_not_dep_intros;
- repeat
- (match reverse goal with
- | id: ?X1 |- _ => $t_is_conj; elim id; do 2 intro; clear id
- | id: (Coq.Init.Logic.iff _ _) |- _ => elim id; do 2 intro; clear id
- | id: (Coq.Init.Logic.not _) |- _ => red in id
- | id: ?X1 |- _ => $t_is_disj; elim id; intro; clear id
- | id0: (forall (_: ?X1), ?X2), id1: ?X1|- _ =>
- (* generalize (id0 id1); intro; clear id0 does not work
- (see Marco Maggiesi's bug PR#301)
- so we instead use Assert and exact. *)
- assert X2; [exact (id0 id1) | clear id0]
- | id: forall (_ : ?X1), ?X2|- _ =>
- $t_is_unit_or_eq; cut X2;
- [ intro; clear id
- | (* id : forall (_: ?X1), ?X2 |- ?X2 *)
- cut X1; [exact id| $c1; fail]
- ]
- | id: forall (_ : ?X1), ?X2|- _ =>
- $t_flatten_contravariant_conj
- (* moved from "id:(?A/\?B)->?X2|-" to "?A->?B->?X2|-" *)
- | id: forall (_: Coq.Init.Logic.iff ?X1 ?X2), ?X3|- _ =>
- assert (forall (_: forall _:X1, X2), forall (_: forall _: X2, X1), X3)
- by (do 2 intro; apply id; split; assumption);
- clear id
- | id: forall (_:?X1), ?X2|- _ =>
- $t_flatten_contravariant_disj
- (* moved from "id:(?A\/?B)->?X2|-" to "?A->?X2,?B->?X2|-" *)
- | |- ?X1 => $t_is_conj; split
- | |- (Coq.Init.Logic.iff _ _) => split
- | |- (Coq.Init.Logic.not _) => red
- end;
- $t_not_dep_intros) >>
-
-let rec tauto_intuit flags t_reduce solver =
- let t_axioms = tacticIn (axioms flags)
- and t_simplif = tacticIn (simplif flags)
- and t_is_disj = tacticIn (is_disj flags) in
- let lfun = make_lfun [("t_solver", solver)] in
- let ist = { default_ist () with lfun = lfun; } in
- let vars = [Id.of_string "t_solver"] in
- (vars, ist, <:tactic<
- let rec t_tauto_intuit :=
- ($t_simplif;$t_axioms
- || match reverse goal with
- | id:forall(_: forall (_: ?X1), ?X2), ?X3|- _ =>
- cut X3;
- [ intro; clear id; t_tauto_intuit
- | cut (forall (_: X1), X2);
- [ exact id
- | generalize (fun y:X2 => id (fun x:X1 => y)); intro; clear id;
- solve [ t_tauto_intuit ]]]
- | id:forall (_:not ?X1), ?X3|- _ =>
- cut X3;
- [ intro; clear id; t_tauto_intuit
- | cut (not X1); [ exact id | clear id; intro; solve [t_tauto_intuit ]]]
- | |- ?X1 =>
- $t_is_disj; solve [left;t_tauto_intuit | right;t_tauto_intuit]
- end
- ||
- (* NB: [|- _ -> _] matches any product *)
- match goal with | |- forall (_ : _), _ => intro; t_tauto_intuit
- | |- _ => $t_reduce;t_solver
- end
- ||
- t_solver
- ) in t_tauto_intuit >>)
-
-let reduction_not_iff _ist =
- match !negation_unfolding, unfold_iff () with
- | true, true -> <:tactic< unfold Coq.Init.Logic.not, Coq.Init.Logic.iff in * >>
- | true, false -> <:tactic< unfold Coq.Init.Logic.not in * >>
- | false, true -> <:tactic< unfold Coq.Init.Logic.iff in * >>
- | false, false -> <:tactic< idtac >>
-
-let t_reduction_not_iff = tacticIn reduction_not_iff
-
-let intuition_gen ist flags tac =
- Proofview.Goal.enter begin fun gl ->
- let tac = Value.of_closure ist tac in
- let env = Proofview.Goal.env gl in
- let vars, ist, intuition = tauto_intuit flags t_reduction_not_iff tac in
- let glb_intuition = Tacintern.glob_tactic_env vars env intuition in
- eval_tactic_ist ist glb_intuition
- end
-
-let tauto_intuitionistic flags =
- Proofview.tclORELSE
- (intuition_gen (default_ist ()) flags <:tactic<fail>>)
- begin function (e, info) -> match e with
- | Refiner.FailError _ | UserError _ ->
- Tacticals.New.tclZEROMSG (str "tauto failed.")
- | e -> Proofview.tclZERO ~info e
- end
-
-let coq_nnpp_path =
- let dir = List.map Id.of_string ["Classical_Prop";"Logic";"Coq"] in
- Libnames.make_path (DirPath.make dir) (Id.of_string "NNPP")
-
-let tauto_classical flags nnpp =
- Proofview.tclORELSE
- (Tacticals.New.tclTHEN (apply nnpp) (tauto_intuitionistic flags))
- begin function (e, info) -> match e with
- | UserError _ -> Tacticals.New.tclZEROMSG (str "Classical tauto failed.")
- | e -> Proofview.tclZERO ~info e
- end
-
-let tauto_gen flags =
- (* spiwack: I use [tclBIND (tclUNIT ())] as a way to delay the effect
- (in [constr_of_global]) to the application of the tactic. *)
- Proofview.tclBIND
- (Proofview.tclUNIT ())
- begin fun () -> try
- let nnpp = Universes.constr_of_global (Nametab.global_of_path coq_nnpp_path) in
- (* try intuitionistic version first to avoid an axiom if possible *)
- Tacticals.New.tclORELSE (tauto_intuitionistic flags) (tauto_classical flags nnpp)
- with Not_found ->
- tauto_intuitionistic flags
- end
-
-let default_intuition_tac = <:tactic< auto with * >>
-
-(* This is the uniform mode dealing with ->, not, iff and types isomorphic to
- /\ and *, \/ and +, False and Empty_set, True and unit, _and_ eq-like types.
- For the moment not and iff are still always unfolded. *)
-let tauto_uniform_unit_flags = {
- binary_mode = true;
- binary_mode_bugged_detection = false;
- strict_in_contravariant_hyp = true;
- strict_in_hyp_and_ccl = true;
- strict_unit = false
-}
-
-(* This is the compatibility mode (not used) *)
-let tauto_legacy_flags = {
- binary_mode = true;
- binary_mode_bugged_detection = true;
- strict_in_contravariant_hyp = true;
- strict_in_hyp_and_ccl = false;
- strict_unit = false
-}
-
-(* This is the improved mode *)
-let tauto_power_flags = {
- binary_mode = false; (* support n-ary connectives *)
- binary_mode_bugged_detection = false;
- strict_in_contravariant_hyp = false; (* supports non-regular connectives *)
- strict_in_hyp_and_ccl = false;
- strict_unit = false
-}
-
-let tauto = tauto_gen tauto_uniform_unit_flags
-let dtauto = tauto_gen tauto_power_flags
-
-TACTIC EXTEND tauto
-| [ "tauto" ] -> [ tauto ]
-END
-
-TACTIC EXTEND dtauto
-| [ "dtauto" ] -> [ dtauto ]
-END
-
-TACTIC EXTEND intuition
-| [ "intuition" ] -> [ intuition_gen ist tauto_uniform_unit_flags default_intuition_tac ]
-| [ "intuition" tactic(t) ] -> [ intuition_gen ist tauto_uniform_unit_flags t ]
-END
-
-TACTIC EXTEND dintuition
-| [ "dintuition" ] -> [ intuition_gen ist tauto_power_flags default_intuition_tac ]
-| [ "dintuition" tactic(t) ] -> [ intuition_gen ist tauto_power_flags t ]
-END
diff --git a/tactics/tauto.mli b/tactics/tauto.mli
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tactics/tauto.mli