From Velus Require Import Common.
From Velus Require Import Environment.
From Velus Require Import Operators.
From Velus Require Import Obc.ObcSyntax.
From Velus Require Import Obc.ObcSemantics.
From Coq Require Import List.
Import List.ListNotations.
Open Scope list_scope.
Module Type OBCINVARIANTS
(
Import Ids :
IDS)
(
Import Op :
OPERATORS)
(
Import OpAux :
OPERATORS_AUX Ids Op)
(
Import SynObc:
OBCSYNTAX Ids Op OpAux)
(
Import SemObc:
OBCSEMANTICS Ids Op OpAux SynObc).
Determine whether an Obc command can modify a variable .
Inductive Can_write_in_var :
ident ->
stmt ->
Prop :=
|
CWIVAssign:
forall x e,
Can_write_in_var x (
Assign x e)
|
CWIVSwitch:
forall x e ss d,
Exists (
fun s =>
Can_write_in_var x (
or_default d s))
ss ->
Can_write_in_var x (
Switch e ss d)
|
CWIVCall_ap:
forall x xs cls i f es,
In x xs ->
Can_write_in_var x (
Call xs cls i f es)
|
CWIVExternCall:
forall y f fty es,
Can_write_in_var y (
ExternCall y f fty es)
|
CWIVComp1:
forall x s1 s2,
Can_write_in_var x s1 ->
Can_write_in_var x (
Comp s1 s2)
|
CWIVComp2:
forall x s1 s2,
Can_write_in_var x s2 ->
Can_write_in_var x (
Comp s1 s2).
Global Hint Constructors Can_write_in_var :
obcinv.
Lemma Can_write_in_var_Switch:
forall e ss d x,
Can_write_in_var x (
Switch e ss d) <-> (
Exists (
fun s =>
Can_write_in_var x (
or_default d s))
ss).
Proof.
split; [inversion_clear 1|intros [HH|HH]]; auto with obcinv.
Qed.
Lemma cannot_write_in_var_Switch:
forall x e ss d,
~
Can_write_in_var x (
Switch e ss d)
<->
Forall (
fun s => ~
Can_write_in_var x (
or_default d s))
ss.
Proof.
Lemma Can_write_in_var_Comp:
forall x s1 s2,
Can_write_in_var x (
Comp s1 s2) <-> (
Can_write_in_var x s1 \/
Can_write_in_var x s2).
Proof.
split; intros HH.
- inversion_clear HH; auto.
- destruct HH; auto with obcinv.
Qed.
Lemma cannot_write_in_var_Comp:
forall x s1 s2,
~
Can_write_in_var x (
Comp s1 s2)
<->
~
Can_write_in_var x s1 /\ ~
Can_write_in_var x s2.
Proof.
intros; split; intro; try (intro HH; inversion_clear HH); intuition.
Qed.
Assert that an Obc command never writes to a variable more than once.
Inductive No_Overwrites :
stmt ->
Prop :=
|
NoOAssign:
forall x e,
No_Overwrites (
Assign x e)
|
NoOAssignSt:
forall x e isreset,
No_Overwrites (
AssignSt x e isreset)
|
NoOSwitch:
forall e ss d,
Forall (
fun s =>
No_Overwrites (
or_default d s))
ss ->
No_Overwrites (
Switch e ss d)
|
NoOCall:
forall xs cls i f es,
No_Overwrites (
Call xs cls i f es)
|
NoOExternCall:
forall y f fty es,
No_Overwrites (
ExternCall y f fty es)
|
NoOComp:
forall s1 s2,
(
forall x,
Can_write_in_var x s1 -> ~
Can_write_in_var x s2) ->
(
forall x,
Can_write_in_var x s2 -> ~
Can_write_in_var x s1) ->
No_Overwrites s1 ->
No_Overwrites s2 ->
No_Overwrites (
Comp s1 s2)
|
NoOSkip:
No_Overwrites Skip.
Global Hint Constructors No_Overwrites :
obcinv.
Lemma cannot_write_in_var_No_Overwrites:
forall s,
(
forall x, ~
Can_write_in_var x s) ->
No_Overwrites s.
Proof.
Assert that Obc calls never involve undefined variables.
Inductive No_Naked_Vars :
stmt ->
Prop :=
|
NNVAssign:
forall x e,
No_Naked_Vars (
Assign x e)
|
NNVAssignSt:
forall x e isreset,
No_Naked_Vars (
AssignSt x e isreset)
|
NNVSwitch:
forall e ss d,
Forall (
fun s =>
No_Naked_Vars (
or_default d s))
ss ->
No_Naked_Vars (
Switch e ss d)
|
NNVCall:
forall xs cls i f es,
Forall (
fun e =>
forall x ty,
e <>
Var x ty)
es ->
No_Naked_Vars (
Call xs cls i f es)
|
NNVExternCall:
forall y f fty es,
No_Naked_Vars (
ExternCall y f fty es)
|
NNVComp:
forall s1 s2,
No_Naked_Vars s1 ->
No_Naked_Vars s2 ->
No_Naked_Vars (
Comp s1 s2)
|
NNVSkip:
No_Naked_Vars Skip.
Global Hint Constructors No_Naked_Vars :
obcinv.
Lemma stmt_eval_mono:
forall p s me ve me'
ve',
stmt_eval p me ve s (
me',
ve') ->
forall x,
Env.In x ve ->
Env.In x ve'.
Proof.
Lemma no_vars_in_args_spec:
forall me ve es vos,
Forall2 (
exp_eval me ve)
es vos ->
Forall (
fun e =>
forall x ty,
e <>
Var x ty)
es ->
Forall (
fun vo =>
vo <>
None)
vos.
Proof.
induction 1 as [|???? Exp]; auto.
inversion_clear 1 as [|?? E].
constructor; auto.
intro; subst.
inv Exp; eapply E; eauto.
Qed.
End OBCINVARIANTS.
Module ObcInvariantsFun
(
Import Ids :
IDS)
(
Import Op :
OPERATORS)
(
Import OpAux:
OPERATORS_AUX Ids Op)
(
Import SynObc:
OBCSYNTAX Ids Op OpAux)
(
Import SemObc:
OBCSEMANTICS Ids Op OpAux SynObc)
<:
OBCINVARIANTS Ids Op OpAux SynObc SemObc.
Include OBCINVARIANTS Ids Op OpAux SynObc SemObc.
End ObcInvariantsFun.