Rocoma.Lib.My_tactics
Tactics
splitb equivalent of split for goals of the form _ && _
Ltac splitb := apply/andP; split.
(* {JM} *)
From Ltac2 Require Import Ltac2.
From Ltac2 Require Bool Ltac1 List Option Control Ident.
Ltac not_subterm x t f :=
match t with
| context [x] => idtac
| _ => f idtac
end.
Ltac2 not_subterm x t f :=
ltac1:(x t f |- not_subterm x t f) (Ltac1.of_ident x) (Ltac1.of_constr t) (Ltac1.lambda (fun t => f (); t)).
Ltac2 rec no_subterm_in_list l t f :=
match l with
| [] => f ()
| x :: l =>
not_subterm x t (fun () => no_subterm_in_list l t f)
end.
Ltac2 clear_but1 l :=
List.iter (fun (h, _, t) =>
if Bool.neg (List.mem Ident.equal h l) then
no_subterm_in_list l t (fun () => try (Std.clear [h]))
else ()
) (List.rev (Control.hyps ())).
(* {JM}
clear_except removes from the context every hypotheses excepts
the listed ones and their requirements.. *)
Tactic Notation "clear_except" ident_list_sep(l, ",") :=
let g := ltac2:(l |-
Option.may (fun l =>
let l := List.map_filter Ltac1.to_ident l in
clear_but1 l
) (Ltac1.to_list l)) in
g l.
(* {FP}
dblib_by_cases simplifies goals in which a decidable integer comparison
appears. *)
Ltac dblib_intro_case_clear :=
let h := fresh in
intro h; case h; clear h.
Ltac dblib_inspect_cases :=
match goal with
| |- context [le_gt_dec ?n ?n'] =>
case (le_gt_dec n n')
| h: context [le_gt_dec ?n ?n'] |- _ =>
revert h; case (le_gt_dec n n'); intro h
| |- context [eq_nat_dec ?n ?n'] =>
case (eq_nat_dec n n')
| h: context [eq_nat_dec ?n ?n'] |- _ =>
revert h; case (eq_nat_dec n n'); intro h
| |- context [(lt_eq_lt_dec ?n ?n')] =>
case (lt_eq_lt_dec n n'); [ dblib_intro_case_clear | idtac ]
| h: context [(lt_eq_lt_dec ?n ?n')] |- _ =>
revert h; case (lt_eq_lt_dec n n'); [ dblib_intro_case_clear | idtac ]; intro h
end.
Ltac dblib_by_cases :=
repeat dblib_inspect_cases; try solve [ intros; exfalso; lia ]; intros.
(* {FP}
push h moves the hypothesis h into the goal. *)
Ltac push h :=
generalize h; clear h.
(* {FP}
ltac_Mark and ltac_mark are dummies. They are used as sentinels by
certain tactics, to mark a position in the context or in the goal. *)
Inductive ltac_Mark : Type :=
| ltac_mark : ltac_Mark.
pop_until_mark moves all hypotheses from the goal into the context,
until a hypothesis of type ltac_Mark is reached. The mark is thrown
away. The tactic fails if no mark appears in the goal.
Ltac pop_until_mark :=
match goal with
| |- (ltac_Mark -> _) => intros _
| _ => intro; pop_until_mark
end.
Ltac injections :=
(* Place an initial mark, so as to not disturb the goal. *)
generalize ltac_mark;
(* Look at every equality hypothesis. *)
repeat match goal with
| h: _ = _ |- _ =>
(* Try to apply the primitive tactic injection to this hypothesis.
If this succeeds, clear h and replace it with the results of
injection. Another mark is used for this purpose. If this fails,
just push h into the goal, as we do not wish to see it any more. *)
first [
generalize ltac_mark; injection h; clear h; pop_until_mark
| push h ]
end;
(* Pop all of the hypotheses that have been set aside above. *)
pop_until_mark.
(* {FP}
The tactic unpack decomposes conjunctions and existential quantifiers
in the hypotheses. Then, it attempts to perform substitutions, if possible. *)
Ltac unpack :=
repeat match goal with
| h: _ /\ _ |- _ =>
destruct h
| h: exists _, _ |- _ =>
destruct h
end;
try subst.
Specialization of f_ext axiom, in order to allow its usage only for
substitution