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 composed when proving binary arithmetic operators. *)
Lemma sim_rel_binary_op:
forall (l_asm l_asm' l_asm'' : registers) (g_asm' g_asm'' : memory) (g_imp' g_imp'' : env)
(n v v' : nat)
(Hsim : sim_rel l_asm n (g_imp', v) (g_asm', (l_asm', tt)))
(Hsim': sim_rel l_asm' (S n) (g_imp'', v') (g_asm'', (l_asm'', tt)))
(op: nat -> nat -> nat),
sim_rel l_asm n (g_imp'', op v v') (g_asm'', (alist_add n (op v v') l_asm'', tt)).