(** * Compatibility with memory injections *)

(** Relating two memory values according to a memory injection. *)

Inductive memval_inject (f: meminj): memval -> memval -> Prop :=
  | memval_inject_byte:
      forall n, memval_inject f (Byte n) (Byte n)
  | memval_inject_frag:
      forall v1 v2 q n,
      Val.inject f v1 v2 ->
      memval_inject f (Fragment v1 q n) (Fragment v2 q n)
  | memval_inject_undef:
      forall mv, memval_inject f Undef mv.(** * Compatibility with memory injections *)

(** Relating two memory values according to a memory injection. *)

Inductive memval_inject (f: meminj): memval -> memval -> Prop :=
  | memval_inject_byte:
      forall n, memval_inject f (Byte n) (Byte n)
  | memval_inject_frag:
      forall v1 v2 q n,
      Val.inject f v1 v2 ->
      memval_inject f (Fragment v1 q n) (Fragment v2 q n)
  | memval_inject_undef:
      forall mv, memval_inject f Undef mv.(** * Compatibility with memory injections *)

(** Relating two memory values according to a memory injection. *)

Inductive memval_inject (f: meminj): memval -> memval -> Prop :=
  | memval_inject_byte:
      forall n, memval_inject f (Byte n) (Byte n)
  | memval_inject_frag:
      forall v1 v2 q n,
      Val.inject f v1 v2 ->
      memval_inject f (Fragment v1 q n) (Fragment v2 q n)
  | memval_inject_undef:
      forall mv, memval_inject f Undef mv.(** * Compatibility with memory injections *)

(** Relating two memory values according to a memory injection. *)

Inductive memval_inject (f: meminj): memval -> memval -> Prop :=
  | memval_inject_byte:
      forall n, memval_inject f (Byte n) (Byte n)
  | memval_inject_frag:
      forall v1 v2 q n,
      Val.inject f v1 v2 ->
      memval_inject f (Fragment v1 q n) (Fragment v2 q n)
  | memval_inject_undef:
      forall mv, memval_inject f Undef mv.

(* Specifications: *)
Lemma memval_inject_incr: forall f f' v1 v2, memval_inject f v1 v2 -> inject_incr f f' -> memval_inject f' v1 v2.
Lemma proj_bytes_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> forall bl, proj_bytes vl = Some bl -> proj_bytes vl' = Some bl.
Lemma check_value_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> forall v v' q n, check_value n v q vl = true -> Val.inject f v v' -> v <> Vundef -> check_value n v' q vl' = true.
Lemma proj_value_inject: forall f q vl1 vl2, list_forall2 (memval_inject f) vl1 vl2 -> Val.inject f (proj_value q vl1) (proj_value q vl2).
Lemma proj_bytes_not_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> proj_bytes vl = None -> proj_bytes vl' <> None -> In Undef vl.
Lemma check_value_undef: forall n q v vl, In Undef vl -> check_value n v q vl = false.
Lemma proj_value_undef: forall q vl, In Undef vl -> proj_value q vl = Vundef.
Theorem decode_val_inject: forall f vl1 vl2 chunk, list_forall2 (memval_inject f) vl1 vl2 -> Val.inject f (decode_val chunk vl1) (decode_val chunk vl2).
Lemma inj_bytes_inject: forall f bl, list_forall2 (memval_inject f) (inj_bytes bl) (inj_bytes bl).
Lemma repeat_Undef_inject_any: forall f vl, list_forall2 (memval_inject f) (list_repeat (length vl) Undef) vl.
Lemma repeat_Undef_inject_encode_val: forall f chunk v, list_forall2 (memval_inject f) (list_repeat (size_chunk_nat chunk) Undef) (encode_val chunk v).
Lemma repeat_Undef_inject_self: forall f n, list_forall2 (memval_inject f) (list_repeat n Undef) (list_repeat n Undef).
Lemma inj_value_inject: forall f v1 v2 q, Val.inject f v1 v2 -> list_forall2 (memval_inject f) (inj_value q v1) (inj_value q v2).
Theorem encode_val_inject: forall f v1 v2 chunk, Val.inject f v1 v2 -> list_forall2 (memval_inject f) (encode_val chunk v1) (encode_val chunk v2).
Lemma memval_inject_incr: forall f f' v1 v2, memval_inject f v1 v2 -> inject_incr f f' -> memval_inject f' v1 v2.
Lemma proj_bytes_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> forall bl, proj_bytes vl = Some bl -> proj_bytes vl' = Some bl.
Lemma check_value_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> forall v v' q n, check_value n v q vl = true -> Val.inject f v v' -> v <> Vundef -> check_value n v' q vl' = true.
Lemma proj_value_inject: forall f q vl1 vl2, list_forall2 (memval_inject f) vl1 vl2 -> Val.inject f (proj_value q vl1) (proj_value q vl2).
Lemma proj_bytes_not_inject: forall f vl vl', list_forall2 (memval_inject f) vl vl' -> proj_bytes vl = None -> proj_bytes vl' <> None -> In Undef vl.
Lemma check_value_undef: forall n q v vl, In Undef vl -> check_value n v q vl = false.
Lemma proj_value_undef: forall q vl, In Undef vl -> proj_value q vl = Vundef.
Theorem decode_val_inject: forall f vl1 vl2 chunk, list_forall2 (memval_inject f) vl1 vl2 -> Val.inject f (decode_val chunk vl1) (decode_val chunk vl2).
Lemma inj_bytes_inject: forall f bl, list_forall2 (memval_inject f) (inj_bytes bl) (inj_bytes bl).
Lemma repeat_Undef_inject_any: forall f vl, list_forall2 (memval_inject f) (list_repeat (length vl) Undef) vl.
Lemma repeat_Undef_inject_encode_val: forall f chunk v, list_forall2 (memval_inject f) (list_repeat (size_chunk_nat chunk) Undef) (encode_val chunk v).
Lemma repeat_Undef_inject_self: forall f n, list_forall2 (memval_inject f) (list_repeat n Undef) (list_repeat n Undef).
Lemma inj_value_inject: forall f v1 v2 q, Val.inject f v1 v2 -> list_forall2 (memval_inject f) (inj_value q v1) (inj_value q v2).
Theorem encode_val_inject: forall f v1 v2 chunk, Val.inject f v1 v2 -> list_forall2 (memval_inject f) (encode_val chunk v1) (encode_val chunk v2).