(*map typeof bl = map (@snd _ _) (fst fsig) ->*)
(*    Forall (fun it => complete_type (composite_types Delta) (snd it) = true) (fn_vars (snd fsig)) ->*)
(*filter_genv psi = ge_of rho ->*)

(* Specifications: *)
Lemma func_at_func_at':
forall fs loc, func_at fs loc |-- func_at' fs loc.
Lemma semax_call:
forall Delta (A: TypeTree)
(P Q : forall ts, dependent_type_functor_rec ts (AssertTT A) mpred)
(NEP: super_non_expansive P) (NEQ: super_non_expansive Q)
(ts: list Type) (x : dependent_type_functor_rec ts A mpred)
F ret argsig retsig cc a bl,
Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params argsig) retsig cc ->
(retsig = Tvoid -> ret = None) ->
tc_fn_return Delta ret retsig ->
semax Espec Delta
(fun rho => (|>(tc_expr Delta a rho && tc_exprlist Delta (snd (split argsig)) bl rho))  &&
(func_ptr (mk_funspec (argsig,retsig) cc A P Q NEP NEQ) (eval_expr a rho) &&
(|>(F rho * P ts x (make_args (map (@fst  _ _) argsig)
(eval_exprlist (snd (split argsig)) bl rho) rho )))))
(Scall ret a bl)
(normal_ret_assert
(fun rho => (EX old:val, substopt ret old F rho * maybe_retval (Q ts x) retsig ret rho))).
Lemma semax_call_alt:
forall Delta (A: TypeTree)
(P Q : forall ts, dependent_type_functor_rec ts (AssertTT A) mpred)
(NEP: super_non_expansive P) (NEQ: super_non_expansive Q)
ts x F ret argsig retsig cc a bl,
Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params argsig) retsig cc ->
(retsig = Tvoid -> ret = None) ->
tc_fn_return Delta ret retsig ->
semax Espec Delta
(fun rho => (|> (tc_expr Delta a rho && tc_exprlist Delta (snd (split argsig)) bl rho))  &&
(func_ptr (mk_funspec (argsig,retsig) cc A P Q NEP NEQ) (eval_expr a rho) &&
(|>(F rho * P ts x (make_args (map (@fst  _ _) argsig)
(eval_exprlist (snd (split argsig)) bl rho) rho )))))
(Scall ret a bl)
(normal_ret_assert
(fun rho => (EX old:val, substopt ret old F rho * maybe_retval (Q ts x) retsig ret rho))).
Lemma call_cont_idem: forall k, call_cont (call_cont k) = call_cont k.
Definition cast_expropt (e: option expr) t : environ -> option val :=
match e with Some e' => `Some (eval_expr (Ecast e' t))  | None => `None end.
Lemma call_cont_current_function:
forall {k i f e t l}, call_cont k = Kcall i f e t :: l -> current_function k = Some f.