Lecture notes 20190604
More Semantics 5 Separation 1
Require Import Coq.Relations.Relation_Operators.
Require Import Coq.Relations.Relation_Definitions.
Require Export Coq.ZArith.ZArith.
Require Export Coq.Strings.String.
Require Export Coq.Logic.Classical.
Arguments clos_refl_trans {A} _ _ _.
Arguments clos_refl_trans_1n {A} _ _ _.
Arguments clos_refl_trans_n1 {A} _ _ _.
Open Scope Z.
Require Import Coq.Relations.Relation_Definitions.
Require Export Coq.ZArith.ZArith.
Require Export Coq.Strings.String.
Require Export Coq.Logic.Classical.
Arguments clos_refl_trans {A} _ _ _.
Arguments clos_refl_trans_1n {A} _ _ _.
Arguments clos_refl_trans_n1 {A} _ _ _.
Open Scope Z.
Definition var: Type := nat.
Inductive aexp : Type :=
| ANum (n : Z)
| AId (X : var)
| APlus (a1 a2 : aexp)
| AMinus (a1 a2 : aexp)
| AMult (a1 a2 : aexp)
| ADeref (a1: aexp) (* <-- new *)
| AAddr (a1: aexp). (* <-- new *)
Inductive bexp : Type :=
| BTrue
| BFalse
| BEq (a1 a2 : aexp)
| BLe (a1 a2 : aexp)
| BNot (b : bexp)
| BAnd (b1 b2 : bexp).
Inductive com : Type :=
| CSkip
| CAss (a1 a2 : aexp) (* <-- new *)
| CSeq (c1 c2 : com)
| CIf (b : bexp) (c1 c2 : com)
| CWhile (b : bexp) (c : com).
Definition var2addr (X: var): Z := Z.of_nat X + 1.
Definition state: Type := Z → option Z.
Inductive aevalR : aexp → state → Z → Prop :=
| E_ANum n st:
aevalR (ANum n) st n
| E_AId X st n:
st (var2addr X) = Some n →
aevalR (AId X) st n
| E_APlus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (APlus e1 e2) st (n1 + n2)
| E_AMinus (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMinus e1 e2) st (n1 - n2)
| E_AMult (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2) :
aevalR (AMult e1 e2) st (n1 * n2)
| E_ADeref (e1: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : st n1 = Some n2) :
aevalR (ADeref e1) st n2
| E_AAddre (e1: aexp) (n1: Z) st
(H1 : aevalL e1 st n1):
aevalR (AAddr e1) st n1
with aevalL : aexp → state → Z → Prop :=
| EL_AId X st:
aevalL (AId X) st (var2addr X)
| EL_ADeref (e1: aexp) (n1: Z) st
(H1 : aevalR e1 st n1) :
aevalL (ADeref e1) st n1.
Inductive beval : bexp → state → bool → Prop :=
| E_BTrue st:
beval BTrue st true
| E_BFalse st:
beval BFalse st false
| E_BEqTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 = n2) :
beval (BEq e1 e2) st true
| E_BEqFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≠ n2) :
beval (BEq e1 e2) st false
| E_BLeTrue (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 < n2) :
beval (BLe e1 e2) st true
| E_BLeFalse (e1 e2: aexp) (n1 n2: Z) st
(H1 : aevalR e1 st n1)
(H2 : aevalR e2 st n2)
(H3 : n1 ≥ n2) :
beval (BLe e1 e2) st false
| E_BNot (e: bexp) (b: bool) st
(H1 : beval e st b):
beval (BNot e) st (negb b)
| E_BAnd (e1 e2: bexp) (b1 b2: bool) st
(H1 : beval e1 st b1)
(H2 : beval e2 st b2):
beval (BAnd e1 e2) st (andb b1 b2).
Module Example.
The following statements are all straightforward if you know a little bit
about C programming. The point here is not to persuad yourself that they are
correct. It is rather important to see that we can formally prove them under
our definitions above. We suppose that X and Y are variable 0 and 1.
Definition X := 0%nat.
Definition Y := 1%nat.
Definition Y := 1%nat.
Suppose st is a program state such that the values stored on X and Y
are 100 and 99. Also, we assume that the value stored on address 99 and 100 are
both 0, and 0 is a null address.
Parameter st: state.
Hypothesis stX: st (var2addr X) = Some 100.
Hypothesis stY: st (var2addr Y) = Some 99.
Hypothesis st99: st 99 = Some 0.
Hypothesis st100: st 100 = Some 0.
Hypothesis st0: st 0 = None.
Hypothesis stX: st (var2addr X) = Some 100.
Hypothesis stY: st (var2addr Y) = Some 99.
Hypothesis st99: st 99 = Some 0.
Hypothesis st100: st 100 = Some 0.
Hypothesis st0: st 0 = None.
Here are two basic statements.
Fact ex1: aevalR (AId X) st 100.
Proof. apply E_AId. apply stX. Qed.
Fact ex2: aevalR (AId Y) st 99.
Proof. apply E_AId. apply stY. Qed.
Proof. apply E_AId. apply stX. Qed.
Fact ex2: aevalR (AId Y) st 99.
Proof. apply E_AId. apply stY. Qed.
The following statements talk about X and Y's address.
Fact ex3: aevalL (AId X) st 1.
Proof. apply EL_AId. Qed.
Fact ex4: aevalL (AId Y) st 2.
Proof. apply EL_AId. Qed.
Fact ex5: aevalR (AAddr (AId X)) st 1.
Proof. apply E_AAddre. apply EL_AId. Qed.
Fact ex6: aevalR (AAddr (AId Y)) st 2.
Proof. apply E_AAddre. apply EL_AId. Qed.
Proof. apply EL_AId. Qed.
Fact ex4: aevalL (AId Y) st 2.
Proof. apply EL_AId. Qed.
Fact ex5: aevalR (AAddr (AId X)) st 1.
Proof. apply E_AAddre. apply EL_AId. Qed.
Fact ex6: aevalR (AAddr (AId Y)) st 2.
Proof. apply E_AAddre. apply EL_AId. Qed.
We can also use the values stored in X and Y as addresses.
Fact ex7: aevalR (ADeref (AId X)) st 0. (* The value of expreesion * X. *)
Proof. eapply E_ADeref. apply E_AId. apply stX. apply st100. Qed.
Fact ex8: aevalR (ADeref (AId Y)) st 0. (* The value of expreesion * Y. *)
Proof. eapply E_ADeref. apply E_AId. apply stY. apply st99. Qed.
Proof. eapply E_ADeref. apply E_AId. apply stX. apply st100. Qed.
Fact ex8: aevalR (ADeref (AId Y)) st 0. (* The value of expreesion * Y. *)
Proof. eapply E_ADeref. apply E_AId. apply stY. apply st99. Qed.
It is not too weird to talk about dereference of dereference.
Fact ex9: ∀v, ¬aevalR (ADeref (ADeref (AId X))) st v.
(* The value of expreesion * * X. *)
Proof.
unfold not.
intros.
inversion H; subst.
inversion H0; subst.
inversion H3; subst.
rewrite stX in H5.
injection H5 as ?.
subst n0.
rewrite st100 in H4.
injection H4 as ?.
subst n1.
rewrite st0 in H2.
discriminate H2.
Qed.
End Example.
(* The value of expreesion * * X. *)
Proof.
unfold not.
intros.
inversion H; subst.
inversion H0; subst.
inversion H3; subst.
rewrite stX in H5.
injection H5 as ?.
subst n0.
rewrite st100 in H4.
injection H4 as ?.
subst n1.
rewrite st0 in H2.
discriminate H2.
Qed.
End Example.
Programs' Denotations
Inductive ceval : com → state → option state → Prop :=
| E_Skip st:
ceval CSkip st (Some st)
| E_AssSucc st1 st2 E E' n n' (* <-- new *)
(H1: aevalL E st1 n)
(H2: aevalR E' st1 n')
(H3: st1 n ≠ None)
(H4: st2 n = Some n')
(H5: ∀n'', n ≠ n'' → st1 n'' = st2 n''):
ceval (CAss E E') st1 (Some st2)
| E_AssFail1 st1 E E' (* <-- new *)
(H1: ∀n, ¬aevalL E st1 n):
ceval (CAss E E') st1 None
| E_AssFail2 st1 E E' (* <-- new *)
(H1: ∀n', ¬aevalR E' st1 n'):
ceval (CAss E E') st1 None
| E_AssFail3 st1 E E' n (* <-- new *)
(H1: aevalL E st1 n)
(H2: st1 n = None):
ceval (CAss E E') st1 None
| E_SeqSafe c1 c2 st st' o
(H1: ceval c1 st (Some st'))
(H2: ceval c2 st' o):
ceval (CSeq c1 c2) st o
| E_SeqCrush c1 c2 st
(H1: ceval c1 st None):
ceval (CSeq c1 c2) st None
| E_IfTrue st o b c1 c2
(H1: beval b st true)
(H2: ceval c1 st o):
ceval (CIf b c1 c2) st o
| E_IfFalse st o b c1 c2
(H1: beval b st false)
(H2: ceval c2 st o):
ceval (CIf b c1 c2) st o
| E_IfFail st b c1 c2
(H1: ¬beval b st true)
(H2: ¬beval b st false):
ceval (CIf b c1 c2) st None
| E_WhileFalse b st c
(H1: beval b st false):
ceval (CWhile b c) st (Some st)
| E_WhileTrue st o b c
(H1: beval b st true)
(H2: ceval (CSeq c (CWhile b c)) st o):
ceval (CWhile b c) st o
| E_WhileFail st b c
(H1: ¬beval b st true)
(H2: ¬beval b st false):
ceval (CWhile b c) st None.
| E_Skip st:
ceval CSkip st (Some st)
| E_AssSucc st1 st2 E E' n n' (* <-- new *)
(H1: aevalL E st1 n)
(H2: aevalR E' st1 n')
(H3: st1 n ≠ None)
(H4: st2 n = Some n')
(H5: ∀n'', n ≠ n'' → st1 n'' = st2 n''):
ceval (CAss E E') st1 (Some st2)
| E_AssFail1 st1 E E' (* <-- new *)
(H1: ∀n, ¬aevalL E st1 n):
ceval (CAss E E') st1 None
| E_AssFail2 st1 E E' (* <-- new *)
(H1: ∀n', ¬aevalR E' st1 n'):
ceval (CAss E E') st1 None
| E_AssFail3 st1 E E' n (* <-- new *)
(H1: aevalL E st1 n)
(H2: st1 n = None):
ceval (CAss E E') st1 None
| E_SeqSafe c1 c2 st st' o
(H1: ceval c1 st (Some st'))
(H2: ceval c2 st' o):
ceval (CSeq c1 c2) st o
| E_SeqCrush c1 c2 st
(H1: ceval c1 st None):
ceval (CSeq c1 c2) st None
| E_IfTrue st o b c1 c2
(H1: beval b st true)
(H2: ceval c1 st o):
ceval (CIf b c1 c2) st o
| E_IfFalse st o b c1 c2
(H1: beval b st false)
(H2: ceval c2 st o):
ceval (CIf b c1 c2) st o
| E_IfFail st b c1 c2
(H1: ¬beval b st true)
(H2: ¬beval b st false):
ceval (CIf b c1 c2) st None
| E_WhileFalse b st c
(H1: beval b st false):
ceval (CWhile b c) st (Some st)
| E_WhileTrue st o b c
(H1: beval b st true)
(H2: ceval (CSeq c (CWhile b c)) st o):
ceval (CWhile b c) st o
| E_WhileFail st b c
(H1: ¬beval b st true)
(H2: ¬beval b st false):
ceval (CWhile b c) st None.
Inductive aexp_halt: aexp → Prop :=
| AH_num : ∀n, aexp_halt (ANum n).
Inductive astepR : state → aexp → aexp → Prop :=
| ASR_Id : ∀st X n,
st (var2addr X) = Some n →
astepR st
(AId X) (ANum n)
| ASR_Plus1 : ∀st a1 a1' a2,
astepR st
a1 a1' →
astepR st
(APlus a1 a2) (APlus a1' a2)
| ASR_Plus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astepR st
a2 a2' →
astepR st
(APlus a1 a2) (APlus a1 a2')
| ASR_Plus : ∀st n1 n2,
astepR st
(APlus (ANum n1) (ANum n2)) (ANum (n1 + n2))
| ASR_Minus1 : ∀st a1 a1' a2,
astepR st
a1 a1' →
astepR st
(AMinus a1 a2) (AMinus a1' a2)
| ASR_Minus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astepR st
a2 a2' →
astepR st
(AMinus a1 a2) (AMinus a1 a2')
| ASR_Minus : ∀st n1 n2,
astepR st
(AMinus (ANum n1) (ANum n2)) (ANum (n1 - n2))
| ASR_Mult1 : ∀st a1 a1' a2,
astepR st
a1 a1' →
astepR st
(AMult a1 a2) (AMult a1' a2)
| ASR_Mult2 : ∀st a1 a2 a2',
aexp_halt a1 →
astepR st
a2 a2' →
astepR st
(AMult a1 a2) (AMult a1 a2')
| ASR_Mult : ∀st n1 n2,
astepR st
(AMult (ANum n1) (ANum n2)) (ANum (n1 * n2))
| ASR_DerefStep : ∀st a1 a1',
astepR st
a1 a1' →
astepR st
(ADeref a1) (ADeref a1')
| ASR_Deref : ∀st n n',
st n = Some n' →
astepR st
(ADeref (ANum n)) (ANum n')
| ASR_AddrStep : ∀st a1 a1',
astepL st
a1 a1' →
astepR st
(AAddr a1) (AAddr a1')
| ASR_Addr : ∀st n,
astepR st
(AAddr (ADeref (ANum n))) (ANum n)
with astepL : state → aexp → aexp → Prop :=
| ASL_Id: ∀st X,
astepL st
(AId X) (ADeref (ANum (var2addr X)))
| ASL_DerefStep: ∀st a1 a1',
astepR st
a1 a1' →
astepL st
(ADeref a1) (ADeref a1')
.
Inductive bstep : state → bexp → bexp → Prop :=
| BS_Eq1 : ∀st a1 a1' a2,
astepR st
a1 a1' →
bstep st
(BEq a1 a2) (BEq a1' a2)
| BS_Eq2 : ∀st a1 a2 a2',
aexp_halt a1 →
astepR st
a2 a2' →
bstep st
(BEq a1 a2) (BEq a1 a2')
| BS_Eq_True : ∀st n1 n2,
n1 = n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BTrue
| BS_Eq_False : ∀st n1 n2,
n1 ≠ n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BFalse
| BS_Le1 : ∀st a1 a1' a2,
astepR st
a1 a1' →
bstep st
(BLe a1 a2) (BLe a1' a2)
| BS_Le2 : ∀st a1 a2 a2',
aexp_halt a1 →
astepR st
a2 a2' →
bstep st
(BLe a1 a2) (BLe a1 a2')
| BS_Le_True : ∀st n1 n2,
n1 ≤ n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BTrue
| BS_Le_False : ∀st n1 n2,
n1 > n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BFalse
| BS_NotStep : ∀st b1 b1',
bstep st
b1 b1' →
bstep st
(BNot b1) (BNot b1')
| BS_NotTrue : ∀st,
bstep st
(BNot BTrue) BFalse
| BS_NotFalse : ∀st,
bstep st
(BNot BFalse) BTrue
| BS_AndStep : ∀st b1 b1' b2,
bstep st
b1 b1' →
bstep st
(BAnd b1 b2) (BAnd b1' b2)
| BS_AndTrue : ∀st b,
bstep st
(BAnd BTrue b) b
| BS_AndFalse : ∀st b,
bstep st
(BAnd BFalse b) BFalse.
Inductive cstep : (com * state) → (com * state) → Prop :=
| CS_AssStep1 st E1 E1' E2 (* <-- new *)
(H1: astepL st E1 E1'):
cstep (CAss E1 E2, st) (CAss E1' E2, st)
| CS_AssStep2 st n E2 E2' (* <-- new *)
(H1: astepR st E2 E2'):
cstep (CAss (ADeref (ANum n)) E2, st) (CAss (ADeref (ANum n)) E2', st)
| CS_Ass st1 st2 n1 n2 (* <-- new *)
(H1: st1 n1 ≠ None)
(H2: st2 n1 = Some n2)
(H3: ∀n, n1 ≠ n → st1 n = st2 n):
cstep (CAss (ADeref (ANum n1)) (ANum n2), st1) (CSkip, st2)
| CS_SeqStep st c1 c1' st' c2
(H1: cstep (c1, st) (c1', st')):
cstep (CSeq c1 c2 , st) (CSeq c1' c2, st')
| CS_Seq st c2:
cstep (CSeq CSkip c2, st) (c2, st)
| CS_IfStep st b b' c1 c2
(H1: bstep st b b'):
cstep (CIf b c1 c2, st) (CIf b' c1 c2, st)
| CS_IfTrue st c1 c2:
cstep (CIf BTrue c1 c2, st) (c1, st)
| CS_IfFalse st c1 c2:
cstep (CIf BFalse c1 c2, st) (c2, st)
| CS_While st b c:
cstep
(CWhile b c, st)
(CIf b (CSeq c (CWhile b c)) CSkip, st).
Advanced: Separation Logic
Module Separation_logic.
Definition logical_var: Type := nat.
Inductive aexp' : Type :=
| ANum' (t : term)
| AId' (X: var)
| APlus' (a1 a2 : aexp')
| AMinus' (a1 a2 : aexp')
| AMult' (a1 a2 : aexp')
| ADeref' (a1: aexp') (* <-- new *)
| AAddr' (a1: aexp') (* <-- new *)
with term : Type :=
| TNum (n : Z)
| TId (x: logical_var)
| TDenote (a : aexp')
| TPlus (t1 t2 : term)
| TMinus (t1 t2 : term)
| TMult (t1 t2 : term).
Inductive bexp' : Type :=
| BTrue'
| BFalse'
| BEq' (a1 a2 : aexp')
| BLe' (a1 a2 : aexp')
| BNot' (b : bexp')
| BAnd' (b1 b2 : bexp').
Coercion ANum' : term >-> aexp'.
Coercion AId' : var >-> aexp'.
Bind Scope vimp_scope with aexp'.
Bind Scope vimp_scope with bexp'.
Delimit Scope vimp_scope with vimp.
Notation "x + y" := (APlus' x y) (at level 50, left associativity) : vimp_scope.
Notation "x - y" := (AMinus' x y) (at level 50, left associativity) : vimp_scope.
Notation "x * y" := (AMult' x y) (at level 40, left associativity) : vimp_scope.
Notation "x ≤ y" := (BLe' x y) (at level 70, no associativity) : vimp_scope.
Notation "x == y" := (BEq' x y) (at level 70, no associativity) : vimp_scope.
Notation "x && y" := (BAnd' x y) (at level 40, left associativity) : vimp_scope.
Notation "'!' b" := (BNot' b) (at level 39, right associativity) : vimp_scope.
Coercion TNum : Z >-> term.
Coercion TId: logical_var >-> term.
Bind Scope term_scope with term.
Delimit Scope term_scope with term.
Notation "x + y" := (TPlus x y) (at level 50, left associativity) : term_scope.
Notation "x - y" := (TMinus x y) (at level 50, left associativity) : term_scope.
Notation "x * y" := (TMult x y) (at level 40, left associativity) : term_scope.
Notation "[[ a ]]" := (TDenote ((a)%vimp)) (at level 30, no associativity) : term_scope.
Definition logical_var: Type := nat.
Inductive aexp' : Type :=
| ANum' (t : term)
| AId' (X: var)
| APlus' (a1 a2 : aexp')
| AMinus' (a1 a2 : aexp')
| AMult' (a1 a2 : aexp')
| ADeref' (a1: aexp') (* <-- new *)
| AAddr' (a1: aexp') (* <-- new *)
with term : Type :=
| TNum (n : Z)
| TId (x: logical_var)
| TDenote (a : aexp')
| TPlus (t1 t2 : term)
| TMinus (t1 t2 : term)
| TMult (t1 t2 : term).
Inductive bexp' : Type :=
| BTrue'
| BFalse'
| BEq' (a1 a2 : aexp')
| BLe' (a1 a2 : aexp')
| BNot' (b : bexp')
| BAnd' (b1 b2 : bexp').
Coercion ANum' : term >-> aexp'.
Coercion AId' : var >-> aexp'.
Bind Scope vimp_scope with aexp'.
Bind Scope vimp_scope with bexp'.
Delimit Scope vimp_scope with vimp.
Notation "x + y" := (APlus' x y) (at level 50, left associativity) : vimp_scope.
Notation "x - y" := (AMinus' x y) (at level 50, left associativity) : vimp_scope.
Notation "x * y" := (AMult' x y) (at level 40, left associativity) : vimp_scope.
Notation "x ≤ y" := (BLe' x y) (at level 70, no associativity) : vimp_scope.
Notation "x == y" := (BEq' x y) (at level 70, no associativity) : vimp_scope.
Notation "x && y" := (BAnd' x y) (at level 40, left associativity) : vimp_scope.
Notation "'!' b" := (BNot' b) (at level 39, right associativity) : vimp_scope.
Coercion TNum : Z >-> term.
Coercion TId: logical_var >-> term.
Bind Scope term_scope with term.
Delimit Scope term_scope with term.
Notation "x + y" := (TPlus x y) (at level 50, left associativity) : term_scope.
Notation "x - y" := (TMinus x y) (at level 50, left associativity) : term_scope.
Notation "x * y" := (TMult x y) (at level 40, left associativity) : term_scope.
Notation "[[ a ]]" := (TDenote ((a)%vimp)) (at level 30, no associativity) : term_scope.
We choose not to create notations for ADeref' and AAddr'. Such that we
do not need to parse two differnt * and &.
Fixpoint ainj (a: aexp): aexp' :=
match a with
| ANum n ⇒ ANum' (TNum n)
| AId X ⇒ AId' X
| APlus a1 a2 ⇒ APlus' (ainj a1) (ainj a2)
| AMinus a1 a2 ⇒ AMinus' (ainj a1) (ainj a2)
| AMult a1 a2 ⇒ AMult' (ainj a1) (ainj a2)
| ADeref a1 ⇒ ADeref' (ainj a1)
| AAddr a1 ⇒ AAddr' (ainj a1)
end.
Fixpoint binj (b : bexp): bexp' :=
match b with
| BTrue ⇒ BTrue'
| BFalse ⇒ BFalse'
| BEq a1 a2 ⇒ BEq' (ainj a1) (ainj a2)
| BLe a1 a2 ⇒ BLe' (ainj a1) (ainj a2)
| BNot b1 ⇒ BNot' (binj b1)
| BAnd b1 b2 ⇒ BAnd' (binj b1) (binj b2)
end.
Coercion ainj: aexp >-> aexp'.
Coercion binj: bexp >-> bexp'.
Inductive Assertion : Type :=
| AssnLe (t1 t2 : term)
| AssnLt (t1 t2 : term)
| AssnEq (t1 t2 : term)
| AssnMapsto (t1 t2 : term) (* <-- new *)
| AssnSafeA (a: aexp') (* <-- new *)
| AssnSafeB (b: bexp') (* <-- new *)
| AssnDenote (b: bexp')
| AssnOr (P1 P2 : Assertion)
| AssnAnd (P1 P2 : Assertion)
| AssnImpl (P1 P2 : Assertion)
| AssnSep (P1 P2 : Assertion) (* <-- new *)
| AssnEmp (* <-- new *)
| AssnNot (P: Assertion)
| AssnExists (x: logical_var) (P: Assertion)
| AssnForall (x: logical_var) (P: Assertion).
Bind Scope assert_scope with Assertion.
Delimit Scope assert_scope with assert.
Notation "x ≤ y" := (AssnLe ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "x '<' y" := (AssnLt ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "x == y" := (AssnEq ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "[[ b ]]" := (AssnDenote ((b)%vimp)) (at level 30, no associativity) : assert_scope.
Notation "P1 'SEP' P2" := (AssnSep P1 P2) (at level 72, left associativity) : assert_scope.
Notation "P1 'OR' P2" := (AssnOr P1 P2) (at level 76, left associativity) : assert_scope.
Notation "P1 'AND' P2" := (AssnAnd P1 P2) (at level 74, left associativity) : assert_scope.
Notation "P1 'IMPLY' P2" := (AssnImpl P1 P2) (at level 74, left associativity) : assert_scope.
Notation "'NOT' P" := (AssnNot P) (at level 73, right associativity) : assert_scope.
Notation "'EXISTS' x ',' P " := (AssnExists x ((P)%assert)) (at level 77, right associativity) : assert_scope.
Notation "'FORALL' x ',' P " := (AssnForall x ((P)%assert)) (at level 77, right associativity) : assert_scope.
match a with
| ANum n ⇒ ANum' (TNum n)
| AId X ⇒ AId' X
| APlus a1 a2 ⇒ APlus' (ainj a1) (ainj a2)
| AMinus a1 a2 ⇒ AMinus' (ainj a1) (ainj a2)
| AMult a1 a2 ⇒ AMult' (ainj a1) (ainj a2)
| ADeref a1 ⇒ ADeref' (ainj a1)
| AAddr a1 ⇒ AAddr' (ainj a1)
end.
Fixpoint binj (b : bexp): bexp' :=
match b with
| BTrue ⇒ BTrue'
| BFalse ⇒ BFalse'
| BEq a1 a2 ⇒ BEq' (ainj a1) (ainj a2)
| BLe a1 a2 ⇒ BLe' (ainj a1) (ainj a2)
| BNot b1 ⇒ BNot' (binj b1)
| BAnd b1 b2 ⇒ BAnd' (binj b1) (binj b2)
end.
Coercion ainj: aexp >-> aexp'.
Coercion binj: bexp >-> bexp'.
Inductive Assertion : Type :=
| AssnLe (t1 t2 : term)
| AssnLt (t1 t2 : term)
| AssnEq (t1 t2 : term)
| AssnMapsto (t1 t2 : term) (* <-- new *)
| AssnSafeA (a: aexp') (* <-- new *)
| AssnSafeB (b: bexp') (* <-- new *)
| AssnDenote (b: bexp')
| AssnOr (P1 P2 : Assertion)
| AssnAnd (P1 P2 : Assertion)
| AssnImpl (P1 P2 : Assertion)
| AssnSep (P1 P2 : Assertion) (* <-- new *)
| AssnEmp (* <-- new *)
| AssnNot (P: Assertion)
| AssnExists (x: logical_var) (P: Assertion)
| AssnForall (x: logical_var) (P: Assertion).
Bind Scope assert_scope with Assertion.
Delimit Scope assert_scope with assert.
Notation "x ≤ y" := (AssnLe ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "x '<' y" := (AssnLt ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "x == y" := (AssnEq ((x)%term) ((y)%term)) (at level 70, no associativity) : assert_scope.
Notation "[[ b ]]" := (AssnDenote ((b)%vimp)) (at level 30, no associativity) : assert_scope.
Notation "P1 'SEP' P2" := (AssnSep P1 P2) (at level 72, left associativity) : assert_scope.
Notation "P1 'OR' P2" := (AssnOr P1 P2) (at level 76, left associativity) : assert_scope.
Notation "P1 'AND' P2" := (AssnAnd P1 P2) (at level 74, left associativity) : assert_scope.
Notation "P1 'IMPLY' P2" := (AssnImpl P1 P2) (at level 74, left associativity) : assert_scope.
Notation "'NOT' P" := (AssnNot P) (at level 73, right associativity) : assert_scope.
Notation "'EXISTS' x ',' P " := (AssnExists x ((P)%assert)) (at level 77, right associativity) : assert_scope.
Notation "'FORALL' x ',' P " := (AssnForall x ((P)%assert)) (at level 77, right associativity) : assert_scope.
Now, what we need is a new assignment rule:
{{ SafeA(AAddr E1) AND SafeA(E2) AND [[AAddr E1]] == V1 AND [[E2]] == V2 AND
Mapsto(V1, V) SEP P }}
E1 ::= E2
{{ Mapsto(V1, V2) SEP P }}
Adding all other Hoare logic proof rules together, it is enough to verify all
programs. However, the following proof rule is more important in separation logic:
Mapsto(V1, V) SEP P }}
E1 ::= E2
{{ Mapsto(V1, V2) SEP P }}
{{ P }} c {{ Q }}
-----------------------------
{{ P SEP F }} c {{ Q SEP F }}
It is called frame rule.
-----------------------------
{{ P SEP F }} c {{ Q SEP F }}
End Separation_logic.
(* Mon Jun 10 15:13:09 UTC 2019 *)
(* Mon Jun 10 15:13:09 UTC 2019 *)