(* this file is a version of veric/semax_ext.v that let external specifications reason about the oracle. *)
(* NOTE.   ext_link: Strings.String.string -> ident represents the mapping from the _name_ of an external function (an ASCII string) to the [ident] that's used to represent it in this program module. That mapping can be computed from the prog_defs component of the Clight.program produced by clightgen. *)
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 (make_ext_args (filter_genv (symb2genv ge_s)) ids args) 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 (make_ext_args (filter_genv ge) n args) |-- P a z (make_ext_args (filter_genv ge') n args)
end.

Lemma all_funspecsOracle_wf f : wf_funspecOracle f.
Program Definition funspecOracle2jspec (ext_link: Strings.String.string -> ident) f : juicy_ext_spec Z :=
Build_juicy_ext_spec _ (funspecOracle2extspec ext_link f) _ _ _.