Program Definition funspec2jspec (ext_link: Strings.String.string -> ident) f : juicy_ext_spec Z :=
  Build_juicy_ext_spec _ (funspec2extspec ext_link f) _ _ _.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.