Local Open Scope nat_scope.
Local Open Scope pred.
Record juicy_ext_spec (Z: Type) := {
JE_spec:> external_specification juicy_mem external_function Z;
JE_pre_hered: forall e t ge_s typs args z, hereditary age (ext_spec_pre JE_spec e t ge_s typs args z);
JE_post_hered: forall e t ge_s tret rv z, hereditary age (ext_spec_post JE_spec e t ge_s tret rv z);
JE_exit_hered: forall rv z, hereditary age (ext_spec_exit JE_spec rv z)
}.
Class OracleKind := {
OK_ty : Type;
OK_spec: juicy_ext_spec OK_ty
}.
(*! The void ext_spec *)
Definition void_spec T : external_specification juicy_mem external_function T :=
Build_external_specification
juicy_mem external_function T
(fun ef => False)
(fun ef Hef ge tys vl m z => False)
(fun ef Hef ge ty vl m z => False)
(fun rv m z => False).
Definition ok_void_spec (T : Type) : OracleKind.
refine (Build_OracleKind T (Build_juicy_ext_spec _ (void_spec T) _ _ _)).
(*Lenb: removed here. To be moved a more CLight-specific place Record jm_init_package: Type := { jminit_m: Memory.mem; jminit_prog: program; jminit_G: tycontext.funspecs; jminit_lev: nat; jminit_init_mem: Genv.init_mem jminit_prog = Some jminit_m; jminit_defs_no_dups:   list_norepet (prog_defs_names jminit_prog); jminit_fdecs_match: match_fdecs (prog_funct jminit_prog) jminit_G }.  Definition init_jmem {G} (ge: G) (jm: juicy_mem) (d: jm_init_package) := jm = initial_jm (jminit_prog d) (jminit_m d) (jminit_G d) (jminit_lev d) (jminit_init_mem d) (jminit_defs_no_dups d) (jminit_fdecs_match d). *)
Definition juicy_core_sem
{C} (csem: @CoreSemantics C mem) :
@CoreSemantics C juicy_mem :=
@Build_CoreSemantics _ juicy_mem
(j_initial_core csem)
(j_at_external csem)
(j_after_external csem)
(j_halted csem)
(jstep csem)
(jstep_not_halted csem)
(jstep_not_at_external csem)
(*  (j_at_external_halted_excl csem)*).  Section upd_exit. Context {Z : Type}. Variable spec : juicy_ext_spec Z.  Definition upd_exit' (Q_exit : option val -> Z -> juicy_mem -> Prop) := {| ext_spec_type := ext_spec_type spec ; ext_spec_pre := ext_spec_pre spec ; ext_spec_post := ext_spec_post spec ; ext_spec_exit := Q_exit |}.  Definition upd_exit'' (ef : external_function) (x : ext_spec_type spec ef) ge := upd_exit' (ext_spec_post spec ef x ge (sig_res (ef_sig ef))).  Program Definition upd_exit {ef : external_function} (x : ext_spec_type spec ef) ge := Build_juicy_ext_spec _ (upd_exit'' _ x ge) _ _ _. Next Obligation. intros. eapply JE_pre_hered; eauto. Qed. Next Obligation. intros. eapply JE_post_hered; eauto. Qed. Next Obligation. intros. eapply JE_post_hered; eauto. Qed. End upd_exit.  Obligation Tactic := Tactics.program_simpl.  Program Definition juicy_mem_op (P : pred rmap) : pred juicy_mem := fun jm => P (m_phi jm). Next Obligation. intro; intros. apply age1_juicy_mem_unpack in H. destruct H. eapply pred_hereditary; eauto. Qed.  Lemma age_resource_decay: forall b jm1 jm2 jm1' jm2', resource_decay b jm1 jm2 -> age jm1 jm1' -> age jm2 jm2' -> level jm1 = S (level jm2) -> resource_decay b jm1' jm2'.  Lemma necR_PURE' phi0 phi k p adr : necR phi0 phi -> phi @ adr = PURE k p -> (*a stronger theorem is possible -- this one doesn't relate p, pp*)
exists pp, phi0 @ adr = PURE k pp.
Definition jm_update m m' := m_dry m' = m_dry m /\ level m' = level m /\
resource_at (m_phi m') = resource_at (m_phi m).
Definition has_ext {Z} (ora : Z) : mpred.mpred := @own (ext_PCM _) 0 (Some (Tsh, Some ora), None) NoneP.
Definition jm_bupd {Z} (ora : Z) P m := forall C : ghost,
(* use the external state to restrict the ghost moves *)
join_sub (Some (ext_ref ora, NoneP) :: nil) C ->
joins (ghost_of (m_phi m)) (ghost_approx m C) ->
exists m' : juicy_mem, joins (ghost_of (m_phi m')) ((ghost_approx m) C) /\
jm_update m m' /\ P m'.

Lemma jm_bupd_intro: forall {Z} (ora : Z) (P : juicy_mem -> Prop) m, P m -> jm_bupd ora P m.