Module FEnv
Require Import Freevar.
Require Import List.
Require Import Setoid.
Require Import Morphisms.
Require Import Misc.
Fixpoint env_find {
A :
Type} (
e :
list (
freevar *
A)) (
x :
freevar) :=
match e with
|
nil =>
None
| (
y,
r) ::
e =>
if freevar_eq_dec x y then Some r else env_find e x
end.
Definition env_same {
A :
Type} (
e1 e2 :
list (
freevar *
A)) :=
forall x,
env_find e1 x =
env_find e2 x.
Global Instance env_same_Reflexive {
A :
Type} :
Reflexive (@
env_same A).
Proof.
firstorder.
Qed.
Global Instance env_same_Transitive {
A :
Type} :
Transitive (@
env_same A).
Proof.
firstorder congruence.
Qed.
Global Instance env_same_Symmetric {
A :
Type} :
Symmetric (@
env_same A).
Proof.
firstorder congruence.
Qed.
Global Instance env_same_Equivalence {
A :
Type} :
Equivalence (@
env_same A).
Proof.
split; auto with typeclass_instances.
Qed.
Notation "
e1 '==='
e2" := (
env_same e1 e2) (
at level 70).
Lemma env_find_app :
forall A (
env1 env2 :
list (
freevar *
A))
x,
env_find (
env1 ++
env2)
x =
match env_find env1 x with Some t =>
Some t |
None =>
env_find env2 x end.
Proof.
intros. induction env1 as [|[y u] env1].
- reflexivity.
- simpl. destruct freevar_eq_dec.
+ reflexivity.
+ assumption.
Qed.
Global Instance env_same_app_Proper {
A :
Type} :
Proper (
env_same ==>
env_same ==>
env_same) (@
app (
freevar *
A)).
Proof.
intros e1 e2 H12 e3 e4 H34 x.
rewrite !env_find_app.
rewrite H12, H34.
reflexivity.
Qed.
Global Instance env_same_cons_Proper {
A :
Type} :
Proper (
eq ==>
env_same ==>
env_same) (@
cons (
freevar *
A)).
Proof.
intros z1 z2 -> e1 e2 H12 x.
apply (env_same_app_Proper (z2 :: nil) (z2 :: nil)); [reflexivity | assumption].
Qed.
Fixpoint update_env {
A :
Type} (
env :
list (
freevar *
A))
x v :=
match env with
|
nil => (
x,
v) ::
nil
| (
y,
u) ::
env =>
if freevar_eq_dec x y then (
x,
v) ::
env else (
y,
u) ::
update_env env x v
end.
Lemma env_find_map_assq :
forall (
B C :
Type) (
f :
freevar ->
B ->
C) (
L :
list (
freevar *
B))
x,
env_find (
map_assq f L)
x =
match env_find L x with Some u =>
Some (
f x u) |
None =>
None end.
Proof.
intros B C f L x. induction L as [|[y a] L].
- reflexivity.
- simpl. destruct freevar_eq_dec.
+ subst. reflexivity.
+ assumption.
Qed.
Inductive unique_env {
A :
Type} :
list (
freevar *
A) ->
Prop :=
|
unique_env_nil :
unique_env nil
|
unique_env_cons :
forall x t env,
env_find env x =
None ->
unique_env env ->
unique_env ((
x,
t) ::
env).
Lemma unique_env_map_assq :
forall (
A B :
Type) (
f :
freevar ->
A ->
B)
env,
unique_env (
map_assq f env) <->
unique_env env.
Proof.
intros A B f env. induction env as [|[x u] env].
- simpl. split; constructor.
- simpl. split; intros H; constructor; inversion H; subst.
+ rewrite env_find_map_assq in H2; destruct env_find; congruence.
+ tauto.
+ rewrite env_find_map_assq, H2; reflexivity.
+ tauto.
Qed.
Lemma unique_env_inv :
forall A (
env :
list (
freevar *
A))
x t,
unique_env ((
x,
t) ::
env) ->
unique_env env /\
env_find env x =
None.
Proof.
intros A env x t H; inversion H; subst; tauto.
Qed.
Lemma unique_env_inv_iff :
forall A (
env :
list (
freevar *
A))
x t,
unique_env ((
x,
t) ::
env) <->
unique_env env /\
env_find env x =
None.
Proof.
intros. split.
- apply unique_env_inv.
- intros [? ?]; constructor; assumption.
Qed.
Lemma unique_env_cons_mid_iff :
forall A (
env1 env2 :
list (
freevar *
A))
x t,
unique_env (
env1 ++ (
x,
t) ::
env2) <->
unique_env (
env1 ++
env2) /\
env_find (
env1 ++
env2)
x =
None.
Proof.
intros A; induction env1 as [|[y u] env1]; intros env2 x t.
- simpl. rewrite unique_env_inv_iff. reflexivity.
- simpl. rewrite !unique_env_inv_iff.
rewrite IHenv1, !env_find_app; simpl in *.
repeat destruct env_find; repeat destruct freevar_eq_dec; intuition congruence.
Qed.
Lemma unique_env_cons_mid :
forall A (
env1 env2 :
list (
freevar *
A))
x t,
unique_env (
env1 ++ (
x,
t) ::
env2) ->
unique_env (
env1 ++
env2) /\
env_find (
env1 ++
env2)
x =
None.
Proof.
intros. rewrite <- unique_env_cons_mid_iff. eassumption.
Qed.
Lemma env_cons_mid_eq :
forall (
A :
Type) (
env1 env2 :
list (
freevar *
A))
x u,
env_find env1 x =
None ->
env1 ++ (
x,
u) ::
env2 === (
x,
u) ::
env1 ++
env2.
Proof.
intros A env1 env2 x u Hx y. simpl. rewrite !env_find_app; simpl.
destruct freevar_eq_dec.
- subst. rewrite Hx. reflexivity.
- reflexivity.
Qed.
Lemma env_cons_mid_eq2 :
forall (
A :
Type) (
env1 env2 :
list (
freevar *
A))
x u,
env_find (
env1 ++
env2)
x =
None ->
env1 ++ (
x,
u) ::
env2 === (
x,
u) ::
env1 ++
env2.
Proof.
intros. apply env_cons_mid_eq.
rewrite env_find_app in H. destruct env_find; tauto.
Qed.
Lemma env_find_exists :
forall A (
env :
list (
freevar *
A))
x t,
env_find env x =
Some t ->
exists env1 env2,
env =
env1 ++ (
x,
t) ::
env2.
Proof.
intros. induction env as [|[y u] env].
- simpl in *. congruence.
- simpl in *. destruct freevar_eq_dec.
+ exists nil. exists env. simpl. congruence.
+ destruct (IHenv H) as (env1 & env2 & IH).
exists ((y, u) :: env1). exists env2.
rewrite IH. reflexivity.
Qed.
Lemma env_find_update_env :
forall A (
e :
list (
freevar *
A))
x y v,
env_find (
update_env e x v)
y =
if freevar_eq_dec x y then Some v else env_find e y.
Proof.
intros. induction e as [|[z u] e].
- simpl. repeat (destruct freevar_eq_dec); congruence.
- simpl. repeat (destruct freevar_eq_dec; simpl); congruence.
Qed.
Lemma update_env_same :
forall A (
e :
list (
freevar *
A))
x v,
update_env e x v === (
x,
v) ::
e.
Proof.
intros A e x v y. simpl.
rewrite env_find_update_env.
repeat destruct freevar_eq_dec; congruence.
Qed.
Lemma update_env_unique :
forall A (
env :
list (
freevar *
A))
x v,
unique_env env ->
unique_env (
update_env env x v).
Proof.
intros. induction env as [|[y u] env].
- simpl. constructor; [reflexivity|constructor].
- simpl. destruct freevar_eq_dec.
+ subst. inversion H; constructor; assumption.
+ inversion H; subst. constructor.
* rewrite env_find_update_env.
destruct freevar_eq_dec; congruence.
* auto.
Qed.
Fixpoint uniquify_env {
A :
Type} (
env :
list (
freevar *
A)) :=
match env with
|
nil =>
nil
| (
y,
u) ::
env => (
y,
u) ::
filter (
fun '(
x,
v) =>
if freevar_eq_dec x y then false else true) (
uniquify_env env)
end.
Lemma env_find_filter_unique :
forall (
A :
Type) (
env :
list (
freevar *
A))
P x,
unique_env env ->
env_find (
filter P env)
x =
match env_find env x with Some u =>
if P (
x,
u)
then Some u else None |
None =>
None end.
Proof.
intros A env P x Hunique. induction env as [|[y u] env].
- reflexivity.
- simpl in *. destruct (P (y, u)) eqn:HP; simpl.
+ destruct freevar_eq_dec.
* subst. rewrite HP; simpl. reflexivity.
* apply IHenv. inversion Hunique; assumption.
+ destruct freevar_eq_dec.
* subst. rewrite HP; simpl.
inversion Hunique; subst.
rewrite IHenv, H1; auto.
* apply IHenv. inversion Hunique; assumption.
Qed.
Lemma unique_env_filter :
forall (
A :
Type) (
env :
list (
freevar *
A))
P,
unique_env env ->
unique_env (
filter P env).
Proof.
intros A env P H. induction H.
- constructor.
- simpl. destruct (P (x, t)).
+ constructor.
* rewrite env_find_filter_unique by assumption.
rewrite H; reflexivity.
* assumption.
+ assumption.
Qed.
Lemma uniquify_env_unique :
forall (
A :
Type) (
env :
list (
freevar *
A)),
unique_env (
uniquify_env env).
Proof.
intros. induction env as [|[y u] env].
- simpl. constructor.
- simpl. constructor.
+ rewrite env_find_filter_unique by assumption.
destruct freevar_eq_dec; destruct env_find; congruence.
+ apply unique_env_filter. assumption.
Qed.
Lemma uniquify_env_same :
forall (
A :
Type) (
env :
list (
freevar *
A)),
uniquify_env env ===
env.
Proof.
intros. induction env as [|[y u] env].
- simpl. reflexivity.
- simpl. intros x. simpl.
destruct freevar_eq_dec.
+ reflexivity.
+ rewrite env_find_filter_unique by (apply uniquify_env_unique).
rewrite IHenv. destruct env_find; [|reflexivity].
destruct freevar_eq_dec; congruence.
Qed.
Lemma sublist_ordered_env_find :
forall (
A :
Type) (
env1 env2 :
list (
freevar *
A))
x,
sublist_ordered env2 env1 ->
unique_env env1 ->
forall t,
env_find env2 x =
Some t ->
env_find env1 x =
Some t.
Proof.
intros A env1 env2 x H. induction H; intros Hunique t Hfind.
+ assumption.
+ destruct x0 as [y u]. simpl in *.
destruct freevar_eq_dec; [assumption|].
apply IHsublist_ordered; [inversion Hunique|]; assumption.
+ destruct x0 as [y u]. simpl in *.
destruct freevar_eq_dec.
* subst. apply IHsublist_ordered in Hfind; inversion Hunique; subst; congruence.
* apply IHsublist_ordered; [inversion Hunique|]; assumption.
Qed.
Lemma sublist_ordered_unique_env :
forall (
A :
Type) (
env1 env2 :
list (
freevar *
A)),
sublist_ordered env2 env1 ->
unique_env env1 ->
unique_env env2.
Proof.
intros A env1 env2 H. induction H.
- intros; assumption.
- destruct x as [y u]. intros Hunique. inversion Hunique; subst.
constructor; [|tauto].
destruct (env_find L1 y) eqn:Hfind; [|reflexivity].
eapply sublist_ordered_env_find in Hfind; [|eassumption|eassumption]. congruence.
- intros Hunique. inversion Hunique. tauto.
Qed.
Global Instance map_assq_env_Proper {
A B :
Type} :
Proper ((
eq ==>
eq ==>
eq) ==>
env_same ==>
env_same) (@
map_assq freevar A B).
Proof.
intros f1 f2 Hf e1 e2 He x.
rewrite !env_find_map_assq, He. destruct (env_find e2 x); [|reflexivity].
f_equal. apply Hf; reflexivity.
Qed.
Lemma env_find_In2 :
forall A x u (
env :
list (
freevar *
A)), (
x,
u) \
in env ->
exists v,
env_find env x =
Some v.
Proof.
intros A x u env Hin. induction env as [|[y v] env].
- simpl in Hin; tauto.
- simpl. destruct freevar_eq_dec.
+ subst. exists v. reflexivity.
+ apply IHenv. simpl in Hin. intuition congruence.
Qed.
Lemma uniquify_env_not_in :
forall A x u (
env :
list (
freevar *
A)),
env_find env x =
None ->
uniquify_env ((
x,
u) ::
env) = (
x,
u) ::
uniquify_env env.
Proof.
intros A x u env Hx.
simpl. f_equal. apply Forall_filter_eq. rewrite Forall_forall.
intros [y v] H. destruct freevar_eq_dec; [|congruence]. subst.
exfalso. apply env_find_In2 in H. destruct H as [w H]; rewrite uniquify_env_same in H; congruence.
Qed.
Lemma env_find_In :
forall (
A :
Type) (
env :
list (
freevar *
A))
x u,
env_find env x =
Some u ->
In (
x,
u)
env.
Proof.
induction env as [|[y v] env].
- intros; simpl in *. congruence.
- intros; simpl in *.
destruct freevar_eq_dec.
+ left; congruence.
+ right; apply IHenv. assumption.
Qed.
Lemma update_env_app :
forall (
A :
Type) (
env1 env2 :
list (
freevar *
A))
x u,
env_find env1 x =
None ->
update_env (
env1 ++
env2)
x u =
env1 ++
update_env env2 x u.
Proof.
intros A env1 env2 x u Hx. induction env1 as [|[y v] env1].
- reflexivity.
- simpl in *. destruct freevar_eq_dec; [congruence|].
f_equal; tauto.
Qed.
Lemma env_move_to_front A (
env :
list (
freevar *
A))
x u :
unique_env env ->
env_find env x =
Some u ->
exists env1 env2,
env =
env1 ++ (
x,
u) ::
env2 /\
env === (
x,
u) ::
env1 ++
env2 /\
unique_env ((
x,
u) ::
env1 ++
env2).
Proof.
intros Hunique Hfind. apply env_find_exists in Hfind. destruct Hfind as (env1 & env2 & H). exists env1. exists env2.
split; [assumption|].
split; subst.
- intros y. rewrite unique_env_cons_mid_iff in Hunique. simpl.
rewrite !env_find_app in *. simpl.
destruct freevar_eq_dec.
+ subst. destruct env_find, Hunique; congruence.
+ reflexivity.
- rewrite unique_env_cons_mid_iff in Hunique. constructor; tauto.
Qed.
Global Instance update_env_Proper {
A :
Type} :
Proper (
env_same ==>
eq ==>
eq ==>
env_same) (@
update_env A).
Proof.
intros env1 env2 He x1 x2 -> u1 u2 ->.
rewrite !update_env_same. rewrite He. reflexivity.
Qed.
Lemma Forall_env_find :
forall A (
P :
freevar *
A ->
Prop)
L x t,
Forall P L ->
env_find L x =
Some t ->
P (
x,
t).
Proof.
intros. induction L as [|[y u] L].
- simpl in *. congruence.
- simpl in *. destruct freevar_eq_dec.
+ injection H0. intros; subst. rewrite Forall_cons_iff in H. tauto.
+ apply IHL; [rewrite Forall_cons_iff in H; tauto|]. assumption.
Qed.