(* ------------------------------------------------------------------------ *) (* Adapted from Celsius project : https://github.com/clementblaudeau/celsius *) From Stdlib Require Export String List Psatz Program.Tactics Arith. Import ListNotations. Global Hint Extern 50 => lia: lia. Global Hint Extern 50 => cbn: cbn. Global Hint Extern 50 => cbn; intuition auto: cbn_intuition. Ltac options := unfold option_map in *. Ltac invert_constructor_equalities := match goal with | H: ?F _ = ?F _ |- _ => is_constructor F; inversion H; clear H | H: ?F _ _ = ?F _ _ |- _ => is_constructor F; inversion H; clear H | H: ?F _ _ _ = ?F _ _ _ |- _ => is_constructor F; inversion H; clear H | H: ?F _ _ _ _ = ?F _ _ _ _ |- _ => is_constructor F; inversion H; clear H | H: ?F _ _ _ _ _ = ?F _ _ _ _ _ |- _ => is_constructor F; inversion H; clear H | H: ?F _ _ _ _ _ _ = ?F _ _ _ _ _ _ |- _ => is_constructor F; inversion H; clear H end. Ltac destruct_exists := match goal with | H: exists x, _ |- _ => let freshX := fresh x in let matched := fresh "matched_exists" in destruct H as [ freshX ] eqn:matched end. Ltac destruct_and := match goal with | H: _ /\ _ |- _ => destruct H end. Global Hint Rewrite Bool.andb_true_iff: bools. Global Hint Rewrite Bool.andb_false_iff: bools. Global Hint Rewrite Bool.orb_true_iff: bools. Global Hint Rewrite Bool.orb_false_iff: bools. Global Hint Rewrite Bool.negb_true_iff: bools. Global Hint Rewrite Bool.negb_false_iff: bools. Ltac bools := autorewrite with bools in *. Ltac destruct_match := match goal with | [ |- context[match ?t with _ => _ end]] => let matched := fresh "matched" in destruct t eqn:matched | [ H: context[match ?t with _ => _ end] |- _ ] => let matched := fresh "matched" in destruct t eqn:matched end. Ltac flatten := repeat subst || match goal with | H : _ \/ _ |- _ => let fresh1 := fresh H in let fresh2 := fresh H in destruct H as [fresh1 | fresh2] | H : _ /\ _ |- _ => let fresh1 := fresh H in let fresh2 := fresh H in destruct H as [fresh1 fresh2] | H : exists a, _ |- _ => let fresh_a := fresh a in destruct H as [fresh_a H] end || invert_constructor_equalities. Ltac ground := repeat destruct_match || flatten. Ltac light := (intros) || (intuition auto) || (congruence) || (subst) || (cbn in *) || (autounfold in *) .
Taken from Cpdt
Succeed iff x is in the list ls, represented with left-associated nested tuples.
Ltac inList x ls :=
match ls with
| x => idtac
| (_, x) => idtac
| (?LS, _) => inList x LS
end.
Taken from Cpdt
Ltac step_inversion predicates := let invert H F := inList F predicates; (inversion H; fail) || (inversion H; [ idtac ]; clear H) in match goal with | [ H: ?F _ |- _ ] => invert H F | [ H: ?F _ _ |- _ ] => invert H F | [ H: ?F _ _ _ |- _ ] => invert H F | [ H: ?F _ _ _ _ |- _ ] => invert H F | [ H: ?F _ _ _ _ _ |- _ ] => invert H F | [ H: ?F _ _ _ _ _ _ |- _ ] => invert H F end. Ltac containsExistential := match goal with | [ |- ?G ] => has_evar G end. Ltac noExistential := tryif containsExistential then fail else idtac. Ltac removeDuplicateProps := match goal with | [ H1: ?P, H2: ?P |- _ ] => match type of P with | Prop => idtac end; clear H2 end. Ltac isThere P := match goal with | H: ?Q |- _ => unify P Q (* | |- ?Q => unify P Q *) end. Ltac notThere P := tryif (isThere P) then fail else idtac. Ltac not_var P := tryif (is_var P) then fail else idtac. Ltac noUnify P Q := tryif (unify P Q) then fail else idtac. Lemma strong_and: forall (A B: Prop), A -> (A -> B) -> (exists _: A, B). Proof. eauto. Qed. Ltac step_gen := match goal with | _ => progress light | _ => apply strong_and | H: exists x, _ |- _ => let x' := fresh x in destruct H as [ x' ] | [ p: ?A*?B |- _ ] => destruct p | [ H: (_,_) = (_,_) |- _ ] => inversion H; clear H | H: _ |- _ => injection H; clear H | |- NoDup _ => constructor | H: forall a, _ -> _ |- _ => pose proof (H _ eq_refl); clear H | H: forall a b, _ -> _ |- _ => pose proof (H _ _ eq_refl); clear H | H: forall a b c, _ -> _ |- _ => pose proof (H _ _ _ eq_refl); clear H | H: forall a b c d, _ -> _ |- _ => pose proof (H _ _ _ _ eq_refl); clear H | H: forall a b c d e, _ -> _ |- _ => pose proof (H _ _ _ _ _ eq_refl); clear H | [ |- context[match ?t with _ => _ end]] => let matched := fresh "matched" in destruct t eqn:matched | [ H: context[match ?t with _ => _ end] |- _ ] => let matched := fresh "matched" in destruct t eqn:matched | _ => removeDuplicateProps | H := _: ?T |- _ => noUnify T string; clearbody H | _ => noExistential; solve [ constructor ] | _ => noExistential; solve [ constructor; constructor ] end. Ltac step := step_gen || step_inversion (List.Forall, List.In). Ltac steps := repeat step. Ltac apply_any := match goal with | H: _ |- _ => apply H end. Ltac rewrite_any := match goal with | H: _ |- _ => rewrite H in * end. Ltac erewrite_any := match goal with | H: _ |- _ => erewrite H in * end. Ltac rewrite_back_any := match goal with | H: _ |- _ => rewrite <- H in * end. Ltac eapply_any := match goal with | H: _ |- _ => eapply H end. Ltac apply_anywhere f := match goal with | H: _ |- _ => apply f in H end. Ltac eapply_anywhere f := match goal with | H: _ |- _ => eapply f in H end. Ltac rewrite_anywhere f := match goal with | H: _ |- _ => rewrite f in H end. Ltac erewrite_anywhere f := match goal with | H: _ |- _ => erewrite f in H end. Ltac destruct_eq H := match H with | ?a = ?b => let fresh_H := fresh "Heq" in pose proof (PeanoNat.Nat.eq_dec a b) as [fresh_H | fresh_H] end. Ltac modus_ponens := repeat match goal with | H1 : ?P -> ?Q, H2: ?P |- _ => pose proof (H1 H2) ; clear H1 end. Ltac nat_le_trans := repeat match goal with |H1: ?a <= ?b, H2: ?b <= ?c |- _ => match goal with | H3 : a <= c |- _ => fail 1 | _ => assert (a <= c) by lia end end. Ltac modus := repeat match goal with | H: ?A -> ?B, H': ?A |- _ => specialize (H H') end. Ltac app_eq_nil := repeat match goal with | H: nil = _ ++ (_ :: _) |- _ => symmetry in H | H: _ ++ (_ :: _) = nil |- _ => exfalso; apply app_eq_nil in H as [_ H]; inversion H end. Global Hint Extern 1 => app_eq_nil: core. Require Export LibTactics. Ltac cross_rewrites := repeat match goal with | H: ?A = ?B, H': ?A = ?C |- _ => rewrite H in H'; inverts H' end. Global Hint Extern 1 => cross_rewrites: core. Ltac destruct_if_eqb:= match goal with | H : context [if Nat.eqb ?a ?b then _ else _ ] |- _ => let Heq := fresh "Heq" in destruct (Nat.eqb a b) eqn:Heq; [apply PeanoNat.Nat.eqb_eq in Heq ; rewrites Heq in * ; clear Heq | apply PeanoNat.Nat.eqb_neq in Heq ] end.