From Velus Require Import Stc.
From Velus Require Import Obc.
From Velus Require Import StcToObc.Translation.
From Velus Require Import StcToObc.StcMemoryCorres.
From Velus Require Import VelusMemory.
From Velus Require Import Common.
From Velus Require Import Environment.
From Coq Require Import List.
Import List.ListNotations.
From Coq Require Import Setoid Morphisms.
Open Scope nat.
Open Scope list.
Module Type CORRECTNESS
(
Import Ids :
IDS)
(
Import Op :
OPERATORS)
(
Import OpAux :
OPERATORS_AUX Op)
(
Import Str :
INDEXEDSTREAMS Op OpAux)
(
Import CE :
COREEXPR Ids Op OpAux Str)
(
Import Stc :
STC Ids Op OpAux Str CE)
(
Import Obc :
OBC Ids Op OpAux)
(
Import Trans :
TRANSLATION Ids Op OpAux CE.Syn Stc.Syn Obc.Syn)
(
Import Corres :
STCMEMORYCORRES Ids Op CE.Syn Stc.Syn Stc.Last).
Inductive eq_if_present:
value ->
option val ->
Prop :=
|
EqP:
forall v,
eq_if_present (
present v) (
Some v)
|
EqA:
forall v,
eq_if_present absent v.
Hint Constructors eq_if_present.
Definition value_to_option (
v:
value) :
option val :=
match v with
|
absent =>
None
|
present c =>
Some c
end.
Definition equiv_env (
in_domain:
ident ->
Prop) (
R:
env)
(
mems:
PS.t) (
me:
menv) (
ve:
venv) :
Prop :=
forall x v,
in_domain x ->
sem_var_instant R x v ->
eq_if_present v (
if PS.mem x mems then find_val x me else Env.find x ve).
Lemma equiv_env_map:
forall (
in_dom1 in_dom2:
ident ->
Prop)
R mems me ve,
(
forall x,
in_dom2 x ->
in_dom1 x) ->
equiv_env in_dom1 R mems me ve ->
equiv_env in_dom2 R mems me ve.
Proof.
unfold equiv_env;
intros ???????
Eq ????.
apply Eq;
auto.
Qed.
Ltac weaken_equiv_env_with tac :=
match goal with
H:
equiv_env ?
in_dom1 ?
R ?
mems ?
me ?
ve
|-
equiv_env ?
in_dom2 ?
R ?
mems ?
me ?
ve =>
eapply equiv_env_map; [|
exact H];
tac
end.
Tactic Notation "
weaken_equiv_env" "
with"
tactic(
tac) :=
weaken_equiv_env_with tac.
Tactic Notation "
weaken_equiv_env" :=
weaken_equiv_env with now (
constructor;
auto).
Hint Extern 4 (
equiv_env _ _ _ _ _) =>
weaken_equiv_env.
Lemma eq_if_present_present:
forall vo c,
eq_if_present (
present c)
vo <->
vo =
Some c.
Proof.
simpl; split.
- now inversion 1.
- intros ->; auto.
Qed.
Ltac split_env_assumption :=
match goal with
|
Equiv:
context Is_free_in_exp [
_],
Hvar:
sem_var_instant _ _ _ |-
_ =>
apply Equiv in Hvar; [|
solve [
constructor;
auto]]
|
Equiv:
context Is_free_in_clock [
_],
Hvar:
sem_var_instant _ _ _ |-
_ =>
apply Equiv in Hvar; [|
solve [
constructor;
auto]]
end.
Inductive Is_present_in (
mems:
PS.t) (
me:
menv) (
ve:
venv):
clock ->
Prop :=
|
IsCbase:
Is_present_in mems me ve Cbase
|
IsCon:
forall ck x v b,
Is_present_in mems me ve ck ->
exp_eval me ve (
tovar mems (
x,
bool_type)) (
Some v) ->
val_to_bool v =
Some b ->
Is_present_in mems me ve (
Con ck x b).
Inductive Is_absent_in (
mems:
PS.t) (
me:
menv) (
ve:
venv):
clock ->
Prop :=
|
IsAbs1:
forall ck x v,
Is_absent_in mems me ve ck ->
Is_absent_in mems me ve (
Con ck x v)
|
IsAbs2:
forall ck x v b,
Is_present_in mems me ve ck ->
exp_eval me ve (
tovar mems (
x,
bool_type)) (
Some v) ->
val_to_bool v =
Some b ->
Is_absent_in mems me ve (
Con ck x (
negb b)).
Hint Constructors Is_present_in Is_absent_in.
Lemma stmt_eval_Control_fwd:
forall prog me ve mems ck s me'
ve',
stmt_eval prog me ve (
Control mems ck s) (
me',
ve') ->
(
Is_present_in mems me ve ck
/\
stmt_eval prog me ve s (
me',
ve'))
\/
(
Is_absent_in mems me ve ck
/\
me' =
me /\
ve' =
ve).
Proof.
intros *
StEval.
revert dependent s.
induction ck;
intuition.
simpl in *;
cases;
apply IHck in StEval as [[
Hp Hs]|[
Hp [
Hmenv Henv]]];
intuition;
inv Hs.
-
cases;
intuition;
eauto.
chase_skip.
assert (
true =
negb false)
as ->
by reflexivity;
eauto.
-
cases;
intuition;
eauto.
chase_skip.
assert (
false =
negb true)
as ->
by reflexivity;
eauto.
Qed.
Fact stmt_eval_Control:
forall prog mems me ve ck s,
(
Is_absent_in mems me ve ck ->
stmt_eval prog me ve (
Control mems ck s) (
me,
ve))
/\
(
forall me'
ve',
Is_present_in mems me ve ck ->
stmt_eval prog me ve s (
me',
ve') ->
stmt_eval prog me ve (
Control mems ck s) (
me',
ve')).
Proof.
Hint Constructors stmt_eval.
intros;
revert s;
induction ck;
split;
auto.
-
inversion 1.
-
inversion_clear 1
as [???
Hp|????
Hp];
simpl;
cases;
apply IHck with (1 :=
Hp);
eauto.
-
inversion_clear 1
as [|????
Hp];
simpl;
intros;
cases;
apply IHck with (1 :=
Hp);
eauto.
Qed.
If the clock is absent, then the controlled statement evaluates as
a Skip.
Lemma stmt_eval_Control_absent:
forall prog mems me ve ck s,
Is_absent_in mems me ve ck ->
stmt_eval prog me ve (
Control mems ck s) (
me,
ve).
Proof.
If the clock is present, then the controlled statement evaluates
as the underlying one.
Lemma stmt_eval_Control_present:
forall prog mems me ve ck s me'
ve',
Is_present_in mems me ve ck ->
stmt_eval prog me ve s (
me',
ve') ->
stmt_eval prog me ve (
Control mems ck s) (
me',
ve').
Proof.
Section ExprClock.
Variable mems:
PS.t.
Variable R:
env.
Variable (
me:
menv) (
ve:
venv).
Lemma exp_correct:
forall e c,
sem_exp_instant true R e (
present c) ->
equiv_env (
fun x =>
CE.IsF.Is_free_in_exp x e)
R mems me ve ->
exp_eval me ve (
translate_exp mems e) (
Some c).
Proof.
induction e;
inversion_clear 1;
simpl;
intros;
auto.
-
match goal with H:
_ =
_ |-
_ =>
inv H end.
econstructor;
congruence.
-
split_env_assumption;
cases;
try rewrite eq_if_present_present in *;
eauto using exp_eval.
take (
Env.find _ _ =
_)
and rewrite <-
it;
constructor.
-
econstructor;
eauto;
now rewrite typeof_correct.
-
econstructor;
eauto;
now rewrite 2
typeof_correct.
Qed.
Hint Resolve exp_correct.
Lemma arg_correct:
forall me ve mems cvars ck e c,
exp_eval me ve (
translate_exp mems e) (
Some c) ->
exp_eval me ve (
translate_arg mems cvars ck e) (
Some c).
Proof.
Hint Resolve arg_correct.
Lemma cexp_correct:
forall e c prog x,
sem_cexp_instant true R e (
present c) ->
equiv_env (
fun x =>
Is_free_in_cexp x e)
R mems me ve ->
stmt_eval prog me ve (
translate_cexp mems x e) (
me,
Env.add x c ve).
Proof.
Hint Resolve cexp_correct.
Lemma clock_correct_true:
forall base ck,
equiv_env (
fun x =>
Is_free_in_clock x ck)
R mems me ve ->
sem_clock_instant base R ck true ->
Is_present_in mems me ve ck.
Proof.
induction ck;
eauto.
inversion_clear 2;
subst.
econstructor;
eauto.
unfold tovar;
split_env_assumption.
cases;
try rewrite eq_if_present_present in *;
eauto using exp_eval.
take (
Env.find _ _ =
_)
and rewrite <-
it;
auto.
Qed.
Lemma clock_correct_false:
forall ck,
equiv_env (
fun x =>
Is_free_in_clock x ck)
R mems me ve ->
sem_clock_instant true R ck false ->
Is_absent_in mems me ve ck.
Proof.
induction ck as [|??
x]; [
now inversion 2|].
intro Henv.
inversion_clear 1;
auto.
econstructor 2;
eauto.
-
eapply clock_correct_true;
eauto.
-
unfold tovar;
split_env_assumption.
cases;
try rewrite eq_if_present_present in *;
eauto using exp_eval.
take (
Env.find _ _ =
_)
and rewrite <-
it;
auto.
Qed.
Variable ck:
clock.
Hypothesis Equiv:
equiv_env (
fun x =>
Is_free_in_clock x ck)
R mems me ve.
Corollary stmt_eval_Control_absent':
forall prog s,
sem_clock_instant true R ck false ->
stmt_eval prog me ve (
Control mems ck s) (
me,
ve).
Proof.
Corollary stmt_eval_Control_present':
forall base prog s me'
ve',
sem_clock_instant base R ck true ->
stmt_eval prog me ve s (
me',
ve') ->
stmt_eval prog me ve (
Control mems ck s) (
me',
ve').
Proof.
End ExprClock.
Reset correctness
Definition add_mems (
mems:
list (
ident * (
const *
clock))) (
me:
menv) :
menv :=
Mem (
fold_left (
fun vs xc =>
Env.add (
fst xc) (
sem_const (
fst (
snd xc)))
vs)
mems (
values me))
(
instances me).
Lemma find_inst_add_mems:
forall x me xs,
find_inst x (
add_mems xs me) =
find_inst x me.
Proof.
reflexivity. Qed.
Lemma add_mems_cons:
forall x c ck xs me,
add_mems ((
x, (
c,
ck)) ::
xs)
me =
add_mems xs (
add_val x (
sem_const c)
me).
Proof.
reflexivity. Qed.
Lemma add_mems_nil:
forall me,
add_mems []
me =
me.
Proof.
destruct me; reflexivity. Qed.
Lemma add_mems_gss:
forall x c ck xs me,
~
InMembers x xs ->
find_val x (
add_mems ((
x, (
c,
ck)) ::
xs)
me) =
Some (
sem_const c).
Proof.
Lemma find_val_add_mems_in:
forall x c ck xs me,
NoDupMembers xs ->
In (
x, (
c,
ck))
xs ->
find_val x (
add_mems xs me) =
Some (
sem_const c).
Proof.
intros *
Nodup Hin.
revert me;
induction xs as [|(?,(? & ?))];
intros.
-
inversion Hin.
-
inv Nodup.
destruct Hin as [
E|?].
+
inv E.
now apply add_mems_gss.
+
rewrite add_mems_cons;
auto.
Qed.
Lemma find_val_add_mems_inv:
forall x xs me v,
find_val x (
add_mems xs me) =
Some v ->
(
NoDupMembers xs ->
InMembers x xs ->
exists c ck,
v =
sem_const c /\
In (
x, (
c,
ck))
xs)
/\
(~
InMembers x xs ->
find_val x me =
Some v).
Proof.
intros *
Find;
split; [
intros *
Nodup Hin|
intros *
Hin].
-
revert dependent me;
induction xs as [|(
x', (
c,
ck))];
intros;
inv Hin;
inv Nodup.
+
rewrite add_mems_gss in Find;
auto;
inv Find.
exists c,
ck;
intuition.
+
rewrite add_mems_cons in Find.
edestruct IHxs as (?&?&?&?);
eauto.
do 2
eexists;
intuition;
eauto;
right;
eauto.
-
revert dependent me;
induction xs as [|(
x', (
c',
ck'))];
intros.
+
now rewrite add_mems_nil in Find.
+
rewrite add_mems_cons in Find.
apply NotInMembers_cons in Hin as (? & ?).
apply IHxs in Find;
auto.
rewrite find_val_gso in Find;
auto.
Qed.
Lemma reset_mems_spec:
forall mems prog me ve,
stmt_eval prog me ve (
reset_mems mems) (
add_mems mems me,
ve).
Proof.
Lemma translate_reset_comp:
forall prog me ve s me'
ve',
stmt_eval prog me ve (
translate_reset s) (
me',
ve')
<->
stmt_eval prog me ve (
reset_mems s.(
s_lasts)) (
add_mems s.(
s_lasts)
me,
ve)
/\
stmt_eval prog (
add_mems s.(
s_lasts)
me)
ve (
reset_insts s.(
s_subs)) (
me',
ve').
Proof.
Lemma add_mems_reset_lasts:
forall s me,
reset_lasts s (
add_mems s.(
s_lasts)
me).
Proof.
Lemma add_mems_state_closed_lasts:
forall lasts me,
state_closed_lasts (
map fst lasts)
me ->
state_closed_lasts (
map fst lasts) (
add_mems lasts me).
Proof.
Lemma reset_insts_reset_lasts:
forall subs prog me ve me'
ve'
s,
stmt_eval prog me ve (
reset_insts subs) (
me',
ve') ->
reset_lasts s me ->
reset_lasts s me'.
Proof.
Lemma reset_insts_state_closed_lasts:
forall subs lasts prog me ve me'
ve',
stmt_eval prog me ve (
reset_insts subs) (
me',
ve') ->
state_closed_lasts lasts me ->
state_closed_lasts lasts me'.
Proof.
Lemma reset_insts_same_venv:
forall subs prog me ve me'
ve',
stmt_eval prog me ve (
reset_insts subs) (
me',
ve') ->
ve' =
ve.
Proof.
Lemma call_reset_inv:
forall f P s P'
me me'
rvs,
find_system f P =
Some (
s,
P') ->
stmt_call_eval (
translate P)
me f reset []
me'
rvs ->
stmt_eval (
translate P')
me vempty (
translate_reset s) (
me',
vempty)
/\
rvs = [].
Proof.
Lemma call_reset_reset_lasts:
forall me'
P me f s P',
find_system f P =
Some (
s,
P') ->
stmt_call_eval (
translate P)
me f reset []
me' [] ->
reset_lasts s me'.
Proof.
Lemma call_reset_state_closed_lasts:
forall me'
P me f s P',
find_system f P =
Some (
s,
P') ->
stmt_call_eval (
translate P)
me f reset []
me' [] ->
state_closed_lasts (
map fst s.(
s_lasts))
me ->
state_closed_lasts (
map fst s.(
s_lasts))
me'.
Proof.
Lemma reset_insts_not_InMembers:
forall subs prog me ve me'
ve'
x,
stmt_eval prog me ve (
reset_insts subs) (
me',
ve') ->
~
InMembers x subs ->
find_inst x me' =
find_inst x me.
Proof.
Lemma reset_insts_in:
forall s P P'
me ve me'
ve'
i f g,
find_system f P =
Some (
s,
P') ->
stmt_eval (
translate P')
me ve (
reset_insts s.(
s_subs)) (
me',
ve') ->
In (
i,
g)
s.(
s_subs) ->
find_system g P' <>
None ->
exists me_i,
stmt_call_eval (
translate P') (
match find_inst i me with
|
Some om =>
om
|
None =>
mempty
end)
g reset []
me_i []
/\
find_inst i me' =
Some me_i.
Proof.
Lemma find_inst_reset_insts_inv:
forall subs prog me ve me'
ve'
x me_x,
stmt_eval prog me ve (
reset_insts subs) (
me',
ve') ->
find_inst x me' =
Some me_x ->
InMembers x subs
\/
find_inst x me =
Some me_x.
Proof.
Lemma call_reset_initial_state:
forall me'
P me f s P',
Ordered_systems P ->
find_system f P =
Some (
s,
P') ->
stmt_call_eval (
translate P)
me f reset []
me' [] ->
initial_state P f me' /\ (
state_closed P f me ->
state_closed P f me').
Proof.
Lemma reset_insts_exists:
forall s P me ve,
(
forall me'
f s'
P',
find_system f P =
Some (
s',
P') ->
exists me'',
stmt_call_eval (
translate P)
me'
f reset []
me'' []) ->
(
forall i g,
In (
i,
g)
s.(
s_subs) ->
exists s P',
find_system g P =
Some (
s,
P')) ->
exists me',
stmt_eval (
translate (
P))
me ve (
reset_insts s.(
s_subs)) (
me',
ve).
Proof.
unfold reset_insts.
intro;
induction s.(
s_subs)
as [|(
x,
b')];
simpl in *;
intros *
IH Spec;
eauto using stmt_eval.
setoid_rewrite stmt_eval_fold_left_lift.
edestruct Spec as (?&?&
Find);
eauto.
eapply IH in Find as (?&?).
edestruct IHl;
eauto 7.
do 3
eexists;
split;
eauto.
econstructor;
eauto.
change ve with (
Env.adds_opt [] []
ve).
econstructor;
eauto.
Qed.
Lemma reset_exists:
forall P f s P'
me,
Ordered_systems P ->
find_system f P =
Some (
s,
P') ->
exists me',
stmt_call_eval (
translate P)
me f reset []
me' [].
Proof.
Theorem reset_spec:
forall P me f s P',
Ordered_systems P ->
find_system f P =
Some (
s,
P') ->
exists me',
stmt_call_eval (
translate P)
me f reset []
me' []
/\
initial_state P f me'
/\ (
state_closed P f me ->
state_closed P f me').
Proof.
Step correctness
Lemma value_to_option_adds_opt:
forall R ve x xs v vs,
In x xs ->
NoDup xs ->
Forall (
fun x =>
Env.find x ve =
None)
xs ->
Forall2 (
sem_var_instant R)
xs vs ->
sem_var_instant R x v ->
Env.find x (
Env.adds_opt xs (
map value_to_option vs)
ve) =
value_to_option v.
Proof.
Lemma eq_if_present_adds_opt:
forall R ve x xs c vs ovs,
In x xs ->
Forall2 (
sem_var_instant R)
xs vs ->
Forall2 eq_if_present vs ovs ->
sem_var_instant R x (
present c) ->
Env.find x (
Env.adds_opt xs ovs ve) =
Some c.
Proof.
induction xs as [|
x'].
now inversion 1.
destruct (
ident_eq_dec x x')
as [
Heq|
Hneq];
intros *
Hin Hvar Hovals Hxsem.
+
subst.
apply Forall2_left_cons in Hvar as (
v &
vs' &
Hyss &
Hvs & ?).
rewrite Hyss in Hovals.
apply Forall2_left_cons in Hovals
as (
ov &
ovals' &
Hovals &
Heqp & ?).
pose proof (
sem_var_instant_det _ _ _ _ Hvs Hxsem)
as Hpvc.
subst;
inv Heqp.
now rewrite Env.find_gsss_opt.
+
pose proof (
Forall2_length _ _ _ Hvar)
as Hlenyss.
pose proof (
Forall2_length _ _ _ Hovals)
as Hlenovals.
destruct vs;
try discriminate.
destruct ovs;
try discriminate.
rewrite Env.find_gsso_opt;
auto.
inv Hin.
now contradiction Hneq.
inv Hvar;
inv Hovals;
eauto.
Qed.
Definition correct_system (
P:
Stc.Syn.program) (
f:
ident) :
Prop :=
forall S xs ys S'
me ins,
sem_system P f S xs ys S' ->
Forall2 eq_if_present xs ins ->
Exists (
fun v =>
v <>
absent)
xs ->
me ≋
S ->
exists me',
stmt_call_eval (
translate P)
me f step ins me' (
map value_to_option ys)
/\
me' ≋
S'.
Definition correct_program (
P:
Stc.Syn.program) :
Prop :=
forall f,
correct_system P f.
Lemma noops_exp_exp_eval:
forall isub R mems me ve vars e v xck bck lck,
sem_clocked_vars_instant true R vars ->
equiv_env (
fun x =>
CE.IsF.Is_free_in_exp x e)
R mems me ve ->
noops_exp xck e ->
wc_exp vars e lck ->
instck bck isub xck =
Some lck ->
sem_clock_instant true R bck true ->
sem_exp_instant true R e v ->
sem_clock_instant true R lck false ->
(
forall x,
PS.In x mems ->
find_val x me <>
None) ->
exists v,
exp_eval me ve (
translate_exp mems e)
v.
Proof.
Lemma TcCall_check_args_translate_arg:
forall P R mems clkvars me ve icks i ys ck rst f es ess,
(
forall x ck,
In (
x,
ck)
icks -> ~
PS.In x mems ->
Env.find x clkvars =
Some ck) ->
sem_clocked_vars_instant true R icks ->
equiv_env (
fun x =>
CE.IsF.Is_free_in_aexps x ck es)
R mems me ve ->
(
forall x,
PS.In x mems ->
find_val x me <>
None) ->
wc_trconstr P icks (
TcCall i ys ck rst f es) ->
normal_args_tc P (
TcCall i ys ck rst f es) ->
sem_exps_instant true R es ess ->
sem_clock_instant true R ck true ->
exists vos,
Forall2 eq_if_present ess vos
/\
Forall2 (
exp_eval me ve) (
map (
translate_arg mems clkvars ck)
es)
vos.
Proof.
intros *
Hcvars Hcm EqEnv Himems Hwc Hnorm Hles Hcksem.
apply Forall2_Forall2_exists,
Forall2_map_2,
Forall2_swap_args.
inversion_clear Hwc as [| | |????????
sub Hfind Hwci Hwco].
inversion_clear Hnorm as [| | |????????
Hfind'
Hnorm'].
rewrite Hfind in Hfind';
inv Hfind'.
rewrite Forall2_map_1,
Forall2_swap_args in Hnorm'.
apply Forall2_trans_ex with (1:=
Hnorm'),
Forall2_same in Hwci.
clear Hwco Hfind Hnorm'.
apply Forall2_impl_In with (2:=
Hles).
intros le v Hlein Hvin Hsem.
apply Forall_forall with (2:=
Hlein)
in Hwci
as ((
x, (
xty,
xck)) &
Hin &
Hnorm &
Hsubv & (
lck &
WClck &
Hinst)).
simpl in *.
assert (
WClck':=
WClck).
assert (
equiv_env (
fun x =>
CE.IsF.Is_free_in_exp x le)
R mems me ve)
by (
weaken_equiv_env with constructor;
apply Exists_exists;
eauto).
eapply clock_match_instant_exp in WClck'
as [(
Hsem' &
Hcksem')|((
c &
Hsem') &
Hcksem')];
eauto;
apply sem_exp_instant_det with (1:=
Hsem)
in Hsem';
subst v.
-
eapply noops_exp_exp_eval in Hnorm as (
v' &
Hv');
eauto.
simpl;
exists v';
eauto.
split;
destruct le;
eauto using exp_eval.
destruct xck.
+
inv Hinst.
now apply sem_clock_instant_det with (1:=
Hcksem)
in Hcksem'.
+
simpl in Hinst.
destruct (
instck ck sub xck)
eqn:
Hck;
try discriminate.
match goal with H:
context [
sub ?
i] |-
_ =>
destruct (
sub i)
eqn:
Hisub;
try discriminate end.
injection Hinst;
intro;
subst lck.
inversion_clear WClck as [|? ? ?
Hicks| | |].
simpl in Hv';
destruct (
PS.mem i0 mems)
eqn:
E.
*
unfold translate_arg,
var_on_base_clock;
simpl;
rewrite E;
simpl;
auto.
*{
apply Hcvars in Hicks.
-
unfold translate_arg,
var_on_base_clock;
simpl;
rewrite Hicks,
E;
simpl.
now rewrite instck_subclock_not_clock_eq with (1:=
Hck).
-
apply PSE.MP.Dec.F.not_mem_iff;
auto.
}
-
exists (
Some c);
simpl;
split;
eauto using arg_correct,
exp_correct.
Qed.
Lemma trconstr_cons_correct:
forall tc tcs P R S I S'
me ve inputs mems icks clkvars,
correct_program P ->
sem_trconstr P true R S I S'
tc ->
wc_trconstr P icks tc ->
normal_args_tc P tc ->
Ordered_systems P ->
Is_well_sch inputs mems (
tc ::
tcs) ->
NoDup (
inputs ++
variables (
tc ::
tcs)) ->
NoDup (
defined (
tc ::
tcs)) ->
reset_consistency (
tc ::
tcs) ->
(
forall i f Si,
In (
i,
f) (
resets_of (
tc ::
tcs)) ->
find_inst i S =
Some Si ->
state_closed P f Si) ->
(
forall i f Ii,
In (
i,
f) (
resets_of (
tc ::
tcs)) ->
find_inst i I =
Some Ii ->
state_closed P f Ii) ->
Memory_Corres tcs S I S'
me ->
equiv_env (
fun x =>
Is_free_in_tc x tc)
R mems me ve ->
sem_clocked_vars_instant true R icks ->
(
forall x ck,
In (
x,
ck)
icks -> ~
PS.In x mems ->
Env.find x clkvars =
Some ck) ->
(
forall x,
PS.In x mems ->
find_val x me <>
None) ->
(
forall x, ~
In x inputs -> ~
Is_defined_in x tcs ->
Env.find x ve =
None) ->
exists me'
ve',
stmt_eval (
translate P)
me ve (
translate_tc mems clkvars tc) (
me',
ve')
/\
Memory_Corres (
tc ::
tcs)
S I S'
me'
/\
forall x v,
Is_variable_in_tc x tc ->
sem_var_instant R x v ->
Env.find x ve' =
value_to_option v.
Proof.
intros *
IH Sem Hwc Hnormal Ord Wsch Vars Defs StepReset
Closed TransClosed Corres Equiv Hcm Hcvars Hmems Hve.
assert (
forall x,
Is_defined_in_tc x tc -> ~
Is_defined_in x tcs)
as Defs'
by (
intro;
rewrite Is_defined_in_defined,
Is_defined_in_defined_tc;
simpl in Defs;
intros;
eapply NoDup_app_In in Defs;
eauto).
clear Defs.
inversion Sem as [?????????
Hexp Hvar|
???????????
Hvar Hexp|
???????????
FindI Init|
???????????????
Hexps Hck Find_S Find_I Hsystem Hvars];
subst;
simpl.
-
inv Hexp;
exists me;
eexists;
split;
try solve [
eapply stmt_eval_Control_absent';
eauto;
auto].
+
eapply stmt_eval_Control_present';
eauto;
auto.
eapply cexp_correct;
eauto.
+
split.
*
apply Memory_Corres_Def;
auto.
*
inversion_clear 1;
intros Hvar'.
eapply sem_var_instant_det in Hvar;
eauto.
inv Hvar;
rewrite Env.gss;
auto.
+
split.
*
apply Memory_Corres_Def;
auto.
*
inversion_clear 1;
intros Hvar'.
eapply sem_var_instant_det in Hvar;
eauto.
unfold variables in Vars.
subst;
simpl in *;
apply NoDup_app_cons in Vars as (
Hnin & ?).
apply Hve;
auto using Is_defined_in_tc.
intro;
apply Hnin,
in_app;
auto.
-
inv Hexp;
eexists;
exists ve;
split;
try solve [
eapply stmt_eval_Control_absent';
eauto;
auto].
+
eapply stmt_eval_Control_present';
eauto using stmt_eval,
exp_correct;
auto.
+
split;
try inversion 1.
apply Memory_Corres_Next_present;
auto.
+
split;
try inversion 1.
apply Memory_Corres_Next_absent;
auto;
congruence.
-
destruct r.
+
pose proof Init.
inversion_clear Init as [?????
Find Rst].
edestruct reset_spec as (
me' &?&?&
SpecInit);
eauto.
do 2
eexists;
split.
*
eapply stmt_eval_Control_present';
eauto;
auto.
econstructor;
eauto.
*{
split;
try inversion 1.
eapply Memory_Corres_Reset_present;
eauto.
-
eapply initial_state_det;
eauto.
+
apply SpecInit.
unfold instance_match in *.
destruct (
find_inst i me)
eqn:
E.
*
assert (
state_corres i S me)
as Scorres.
{
apply Corres;
split.
-
eapply Reset_not_Step_in;
eauto.
-
eapply Reset_not_Reset_in;
eauto.
}
unfold state_corres in Scorres.
rewrite E in Scorres.
apply orel_find_inst_Some in Scorres as (?&<-&?).
eapply Closed;
simpl;
eauto.
*
eapply state_closed_empty;
eauto.
+
eapply TransClosed;
eauto;
simpl;
auto.
-
eapply Reset_not_Step_in;
eauto.
}
+
exists me,
ve;
split;
try eapply stmt_eval_Control_absent';
eauto;
auto.
split;
try inversion 1.
apply orel_find_inst_Some in Init as (?&?&?).
eapply Memory_Corres_Reset_absent;
try symmetry;
eauto.
eapply Reset_not_Reset_in;
eauto.
-
apply Step_not_Step_Reset_in in Wsch;
auto.
destruct (
clock_of_instant xs)
eqn:
E.
+
assert (
Exists (
fun v =>
v <>
absent)
xs)
by (
apply clock_of_instant_true;
auto).
assert (
exists vos,
Forall2 eq_if_present xs vos
/\
Forall2 (
exp_eval me ve)
(
map (
translate_arg mems clkvars ck)
es)
vos)
as (
ivals &
Hivals &
Hievals)
by (
eapply TcCall_check_args_translate_arg;
eauto).
unfold correct_program,
correct_system in IH.
eapply IH in Hsystem as (
me' &?&?);
eauto.
*{
do 2
eexists;
split.
-
eapply stmt_eval_Control_present';
eauto;
auto.
econstructor;
eauto.
-
split.
+
eapply Memory_Corres_Call_present;
eauto.
+
inversion_clear 1;
intros Hvar.
simpl in Vars;
apply NoDup_swap in Vars.
eapply value_to_option_adds_opt;
eauto.
*
apply NoDup_app_weaken in Vars;
auto.
*
apply Forall_forall;
intros y Hin.
assert (~
In y inputs)
by
(
rewrite app_assoc in Vars;
apply NoDup_app_weaken in Vars;
eapply NoDup_app_In;
eauto).
apply Hve;
auto using Is_defined_in_tc.
}
*{
destruct rst;
apply Corres in Wsch;
unfold instance_match.
-
unfold state_corres in Wsch;
rewrite Find_I in Wsch.
symmetry in Wsch;
apply orel_find_inst_Some in Wsch as (?&?& ->);
auto.
-
unfold state_corres in Wsch;
rewrite Find_S in Wsch;
auto.
symmetry in Wsch;
apply orel_find_inst_Some in Wsch as (?&?& ->);
auto.
}
+
assert (
absent_list xs)
by (
apply clock_of_instant_false;
auto).
apply sem_system_absent in Hsystem as (? & ?);
auto.
exists me,
ve;
split;
try eapply stmt_eval_Control_absent';
eauto;
auto.
split;
eauto using Memory_Corres_Call_absent.
inversion_clear 1;
intros Hvar.
eapply Forall2_in_left in Hvars as (
v' &
Hin &?);
eauto.
eapply sem_var_instant_det in Hvar;
eauto;
subst v'.
eapply Forall_forall in Hin;
eauto.
simpl in Hin;
subst;
simpl.
unfold variables in Vars.
simpl in *.
apply Hve;
auto using Is_defined_in_tc.
eapply NoDup_swap,
NoDup_app_In in Vars;
eauto.
intro;
apply Vars,
in_app;
auto.
Qed.
Lemma stmt_eval_translate_cexp_menv_inv:
forall prog me ve mems x me'
ve'
e,
stmt_eval prog me ve (
translate_cexp mems x e) (
me',
ve') ->
me' =
me.
Proof.
induction e; simpl; inversion_clear 1; auto; cases.
Qed.
Lemma stmt_eval_translate_cexp_venv_inv:
forall prog me ve mems x me'
ve'
e,
stmt_eval prog me ve (
translate_cexp mems x e) (
me',
ve') ->
exists c,
ve' =
Env.add x c ve.
Proof.
induction e; inversion_clear 1; cases; eauto.
Qed.
Lemma not_Is_defined_in_tc_stmt_eval_menv_inv:
forall tc x P me ve mems clkvars me'
ve',
~
Is_defined_in_tc x tc ->
stmt_eval (
translate P)
me ve (
translate_tc mems clkvars tc) (
me',
ve') ->
find_val x me' =
find_val x me.
Proof.
Corollary not_Is_defined_in_stmt_eval_menv_inv:
forall tcs x P me ve mems clkvars me'
ve',
~
Is_defined_in x tcs ->
stmt_eval (
translate P)
me ve (
translate_tcs mems clkvars tcs) (
me',
ve') ->
find_val x me' =
find_val x me.
Proof.
Lemma not_Is_defined_in_tc_stmt_eval_venv_inv:
forall tc x P me ve mems clkvars me'
ve',
~
Is_defined_in_tc x tc ->
stmt_eval (
translate P)
me ve (
translate_tc mems clkvars tc) (
me',
ve') ->
Env.find x ve' =
Env.find x ve.
Proof.
Corollary not_Is_defined_in_stmt_eval_venv_inv:
forall tcs x P me ve mems clkvars me'
ve',
~
Is_defined_in x tcs ->
stmt_eval (
translate P)
me ve (
translate_tcs mems clkvars tcs) (
me',
ve') ->
Env.find x ve' =
Env.find x ve.
Proof.
Lemma value_corres_equal_memory:
forall x S me,
S ≋
me ->
value_corres x S me.
Proof.
Lemma state_corres_equal_memory:
forall s S me,
S ≋
me ->
state_corres s S me.
Proof.
Lemma Memory_Corres_empty_equal_memory:
forall S I S'
me,
S ≋
me ->
Memory_Corres []
S I S'
me.
Proof.
Lemma sem_trconstrs_is_last_in:
forall tcs P base R S I S'
x v,
Forall (
sem_trconstr P base R S I S')
tcs ->
Is_last_in x tcs ->
sem_var_instant R x (
present v) ->
find_val x S =
Some v.
Proof.
induction tcs; inversion_clear 1 as [|?? Sem];
inversion_clear 1 as [?? Last|]; eauto; intros.
inv Last; inv Sem.
cases; congruence.
Qed.
Lemma not_Is_variable_in_tc_stmt_eval_env_inv:
forall prog x tc me ve mems clkvars me'
ve',
~
Is_variable_in_tc x tc ->
stmt_eval prog me ve (
translate_tc mems clkvars tc) (
me',
ve') ->
Env.find x ve' =
Env.find x ve.
Proof.
Lemma trconstrs_app_correct:
forall tcs'
tcs P R S I S'
me ve inputs mems clkvars icks,
let alltcs :=
tcs ++
tcs'
in
correct_program P ->
Forall (
sem_trconstr P true R S I S')
alltcs ->
Forall (
wc_trconstr P icks)
alltcs ->
Forall (
normal_args_tc P)
alltcs ->
sem_clocked_vars_instant true R icks ->
(
forall x ck,
In (
x,
ck)
icks -> ~
PS.In x mems ->
Env.find x clkvars =
Some ck) ->
(
forall x,
PS.In x mems ->
find_val x me <>
None) ->
Ordered_systems P ->
Is_well_sch inputs mems alltcs ->
NoDup (
inputs ++
variables alltcs) ->
NoDup (
defined alltcs) ->
reset_consistency alltcs ->
(
forall i f Si,
In (
i,
f) (
resets_of alltcs) ->
find_inst i S =
Some Si ->
state_closed P f Si) ->
(
forall i f Ii,
In (
i,
f) (
resets_of alltcs) ->
find_inst i I =
Some Ii ->
state_closed P f Ii) ->
(
forall x,
PS.In x mems ->
Is_last_in x alltcs) ->
(
forall x,
In x inputs -> ~
Is_defined_in x alltcs) ->
(
forall x c,
In x inputs ->
sem_var_instant R x (
present c) ->
Env.find x ve =
Some c) ->
(
forall x,
Env.find x ve <>
None ->
In x inputs) ->
me ≋
S ->
exists me'
ve',
stmt_eval (
translate P)
me ve (
translate_tcs mems clkvars tcs') (
me',
ve')
/\
Memory_Corres tcs'
S I S'
me'
/\
forall x v,
Is_variable_in x tcs' ->
sem_var_instant R x v ->
Env.find x ve' =
value_to_option v.
Proof.
induction tcs'
as [|
tc];
simpl;
intros ? ? ? ? ? ? ? ? ? ? ? ? ?
Htcs Hwc Hnormal Hcm Hcvars Hmems Ord Wsch Vars Defs StepReset
Closed TransClosed SpecLast SpecInput EquivInput EquivInput'
Corres.
-
exists me,
ve.
split;
eauto using stmt_eval;
split;
auto.
+
now apply Memory_Corres_empty_equal_memory.
+
inversion 1.
-
pose proof Wsch as Wsch';
apply Is_well_sch_app in Wsch'.
pose proof Vars as Vars';
rewrite variables_app in Vars'.
pose proof Defs as Defs';
rewrite defined_app in Defs'.
rewrite NoDup_swap,
Permutation.Permutation_app_comm in Vars';
apply NoDup_app_weaken in Vars'.
rewrite Permutation.Permutation_app_comm in Defs';
apply NoDup_app_weaken in Defs'.
pose proof StepReset as StepReset';
eapply reset_consistency_app in StepReset';
eauto.
pose proof Htcs as Htcs';
apply Forall_app_weaken in Htcs';
inv Htcs'.
pose proof Hwc as Hwc';
apply Forall_app_weaken in Hwc';
inv Hwc'.
pose proof Hnormal as Hnormal';
apply Forall_app_weaken in Hnormal';
inv Hnormal'.
rewrite List_shift_first in Wsch,
Vars,
Defs,
StepReset,
Htcs,
SpecLast,
SpecInput,
Closed,
TransClosed,
Hwc,
Hnormal.
edestruct IHtcs'
with (
ve :=
ve) (
me :=
me)
as (
me' &
ve' &?&?&
Env);
eauto.
edestruct trconstr_cons_correct with (
ve :=
ve') (
me :=
me')
as (
me'' &
ve'' &?&?&?);
eauto using Is_well_sch.
+
intros;
eapply Closed;
eauto.
rewrite <-
List_shift_first,
resets_of_app,
in_app;
auto.
+
intros;
eapply TransClosed;
eauto.
rewrite <-
List_shift_first,
resets_of_app,
in_app;
auto.
+
intros x v Free Hvar.
inversion_clear Wsch'
as [|???
FreeSpec].
apply FreeSpec in Free.
cases_eqn E.
*
erewrite not_Is_defined_in_stmt_eval_menv_inv;
eauto.
rewrite Corres.
destruct v;
simpl;
auto.
eapply sem_trconstrs_is_last_in in Htcs;
eauto;
rewrite Htcs;
auto.
*
destruct Free as [
IsVar|].
--
eapply Env in IsVar;
eauto.
destruct v;
simpl;
auto.
rewrite IsVar;
simpl;
auto.
--
assert (~
Is_defined_in x tcs')
by (
intro;
eapply SpecInput,
Exists_app;
eauto).
erewrite not_Is_defined_in_stmt_eval_venv_inv;
eauto.
destruct v;
simpl;
auto.
assert (
Env.find x ve =
Some v)
as ->;
auto.
+
intros;
eapply stmt_eval_find_val_mono;
eauto.
+
intros *
Hnin ?;
erewrite not_Is_defined_in_stmt_eval_venv_inv;
eauto.
apply not_Some_is_None;
intros *
E.
apply Hnin,
EquivInput',
not_None_is_Some;
eauto.
+
exists me'',
ve'';
split; [|
split];
auto.
*
unfold translate_tcs;
simpl.
rewrite stmt_eval_fold_left_shift;
setoid_rewrite stmt_eval_eq_Comp_Skip2;
eauto.
*
intros x v IsVar Hvar.
destruct (
Is_variable_in_tc_dec x tc)
as [|
Nvar];
auto.
erewrite not_Is_variable_in_tc_stmt_eval_env_inv;
eauto.
inv IsVar;
auto.
contradiction.
Qed.
Corollary trconstrs_correct:
forall tcs P R S I S'
me ve inputs mems clkvars icks,
correct_program P ->
Forall (
sem_trconstr P true R S I S')
tcs ->
Forall (
wc_trconstr P icks)
tcs ->
Forall (
normal_args_tc P)
tcs ->
sem_clocked_vars_instant true R icks ->
(
forall x ck,
In (
x,
ck)
icks -> ~
PS.In x mems ->
Env.find x clkvars =
Some ck) ->
(
forall x,
PS.In x mems ->
find_val x me <>
None) ->
Ordered_systems P ->
(
forall i f Si,
In (
i,
f) (
resets_of tcs) ->
find_inst i S =
Some Si ->
state_closed P f Si) ->
(
forall i f Ii,
In (
i,
f) (
resets_of tcs) ->
find_inst i I =
Some Ii ->
state_closed P f Ii) ->
Is_well_sch inputs mems tcs ->
NoDup (
inputs ++
variables tcs) ->
NoDup (
defined tcs) ->
reset_consistency tcs ->
(
forall x,
PS.In x mems ->
Is_last_in x tcs) ->
(
forall x,
In x inputs -> ~
Is_defined_in x tcs) ->
(
forall x c,
In x inputs ->
sem_var_instant R x (
present c) ->
Env.find x ve =
Some c) ->
(
forall x,
Env.find x ve <>
None ->
In x inputs) ->
me ≋
S ->
exists me'
ve',
stmt_eval (
translate P)
me ve (
translate_tcs mems clkvars tcs) (
me',
ve')
/\
Memory_Corres tcs S I S'
me'
/\
forall x v,
Is_variable_in x tcs ->
sem_var_instant R x v ->
Env.find x ve' =
value_to_option v.
Proof.
Lemma state_closed_insts_InMembers:
forall P subs S s Ss,
state_closed_insts P subs S ->
find_inst s S =
Some Ss ->
InMembers s subs.
Proof.
intros *
Closed Sub;
apply Closed in Sub as (?&?&?).
eapply In_InMembers;
eauto.
Qed.
Lemma Memory_Corres_equal_memory:
forall P tcs S I S'
me lasts subs,
Memory_Corres tcs S I S'
me ->
state_closed_lasts lasts S ->
state_closed_insts P subs S ->
state_closed_lasts lasts S' ->
state_closed_insts P subs S' ->
(
forall x,
In x lasts <->
Is_last_in x tcs) ->
(
forall i,
InMembers i subs ->
exists k,
Is_sub_in i k tcs) ->
(
forall i,
Reset_in i tcs ->
Step_in i tcs) ->
me ≋
S'.
Proof.
intros * (
Lasts &
Insts)
LastClosed InstsClosed LastClosed'
InstsClosed'
SpecLast SpecInst WSCH.
split.
-
intro x;
destruct (
Is_last_in_dec x tcs)
as [
Last|
Nlast].
+
apply Lasts in Last;
auto.
+
assert (
find_val x S =
None).
{
apply not_Some_is_None;
intros *
Find;
apply Nlast,
SpecLast,
LastClosed.
apply not_None_is_Some;
eauto.
}
assert (
find_val x S' =
None)
as E'.
{
apply not_Some_is_None;
intros *
Find;
apply Nlast,
SpecLast,
LastClosed'.
apply not_None_is_Some;
eauto.
}
unfold value_corres,
find_val in *.
apply Lasts in Nlast.
rewrite E';
rewrite <-
Nlast;
auto.
-
split.
+
setoid_rewrite Env.In_find;
intro i.
destruct (
Step_in_dec i tcs)
as [
Step|
Nstep].
*
apply Insts in Step.
unfold state_corres,
find_inst in Step.
split;
intros (?&
Find);
rewrite Find in Step.
--
apply orel_find_inst_Some in Step as (?&?&?);
eauto.
--
symmetry in Step;
apply orel_find_inst_Some in Step as (?&?&?);
eauto.
*
destruct (
Reset_in_dec i tcs)
as [
Rst|
Nrst].
--
apply WSCH in Rst;
contradiction.
--
assert (~
exists k,
Is_sub_in i k tcs)
as Nsub.
{
intros (?&
Sub).
apply Exists_exists in Sub as (?&?&
Sub).
inv Sub.
-
apply Nrst,
Exists_exists;
eauto using Is_sub_in_tc.
-
apply Nstep,
Exists_exists;
eauto using Is_sub_in_tc.
}
assert (
state_corres i S me)
as Corres by (
apply Insts;
auto).
assert (
find_inst i S =
None).
{
apply not_Some_is_None;
intros *
Find;
apply Nsub,
SpecInst.
eapply state_closed_insts_InMembers in InstsClosed;
eauto.
}
assert (
find_inst i S' =
None)
as E'.
{
apply not_Some_is_None;
intros *
Find;
apply Nsub,
SpecInst.
eapply state_closed_insts_InMembers in InstsClosed';
eauto.
}
assert (
find_inst i me =
None)
as E.
{
apply not_Some_is_None;
intros *
Find.
unfold state_corres in Corres;
rewrite Find in Corres.
apply orel_find_inst_Some in Corres as (?&?&?).
congruence.
}
setoid_rewrite E';
setoid_rewrite E;
reflexivity.
+
setoid_rewrite Env.Props.P.F.find_mapsto_iff.
intros i me_i Si'
Find Find'.
destruct (
Step_in_dec i tcs)
as [
Step|
Nstep].
*
apply Insts in Step.
unfold state_corres,
find_inst in Step.
rewrite Find,
Find'
in Step.
inv Step;
symmetry;
auto.
*
destruct (
Reset_in_dec i tcs)
as [
Rst|
Nrst].
--
apply WSCH in Rst;
contradiction.
--
assert (~ (
Step_in i tcs \/
Reset_in i tcs))
as NstpRst by tauto.
assert (~
exists k,
Is_sub_in i k tcs)
as Nsub.
{
intros (?&
Sub).
apply Exists_exists in Sub as (?&?&
Sub).
inv Sub.
-
apply Nrst,
Exists_exists;
eauto using Is_sub_in_tc.
-
apply Nstep,
Exists_exists;
eauto using Is_sub_in_tc.
}
exfalso.
apply Nsub,
SpecInst.
eapply state_closed_insts_InMembers in InstsClosed';
eauto.
Qed.
Theorem correctness:
forall P f,
Well_defined P ->
wc_program P ->
correct_system P f.
Proof.
induction P as [|
system];
unfold correct_system;
intros b (
Ord &
WSCH &
NormalArgs)
WC ??????
Sem Tcs Spec E;
pose proof Sem;
inversion_clear Sem as [?????????
Find ?
Outs Hscv Htcs Closed TransClosed Closed'];
try now inv Find.
pose proof Find as Find'.
simpl in Find.
pose proof Ord.
inv Ord;
inv WSCH;
destruct NormalArgs as (
Hnormal&?);
inversion_clear WC as [|???
WCb].
assert (
Well_defined P)
by (
split;
auto).
assert (
correct_program P)
by (
unfold correct_program;
intros;
auto).
destruct WCb as (?&?&?&
WCtcs);
rewrite 2
idck_app, <-2
app_assoc in WCtcs.
destruct (
ident_eqb (
s_name system)
b)
eqn:
Eq.
-
inv Find.
assert (
clock_of_instant xs =
true)
as Clock by now apply clock_of_instant_true.
rewrite Clock in Htcs.
assert (~
Is_system_in (
s_name s) (
s_tcs s))
by (
eapply find_system_not_Is_system_in;
eauto).
apply normal_args_system_cons in Hnormal;
auto.
apply sem_trconstrs_cons in Htcs;
auto.
edestruct trconstrs_correct
with (
ve :=
Env.adds_opt (
map fst (
m_in (
step_method s)))
ins vempty)
(
clkvars :=
Env.adds_with snd s.(
s_out)
(
Env.adds_with snd s.(
s_vars)
(
Env.from_list_with snd s.(
s_in))))
as (
me' &
ve' &?&?&
Equiv);
eauto.
+
apply Forall_forall.
intros (
x,
ck)
Hxin.
apply in_app in Hxin as [
Hxin|
Hxin].
*
rewrite <-
Clock;
eapply Forall_forall in Hscv;
eauto.
*{
eapply sem_clocked_var_instant_tcs with (
P :=
P') (
tcs :=
s_tcs s);
eauto.
-
apply fst_NoDupMembers;
rewrite 3
map_app, 4
map_fst_idck.
apply s_nodup.
-
rewrite s_defined, <-
s_vars_out_in_tcs, <-
s_lasts_in_tcs,
<-
app_assoc, 2
map_app, 3
map_fst_idck;
auto.
}
+
intros *
Hin Hnin.
rewrite ps_from_list_In in Hnin.
pose proof (
s_nodup s)
as Nodup.
rewrite 3
in_app in Hin;
destruct Hin as [
Hin|[
Hin|[
Hin|
Hin]]];
apply In_idck_exists in Hin as (?&?).
*{
apply (
NoDup_app_In x)
in Nodup.
-
unfold Env.from_list_with.
rewrite 2
Env.gsso_with.
+
erewrite Env.In_find_adds_with;
eauto;
simpl;
auto.
do 2
eapply NoDupMembers_app_l;
rewrite <-
app_assoc;
apply s_nodup_vars.
+
intros Hin;
apply Nodup,
in_app;
left;
apply fst_InMembers;
auto.
+
intros Hin;
apply Nodup;
rewrite 2
in_app;
right;
left;
apply fst_InMembers;
auto.
-
apply in_map_iff;
eexists; (
intuition eauto);
auto.
}
*{
rewrite Permutation.Permutation_app_comm in Nodup.
apply NoDup_app_weaken, (
NoDup_app_In x)
in Nodup.
-
rewrite Env.gsso_with.
+
erewrite Env.In_find_adds_with;
eauto;
simpl;
auto.
eapply NoDupMembers_app_l;
eapply NoDupMembers_app_r;
apply s_nodup_vars.
+
intros Hin;
apply Nodup,
in_app;
left;
apply fst_InMembers;
auto.
-
apply in_map_iff;
eexists; (
intuition eauto);
auto.
}
*
erewrite Env.In_find_adds_with;
eauto;
simpl;
auto.
do 2
eapply NoDupMembers_app_r;
apply s_nodup_vars.
*
exfalso;
apply Hnin,
in_map_iff;
eexists; (
intuition eauto);
auto.
+
setoid_rewrite ps_from_list_In;
intros.
rewrite E;
eapply sem_system_find_val;
eauto.
+
inversion_clear Closed as [?????
Find ?
Insts];
rewrite Find in Find';
inv Find'.
intros ?
b' ?
Hin Sub.
apply Insts in Sub as (
b'' &?&?).
apply s_reset_incl in Hin.
rewrite <-
s_subs_calls_of in Hin.
assert (
b' =
b'')
as ->;
auto.
eapply NoDupMembers_det in Hin;
eauto.
apply s_nodup_subs.
+
inversion_clear TransClosed as [?????
Find ?
Insts];
rewrite Find in Find';
inv Find'.
intros ?
b' ?
Hin Sub.
apply Insts in Sub as (
b'' &?&?).
apply s_reset_incl in Hin.
rewrite <-
s_subs_calls_of in Hin.
assert (
b' =
b'')
as ->;
auto.
eapply NoDupMembers_det in Hin;
eauto.
apply s_nodup_subs.
+
rewrite <-
s_vars_out_in_tcs, <-2
map_app, <-
fst_NoDupMembers.
apply s_nodup_vars.
+
apply s_nodup_defined.
+
apply s_reset_consistency.
+
intros;
apply lasts_of_In,
ps_from_list_In;
auto.
rewrite <-
s_lasts_in_tcs;
auto.
+
intros;
apply s_ins_not_def,
fst_InMembers;
auto.
+
simpl;
intros;
eapply eq_if_present_adds_opt;
eauto;
rewrite map_fst_idty;
auto.
+
simpl;
rewrite map_fst_idty;
intros *
Find.
apply not_None_is_Some in Find as (?&
Find);
apply Env.find_adds_opt_spec_Some in Find.
*
rewrite Env.gempty in Find;
destruct Find as [
Hin|];
try discriminate.
eapply in_combine_l;
eauto.
*
transitivity (
length xs);
eapply Forall2_length;
eauto.
+
exists me';
split.
*{
apply find_system_translate in Find'
as (?&?&?&?&?);
subst.
econstructor;
eauto.
-
apply exists_step_method.
-
simpl;
transitivity (
length xs).
+
symmetry;
eapply Forall2_length;
eauto.
+
rewrite length_idty, <-
map_length with (
f :=
fst);
symmetry;
eapply Forall2_length;
eauto.
-
simpl;
eauto.
-
simpl;
rewrite map_fst_idty.
clear -
Outs Equiv.
rewrite Forall2_map_2.
eapply Forall2_impl_In;
eauto;
intros.
apply Equiv;
auto.
apply Is_variable_in_variables.
rewrite <-
s_vars_out_in_tcs,
in_app;
auto.
}
*{
inv Closed;
inv Closed';
repeat match goal with
H:
find_system ?
b ?
P =
_,
H':
find_system ?
b ?
P =
_ |-
_ =>
rewrite H in H';
inv H'
end.
eapply Memory_Corres_equal_memory;
eauto.
-
intro;
now rewrite s_lasts_in_tcs,
lasts_of_In.
-
setoid_rewrite s_subs_calls_of;
apply calls_of_Is_sub_in.
-
intros *
Rst;
apply s_no_single_reset,
Step_with_reset_in_Step_in in Rst;
auto.
}
-
apply sem_trconstrs_cons in Htcs;
auto.
+
apply ident_eqb_neq in Eq.
apply state_closed_other in Closed;
apply state_closed_other in TransClosed;
apply state_closed_other in Closed';
auto.
edestruct IHP as (
me' &?&?);
eauto using sem_system.
exists me';
split;
auto.
apply stmt_call_eval_cons;
auto.
+
eapply find_system_later_not_Is_system_in;
eauto.
Qed.
Corollary correctness_loop_call:
forall P f xss yss ins S0,
Well_defined P ->
wc_program P ->
initial_state P f S0 ->
loop P f xss yss S0 0 ->
(
forall n,
Forall2 eq_if_present (
xss n) (
ins n)) ->
(
forall n,
Exists (
fun v =>
v <>
absent) (
xss n)) ->
exists me0,
stmt_call_eval (
translate P)
mempty f reset []
me0 []
/\
loop_call (
translate P)
f step ins (
fun n =>
map value_to_option (
yss n)) 0
me0
/\
me0 ≋
S0.
Proof.
intros *
Wdef WC Init Loop Spec Clock.
pose proof Loop as Loop';
inversion_clear Loop'
as [???????
Sem].
inv Sem.
assert (
Ordered_systems P)
as Ord by apply Wdef.
eapply reset_spec with (
me :=
mempty)
in Ord as (
me' &?&?&
Closed);
eauto.
assert (
me' ≋
S0)
as Eq
by (
eapply initial_state_det;
eauto;
eapply Closed,
state_closed_empty;
eauto).
exists me';
split; [|
split];
auto.
clear -
Loop Wdef WC Eq Spec Clock.
revert Loop Eq;
revert me'
S0.
generalize 0.
cofix COFIX;
intros.
inversion_clear Loop as [???????
Sem].
eapply correctness in Sem as (?&?&?);
eauto.
econstructor;
eauto.
Qed.
End CORRECTNESS.
Module CorrectnessFun
(
Ids :
IDS)
(
Op :
OPERATORS)
(
OpAux :
OPERATORS_AUX Op)
(
Str :
INDEXEDSTREAMS Op OpAux)
(
CE :
COREEXPR Ids Op OpAux Str)
(
Stc :
STC Ids Op OpAux Str CE)
(
Obc :
OBC Ids Op OpAux)
(
Trans :
TRANSLATION Ids Op OpAux CE.Syn Stc.Syn Obc.Syn)
(
Corres :
STCMEMORYCORRES Ids Op CE.Syn Stc.Syn Stc.Last)
<:
CORRECTNESS Ids Op OpAux Str CE Stc Obc Trans Corres.
Include CORRECTNESS Ids Op OpAux Str CE Stc Obc Trans Corres.
End CorrectnessFun.