Definition ignores_juice Z (J: external_specification juicy_mem external_function Z) : Prop :=
  (forall e t b tl vl x jm jm',
     m_dry jm = m_dry jm' ->
    ext_spec_pre J e t b tl vl x jm ->
    ext_spec_pre J e t b tl vl x jm') /\
 (forall ef t b ot v x jm jm',
     m_dry jm = m_dry jm' -> 
    ext_spec_post J ef t b ot v x jm ->
    ext_spec_post J ef t b ot v x jm') /\
 (forall v x jm jm',
     m_dry jm = m_dry jm' -> 
     ext_spec_exit J v x jm ->
     ext_spec_exit J v x jm').Definition mem_evolve (m m': mem) : Prop :=
   (* dry version of resource_decay *)
 forall loc,
 match access_at m loc Cur, access_at m' loc Cur with
 | None, None => True
 | None, Some Freeable => True
 | Some Freeable, None => True
 | Some Writable, Some p' => p' = Writable
 | Some p, Some p' => p=p' /\ access_at m loc Max = access_at m' loc Max
 | _, _ => False
 end.Definition ext_spec_mem_evolve (Z: Type) 
  (D: external_specification mem external_function Z) :=
 forall ef w b tl vl ot v z m z' m',
    ext_spec_pre D ef w b tl vl z m ->
    ext_spec_post D ef w b ot v z' m' ->
    mem_evolve m m'.Definition juicy_dry_ext_spec (Z: Type)
   (J: external_specification juicy_mem external_function Z)
   (D: external_specification mem external_function Z)
   (dessicate: forall ef jm, ext_spec_type J ef -> ext_spec_type D ef) :=
  (forall e t t' b tl vl x jm,
    dessicate e jm t = t' ->
    (ext_spec_pre J e t b tl vl x jm ->
    ext_spec_pre D e t' b tl vl x (m_dry jm))) /\
 (forall ef t t' b ot v x jm0 jm,
    (exists tl vl x0, dessicate ef jm0 t = t' /\ ext_spec_pre J ef t b tl vl x0 jm0) ->
(*    Hrel n jm0 jm ->*)
    resource_at (m_phi jm) = resource_fmap (approx (level jm)) (approx (level jm)) oo juicy_mem_lemmas.rebuild_juicy_mem_fmap jm0 (m_dry jm) ->
    (ext_spec_post D ef t' b ot v x (m_dry jm) ->
     ext_spec_post J ef t b ot v x jm)) /\
 (forall v x jm,
     ext_spec_exit J v x jm <->
     ext_spec_exit D v x (m_dry jm)).Definition juicy_dry_ext_spec_make (Z: Type) 
   (J: external_specification juicy_mem external_function Z) :
   external_specification mem external_function Z.Definition dessicate_id Z 
   (J: external_specification juicy_mem external_function Z) :
   forall ef (jm : juicy_mem), ext_spec_type J ef -> 
       ext_spec_type (juicy_dry_ext_spec_make Z J) ef.(*Lemma jdes_make_lemma:
  forall Z J, ignores_juice Z J ->
    juicy_dry_ext_spec Z J (juicy_dry_ext_spec_make Z J)
     (dessicate_id Z J) ().
Proof.
intros.
destruct H as [? [? ?]], J; split; [ | split3]; simpl in *; intros; auto.
-
subst t'.
eapply H. symmetry; eassumption.  auto.
-
destruct H2 as (? & ? & ? & ? & ?).
subst t'.
eapply H0; auto.
-
eapply H1. symmetry; eassumption. auto.
Qed.*)

Definition mem_rmap_cohere m phi :=
  contents_cohere m phi /\
  access_cohere m phi /\
  max_access_cohere m phi /\ alloc_cohere m phi.

Lemma whole_program_sequential_safety: forall {CS: compspecs} {Espec: OracleKind} (initial_oracle: OK_ty) (dryspec: ext_spec OK_ty) (dessicate : forall (ef : external_function) jm, ext_spec_type OK_spec ef -> ext_spec_type dryspec ef) (JDE: juicy_dry_ext_spec _ (@JE_spec OK_ty OK_spec) dryspec dessicate) (DME: ext_spec_mem_evolve _ dryspec) prog V G m, @semax_prog Espec (*NullExtension.Espec*) CS prog V G -> Genv.init_mem prog = Some m -> exists b, exists q, exists m', Genv.find_symbol (Genv.globalenv prog) (prog_main prog) = Some b /\ initial_core (cl_core_sem (globalenv prog)) 0 m q m' (Vptr b Ptrofs.zero) nil /\ forall n, @dry_safeN _ _ _ OK_ty (genv_symb_injective) (coresem_extract_cenv (cl_core_sem (globalenv prog)) (prog_comp_env prog)) (*(dryspec OK_ty)*) dryspec (Build_genv (Genv.globalenv prog) (prog_comp_env prog)) n initial_oracle q m'.