Library Rustre.Dataflow.NoDup
Require Import PArith.
Require Import List.
Import List.ListNotations.
Open Scope list_scope.
Require Import Rustre.Common.
Require Import Rustre.Dataflow.Syntax.
Require Import Rustre.Dataflow.IsVariable.
Require Import Rustre.Dataflow.IsDefined.
Require Import Rustre.Dataflow.Memories.
Require Import List.
Import List.ListNotations.
Open Scope list_scope.
Require Import Rustre.Common.
Require Import Rustre.Dataflow.Syntax.
Require Import Rustre.Dataflow.IsVariable.
Require Import Rustre.Dataflow.IsDefined.
Require Import Rustre.Dataflow.Memories.
No duplication of variables
Inductive NoDup_defs : list equation → Prop :=
| NDDNil: NoDup_defs nil
| NDDEqDef:
∀ x ck e eqs,
NoDup_defs eqs →
¬Is_defined_in_eqs x eqs →
NoDup_defs (EqDef x ck e :: eqs)
| NDDEqApp:
∀ x ck f e eqs,
NoDup_defs eqs →
¬Is_defined_in_eqs x eqs →
NoDup_defs (EqApp x ck f e :: eqs)
| NDDEqFby:
∀ x ck v e eqs,
NoDup_defs eqs →
¬Is_defined_in_eqs x eqs →
NoDup_defs (EqFby x ck v e :: eqs).
Lemma NoDup_defs_cons:
∀ eq eqs,
NoDup_defs (eq :: eqs) → NoDup_defs eqs.
Proof.
intros eq eqs Hndd.
destruct eq; inversion_clear Hndd; assumption.
Qed.
Lemma not_Is_variable_in_memories:
∀ x eqs,
PS.In x (memories eqs)
→ NoDup_defs eqs
→ ¬Is_variable_in_eqs x eqs.
Proof.
intros x eqs Hinm Hndd.
pose proof (Is_defined_in_memories _ _ Hinm) as Hdin.
unfold memories, Is_variable_in_eqs in ×.
induction eqs as [eq|eq eqs IH].
- simpl in *; intro; not_In_empty.
- apply Is_defined_in_cons in Hdin.
inversion Hndd
as [|y ck e ? Hndds Hndi|y ck f e ? Hndds Hndi|y ck v0 e ? Hndds Hndi];
subst; clear Hndd.
+ destruct Hdin as [Hdin|[Hndin Hdins]].
simpl in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
apply Is_defined_in_memories in Hinm.
inversion He; subst; clear He.
contradiction.
inversion Hdin; subst; clear Hdin.
apply Is_variable_in_eqs_Is_defined_in_eqs in He.
contradiction.
simpl in Hinm.
apply IH with (2:=Hndds) (3:=Hdins) in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
inversion He; subst; clear He.
apply Hndin; now constructor.
contradiction.
+ destruct Hdin as [Hdin|[Hndin Hdins]].
simpl in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
apply Is_defined_in_memories in Hinm.
inversion He; subst; clear He.
contradiction.
inversion Hdin; subst; clear Hdin.
apply Is_variable_in_eqs_Is_defined_in_eqs in He.
contradiction.
simpl in Hinm.
apply IH with (2:=Hndds) (3:=Hdins) in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
inversion He; subst; clear He.
apply Hndin; now constructor.
contradiction.
+ destruct Hdin as [Hdin|[Hndin Hdins]].
simpl in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
inversion He; subst; clear He.
inversion Hdin; subst; clear Hdin.
apply Is_variable_in_eqs_Is_defined_in_eqs in He.
contradiction.
simpl in Hinm.
apply In_fold_left_memory_eq in Hinm.
destruct Hinm as [Hinm|Hinm].
apply IH with (2:=Hndds) (3:=Hdins) in Hinm.
intro He; apply List.Exists_cons in He; destruct He as [He|He].
inversion He; subst; clear He.
contradiction.
apply PS.add_spec in Hinm.
destruct Hinm as [Hinm|Hinm]; [|now not_In_empty].
rewrite Hinm in ×.
exfalso; apply Hndin; now constructor.
Qed.