Definition update (s : store) (c : cell) (v : nat) : store :=
  fun c' : cell =>
  match cell_eq_dec c' c with
  | left _ => v
  | right _ => s c'
  end.(* semantics of target language *)

Definition Si (s : store) (i : instr) : store :=
  match i with
  | LI n => update s Acc n
  | LOAD r => update s Acc (s (Reg r))
  | STO r => update s (Reg r) (s Acc)
  | ADD r => update s Acc (s (Reg r) + s Acc)
  end.Definition list1 (i : instr) := i :: nil.Fixpoint Sl (s : store) (l : list instr) {struct l} : store :=
  match l with
  | nil => s
  | i :: l' => Sl (Si s i) l'
  end.(* the compiler *)

Definition symt := string -> nat.Fixpoint C (m : symt) (r : nat) (e : expr) {struct e} : 
 list instr :=
  match e with
  | Lit n => list1 (LI n)
  | Var s => list1 (LOAD (m s))
  | Plus e1 e2 =>
      (C m r e1 ++ list1 (STO r)) ++ C m (S r) e2 ++ list1 (ADD r)
  end.

(* Specifications: *)
Lemma Sl_append : forall (l1 l2 : list instr) (s : store), Sl s (l1 ++ l2) = Sl (Sl s l1) l2.
Lemma Sl_invariant : forall (m : symt) (e : expr) (r r' : nat), r' < r -> forall s : store, Sl s (C m r e) (Reg r') = s (Reg r').
Theorem correctness : forall (e : expr) (m : symt) (s : state) (s' : store) (r : nat), (forall v : string, m v < r) -> (forall v : string, s v = s' (Reg (m v))) -> Sl s' (C m r e) Acc = E s e /\ (forall x : nat, x < r -> Sl s' (C m r e) (Reg x) = s' (Reg x)).