Next Obligation.
destruct f; simpl; unfold funspec2pre, pureat; simpl; destruct f; simpl;
destruct f; simpl; intros.
if_tac [e0|e0].
* destruct e; try discriminate; injection e0 as E; subst i sg; intros a a' Hage.
intros [Hargs [phi0 [phi1 [Hjoin [Hx [Hy Hg]]]]]].
apply age1_juicy_mem_unpack in Hage.
destruct Hage as [Hage Hdry].
destruct (age1_join2 phi0 Hjoin Hage) as [x' [y' [Hjoin' [Hage' H]]]].
split; auto. exists x', y'; split; auto.
destruct P. split. eapply h; eauto.
split. apply (necR_trans (fst t0) phi1 y'); auto.
unfold necR. constructor; auto.
erewrite age1_ghost_of by eauto.
change (Some (ghost_PCM.ext_ref z, NoneP) :: nil) with
(own.ghost_approx (m_phi a') (Some (ghost_PCM.ext_ref z, NoneP) :: nil)).
destruct Hg; eexists; apply ghost_fmap_join; eauto.
* intros ? ?; auto.
destruct Espec; simpl; apply JE_pre_hered.
Qed.
Next Obligation.
destruct f; simpl; unfold funspec2post, pureat; simpl; destruct f; simpl;
destruct f; simpl; intros.
if_tac [e0|e0].
* destruct e; try discriminate; injection e0 as E; subst i sg. intros a a' Hage. destruct Q; simpl.
intros [phi0 [phi1 [Hjoin [Hx [Hy Hg]]]]].
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]|].
split. apply (necR_trans (fst t0) phi1 y'); auto.
unfold necR. constructor; auto.
erewrite age1_ghost_of by eauto.
change (Some (ghost_PCM.ext_ref z, NoneP) :: nil) with
(own.ghost_approx (m_phi a') (Some (ghost_PCM.ext_ref z, NoneP) :: nil)).
destruct Hg; eexists; apply ghost_fmap_join; eauto.
* 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 funspecs2jspec.
Definition funspecs_norepeat (fs : funspecs) := list_norepet (map fst fs).
Fixpoint add_funspecs_rec (ext_link: Strings.String.string -> ident) (Z : Type) (Espec : juicy_ext_spec Z) (fs : funspecs) :=
match fs with
| nil => Espec
| cons (i,f) fs' => funspec2jspec Z (add_funspecs_rec ext_link Z Espec fs') ext_link (i,f)
end.

(* Specifications: *)
Lemma add_funspecs_pre  (ext_link: Strings.String.string -> ident)
{Z fs id sig cc A P Q NEP NEQ}
{x: sigT (fun ts => dependent_type_functor_rec ts A mpred)} {args m} Espec tys ge_s phi0 phi1 :
let ef := EF_external id (funsig2signature sig cc) in
funspecs_norepeat fs ->
In (ext_link id, (mk_funspec sig cc A P Q NEP NEQ)) fs ->
join phi0 phi1 (m_phi m) ->
Val.has_type_list args (sig_args (ef_sig ef)) ->
P (projT1 x) (projT2 x) (make_ext_args (filter_genv (symb2genv ge_s)) (fst (split (fst sig))) args) phi0 ->
exists x' : ext_spec_type (JE_spec _ (add_funspecs_rec ext_link Z Espec fs)) ef,
JMeq (phi1, x) x'
/\ forall z, joins (ghost_of (m_phi m)) (Some (ghost_PCM.ext_ref z, NoneP) :: nil) ->
ext_spec_pre (add_funspecs_rec ext_link Z Espec fs) ef x' ge_s tys args z m.
Lemma add_funspecs_pre_void  (ext_link: Strings.String.string -> ident)
{Z fs id sig cc A P Q NEP NEQ}
{x: sigT (fun ts => dependent_type_functor_rec ts A mpred)}
{args m} Espec tys ge_s phi0 phi1 :
let ef := EF_external id (mksignature (map typ_of_type (map snd sig)) None cc) in
funspecs_norepeat fs ->
In (ext_link id, (mk_funspec (sig, tvoid) cc A P Q NEP NEQ)) fs ->
join phi0 phi1 (m_phi m) ->
Val.has_type_list args (sig_args (ef_sig ef)) ->
P (projT1 x) (projT2 x) (make_ext_args (filter_genv (symb2genv ge_s)) (fst (split sig)) args) phi0 ->
exists x' : ext_spec_type (JE_spec _ (add_funspecs_rec ext_link Z Espec fs)) ef,
JMeq (phi1, x) x'
/\ forall z, joins (ghost_of (m_phi m)) (Some (ghost_PCM.ext_ref z, NoneP) :: nil) ->
ext_spec_pre (add_funspecs_rec ext_link Z Espec fs) ef x' ge_s tys args z m.
Lemma add_funspecs_post_void (ext_link: Strings.String.string -> ident)
{Z Espec tret fs id sig cc A P Q NEP NEQ x ret m z ge_s} :
let ef := EF_external id (mksignature (map typ_of_type (map snd sig)) None cc) in
funspecs_norepeat fs ->
In (ext_link id, (mk_funspec (sig, tvoid) cc A P Q NEP NEQ)) fs ->
ext_spec_post (add_funspecs_rec ext_link Z Espec fs) ef x ge_s tret ret z m ->
exists (phi0 phi1 phi1' : rmap) (x': sigT (fun ts => dependent_type_functor_rec ts A mpred)),
join phi0 phi1 (m_phi m)
/\ necR phi1' phi1
/\ JMeq x (phi1', x')
/\ Q (projT1 x') (projT2 x') (make_ext_rval (filter_genv (symb2genv ge_s)) ret) phi0.
Lemma add_funspecs_post (ext_link: Strings.String.string -> ident){Z Espec tret fs id sig cc A P Q NEP NEQ x ret m z ge_s} :
let ef := EF_external id (funsig2signature sig cc) in
funspecs_norepeat fs ->
In (ext_link id, (mk_funspec sig cc A P Q NEP NEQ)) fs ->
ext_spec_post (add_funspecs_rec ext_link Z Espec fs) ef x ge_s tret ret z m ->
exists (phi0 phi1 phi1' : rmap) (x': sigT (fun ts => dependent_type_functor_rec ts A mpred)),
join phi0 phi1 (m_phi m)
/\ necR phi1' phi1
/\ JMeq x (phi1',x')
/\ Q (projT1 x') (projT2 x') (make_ext_rval (filter_genv (symb2genv ge_s)) ret) phi0.