End RAMIF_Q.
Ltac formalize :=
match goal with
| |- @derives ?Pred _ ?g (?l * @allp ?Pred _ ?T ?Func) =>
let g' := fresh "g'" in evar (g': T -> Pred);
let l' := fresh "l'" in evar (l': T -> Pred);
let x := fresh "x" in
let H := fresh "H" in
assert (Func = l' -* g') as H;
[
extensionality x; cbv beta;
match goal with
| |- ?L' -* exp ?G' = _ =>
super_pattern L' x; super_pattern_in_func G' x
| |- ?L' -* ?G' = _ =>
super_pattern L' x; super_pattern G' x
end;
match goal with
| |- ?L' _ -* exp (fun a => ?G' a _) = _ =>
instantiate (1 := L') in (Value of l');
instantiate (1 := exp G') in (Value of g')
| |- ?L' _ -* ?G' _ = _ =>
instantiate (1 := L') in (Value of l');
instantiate (1 := G') in (Value of g')
end;
subst g' l';
reflexivity
| subst g' l'; rewrite H; clear H]
end.
End RAMIF_Q.
Module RAMIF_Q'.
Section RAMIF_Q'.
Context {A : Type}.
Context {ND : NatDed A}.
Context {SL : SepLog A}.
Context {CoSL: CorableSepLog A}.

(* Specifications: *)
Lemma reduce: forall {B} g l p (g' l': B -> A),
corable p ->
g |-- l * (allp (p --> (l' -* g'))) ->
g |-- l * (exp (p && l') -* exp (p && g')).
Lemma solve: forall {B} g l p g' l' F,
corable p ->
g |-- l * F ->
(forall x: B, (p x) && (F * l' x) |-- g' x) ->
g |-- l * (allp (p --> (l' -* g'))).
Lemma weak_ramif_spec: forall {B} g l p (g' l': B -> A),
g |-- l * allp (p --> l' -* g') -> g |-- l * TT.
Lemma plain_spec: forall {B} g l p g' l' (x: B),
corable p ->
g |-- p x ->
g |-- l * allp (p --> (l' -* g')) ->
g |-- l * (l' x -* g' x).
Lemma trans: forall {B BG BL} g m l p pG pL g' mG' mL' l' (fG: B -> BG) (fL: B -> BL),
corable p ->
corable pL ->
corable pG ->
g |-- m * allp (pG --> (mG' -* g')) ->
m |-- l * allp (pL --> (l' -* mL')) ->
(forall b, p b |-- pL (fL b)) ->
(forall b, p b && mL' (fL b) |-- pG (fG b) && mG' (fG b)) ->
g |-- l * allp (p --> (Basics.compose l' fL -* Basics.compose g' fG)).
Lemma split: forall {B} g1 g2 l1 l2 (p g1' g2' l1' l2': B -> A),
(forall x: B, corable (p x)) ->
g1 |-- l1 * allp (p --> (l1' -* g1')) ->
g2 |-- l2 * allp (p --> (l2' -* g2')) ->
g1 * g2 |-- (l1 * l2) * allp (p --> (l1' * l2' -* g1' * g2')).
(* Using split to prove frame will lead to a simpler proof. *)
(* But it requires a unitary separation logic.              *)
Lemma frame: forall {B} g l p g' l' F,
(forall x: B, corable (p x)) ->
g |-- l * allp (p --> (l' -* g')) ->
g * F |-- l * allp (p --> (l' -* g' * Basics.const F)).
Lemma frame_post: forall {B} g l (p g' l' F: B -> A),
(forall x: B, corable (p x)) ->
g |-- l * allp (p --> (l' -* g')) ->
g |-- l * allp (p --> (l' * F -* g' * F)).
Lemma frame_pre: forall {B} g l (p g' l': B -> A) F,
(forall x: B, corable (p x)) ->
g |-- l * allp (p --> (l' -* g')) ->
g * F |-- (l * F) * allp (p --> (l' -* g')).
Lemma exp_right: forall {T B} (a: B -> T) p g l (g': T -> B -> A) (l': B -> A),
corable p ->
g |-- l * allp (p --> (l' -* (fun b => g' (a b) b))) ->
g |-- l * allp (p --> (l' -* exp g')).