(** The simulation diagram. *)

Fixpoint seq_left_depth (s: Csharpminor.stmt) : nat :=
  match s with
  | Csharpminor.Sseq s1 s2 => S (seq_left_depth s1)
  | _ => O
  end.Definition measure (S: Csharpminor.state) : nat :=
  match S with
  | Csharpminor.State fn s k e le m => seq_left_depth s
  | _ => O
  end.(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).(*LENB: Refactoring of original proof:
  1. isolate lemmas for individual cases
  2. Have individual cases be more specific about
     which of the 2 disjuncts they imply
  3. make place swhere meminj's are extended more explicit.
     This is done by exposing meminj's as additional parameter
     of match_state, so that individual lemmas can
     explicitly exisitenitally quantify over the extensions and
     impose additional conditions (eg in case Builtin)
  Other steps one could do:
   - refactoring of states into cores and memories
   - add knowlegsde the amounts to "at_external"*)

Inductive match_statesInj: meminj -> Csharpminor.state -> Cminor.state -> Prop :=
  | matchInj_state:
      forall fn s k e le m tfn ts tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn s k e le m)
                   (State tfn ts tk (Vptr sp Int.zero) te tm)
  | matchInj_state_seq:
      forall fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv f lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs),
      match_statesInj f (Csharpminor.State fn (Csharpminor.Sseq s1 s2) k e le m)
                   (State tfn ts1 tk (Vptr sp Int.zero) te tm)
  | matchInj_callstate:
      forall fd args k m tfd targs tk tm f cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject f args targs),
      match_statesInj f (Csharpminor.Callstate fd args k m)
                   (Callstate tfd targs tk tm)
  | matchInj_returnstate:
      forall v k m tv tk tm f cs cenv
      (MINJ: Mem.inject f m tm)
      (MCS: match_callstack f m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject f v tv),
      match_statesInj f (Csharpminor.Returnstate v k m)
                   (Returnstate tv tk tm).

Lemma transl_step_case_InternalCall: forall cenv f j m tm e cs k tk vargs targs x m1 lenv (*(Param: list_norepet (fn_params_names f ++ fn_vars_names f))*) (Param1: list_norepet (map fst (Csharpminor.fn_vars f))) (Param2 : list_norepet (Csharpminor.fn_params f)) (Param3 : list_disjoint (Csharpminor.fn_params f) (fn_temps f)) (AlocVars : alloc_variables empty_env m (Csharpminor.fn_vars f) e m1) (BindParams: bind_parameters (Csharpminor.fn_params f) vargs (create_undef_temps (fn_temps f)) = Some lenv) (MINJ : Mem.inject j m tm) (MCS : match_callstack j m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv nil cs) (ISCC : Csharpminor.is_call_cont k) (ARGSINJ : val_list_inject j vargs targs) (EQ : transl_function f = OK x), exists T2 : state, plus step tge (Callstate (Internal x) targs tk tm) E0 T2 /\ exists j', inject_incr j j' /\ match_statesInj j' (Csharpminor.State f (Csharpminor.fn_body f) k e lenv m1) T2.