Require Export VST.veric.base.
Require Export VST.veric.shares.
Require Export VST.veric.seplog.
Require Export VST.veric.mapsto_memory_block.
Local Open Scope pred.
Require Export VST.veric.Clight_mapsto_memory_block.
Local Open Scope pred.
(*Definition expr_true (e: Clight.expr) (rho: environ): Prop := bool_val (eval_expr e rho) (Clight.typeof e) = Some true.*)
Definition expr_true {CS: compspecs} e := lift1 (typed_true (typeof e)) (eval_expr e).
Definition expr_false {CS: compspecs} e := lift1 (typed_false (typeof e)) (eval_expr e).
(* Definition fun_assert: forall (fml: funsig) cc (A: TypeTree) (P Q: forall ts, dependent_type_functor_rec ts (AssertTT A) (pred rmap)) (v: val) , pred rmap := res_predicates.fun_assert. *)
Definition eval_lvar (id: ident) (ty: type) (rho: environ) :=
match Map.get (ve_of rho) id with
| Some (b, ty') => if eqb_type ty ty' then Vptr b Ptrofs.zero else Vundef
| None => Vundef
end.
Definition var_block (sh: Share.t) {cs: compspecs} (idt: ident * type) (rho: environ): mpred :=
!! (sizeof (snd idt) <= Ptrofs.max_unsigned) &&
(memory_block sh (sizeof (snd idt))) (eval_lvar (fst idt) (snd idt) rho).
Definition stackframe_of {cs: compspecs} (f: Clight.function) : assert :=
fold_right (fun P Q rho => P rho * Q rho) (fun rho => emp) (map (fun idt => var_block Share.top idt) (Clight.fn_vars f)).
(* Definition stackframe_of (f: Clight.function) : assert := fun rho => sepcon_list (map (fun idt => var_block Share.top idt rho) (Clight.fn_vars f)). *)
Definition tc_formals (formals: list (ident * type)) : environ -> Prop :=
fun rho => tc_vals (map (@snd _ _) formals) (map (fun xt => (eval_id (fst xt) rho)) formals).
(*This definition, and lemma close_precondition_i below, could be moved to general_seplog*)
Program Definition close_precondition (specparams bodyparams: list ident) (P: environ -> pred rmap) (rho: environ) : pred rmap :=
fun phi =>
exists ve', exists te',
(forall n i j, nth_error specparams n = Some i ->
nth_error bodyparams n = Some j ->
Map.get te' i = Map.get (te_of rho) j) /\
app_pred (P (mkEnviron (ge_of rho) ve' te')) phi.
Next Obligation.
intros.
intro; intros.
destruct H0 as [ve' [te' [? ?]]]; exists ve',te'; split; auto.
eapply pred_hereditary; eauto.
Qed.
Definition precondition_closed (fs: list (ident*type)) {A: TypeTree}
(P: forall ts, dependent_type_functor_rec ts (AssertTT A) mpred) : Prop :=
forall ts x,
closed_wrt_vars (not_a_param fs) (P ts x) /\
closed_wrt_lvars (fun _ => True) (P ts x).

Lemma close_precondition_e:
forall al (A: TypeTree) (P:  forall ts, dependent_type_functor_rec ts (AssertTT A) mpred),
precondition_closed al P ->
forall ts x rho,
close_precondition (map fst al) (map fst al)  (P ts x) rho |-- P ts x rho.