Module ProgVar
Definition Le: t -> t -> Prop
:=Pos.le.
Definition isLe: t -> t -> bool
:= Pos.leb.
Lemma LeIsLe: forall x1 x2: t, isLe x1 x2 = true <-> Le x1 x2.
intros x1 x2; unfold isLe, Le. rewrite <- Pos.leb_le.
intuition.
Qed.
Lemma IsLeTotal : forall x1 x2, isLe x1 x2 = true \/ isLe x2 x1 = true.
intros x1 x2.
unfold isLe.
assert (IsLtTotal := PArith.BinPos.Pos.lt_total).
assert (LeIsLtEq := BinPos.Pos.le_lteq).
destruct (IsLtTotal x1 x2) as [h | [h | h]].
refine (Logic.or_introl (Logic.proj2 (LeIsLe _ _) _)).
exact ((Logic.proj2 (LeIsLtEq x1 x2)) (Logic.or_introl h)).
refine (Logic.or_introl (Logic.proj2 (LeIsLe _ _) _)).
exact ((Logic.proj2 (LeIsLtEq x1 x2)) (Logic.or_intror h)).
refine (Logic.or_intror (Logic.proj2 (LeIsLe _ _) _)).
exact ((Logic.proj2 (LeIsLtEq x2 x1)) (Logic.or_introl h)).
Qed.
Definition export: t -> BinNums.positive
:= fun x => x.
Definition import: BinNums.positive -> t
:= fun x => x.
Import Ascii String.
Local Open Scope char_scope.
Local Open Scope Z_scope.
Lemma Psucc_lift n: Zpos (Pos.succ n)=1+(Zpos n).
Proof.
simpl.
case n; simpl; auto.
Qed.
Lemma Zpos_eq n m: n=m <-> Zpos n=Zpos m.
Proof.
intuition; auto.
congruence.
Qed.
Lemma Zpos_Lt n m: Lt n m <-> Zpos n < Zpos m.
Proof.
Lemma Zpos_Le n m: Le n m <-> Zpos n <= Zpos m.
Proof.
Hint Rewrite Zpos_eq Zpos_Lt Zpos_Le Psucc_lift: pos2Z.
Ltac pvar_solve := intros; autorewrite with pos2Z in * |- *; try omega.
Lemma Le_refl : forall x, Le x x.
Proof.
pvar_solve.
Qed.
Lemma Le_antisym: forall x y, Le x y -> Le y x -> x=y.
Proof.
pvar_solve.
Qed.
Lemma Le_trans: forall x y z, Le x y -> Le y z -> Le x z.
Proof.
pvar_solve.
Qed.
Lemma Lt_le_trans:forall x y z, Lt y z -> Le x y -> Lt x z.
Proof.
pvar_solve.
Qed.
Lemma Lt_diff: forall x y, Lt x y -> x = y -> False.
Proof.
pvar_solve.
Qed.
Lemma negLt_le: forall x y, ~Lt x y -> Le y x.
Proof.
pvar_solve.
Qed.
Lemma Lt_negLe: forall x y, Lt x y -> ~Le y x.
Proof.
pvar_solve.
Qed.
Lemma Lt_succ n: Lt n (Pos.succ n).
Proof.
pvar_solve.
Qed.
Lemma Succ_Le_compat_r n m: Le n m -> Le n (Pos.succ m).
Proof.
pvar_solve.
Qed.
Lemma Le_pred n: Le (Pos.pred n) n.
Proof.
case (
Pos.succ_pred_or n).
intros;
subst;
simpl;
intuition.
intros H;
rewrite <-
H at 2.
pvar_solve.
Qed.
Lemma Le_Lt_pred n m: n <> m -> (Lt (Pos.pred n) m <-> Lt n m).
Proof.
case (
Pos.succ_pred_or n).
intros;
subst;
simpl;
intuition.
intros H;
rewrite <-
H at 1 3.
pvar_solve.
Qed.
Lemma xH_min: forall n, Le xH n.
Proof.
intros;
generalize (
Zgt_pos_0 n);
pvar_solve.
Qed.
Definition max : t -> t -> t := PArith.BinPos.Pos.max.
Definition max_l: forall x y, Le x (max x y) := PArith.BinPos.Pos.le_max_l.
Definition max_r: forall x y, Le y (max x y) := PArith.BinPos.Pos.le_max_r.
Lemma max_1_l: forall x, max xH x = x.
Proof.
Lemma max_1_r: forall x, max x xH = x.
Proof.
Lemma rew_max_l: forall n m, Le m n -> max n m=n.
Proof.
Lemma rew_max_r: forall n m, Le n m -> max n m = m.
Proof.
Lemma max_id: forall n, max n n = n.
Proof.
Hint Rewrite max_1_l max_1_r: rwmax1.
Lemma max_assoc m n p : max (max m n) p = max m (max n p).
Proof.
Hint Rewrite max_1_l max_1_r max_id max_assoc: rwmax.
Definition max_comm: forall n m, max n m = max m n := Pos.max_comm.
Create HintDb progvar discriminated.
Hint Resolve xH_min Le_refl Le_pred Le_trans max_l max_r LeIsLe LtIsLt Lt_le_trans Lt_diff Succ_Le_compat_r Lt_succ: progvar.
Lemma Le_max_rew_r: forall x y z, Le x (max y z) <-> (Le x y \/ Le x z).
Proof.
intros;
constructor 1.
apply Pos.max_case_strong;
intuition.
intuition eauto with progvar.
Qed.
Lemma Le_max_rew_l: forall x y z, Le (max y z) x <-> (Le y x /\ Le z x).
Proof.
Lemma Le_max_inject_l: forall x1 x2 y1 y2 z, Le x1 x2 -> Le y1 y2 -> Le (max x2 y2) z -> Le (max x1 y1) z.
Proof.
intros;
rewrite Le_max_rew_l in * |- *;
intuition eauto with progvar.
Qed.
Definition pr: t -> string
:= fun x => String "v" (CoqAddOn.posPr x).
Ltac max_simplify := autorewrite with rwmax1 in * |- ;
repeat (rewrite max_id in * |- *
|| rewrite Le_max_rew_l
|| rewrite Le_max_rew_r);
intuition auto with progvar.
End PVar.
Definition bExt {A B} (pred: A -> Prop) (f1 f2: A -> B)
:= forall x, (pred x) -> (f1 x)=(f2 x).
Lemma bExt_refl {A B} pred (f: A -> B):
bExt pred f f.
Proof.
Lemma bExt_sym {A B} (pred: A -> Prop) (f1 f2: A -> B):
bExt pred f1 f2 -> bExt pred f2 f1.
Proof.
unfold bExt;
intros;
symmetry;
auto.
Qed.
Hint Immediate bExt_sym.
Lemma bExt_trans {A B} (pred: A -> Prop) (f1 f2 f3: A -> B):
bExt pred f1 f2 -> bExt pred f2 f3 -> bExt pred f1 f3.
Proof.
unfold bExt;
intros;
apply eq_trans with (
y:=
f2 x);
auto.
Qed.
Lemma bExt_monotonic {A B} (pred1 pred2: A -> Prop) (f1 f2: A -> B):
bExt pred1 f1 f2 -> (forall x, pred2 x -> pred1 x) -> bExt pred2 f1 f2.
Proof.
Hint Unfold bExt.
Instance bExt_equiv {A B} (pred: A -> Prop): Equivalence (@bExt A B pred).
Proof.
Infix "°=" := (pointwise_relation _ Logic.eq) (at level 70, no associativity).
Hint Unfold pointwise_relation.
Hint Resolve bExt_monotonic: bExt.
Module Mem.
Definition t (A:Type) := PVar.t -> A.
assign x val s = push the pair (x,val) into m
Definition assign {A} (x: PVar.t) (val:A) (m: Mem.t A)
:= fun x' => if PVar.eq_dec x x' then val else (m x').
Lemma assign_in {A} x (val:A) m: assign x val m x = val.
Proof.
Hint Resolve assign_in: progvar.
Hint Rewrite @assign_in: progvar.
Lemma assign_out {A} x (val:A) m x': x<>x' -> assign x val m x' = m x'.
Proof.
Hint Resolve assign_out: progvar.
Lemma assign_id {A} x y (m:Mem.t A): assign x (m x) m y = m y.
Proof.
Hint Resolve assign_id: progvar.
Hint Rewrite @assign_id: progvar.
Lemma assign_commutes {A} x1 x2 (m:Mem.t A) v1 v2:
x1 <> x2 -> assign x1 v1 (assign x2 v2 m) °= assign x2 v2 (assign x1 v1 m).
Proof.
Lemma assign_absorbes {A} x (m:Mem.t A) v1 v2:
assign x v1 (assign x v2 m) °= assign x v1 m.
Proof.
Hint Rewrite @assign_absorbes: progvar.
Add Parametric Morphism A: (@assign A) with
signature Logic.eq ==> Logic.eq ==> pointwise_relation PVar.t Logic.eq ==> pointwise_relation PVar.t Logic.eq
as assign_morphism.
Proof.
Lemma free_equiv {A} x (m1 m2:Mem.t A): bExt (fun x' => x<>x') m1 m2 <-> m1 °= assign x (m1 x) m2.
Proof.
unfold bExt,
assign;
constructor 1;
intros H x';
generalize (
H x');
clear H;
case (
PVar.eq_dec x x');
intros;
subst;
intuition.
Qed.
Definition lift {A B} (f: A -> B) (m:Mem.t A): Mem.t B
:= fun x => f (m x).
Lemma lift_commutes {A B} (f: A -> B) x v m :
(lift f (assign x v m)) °= (assign x (f v) (lift f m)).
Proof.
Hint Rewrite @lift_commutes: vpl.
Add Parametric Morphism A B: (@lift A B) with
signature pointwise_relation A Logic.eq ==> pointwise_relation PVar.t Logic.eq ==> pointwise_relation PVar.t Logic.eq
as lift_morphism.
Proof.
unfold lift;
intros f1 f2 H m1 m2 H0;
congruence.
Qed.
End Mem.
Section MayDependOnDefinitions.
Context `{expr: Type}.
Context {mayDependOn: expr -> PVar.t -> Prop}.
Definition mdBounds (bound: positive) (e: expr) :=
forall x, (mayDependOn e x) -> PVar.Le x bound.
Lemma mdBounds_fold (bound: positive) (e: expr) x: (mayDependOn e x) -> mdBounds bound e -> PVar.Le x bound.
Proof.
Lemma md_mdBounds e x:
mayDependOn e x -> forall bound, mdBounds bound e -> PVar.Lt bound x -> False.
Proof.
unfold mdBounds;
simpl;
intuition eauto with progvar.
Qed.
Context {mdBound: expr -> PVar.t -> PVar.t}.
Class MDBoundVar := {
mdBound_max: forall e bound, (mdBound e bound) = PVar.max bound (mdBound e xH);
mdBound_mdBounds: forall e bound, mdBounds (mdBound e bound) e
}.
Hypothesis mdb_max: forall e bound, (mdBound e bound) = PVar.max bound (mdBound e xH).
Lemma mdBound_le: forall e bound, PVar.Le bound (mdBound e bound).
Proof.
intros.
rewrite mdb_max.
auto with progvar.
Qed.
End MayDependOnDefinitions.
Hint Resolve @mdBound_le: progvar.
Section MDBoundProp.
Context `{mdb:MDBoundVar}.
Lemma mdBound_comm: forall e1 e2 bound, mdBound e1 (mdBound e2 bound) = mdBound e2 (mdBound e1 bound).
Proof.
Lemma mdBound_invol: forall e bound, mdBound e (mdBound e bound) = mdBound e (bound).
Proof.
End MDBoundProp.
Section mdoExtDefinition.
Context {expr: Type} {value: Type} {observer:Type}.
Context (mayDependOn: expr -> PVar.t -> Prop).
Context (eval: expr -> (PVar.t -> value) -> observer).
Context (obs_eq: observer -> observer -> Prop).
Definition frames (pred: PVar.t -> Prop) (e: expr) := forall m1 m2, bExt pred m1 m2 -> obs_eq (eval e m1) (eval e m2).
Lemma frames_monotonic (pred1 pred2: PVar.t -> Prop) (e: expr):
frames pred1 e -> (forall x, pred1 x -> pred2 x) -> frames pred2 e.
Proof.
unfold frames;
eauto with bExt.
Qed.
Definition mdoExt := forall e m1 m2, bExt (mayDependOn e) m1 m2 -> obs_eq (eval e m1) (eval e m2).
End mdoExtDefinition.
Section mdoExtProp.
Context {expr: Type} {value: Type} {observer:Type}.
Context {mayDependOn: expr -> PVar.t -> Prop}.
Context {eval: expr -> (PVar.t -> value) -> observer}.
Context {obs_eq: observer -> observer -> Prop}.
Context {obs_eq_eq:@Equivalence observer obs_eq}.
Context (eval_mdo: mdoExt mayDependOn eval obs_eq).
Instance eval_pointwise_compat: Proper (Logic.eq ==> pointwise_relation PVar.t Logic.eq ==> obs_eq) eval.
Proof.
intros x y H1 m1 m2 H2.
subst.
erewrite eval_mdo;
eauto.
Qed.
Lemma mdoExt_free: forall e x m1 m2, ~(mayDependOn e x) -> bExt (fun x' => x <> x') m1 m2 -> obs_eq (eval e m1) (eval e m2).
Proof.
intros.
eapply eval_mdo;
eauto.
intros y H1.
rewrite H0;
auto.
intro;
subst;
intuition.
Qed.
End mdoExtProp.
Section MayDepOnWithIff.
Context {expr: Type} {value: Type}.
Context {mayDependOn: expr -> PVar.t -> Prop}.
Context {sat: expr -> (PVar.t -> value) -> Prop}.
Context (sat_mdo_impl: mdoExt mayDependOn sat impl).
Lemma sat_mdo_iff: mdoExt mayDependOn sat iff.
Proof.
constructor 1; (
intros;
eapply sat_mdo_impl; [
idtac |
eauto]);
auto.
Qed.
End MayDepOnWithIff.
Section ExtensionalityWithIff.
Context {expr:Type} {value:Type}.
Context (sat: expr -> (PVar.t -> value) -> Prop).
Context (sat_compat_impl: Proper (Logic.eq ==> pointwise_relation PVar.t Logic.eq ==> impl) sat).
Program Instance sat_compat_iff: Proper (Logic.eq ==> pointwise_relation PVar.t Logic.eq ==> iff) sat.
Obligation 1.
constructor 1; rewrite H; rewrite H0; auto.
Qed.
End ExtensionalityWithIff.
Section Rename.
Context {expr: Type} {value: Type} {observer:Type}.
Context (eval: expr -> (PVar.t -> value) -> observer).
Context (obs_eq: observer -> observer -> Prop).
obs_eq is "morally" an equivalence. But a preorder suffices
Context {obs_eq_eq:@PreOrder observer obs_eq}.
Condition stating that re is a rename of e where x is replaced by y.
This is a strong version, with no hypothesis on y
Definition isRename (re e: expr) (x y:PVar.t) : Prop :=
forall m, obs_eq (eval e (Mem.assign x (m y) m)) (eval re m).
A variant of the previous definition, where y is assumed to be "fresh" in the context
(or more exactly, y has no effect on the result of eval e m)
Definition isFreshOnlyRename (re e: expr) (x y:PVar.t): Prop :=
forall m,
(forall m2, bExt (fun x' => y <> x') m m2 -> obs_eq (eval e m) (eval e m2))
-> (forall v, obs_eq (eval e m) (eval re (Mem.assign y (m x) (Mem.assign x v m)))).
Lemma rename_prop (re e: expr) (x y:PVar.t):
(isRename re e x y) -> (isFreshOnlyRename re e x y).
Proof.
End Rename.
Hint Resolve iff_equivalence.
Hint Resolve sat_mdo_iff: progvar.
Hint Unfold mdBounds: progvar.