Section funspecsOracle2jspec.
Variable Z : Type.
Variable Espec : juicy_ext_spec Z.
Definition funspecOracle2pre (ext_link: Strings.String.string -> ident) (A : Type) (P : A -> Z -> environ -> mpred) (ids: list ident) (id: ident) sig (ef: external_function) x ge_s
(tys : list typ) args z m : Prop :=
match oi_eq_dec (Some (id, sig)) (ef_id_sig ext_link ef) as s
return ((if s then (rmap * A)%type else ext_spec_type Espec ef) -> Prop)
with
| left _ =>
fun x => exists phi0 phi1, join phi0 phi1 (m_phi m)
/\ P (snd x) z (seplog.make_args ids args (empty_environ (symb2genv ge_s))) phi0
/\ necR (fst x) phi1
| right n => fun x' => ext_spec_pre Espec ef x' ge_s tys args z m
end x.
Definition funspecOracle2post (ext_link: Strings.String.string -> ident) (A : Type) (Q : A -> Z -> environ -> mpred)
id sig ef x ge_s (tret : option typ) ret z m : Prop :=
match oi_eq_dec (Some (id, sig)) (ef_id_sig ext_link ef) as s
return ((if s then (rmap * A)%type else ext_spec_type Espec ef) -> Prop)
with
| left _ =>
fun x => exists phi0 phi1, join phi0 phi1 (m_phi m)
/\ Q (snd x) z (make_ext_rval (filter_genv (symb2genv ge_s)) ret) phi0
/\ necR (fst x) phi1
| right n => fun x' => ext_spec_post Espec ef x' ge_s tret ret z m
end x.
Inductive funspecOracle : Type :=
mk_funspecOracle : funsig -> calling_convention -> forall A : Type,
(A -> Z -> environ -> mpred) ->
(A -> Z -> environ -> mpred) -> funspecOracle.
Definition funspecOracle2extspec (ext_link: Strings.String.string -> ident) (f : ident * funspecOracle)
: external_specification juicy_mem external_function Z :=
match f with
| (id, mk_funspecOracle ((params, sigret) as fsig) cc A P Q) =>
let sig := funsig2signature fsig cc in
Build_external_specification juicy_mem external_function Z
(fun ef => if oi_eq_dec (Some (id, sig)) (ef_id_sig ext_link ef) then (rmap * A)%type else ext_spec_type Espec ef)
(funspecOracle2pre ext_link A P (fst (split params)) id sig)
(funspecOracle2post ext_link A Q id sig)
(fun rv z m => False)
end.
Local Open Scope pred.
Definition wf_funspecOracle (f : funspecOracle) :=
match f with
| mk_funspecOracle sig cc A P Q =>
forall a (ge ge': genv) n args z,
Genv.genv_symb ge = Genv.genv_symb ge' ->
P a z (seplog.make_args n args (empty_environ ge) ) |-- P a z (seplog.make_args n args (empty_environ ge') )
end.
Program Definition funspecOracle2jspec (ext_link: Strings.String.string -> ident) f : juicy_ext_spec Z :=
Build_juicy_ext_spec _ (funspecOracle2extspec ext_link f) _ _ _.
Next Obligation.
destruct f; simpl; unfold funspecOracle2pre, pureat; simpl; destruct f; simpl;
destruct f; simpl; intros e t0 ge_s typs args z.
if_tac [e0|e0].
* destruct e; try discriminate; injection e0 as E; subst i sg; intros a a' Hage.
intros [phi0 [phi1 [Hjoin [Hx Hy]]]].
apply age1_juicy_mem_unpack in Hage.
destruct Hage as [Hage Hdry].
destruct (age1_join2 phi0 Hjoin Hage) as [x' [y' [Hjoin' [Hage' H]]]].
exists x', y'; split; auto.
destruct m. split. eapply h; eauto.
apply (necR_trans (fst t0) phi1 y'); auto.
unfold necR. constructor; auto.
* intros ? ?; auto.
destruct Espec; simpl; apply JE_pre_hered.
Qed.
Next Obligation.
destruct f; simpl; unfold funspecOracle2post, pureat; simpl; destruct f; simpl;
destruct f; simpl. intros e t0 ge_s tret rv z.
if_tac [e0|e0].
* destruct e; try discriminate; injection e0 as E; subst i sg; intros a a' Hage; destruct m0; simpl.
intros [phi0 [phi1 [Hjoin [Hx Hy]]]].
apply age1_juicy_mem_unpack in Hage.
destruct Hage as [Hage Hdry].
destruct (age1_join2 phi0 Hjoin Hage) as [x' [y' [Hjoin' [Hage' H]]]].
exists x', y'; split; auto.
split; [solve[eapply h; eauto]|].
apply (necR_trans (fst t0) phi1 y'); auto.
unfold necR. constructor; auto.
* intros ? ?; auto.
destruct Espec; simpl; apply JE_post_hered.
Qed.
Next Obligation.
intros ? ? ? ?; destruct f; destruct f; destruct f; simpl.
intros a' Hage; auto.
Qed.
End funspecsOracle2jspec.
Fixpoint add_funspecsOracle_rec (ext_link: string -> ident) Z (Espec : juicy_ext_spec Z) (fs : list (ident * funspecOracle Z)) :=
match fs with
| nil => Espec
| cons (i,f) fs' => funspecOracle2jspec Z (add_funspecsOracle_rec ext_link Z Espec fs') ext_link (i,f)
end.

Lemma add_funspecs_pre  (ext_link: Strings.String.string -> ident)
{Z fs id sig cc A P Q x args m} Espec tys ge_s phi0 phi1 z :
let ef := EF_external id (funsig2signature sig cc) in
list_norepet (map fst fs) ->
In (ext_link id, (mk_funspecOracle Z sig cc A P Q)) fs ->
join phi0 phi1 (m_phi m) ->
P x z (seplog.make_args (fst (split (fst sig))) args (empty_environ (symb2genv ge_s)) ) phi0 ->
exists x' : ext_spec_type (JE_spec _ (add_funspecsOracle_rec ext_link Z Espec fs)) ef,
JMeq (phi1, x) x'
/\ ext_spec_pre (add_funspecsOracle_rec ext_link Z Espec fs) ef x' ge_s tys args z m.