From Coq Require Import PArith.
From Coq Require Import Omega.
From Coq Require Import List.
Import List.ListNotations.
Open Scope list_scope.
From Velus Require Import Common.
From Velus Require Import Operators.
From Velus Require Import Clocks.
From Velus Require Import CoreExpr.CESyntax.
From Velus Require Import NLustre.NLSyntax.
From Velus Require Import NLustre.Memories.
Defined variables
Module Type ISDEFINED
(
Ids :
IDS)
(
Op :
OPERATORS)
(
Import CESyn :
CESYNTAX Op)
(
Import Syn :
NLSYNTAX Ids Op CESyn)
(
Import Mem :
MEMORIES Ids Op CESyn Syn).
Logical predicates:
Inductive Is_defined_in_eq :
ident ->
equation ->
Prop :=
|
DefEqDef:
forall x ck e,
Is_defined_in_eq x (
EqDef x ck e)
|
DefEqApp:
forall x xs ck f e r,
In x xs ->
Is_defined_in_eq x (
EqApp xs ck f e r)
|
DefEqFby:
forall x ck v e,
Is_defined_in_eq x (
EqFby x ck v e).
Definition Is_defined_in (
x:
ident) (
eqs:
list equation) :
Prop :=
List.Exists (
Is_defined_in_eq x)
eqs.
Properties
Hint Constructors Is_defined_in_eq.
Lemma not_Is_defined_in_eq_EqDef:
forall x i ck ce,
~
Is_defined_in_eq x (
EqDef i ck ce) ->
x <>
i.
Proof.
intros x i ck ce H0 xeqi.
rewrite xeqi in H0.
assert (
Is_defined_in_eq i (
EqDef i ck ce))
by auto.
contradiction.
Qed.
Lemma not_Is_defined_in_eq_EqApp:
forall x ys ck f le r,
~
Is_defined_in_eq x (
EqApp ys ck f le r) -> ~
List.In x ys.
Proof.
intros * H. intro.
exfalso. apply H. auto.
Qed.
Lemma Is_defined_in_EqApp:
forall xs ck f es r d,
0 <
length xs ->
Is_defined_in_eq (
hd d xs) (
EqApp xs ck f es r).
Proof.
intros * Length.
constructor.
destruct xs; simpl in *; auto; omega.
Qed.
Lemma not_Is_defined_in_eq_EqFby:
forall x i ck v0 le,
~
Is_defined_in_eq x (
EqFby i ck v0 le) ->
x <>
i.
Proof.
intros x i ck v0 le H0 xeqi.
rewrite xeqi in H0.
assert (
Is_defined_in_eq i (
EqFby i ck v0 le))
by auto.
contradiction.
Qed.
Lemma not_Is_defined_in_cons:
forall x eq eqs,
~
Is_defined_in x (
eq ::
eqs)
<-> ~
Is_defined_in_eq x eq /\ ~
Is_defined_in x eqs.
Proof.
intros x eq eqs. split.
-
intro Hndef; split; intro His_def;
eapply Hndef. now constructor. now constructor 2.
-
intros [Hdef_eq Hdef_eqs] Hdef_all.
inv Hdef_all; eauto.
Qed.
Lemma In_memory_eq_In_defined_eq_gen:
forall x eq S,
PS.In x (
memory_eq S eq)
->
Is_defined_in_eq x eq \/
PS.In x S.
Proof.
intros x eq S.
destruct eq;
simpl;
intro HH;
try intuition.
apply PS.add_spec in HH;
intuition.
subst;
left;
constructor.
Qed.
Corollary In_memory_eq_Is_defined_eq:
forall x eq,
PS.In x (
memory_eq PS.empty eq)
->
Is_defined_in_eq x eq.
Proof.
Lemma Is_defined_in_memories:
forall x eqs,
PS.In x (
memories eqs) ->
Is_defined_in x eqs.
Proof.
Lemma In_EqFby_Is_defined_in:
forall x ck c0 e eqs,
In (
EqFby x ck c0 e)
eqs ->
Is_defined_in x eqs.
Proof.
induction eqs; inversion_clear 1; subst.
now repeat constructor.
constructor 2; intuition.
Qed.
Decision procedures:
Fixpoint defined_eq (
defs:
PS.t) (
eq:
equation) {
struct eq} :
PS.t :=
match eq with
|
EqDef x _ _ =>
PS.add x defs
|
EqApp xs _ _ _ _ =>
ps_adds xs defs
|
EqFby x _ _ _ =>
PS.add x defs
end.
Definition defined (
eqs:
list equation) :
PS.t :=
List.fold_left defined_eq eqs PS.empty.
Silly unfolding property:
Lemma Subset_defined_eq:
forall eq m1 m2,
PS.Subset m1 m2 ->
PS.Subset (
defined_eq m1 eq) (
defined_eq m2 eq).
Proof.
Lemma In_fold_left_defined_eq:
forall x eqs m,
PS.mem x (
List.fold_left defined_eq eqs m) =
true
<->
PS.mem x (
List.fold_left defined_eq eqs PS.empty) =
true \/
PS.In x m.
Proof.
induction eqs as [|
eq].
-
split;
auto.
destruct 1
as [
H|];
auto.
now apply not_In_empty in H;
contradiction.
-
split.
+
intro H.
simpl;
rewrite IHeqs.
setoid_rewrite IHeqs in H.
clear IHeqs.
destruct H as [
H|
H];
auto.
destruct eq;
simpl in *;
try rewrite PS.add_spec in *;
try rewrite ps_adds_spec in *;
destruct H;
auto.
+
simpl.
setoid_rewrite IHeqs.
destruct 1
as [[
H|
H]|
H];
auto.
rewrite <-
Subset_defined_eq with (
m1:=
PS.empty);
auto using PSP.subset_empty.
right.
destruct eq;
simpl;
try apply PS.add_spec;
try apply ps_adds_spec;
auto.
Qed.
Reflection lemmas:
Lemma Is_defined_in_eqP :
forall x eq,
Is_defined_in_eq x eq <->
PS.mem x (
defined_eq PS.empty eq) =
true.
Proof.
Lemma Is_defined_inP:
forall x eqs,
Is_defined_in x eqs <->
PS.mem x (
defined eqs) =
true.
Proof.
Lemma Is_defined_in_vars_defined:
forall x eqs,
Is_defined_in x eqs
<->
In x (
vars_defined eqs).
Proof.
intros;
rewrite Is_defined_inP,
PS.mem_spec.
induction eqs as [ |
eq eqs IHeqs ];
simpl.
-
now rewrite PSF.empty_iff.
-
destruct eq;
rewrite <-
PS.mem_spec;
unfold defined;
simpl.
+
rewrite In_fold_left_defined_eq,
PSF.add_iff,
PSF.empty_iff,
IHeqs;
tauto.
+
unfold vars_defined;
simpl;
rewrite in_app,
In_fold_left_defined_eq,
ps_adds_spec,
PSF.empty_iff,
IHeqs;
tauto.
+
rewrite In_fold_left_defined_eq,
PSF.add_iff,
PSF.empty_iff,
IHeqs;
tauto.
Qed.
Lemma Is_defined_in_eq_dec:
forall x eq, {
Is_defined_in_eq x eq}+{~
Is_defined_in_eq x eq}.
Proof.
Lemma Is_defined_in_dec:
forall x eqs, {
Is_defined_in x eqs}+{~
Is_defined_in x eqs}.
Proof.
Lemma decidable_Is_defined_in:
forall x eqs,
Decidable.decidable (
Is_defined_in x eqs).
Proof.
Properties
Lemma Is_defined_in_var_defined:
forall x eq,
Is_defined_in_eq x eq <->
List.In x (
var_defined eq).
Proof.
Lemma Is_defined_in_cons:
forall x eq eqs,
Is_defined_in x (
eq ::
eqs) ->
Is_defined_in_eq x eq
\/ (~
Is_defined_in_eq x eq /\
Is_defined_in x eqs).
Proof.
Lemma In_memory_eq_In_defined_eq:
forall x eq S,
PS.In x (
memory_eq S eq)
->
PS.In x (
defined_eq S eq).
Proof.
intros x eq S HH.
destruct eq;
match goal with
| |-
context[
EqApp _ _ _ _ _ ] =>
generalize ps_adds_spec;
intro add_spec
|
_ =>
generalize PS.add_spec;
intro add_spec
end;
try (
apply add_spec;
now intuition).
apply add_spec in HH.
destruct HH as [
HH|
HH].
-
rewrite HH;
apply add_spec;
left;
reflexivity.
-
apply add_spec;
right;
exact HH.
Qed.
Lemma In_fold_left_memory_eq_defined_eq:
forall x eqs S,
PS.In x (
List.fold_left memory_eq eqs S)
->
PS.In x (
List.fold_left defined_eq eqs S).
Proof.
Lemma not_Exists_Is_defined_in_n_in:
forall n, ~
Exists (
fun ni=>
Is_defined_in ni n.(
n_eqs)) (
map fst n.(
n_in)).
Proof.
Lemma Is_defined_in_In:
forall x eqs,
Is_defined_in x eqs ->
exists eq,
In eq eqs /\
Is_defined_in_eq x eq.
Proof.
induction eqs as [|
eq].
now inversion 1.
inversion_clear 1
as [? ?
Hdef|? ?
Hex].
-
exists eq;
split;
auto with datatypes.
-
apply Exists_exists in Hex as (
eq' &
Hin &
Hdef).
exists eq';
split;
auto with datatypes.
Qed.
Lemma node_output_defined_in_eqs:
forall n x,
In x (
map fst n.(
n_out)) ->
Is_defined_in x n.(
n_eqs).
Proof.
Lemma node_variable_defined_in_eqs:
forall n x,
In x (
map fst n.(
n_vars)) ->
Is_defined_in x n.(
n_eqs).
Proof.
Lemma vars_defined_cons:
forall eq eqs x,
In x (
vars_defined (
eq ::
eqs))
<-> (
Is_defined_in_eq x eq \/
In x (
vars_defined eqs)).
Proof.
intros.
destruct eq;
simpl;
split;
intro HH;
try destruct HH;
repeat match goal with
| [
H:
Is_defined_in_eq _ _ |-
_ ] =>
now inv H;
auto
| [
H:
In _ (
_ ++
_) |-
_ ] =>
apply in_app_or in H as [|]
| |-
In _ (
_ ++
_) =>
apply in_or_app
end;
subst;
auto.
Qed.
Lemma Exists_Is_defined_in_eq_vars_defined:
forall eqs x,
Exists (
Is_defined_in_eq x)
eqs <->
In x (
vars_defined eqs).
Proof.
induction eqs as [|
eq eqs IH].
now split;
inversion 1.
setoid_rewrite Exists_cons.
setoid_rewrite IH.
now setoid_rewrite vars_defined_cons.
Qed.
Lemma NoDup_vars_defined_cons:
forall eq eqs,
NoDup (
vars_defined (
eq ::
eqs)) ->
NoDup (
vars_defined eqs).
Proof.
destruct eq; [inversion 1| |inversion 1]; auto.
simpl. setoid_rewrite NoDup_app'_iff. intuition.
Qed.
Lemma NoDup_Is_defined_in:
forall eq eqs x,
NoDup (
vars_defined (
eq ::
eqs)) ->
Is_defined_in x (
eq ::
eqs) ->
(
Is_defined_in_eq x eq /\ ~
Is_defined_in x eqs)
\/ (~
Is_defined_in_eq x eq /\
Is_defined_in x eqs).
Proof.
Lemma gather_mems_Is_defined_in:
forall x eqs,
In x (
gather_mems eqs) ->
Is_defined_in x eqs.
Proof.
induction eqs as [|eq eqs IH]. now inversion 1.
intro Hin. destruct eq; [| |destruct Hin as [Hin|Hin]]; simpl in *;
try (now constructor 2; apply IH).
subst. now constructor.
Qed.
Lemma gather_insts_Is_defined_in:
forall x eqs,
InMembers x (
gather_insts eqs) ->
Is_defined_in x eqs.
Proof.
induction eqs as [|eq eqs IH]. now inversion 1.
intro Hin.
destruct eq; [|destruct l; try destruct Hin as [Hin|Hin]|]; simpl in *;
try (now constructor 2; apply IH).
subst. now repeat constructor.
Qed.
Lemma gather_mem_eq_Is_defined_in_eq:
forall eq x,
In x (
gather_mem_eq eq) ->
Is_defined_in_eq x eq.
Proof.
destruct eq; auto; simpl; intros x HH; try contradiction.
destruct HH; subst; auto. contradiction.
Qed.
Lemma gather_inst_eq_Is_defined_in_eq:
forall eq x,
InMembers x (
gather_inst_eq eq) ->
Is_defined_in_eq x eq.
Proof.
destruct eq;
simpl;
try contradiction.
destruct l.
now intuition.
inversion 1;
subst.
now repeat constructor.
match goal with [
H:
InMembers _ [] |-
_ ] =>
inversion H end.
Qed.
Lemma NoDup_In_gather_mems:
forall eq eqs x,
NoDup (
vars_defined (
eq ::
eqs)) ->
In x (
gather_mems (
eq ::
eqs)) ->
(
In x (
gather_mem_eq eq) /\ ~(
In x (
gather_mems eqs)))
\/ (~
In x (
gather_mem_eq eq) /\
In x (
gather_mems eqs)).
Proof.
Lemma NoDup_In_gather_insts:
forall eq eqs x,
NoDup (
vars_defined (
eq ::
eqs)) ->
InMembers x (
gather_insts (
eq ::
eqs)) ->
(
InMembers x (
gather_inst_eq eq) /\ ~(
InMembers x (
gather_insts eqs)))
\/ (~
InMembers x (
gather_inst_eq eq) /\
InMembers x (
gather_insts eqs)).
Proof.
End ISDEFINED.
Module IsDefinedFun
(
Ids :
IDS)
(
Op :
OPERATORS)
(
CESyn :
CESYNTAX Op)
(
Syn :
NLSYNTAX Ids Op CESyn)
(
Mem :
MEMORIES Ids Op CESyn Syn)
<:
ISDEFINED Ids Op CESyn Syn Mem.
Include ISDEFINED Ids Op CESyn Syn Mem.
End IsDefinedFun.