Library Paco.pacotacuser
Require Import Program.Tactics.
Require Export paconotation.
Require Import pacotac.
Set Implicit Arguments.
Require Export paconotation.
Require Import pacotac.
Set Implicit Arguments.
Class paco_class (A : Prop) :=
{ pacoacctyp: Type
; pacoacc : pacoacctyp
; pacomulttyp: Type
; pacomult : pacomulttyp
; pacofoldtyp: Type
; pacofold : pacofoldtyp
; pacounfoldtyp: Type
; pacounfold : pacounfoldtyp
}.
Definition get_paco_cls {A} {cls: paco_class A} (a: A) := cls.
Create HintDb paco.
Ltac paco_class TGT method :=
let typ := fresh "_typ_" in let lem := fresh "_lem_" in
let TMP := fresh "_tmp_" in let X := fresh "_X_" in
let CLS := fresh "_CLS_" in
evar (typ: Type); evar (lem: typ);
assert(TMP: TGT -> True) by (
intros X; set (CLS := method _ (get_paco_cls X));
repeat red in CLS; clear X; revert lem;
match goal with [CLS := ?v |-_] => instantiate (1:= v) end;
clear CLS; exact I);
clear TMP; unfold typ in *; clear typ; revert lem.
Ltac pfold := let x := fresh "_x_" in
repeat red;
match goal with [|- ?G] => paco_class G (@pacofold) end;
intro x; match goal with [x:=?lem|-_] => clear x; eapply lem end.
Ltac _punfold H := let x := fresh "_x_" in
repeat red in H;
let G := type of H in paco_class G (@pacounfold);
intro x; match goal with [x:=?lem|-_] => clear x; eapply lem in H end.
Ltac punfold H := _punfold H; eauto with paco.
Ltac pmult := let x := fresh "_x_" in
repeat red;
match goal with [|- ?G] => paco_class G (@pacomult) end;
intro x; match goal with [x:=?lem|-_] => clear x; eapply lem end.
Tactic Notation "pcofix" ident(CIH) "with" ident(r) :=
let x := fresh "_x_" in
generalize _paco_mark_cons; repeat intro; repeat red;
match goal with [|- ?G] =>
paco_class G (@pacoacc); intro x;
match goal with [x:=?lem|-_] => clear x;
paco_revert_hyp _paco_mark;
pcofix CIH using lem with r
end end.
Tactic Notation "pcofix" ident(CIH) := pcofix CIH with r.
Definition pclearbot_or (P Q: Prop) := P.
Ltac pclearbot :=
generalize _paco_mark_cons;
repeat(
match goal with [H: context [pacoid] |- _] =>
let NH := fresh H in
revert_until H; repeat red in H;
match goal with [Hcrr: context f [or] |- _] =>
match Hcrr with H =>
let P := context f [pclearbot_or] in
assert (NH: P) by (repeat intro; edestruct H ; [eassumption|contradiction]);
clear H; rename NH into H; unfold pclearbot_or in H
end
end
end);
intros; paco_revert_hyp _paco_mark.
Ltac pdestruct H := punfold H; destruct H; pclearbot.
Ltac pinversion H := punfold H; inversion H; pclearbot.
Ltac pmonauto :=
let IN := fresh "IN" in try (repeat intro; destruct IN; eauto; fail).