Lvc.Infra.AutoIndTac



Ltac revert_except E :=
  repeat match goal with
           [H : _ |- _] ⇒
           match H with
             | Efail 1
             | _revert H
               end
         end.

Ltac clear_except E :=
  repeat match goal with
           [H : _ |- _] ⇒
           match H with
             | Efail
             | _clear H
               end
         end.

Ltac clear_all :=
  repeat match goal with
           [H : _ |- _] ⇒ clear H
         end.

Ltac revert_all :=
  repeat match goal with
           [H : _ |- _] ⇒ revert H
         end.


Ltac remember_arguments E :=
  let tac x := (try (is_var x; fail 1); remember (x)) in
  repeat (match type of E with
    | ?t ?x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _ _tac x
    | ?t ?x _ _ _ _ _tac x
    | ?t ?x _ _ _ _tac x
    | ?t ?x _ _ _tac x
    | ?t ?x _ _tac x
    | ?t ?x _tac x
    | ?t ?xtac x
  end).

Ltac clear_dup :=
  match goal with
    | [ H : ?X |- _ ] ⇒
      match goal with
        | [ : ?Y |- _ ] ⇒
          match H with
            | fail 2
            | _unify X Y ; (clear || clear H)
          end
      end
  end.

Ltac inv_eqs :=
  repeat (match goal with
              | [ H : @eq _ ?x ?x |- _ ] ⇒ fail
              | [ H : @eq _ ?x ?y |- _ ] ⇒ progress (inversion H; subst; try clear_dup)
            end).

Ltac clear_trivial_eqs :=
  repeat (progress (match goal with
              | [ H : @eq _ ?x ?x |- _ ] ⇒ clear H
            end)).

Tactic Notation "general" "induction" hyp(H) :=
  remember_arguments H; revert_except H;
  induction H; intros; (try inv_eqs); (try clear_trivial_eqs).

Module Test.
Require Import List.

Inductive decreasing : list natProp :=
  | base : decreasing nil
  | step m n L : decreasing (n::L) → n mdecreasing (m :: n :: L).

Lemma all_zero_by_hand L
  : decreasing (0::L) → x, In x Lx = 0.

Lemma all_zero L
  : decreasing (0::L) → x, In x Lx = 0.
End Test.