Section Simulation_Relation.
(** ** Definition of the simulation relations *)
(** The simulation relation for evaluation of statements. The relation relates two environments of type [alist var value]. The source and target environments exactly agree on user variables. *)
Definition Renv (g_imp : Imp.env) (g_asm : Asm.memory) : Prop :=
forall k v, alist_In k g_imp v <-> alist_In k g_asm v.
Global Instance Renv_refl : Reflexive Renv.
(** The simulation relation for evaluation of expressions.  The relation connects  - the global state at the Imp level  - the memory and register states at the Asm level  and, additionally the returned value at the _Imp_ level. The _Asm_ side does not carry a [value], but a [unit], since its denotation does not return any [value].  The [sim_rel] relation is parameterized by the state of the local [asm] environment before the step, and the name of the variable used to store the result.   It enforces three conditions: - [Renv] on the global environments, ensuring that evaluation of expressions does not change user variables;  - Agreement on the computed value, i.e. the returned value [v] is stored at the assembly level in the expected temporary;  - The "stack" of temporaries used to compute intermediate results is left untouched. *)
Definition sim_rel l_asm n: (env * value) -> (memory * (registers * unit)) -> Prop :=
fun '(g_imp', v) '(g_asm', (l_asm', _))  =>
Renv g_imp' g_asm' /\            (* we don't corrupt any of the imp variables *)
alist_In n l_asm' v /\           (* we get the right value *)
(forall m, m < n -> forall v,              (* we don't mess with anything on the "stack" *)
alist_In m l_asm v <-> alist_In m l_asm' v).
(** ** Facts on the simulation relations *)

(** [sim_rel] can be initialized from [Renv]. *)
Lemma sim_rel_add: forall g_asm l_asm g_imp n v,
Renv g_imp g_asm ->
sim_rel l_asm n  (g_imp, v) (g_asm, (alist_add n v l_asm, tt)).