2018-04-29 00:31:01 +00:00
|
|
|
(** Formal Reasoning About Programs <http://adam.chlipala.net/frap/>
|
|
|
|
* Chapter 15: Connecting to Real-World Programming Languages and Platforms
|
|
|
|
* Author: Adam Chlipala
|
|
|
|
* License: https://creativecommons.org/licenses/by-nc-nd/4.0/ *)
|
|
|
|
|
|
|
|
Require Import FrapWithoutSets SepCancel.
|
|
|
|
Require Import Arith.Div2.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Some odds and ends from past chapters *)
|
|
|
|
|
|
|
|
Notation "m $! k" := (match m $? k with Some n => n | None => O end) (at level 30).
|
|
|
|
|
|
|
|
Ltac simp := repeat (simplify; subst; propositional;
|
|
|
|
try match goal with
|
|
|
|
| [ H : ex _ |- _ ] => invert H
|
|
|
|
end); try linear_arithmetic.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Bitvectors of known length *)
|
|
|
|
|
|
|
|
Inductive word : nat -> Set :=
|
|
|
|
| WO : word O
|
|
|
|
| WS : bool -> forall {n}, word n -> word (S n).
|
|
|
|
|
|
|
|
Fixpoint wordToNat {sz} (w : word sz) : nat :=
|
|
|
|
match w with
|
|
|
|
| WO => O
|
|
|
|
| WS false w => 2 * wordToNat w
|
|
|
|
| WS true w => S (2 * wordToNat w)
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint mod2 (n : nat) : bool :=
|
|
|
|
match n with
|
|
|
|
| 0 => false
|
|
|
|
| 1 => true
|
|
|
|
| S (S n') => mod2 n'
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint natToWord (sz n : nat) : word sz :=
|
|
|
|
match sz with
|
|
|
|
| O => WO
|
|
|
|
| S sz' => WS (mod2 n) (natToWord sz' (div2 n))
|
|
|
|
end.
|
|
|
|
|
|
|
|
Definition wzero {sz} := natToWord sz 0.
|
|
|
|
Definition wone {sz} := natToWord sz 1.
|
|
|
|
Notation "^" := (natToWord _) (at level 0).
|
|
|
|
|
|
|
|
Definition wplus {sz} (w1 w2 : word sz) : word sz :=
|
|
|
|
natToWord sz (wordToNat w1 + wordToNat w2).
|
|
|
|
|
|
|
|
Infix "^+" := wplus (at level 50, left associativity).
|
|
|
|
|
|
|
|
Definition whd {sz} (w : word (S sz)) : bool :=
|
|
|
|
match w in word sz' return match sz' with
|
|
|
|
| O => unit
|
|
|
|
| S _ => bool
|
|
|
|
end with
|
|
|
|
| WO => tt
|
|
|
|
| WS b _ => b
|
|
|
|
end.
|
|
|
|
|
|
|
|
Definition wtl {sz} (w : word (S sz)) : word sz :=
|
|
|
|
match w in word sz' return match sz' with
|
|
|
|
| O => unit
|
|
|
|
| S sz'' => word sz''
|
|
|
|
end with
|
|
|
|
| WO => tt
|
|
|
|
| WS _ w' => w'
|
|
|
|
end.
|
|
|
|
|
|
|
|
Lemma shatter_word : forall {n} (a : word n),
|
|
|
|
match n return word n -> Prop with
|
|
|
|
| O => fun a => a = WO
|
|
|
|
| S _ => fun a => a = WS (whd a) (wtl a)
|
|
|
|
end a.
|
|
|
|
Proof.
|
|
|
|
destruct a; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma shatter_word_S : forall {n} (a : word (S n)),
|
|
|
|
exists b, exists c, a = WS b c.
|
|
|
|
Proof.
|
|
|
|
intros; repeat eexists; apply (shatter_word a).
|
|
|
|
Qed.
|
|
|
|
Lemma shatter_word_0 : forall a : word 0,
|
|
|
|
a = WO.
|
|
|
|
Proof.
|
|
|
|
intros; apply (shatter_word a).
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Hint Resolve shatter_word_0.
|
|
|
|
|
|
|
|
Require Import Coq.Logic.Eqdep_dec.
|
|
|
|
|
|
|
|
Definition weq : forall {sz} (x y : word sz), {x = y} + {x <> y}.
|
|
|
|
refine (fix weq sz (x : word sz) : forall y : word sz, {x = y} + {x <> y} :=
|
|
|
|
match x in word sz return forall y : word sz, {x = y} + {x <> y} with
|
|
|
|
| WO => fun _ => left _ _
|
|
|
|
| WS b x' => fun y => if bool_dec b (whd y)
|
|
|
|
then if weq _ x' (wtl y) then left _ _ else right _ _
|
|
|
|
else right _ _
|
|
|
|
end); clear weq.
|
|
|
|
|
|
|
|
symmetry; apply shatter_word_0.
|
|
|
|
|
|
|
|
subst; symmetry; apply (shatter_word y).
|
|
|
|
|
|
|
|
rewrite (shatter_word y); simpl; intro; injection H; intros;
|
|
|
|
apply n0; apply inj_pair2_eq_dec in H0; [ auto | apply eq_nat_dec ].
|
|
|
|
|
|
|
|
abstract (rewrite (shatter_word y); simpl; intro; apply n0; injection H; auto).
|
|
|
|
Defined.
|
|
|
|
|
|
|
|
|
|
|
|
(** * A simple C-like language with just two data types *)
|
|
|
|
|
|
|
|
Module Type BIT_WIDTH.
|
|
|
|
Parameter bit_width : nat.
|
|
|
|
End BIT_WIDTH.
|
|
|
|
|
|
|
|
Module DeeplyEmbedded(Import BW : BIT_WIDTH).
|
|
|
|
Definition wrd := word bit_width.
|
|
|
|
|
|
|
|
Inductive exp :=
|
|
|
|
| Var (x : var)
|
|
|
|
|
|
|
|
| Const (n : wrd)
|
|
|
|
| Add (x : var) (n : wrd)
|
|
|
|
|
|
|
|
| Head (x : var)
|
|
|
|
| Tail (x : var)
|
|
|
|
|
|
|
|
| NotNull (x : var).
|
|
|
|
|
|
|
|
Inductive stmt :=
|
|
|
|
| Skip
|
|
|
|
| Assign (x : var) (e : exp)
|
|
|
|
| WriteHead (x : var) (e : exp)
|
|
|
|
| WriteTail (x : var) (e : exp)
|
|
|
|
| Seq (s1 s2 : stmt)
|
|
|
|
| IfThenElse (e : exp) (s1 s2 : stmt)
|
|
|
|
| WhileLoop (e : exp) (s1 : stmt).
|
|
|
|
|
|
|
|
Inductive type :=
|
|
|
|
| Scalar
|
|
|
|
| ListPointer (t : type).
|
|
|
|
|
|
|
|
Definition type_eq : forall t1 t2 : type, {t1 = t2} + {t1 <> t2}.
|
|
|
|
decide equality.
|
|
|
|
Defined.
|
|
|
|
|
|
|
|
Record function := {
|
|
|
|
Params : list (var * type);
|
|
|
|
Locals : list (var * type);
|
|
|
|
Return : type;
|
|
|
|
Body : stmt
|
|
|
|
}.
|
|
|
|
|
|
|
|
Section fn.
|
|
|
|
Variable fn : function.
|
|
|
|
|
|
|
|
Definition vars := Params fn ++ Locals fn ++ [("result", Return fn)].
|
|
|
|
|
|
|
|
Fixpoint varType (x : var) (vs : list (var * type)) : option type :=
|
|
|
|
match vs with
|
|
|
|
| nil => None
|
|
|
|
| (y, t) :: vs' => if y ==v x then Some t else varType x vs'
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint expType (e : exp) : option type :=
|
|
|
|
match e with
|
|
|
|
| Var x => varType x vars
|
|
|
|
| Const _ => Some Scalar
|
|
|
|
| Add x _ => match varType x vars with
|
|
|
|
| Some Scalar => Some Scalar
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
| Head x => match varType x vars with
|
|
|
|
| Some (ListPointer t) => Some t
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
| Tail x => match varType x vars with
|
|
|
|
| Some (ListPointer t) => Some (ListPointer t)
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
| NotNull x => match varType x vars with
|
|
|
|
| Some (ListPointer _) => Some Scalar
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
end.
|
|
|
|
|
|
|
|
Fixpoint stmtWf (s : stmt) : bool :=
|
|
|
|
match s with
|
|
|
|
| Skip => true
|
|
|
|
| Assign x e => match varType x vars, expType e with
|
|
|
|
| Some t1, Some t2 =>
|
|
|
|
if type_eq t1 t2 then true else false
|
|
|
|
| _, _ => false
|
|
|
|
end
|
|
|
|
| WriteHead x e => match varType x vars, expType e with
|
|
|
|
| Some (ListPointer t1), Some t2 =>
|
|
|
|
if type_eq t1 t2 then true else false
|
|
|
|
| _, _ => false
|
|
|
|
end
|
|
|
|
| WriteTail x e => match varType x vars, expType e with
|
|
|
|
| Some (ListPointer t1), Some (ListPointer t2) =>
|
|
|
|
if type_eq t1 t2 then true else false
|
|
|
|
| _, _ => false
|
|
|
|
end
|
|
|
|
| Seq s1 s2 => stmtWf s1 && stmtWf s2
|
|
|
|
| IfThenElse e s1 s2 => match expType e with
|
|
|
|
| Some Scalar => stmtWf s1 && stmtWf s2
|
|
|
|
| _ => false
|
|
|
|
end
|
|
|
|
| WhileLoop e s1 => match expType e with
|
|
|
|
| Some Scalar => stmtWf s1
|
|
|
|
| _ => false
|
|
|
|
end
|
|
|
|
end.
|
|
|
|
|
|
|
|
Record functionWf : Prop := {
|
|
|
|
VarsOk : NoDup (map fst (Params fn ++ Locals fn));
|
|
|
|
BodyOk : stmtWf (Body fn) = true
|
|
|
|
}.
|
|
|
|
End fn.
|
|
|
|
|
|
|
|
Inductive value :=
|
|
|
|
| VScalar (n : wrd)
|
|
|
|
| VList (p : wrd).
|
|
|
|
|
|
|
|
Definition heap := fmap (wrd) (value * value).
|
|
|
|
Definition valuation := fmap var value.
|
|
|
|
|
|
|
|
Inductive eval : heap -> valuation -> exp -> value -> Prop :=
|
|
|
|
| VVar : forall H V x v,
|
|
|
|
V $? x = Some v
|
|
|
|
-> eval H V (Var x) v
|
|
|
|
| VConst : forall H V n,
|
|
|
|
eval H V (Const n) (VScalar n)
|
|
|
|
| VAdd : forall H V x n xn,
|
|
|
|
V $? x = Some (VScalar xn)
|
|
|
|
-> eval H V (Add x n) (VScalar (xn ^+ n))
|
|
|
|
| VHead : forall H V x p ph pt,
|
|
|
|
V $? x = Some (VList p)
|
|
|
|
-> H $? p = Some (ph, pt)
|
|
|
|
-> eval H V (Head x) ph
|
|
|
|
| VTail : forall H V x p ph pt,
|
|
|
|
V $? x = Some (VList p)
|
|
|
|
-> H $? p = Some (ph, pt)
|
|
|
|
-> eval H V (Tail x) pt
|
|
|
|
| VNotNull : forall H V x p,
|
|
|
|
V $? x = Some (VList p)
|
|
|
|
-> eval H V (NotNull x) (VScalar (if weq p (^0) then ^1 else ^0)).
|
|
|
|
|
|
|
|
Inductive step : heap * valuation * stmt -> heap * valuation * stmt -> Prop :=
|
|
|
|
| StAssign : forall H V x e v,
|
|
|
|
eval H V e v
|
|
|
|
-> step (H, V, Assign x e) (H, V $+ (x, v), Skip)
|
|
|
|
| StWriteHead : forall H V x e a v hv tv,
|
|
|
|
V $? x = Some (VList a)
|
|
|
|
-> eval H V e v
|
|
|
|
-> H $? a = Some (hv, tv)
|
|
|
|
-> step (H, V, WriteHead x e) (H $+ (a, (v, tv)), V, Skip)
|
|
|
|
| StWriteTail : forall H V x e a v hv tv,
|
|
|
|
V $? x = Some (VList a)
|
|
|
|
-> eval H V e v
|
|
|
|
-> H $? a = Some (hv, tv)
|
|
|
|
-> step (H, V, WriteTail x e) (H $+ (a, (hv, v)), V, Skip)
|
|
|
|
| StSeq1 : forall H V s2,
|
|
|
|
step (H, V, Seq Skip s2) (H, V, s2)
|
|
|
|
| StSeq2 : forall H V s1 s2 H' V' s1',
|
|
|
|
step (H, V, s1) (H', V', s1')
|
|
|
|
-> step (H, V, Seq s1 s2) (H', V', Seq s1' s2)
|
|
|
|
| StIfThen : forall H V e s1 s2 n,
|
|
|
|
eval H V e (VScalar n)
|
|
|
|
-> n <> ^0
|
|
|
|
-> step (H, V, IfThenElse e s1 s2) (H, V, s1)
|
|
|
|
| StIfElse : forall H V e s1 s2,
|
|
|
|
eval H V e (VScalar (^0))
|
|
|
|
-> step (H, V, IfThenElse e s1 s2) (H, V, s2)
|
|
|
|
| StWhileTrue : forall H V e s1 n,
|
|
|
|
eval H V e (VScalar n)
|
|
|
|
-> n <> ^0
|
|
|
|
-> step (H, V, WhileLoop e s1) (H, V, Seq s1 (WhileLoop e s1))
|
|
|
|
| StWhileFalse : forall H V e s1,
|
|
|
|
eval H V e (VScalar (^0))
|
|
|
|
-> step (H, V, WhileLoop e s1) (H, V, Skip).
|
|
|
|
|
|
|
|
|
|
|
|
(** * Separation logic for our language *)
|
|
|
|
|
|
|
|
Module Import S <: SEP.
|
|
|
|
Definition hprop := heap -> Prop.
|
|
|
|
|
|
|
|
Definition himp (p q : hprop) := forall h, p h -> q h.
|
|
|
|
Definition heq (p q : hprop) := forall h, p h <-> q h.
|
|
|
|
|
|
|
|
Definition lift (P : Prop) : hprop :=
|
|
|
|
fun h => P /\ h = $0.
|
|
|
|
|
|
|
|
Definition star (p q : hprop) : hprop :=
|
|
|
|
fun h => exists h1 h2, split h h1 h2 /\ disjoint h1 h2 /\ p h1 /\ q h2.
|
|
|
|
|
|
|
|
Definition exis {A} (p : A -> hprop) : hprop :=
|
|
|
|
fun h => exists x, p x h.
|
|
|
|
|
|
|
|
Notation "[| P |]" := (lift P) : sep_scope.
|
|
|
|
Infix "*" := star : sep_scope.
|
|
|
|
Notation "'exists' x .. y , p" := (exis (fun x => .. (exis (fun y => p)) ..)) : sep_scope.
|
|
|
|
Delimit Scope sep_scope with sep.
|
|
|
|
Notation "p === q" := (heq p%sep q%sep) (no associativity, at level 70).
|
|
|
|
Notation "p ===> q" := (himp p%sep q%sep) (no associativity, at level 70).
|
|
|
|
|
|
|
|
Local Open Scope sep_scope.
|
|
|
|
|
|
|
|
Lemma iff_two : forall A (P Q : A -> Prop),
|
|
|
|
(forall x, P x <-> Q x)
|
|
|
|
-> (forall x, P x -> Q x) /\ (forall x, Q x -> P x).
|
|
|
|
Proof.
|
|
|
|
firstorder.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Local Ltac t := (unfold himp, heq, lift, star, exis; propositional; subst);
|
|
|
|
repeat (match goal with
|
|
|
|
| [ H : forall x, _ <-> _ |- _ ] =>
|
|
|
|
apply iff_two in H
|
|
|
|
| [ H : ex _ |- _ ] => cases H
|
|
|
|
| [ H : split _ _ $0 |- _ ] => apply split_empty_fwd in H
|
|
|
|
end; propositional; subst); eauto 15.
|
|
|
|
|
|
|
|
Theorem himp_heq : forall p q, p === q
|
|
|
|
<-> (p ===> q /\ q ===> p).
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem himp_refl : forall p, p ===> p.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem himp_trans : forall p q r, p ===> q -> q ===> r -> p ===> r.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem lift_left : forall p (Q : Prop) r,
|
|
|
|
(Q -> p ===> r)
|
|
|
|
-> p * [| Q |] ===> r.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem lift_right : forall p q (R : Prop),
|
|
|
|
p ===> q
|
|
|
|
-> R
|
|
|
|
-> p ===> q * [| R |].
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Hint Resolve split_empty_bwd'.
|
|
|
|
|
|
|
|
Theorem extra_lift : forall (P : Prop) p,
|
|
|
|
P
|
|
|
|
-> p === [| P |] * p.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
apply split_empty_fwd' in H1; subst; auto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem star_comm : forall p q, p * q === q * p.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem star_assoc : forall p q r, p * (q * r) === (p * q) * r.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem star_cancel : forall p1 p2 q1 q2, p1 ===> p2
|
|
|
|
-> q1 ===> q2
|
|
|
|
-> p1 * q1 ===> p2 * q2.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem exis_gulp : forall A p (q : A -> _),
|
|
|
|
p * exis q === exis (fun x => p * q x).
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem exis_left : forall A (p : A -> _) q,
|
|
|
|
(forall x, p x ===> q)
|
|
|
|
-> exis p ===> q.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem exis_right : forall A p (q : A -> _) x,
|
|
|
|
p ===> q x
|
|
|
|
-> p ===> exis q.
|
|
|
|
Proof.
|
|
|
|
t.
|
|
|
|
Qed.
|
|
|
|
End S.
|
|
|
|
|
|
|
|
Export S.
|
|
|
|
Module Import Se := SepCancel.Make(S).
|
|
|
|
|
|
|
|
Definition heap1 (a : wrd) (p : value * value) : heap := $0 $+ (a, p).
|
|
|
|
Definition ptsto (a : wrd) (p : value * value) : hprop :=
|
|
|
|
fun h => h = heap1 a p.
|
|
|
|
|
|
|
|
(* Helpful notations, some the same as above *)
|
|
|
|
Notation "[| P |]" := (lift P) : sep_scope.
|
|
|
|
Notation emp := (lift True).
|
|
|
|
Infix "*" := star : sep_scope.
|
|
|
|
Notation "'exists' x .. y , p" := (exis (fun x => .. (exis (fun y => p)) ..)) : sep_scope.
|
|
|
|
Delimit Scope sep_scope with sep.
|
|
|
|
Notation "p === q" := (heq p%sep q%sep) (no associativity, at level 70).
|
|
|
|
Notation "p ===> q" := (himp p%sep q%sep) (no associativity, at level 70).
|
|
|
|
Infix "|->" := ptsto (at level 30) : sep_scope.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Finally, the Hoare logic *)
|
|
|
|
|
|
|
|
Definition hassert := valuation -> hprop.
|
|
|
|
|
|
|
|
Inductive hoare_triple_exp : hassert -> exp -> (value -> hassert) -> Prop :=
|
|
|
|
| HtVar : forall x,
|
|
|
|
hoare_triple_exp (fun V => exists v, [| V $? x = Some v |])%sep
|
|
|
|
(Var x)
|
|
|
|
(fun r V => [| V $? x = Some r |])%sep
|
|
|
|
| HtConst : forall n,
|
|
|
|
hoare_triple_exp (fun _ => emp)%sep
|
|
|
|
(Const n)
|
|
|
|
(fun r _ => [| r = VScalar n |])%sep
|
|
|
|
| HtAdd : forall x n,
|
|
|
|
hoare_triple_exp (fun V => exists xn, [| V $? x = Some (VScalar xn) |])%sep
|
|
|
|
(Add x n)
|
|
|
|
(fun r V => exists xn, [| V $? x = Some (VScalar xn) |]
|
|
|
|
* [| r = VScalar (xn ^+ n) |])%sep
|
|
|
|
| HtHead : forall R x,
|
|
|
|
hoare_triple_exp (fun V => exists a, [| V $? x = Some (VList a) |]
|
|
|
|
* exists p, a |-> p * R p)%sep
|
|
|
|
(Head x)
|
|
|
|
(fun r V => exists a, [| V $? x = Some (VList a) |]
|
|
|
|
* exists vt, a |-> (r, vt) * R (r, vt))%sep
|
|
|
|
| HtTail : forall R x,
|
|
|
|
hoare_triple_exp (fun V => exists a, [| V $? x = Some (VList a) |]
|
|
|
|
* exists p, a |-> p * R p)%sep
|
|
|
|
(Tail x)
|
|
|
|
(fun r V => exists a, [| V $? x = Some (VList a) |]
|
|
|
|
* exists vh, a |-> (vh, r) * R (vh, r))%sep
|
|
|
|
| HtNotNull : forall x,
|
|
|
|
hoare_triple_exp (fun V => exists a, [| V $? x = Some (VList a) |])%sep
|
|
|
|
(NotNull x)
|
|
|
|
(fun r V => exists a, [| V $? x = Some (VList a) |]
|
|
|
|
* [| r = VScalar (if weq a (^0) then ^1 else ^0) |])%sep
|
|
|
|
| HtExpConsequence : forall P e Q P' Q',
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> (forall V, P' V ===> P V)
|
|
|
|
-> (forall r V, Q r V ===> Q' r V)
|
|
|
|
-> hoare_triple_exp P' e Q'
|
|
|
|
| HtExpFrame : forall P e Q R,
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> hoare_triple_exp (fun V => P V * R V)%sep e (fun r V => Q r V * R V)%sep.
|
|
|
|
|
|
|
|
Fixpoint couldChange (s : stmt) (x : var) : bool :=
|
|
|
|
match s with
|
|
|
|
| Skip => false
|
|
|
|
| Assign y _ => if y ==v x then true else false
|
|
|
|
| WriteHead _ _
|
|
|
|
| WriteTail _ _ => false
|
|
|
|
| Seq s1 s2 => couldChange s1 x || couldChange s2 x
|
|
|
|
| IfThenElse _ s1 s2 => couldChange s1 x || couldChange s2 x
|
|
|
|
| WhileLoop _ s1 => couldChange s1 x
|
|
|
|
end.
|
|
|
|
|
|
|
|
Inductive hoare_triple : hassert -> stmt -> hassert -> Prop :=
|
|
|
|
| HtSkip : forall P,
|
|
|
|
hoare_triple P Skip P
|
|
|
|
| HtAssign : forall P x e Q,
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> hoare_triple P (Assign x e) (fun V => exists V' r, Q r V' * [| V = V' $+ (x, r) |])%sep
|
|
|
|
| HtWriteHead : forall P x e R,
|
|
|
|
hoare_triple_exp P e (fun r V => exists a, [| V $? x = Some (VList a) |] * exists vhd vtl, a |-> (vhd, vtl) * R r vhd vtl V)%sep
|
|
|
|
-> hoare_triple P
|
|
|
|
(WriteHead x e)
|
|
|
|
(fun V => exists a, [| V $? x = Some (VList a) |] * exists r vhd vtl, a |-> (r, vtl) * R r vhd vtl V)%sep
|
|
|
|
| HtWriteTail : forall P x e R,
|
|
|
|
hoare_triple_exp P e (fun r V => exists a, [| V $? x = Some (VList a) |] * exists vhd vtl, a |-> (vhd, vtl) * R r vhd vtl V)%sep
|
|
|
|
-> hoare_triple P
|
|
|
|
(WriteTail x e)
|
|
|
|
(fun V => exists a, [| V $? x = Some (VList a) |] * exists r vhd vtl, a |-> (vhd, r) * R r vhd vtl V)%sep
|
|
|
|
| HtSeq : forall P s1 Q s2 R,
|
|
|
|
hoare_triple P s1 Q
|
|
|
|
-> hoare_triple Q s2 R
|
|
|
|
-> hoare_triple P (Seq s1 s2) R
|
|
|
|
| HtIfThenElse : forall P e s1 s2 Q R,
|
2018-04-29 01:23:41 +00:00
|
|
|
hoare_triple_exp P e (fun r V => Q r V * exists n, [| r = VScalar n |])%sep
|
2018-04-29 00:31:01 +00:00
|
|
|
-> hoare_triple (fun V => exists n, Q (VScalar n) V * [| n <> ^0 |])%sep s1 R
|
|
|
|
-> hoare_triple (fun V => Q (VScalar (^0)) V)%sep s2 R
|
|
|
|
-> hoare_triple P (IfThenElse e s1 s2) R
|
|
|
|
| HtWhileLoop : forall I e s1 Q,
|
2018-04-29 01:23:41 +00:00
|
|
|
hoare_triple_exp I e (fun r V => Q r V * exists n, [| r = VScalar n |])%sep
|
2018-04-29 00:31:01 +00:00
|
|
|
-> hoare_triple (fun V => exists n, Q (VScalar n) V * [| n <> ^0 |])%sep s1 I
|
|
|
|
-> hoare_triple I (WhileLoop e s1) (Q (VScalar (^0)))
|
|
|
|
| HtConsequence : forall P s Q P' Q',
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> (forall V, P' V ===> P V)
|
|
|
|
-> (forall V, Q V ===> Q' V)
|
|
|
|
-> hoare_triple P' s Q'
|
|
|
|
| HtFrame : forall P s Q R,
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> (forall V1 V2, (forall x, couldChange s x = false
|
|
|
|
-> V1 $? x = V2 $? x)
|
|
|
|
-> R V1 = R V2)
|
|
|
|
-> hoare_triple (fun V => P V * R V)%sep s (fun V => Q V * R V)%sep.
|
|
|
|
|
|
|
|
Notation "{{ V1 ~> P }} c {{ V2 ~> Q }}" :=
|
|
|
|
(hoare_triple (fun V1 => P%sep) c (fun V2 => Q%sep)) (at level 90, c at next level).
|
|
|
|
|
|
|
|
Lemma HtStrengthen : forall P s Q Q',
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> (forall V, Q V ===> Q' V)
|
|
|
|
-> hoare_triple P s Q'.
|
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma HtWeaken : forall P s Q P',
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> (forall V, P' V ===> P V)
|
|
|
|
-> hoare_triple P' s Q.
|
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Definition trsys_of (H : heap) (V : valuation) (s : stmt) := {|
|
|
|
|
Initial := constant [(H, V, s)];
|
|
|
|
Step := step
|
|
|
|
|}.
|
|
|
|
|
|
|
|
Hint Constructors hoare_triple_exp hoare_triple eval step.
|
|
|
|
|
|
|
|
Lemma eval_subheap : forall H V e r,
|
|
|
|
eval H V e r
|
|
|
|
-> forall H', (forall a v, H $? a = Some v -> H' $? a = Some v)
|
|
|
|
-> eval H' V e r.
|
|
|
|
Proof.
|
|
|
|
invert 1; simplify; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma drop_cells : forall P e Q,
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> forall V H r, eval H V e r
|
|
|
|
-> forall H', P V H'
|
|
|
|
-> (forall a v, H' $? a = Some v -> H $? a = Some v)
|
|
|
|
-> eval H' V e r.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify.
|
|
|
|
|
|
|
|
invert H0; auto.
|
|
|
|
|
|
|
|
invert H0; auto.
|
|
|
|
|
|
|
|
invert H0; auto.
|
|
|
|
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
invert H0; simp.
|
|
|
|
invert H3.
|
|
|
|
apply split_empty_fwd' in H1; subst.
|
|
|
|
invert H6.
|
|
|
|
invert H1; simp.
|
|
|
|
econstructor.
|
|
|
|
eassumption.
|
|
|
|
cases (x2 $? x0).
|
|
|
|
apply H2 in Heq.
|
|
|
|
replace p0 with (r, pt) by equality.
|
|
|
|
eauto.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
unfold ptsto in H6; subst.
|
|
|
|
unfold heap1 in Heq.
|
|
|
|
rewrite lookup_join1 in Heq by (simplify; sets).
|
|
|
|
simplify; equality.
|
|
|
|
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
invert H0; simp.
|
|
|
|
invert H3.
|
|
|
|
apply split_empty_fwd' in H1; subst.
|
|
|
|
invert H6.
|
|
|
|
invert H1; simp.
|
|
|
|
econstructor.
|
|
|
|
eassumption.
|
|
|
|
cases (x2 $? x0).
|
|
|
|
apply H2 in Heq.
|
|
|
|
replace p0 with (ph, r) by equality.
|
|
|
|
eauto.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
unfold ptsto in H6; subst.
|
|
|
|
unfold heap1 in Heq.
|
|
|
|
rewrite lookup_join1 in Heq by (simplify; sets).
|
|
|
|
simplify; equality.
|
|
|
|
|
|
|
|
invert H0; auto.
|
|
|
|
|
|
|
|
eapply IHhoare_triple_exp; eauto.
|
|
|
|
apply H0; auto.
|
|
|
|
|
|
|
|
invert H2; simp.
|
|
|
|
eapply IHhoare_triple_exp in H1.
|
|
|
|
2: eauto.
|
|
|
|
eapply eval_subheap; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold split in H4; subst.
|
|
|
|
rewrite lookup_join1 by eauto using lookup_Some_dom.
|
|
|
|
auto.
|
|
|
|
simplify.
|
|
|
|
unfold split in H4; subst.
|
|
|
|
apply H3.
|
|
|
|
rewrite lookup_join1 by eauto using lookup_Some_dom.
|
|
|
|
auto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma preservation_exp : forall P e Q,
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> forall V H r, P V H -> eval H V e r -> Q r V H.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
cases H0.
|
|
|
|
cases H0.
|
|
|
|
constructor; assumption.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
invert H0.
|
|
|
|
constructor; reflexivity.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
eexists.
|
|
|
|
exists $0, $0; propositional; eauto.
|
|
|
|
constructor; eauto.
|
|
|
|
constructor; equality.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
simp.
|
|
|
|
invert H2.
|
|
|
|
invert H5.
|
|
|
|
cases x1.
|
|
|
|
replace r with v.
|
|
|
|
exists x0.
|
|
|
|
exists $0, H; propositional; eauto.
|
|
|
|
constructor; auto.
|
|
|
|
exists v0.
|
|
|
|
apply split_empty_fwd' in H0; equality.
|
|
|
|
invert H2; simp.
|
|
|
|
unfold split in H5; subst.
|
|
|
|
unfold ptsto in H6; subst.
|
|
|
|
apply split_empty_fwd' in H0; subst.
|
|
|
|
replace x0 with p in * by equality.
|
|
|
|
unfold heap1 in H7.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1 in H7.
|
|
|
|
simplify; equality.
|
|
|
|
simplify; sets.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
simp.
|
|
|
|
invert H2.
|
|
|
|
invert H5.
|
|
|
|
cases x1.
|
|
|
|
replace r with v0.
|
|
|
|
exists x0.
|
|
|
|
exists $0, H; propositional; eauto.
|
|
|
|
constructor; auto.
|
|
|
|
exists v.
|
|
|
|
apply split_empty_fwd' in H0; equality.
|
|
|
|
invert H2; simp.
|
|
|
|
unfold split in H5; subst.
|
|
|
|
unfold ptsto in H6; subst.
|
|
|
|
apply split_empty_fwd' in H0; subst.
|
|
|
|
replace x0 with p in * by equality.
|
|
|
|
unfold heap1 in H7.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1 in H7.
|
|
|
|
simplify; equality.
|
|
|
|
simplify; sets.
|
|
|
|
|
|
|
|
invert H1.
|
|
|
|
invert H0.
|
|
|
|
invert H1.
|
|
|
|
exists p, $0, $0; propositional; eauto.
|
|
|
|
constructor; auto.
|
|
|
|
constructor; auto.
|
|
|
|
|
|
|
|
unfold himp in *; eauto.
|
|
|
|
|
|
|
|
invert H1; simp.
|
|
|
|
exists x, x0; propositional; eauto.
|
|
|
|
eapply IHhoare_triple_exp; eauto.
|
|
|
|
eapply drop_cells; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
rewrite lookup_join1 by eauto using lookup_Some_dom.
|
|
|
|
auto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Opaque heq himp lift star exis ptsto.
|
|
|
|
|
|
|
|
Lemma invert_Assign : forall P x e Q,
|
|
|
|
hoare_triple P (Assign x e) Q
|
|
|
|
-> exists Q', hoare_triple_exp P e Q'
|
|
|
|
/\ forall V r, Q' r V ===> Q (V $+ (x, r)).
|
|
|
|
Proof.
|
|
|
|
induct 1; propositional; eauto.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eassumption.
|
|
|
|
simplify.
|
|
|
|
do 2 eapply exis_right.
|
|
|
|
cancel.
|
|
|
|
|
|
|
|
first_order.
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtExpConsequence.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
|
|
|
reflexivity.
|
|
|
|
etransitivity; eauto.
|
|
|
|
|
|
|
|
first_order.
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtExpFrame.
|
|
|
|
eassumption.
|
|
|
|
simplify.
|
|
|
|
rewrite H0 with (V1 := V) (V2 := V $+ (x, r)).
|
|
|
|
rewrite H2.
|
|
|
|
reflexivity.
|
|
|
|
simplify.
|
|
|
|
cases (x ==v x1); simplify; equality.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_WriteHead : forall P x e Q,
|
|
|
|
hoare_triple P (WriteHead x e) Q
|
|
|
|
-> exists R, hoare_triple_exp P e (fun r V => exists a, [| V $? x = Some (VList a) |] * exists vhd vtl, a |-> (vhd, vtl) * R r vhd vtl V)%sep
|
|
|
|
/\ (forall V, (exists a, [| V $? x = Some (VList a) |] * exists r vhd vtl, a |-> (r, vtl) * R r vhd vtl V) ===> Q V).
|
|
|
|
Proof.
|
|
|
|
induct 1; first_order; eauto.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eassumption.
|
|
|
|
reflexivity.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtExpConsequence.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
|
|
|
simplify.
|
|
|
|
reflexivity.
|
|
|
|
etransitivity; eauto.
|
|
|
|
|
|
|
|
exists (fun r vhd vtl V => x0 r vhd vtl V * R V)%sep.
|
|
|
|
propositional.
|
|
|
|
eapply HtExpConsequence with (Q := fun r V =>
|
|
|
|
((exists a, [|V $? x = Some (VList a)|]
|
|
|
|
* exists vhd vtl, a |-> (vhd, vtl) * x0 r vhd vtl V) * R V)%sep).
|
|
|
|
eapply HtExpFrame.
|
|
|
|
eassumption.
|
|
|
|
reflexivity.
|
|
|
|
cancel.
|
|
|
|
rewrite <- H2.
|
|
|
|
cancel.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_WriteTail : forall P x e Q,
|
|
|
|
hoare_triple P (WriteTail x e) Q
|
|
|
|
-> exists R, hoare_triple_exp P e (fun r V => exists a, [| V $? x = Some (VList a) |] * exists vhd vtl, a |-> (vhd, vtl) * R r vhd vtl V)%sep
|
|
|
|
/\ (forall V, (exists a, [| V $? x = Some (VList a) |] * exists r vhd vtl, a |-> (vhd, r) * R r vhd vtl V) ===> Q V).
|
|
|
|
Proof.
|
|
|
|
induct 1; first_order; eauto.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eassumption.
|
|
|
|
reflexivity.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtExpConsequence.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
|
|
|
simplify.
|
|
|
|
reflexivity.
|
|
|
|
etransitivity; eauto.
|
|
|
|
|
|
|
|
exists (fun r vhd vtl V => x0 r vhd vtl V * R V)%sep.
|
|
|
|
propositional.
|
|
|
|
eapply HtExpConsequence with (Q := fun r V =>
|
|
|
|
((exists a, [|V $? x = Some (VList a)|]
|
|
|
|
* exists vhd vtl, a |-> (vhd, vtl) * x0 r vhd vtl V) * R V)%sep).
|
|
|
|
eapply HtExpFrame.
|
|
|
|
eassumption.
|
|
|
|
reflexivity.
|
|
|
|
cancel.
|
|
|
|
rewrite <- H2.
|
|
|
|
cancel.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_Skip : forall P Q,
|
|
|
|
hoare_triple P Skip Q
|
|
|
|
-> forall V, P V ===> Q V.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify.
|
|
|
|
|
|
|
|
reflexivity.
|
|
|
|
|
|
|
|
do 2 (etransitivity; eauto).
|
|
|
|
|
|
|
|
rewrite IHhoare_triple.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_Seq : forall P s1 s2 Q,
|
|
|
|
hoare_triple P (Seq s1 s2) Q
|
|
|
|
-> exists R, hoare_triple P s1 R
|
|
|
|
/\ hoare_triple R s2 Q.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify; first_order.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtConsequence; eauto; reflexivity.
|
|
|
|
eapply HtConsequence; eauto; reflexivity.
|
|
|
|
|
|
|
|
do 2 eexists.
|
|
|
|
eapply HtFrame; eauto.
|
|
|
|
simplify.
|
|
|
|
apply H0.
|
|
|
|
simplify.
|
|
|
|
apply orb_false_elim in H4; propositional; eauto.
|
|
|
|
eapply HtFrame; eauto.
|
|
|
|
simplify.
|
|
|
|
apply H0.
|
|
|
|
simplify.
|
|
|
|
apply orb_false_elim in H4; propositional; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_IfThenElse : forall P e s1 s2 Q,
|
|
|
|
hoare_triple P (IfThenElse e s1 s2) Q
|
2018-04-29 01:23:41 +00:00
|
|
|
-> exists R, hoare_triple_exp P e (fun r V => R r V * exists n, [| r = VScalar n |])%sep
|
2018-04-29 00:31:01 +00:00
|
|
|
/\ hoare_triple (fun V => exists n, R (VScalar n) V * [| n <> ^0 |])%sep s1 Q
|
|
|
|
/\ hoare_triple (fun V => R (VScalar (^0)) V)%sep s2 Q.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify; first_order.
|
|
|
|
|
|
|
|
eexists; propositional.
|
|
|
|
eapply HtExpConsequence.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
2018-04-29 01:23:41 +00:00
|
|
|
simplify.
|
2018-04-29 00:31:01 +00:00
|
|
|
reflexivity.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
eassumption.
|
|
|
|
assumption.
|
|
|
|
|
|
|
|
exists (fun r V => x r V * R V)%sep; propositional.
|
2018-04-29 01:23:41 +00:00
|
|
|
eapply HtExpConsequence.
|
|
|
|
eapply HtExpFrame.
|
|
|
|
eauto.
|
|
|
|
simplify.
|
|
|
|
reflexivity.
|
|
|
|
simplify.
|
|
|
|
cancel.
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
|
|
|
eapply HtWeaken.
|
|
|
|
eapply HtFrame.
|
|
|
|
eassumption.
|
|
|
|
simplify.
|
|
|
|
apply H0.
|
|
|
|
simplify.
|
|
|
|
apply orb_false_elim in H5; propositional; eauto.
|
|
|
|
simplify.
|
|
|
|
cancel.
|
|
|
|
eapply HtFrame.
|
|
|
|
assumption.
|
|
|
|
simplify.
|
|
|
|
apply H0.
|
|
|
|
simplify.
|
|
|
|
apply orb_false_elim in H5; propositional; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma invert_WhileLoop : forall P e s1 Q,
|
|
|
|
hoare_triple P (WhileLoop e s1) Q
|
|
|
|
-> exists I R, (forall V, P V ===> I V)
|
2018-04-29 01:23:41 +00:00
|
|
|
/\ hoare_triple_exp I e (fun r V => R r V * exists n, [| r = VScalar n |])%sep
|
2018-04-29 00:31:01 +00:00
|
|
|
/\ hoare_triple (fun V => exists n, R (VScalar n) V * [| n <> ^0 |])%sep s1 I
|
|
|
|
/\ (forall V, R (VScalar (^0)) V ===> Q V).
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify; first_order.
|
|
|
|
|
|
|
|
do 2 eexists; propositional; eauto; reflexivity.
|
|
|
|
|
|
|
|
exists x, x0; propositional.
|
|
|
|
etransitivity; eauto.
|
|
|
|
etransitivity; eauto.
|
|
|
|
|
|
|
|
exists (fun V => x V * R V)%sep, (fun r V => x0 r V * R V)%sep; propositional.
|
|
|
|
rewrite H1; reflexivity.
|
2018-04-29 01:23:41 +00:00
|
|
|
eapply HtExpConsequence.
|
|
|
|
eapply HtExpFrame.
|
|
|
|
eauto.
|
|
|
|
simplify.
|
|
|
|
reflexivity.
|
|
|
|
simplify.
|
|
|
|
cancel.
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
|
|
|
eapply HtWeaken.
|
|
|
|
eauto.
|
|
|
|
simplify.
|
|
|
|
cancel.
|
|
|
|
rewrite H4.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Transparent heq himp lift star exis ptsto.
|
|
|
|
|
|
|
|
Lemma preservation : forall s H V s' V' H',
|
|
|
|
step (H, V, s) (H', V', s')
|
|
|
|
-> forall Q, hoare_triple (fun V' H' => H' = H /\ V' = V) s Q
|
|
|
|
-> hoare_triple (fun V'' H'' => H'' = H' /\ V'' = V') s' Q.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify.
|
|
|
|
|
|
|
|
apply invert_Assign in H; simp.
|
|
|
|
eapply preservation_exp in H0; eauto.
|
|
|
|
eapply HtWeaken.
|
|
|
|
auto.
|
|
|
|
unfold himp; simplify.
|
|
|
|
propositional; subst.
|
|
|
|
apply H2; assumption.
|
|
|
|
simplify; auto.
|
|
|
|
|
|
|
|
apply invert_WriteHead in H3; simp.
|
|
|
|
eapply preservation_exp in H1; eauto.
|
|
|
|
simplify.
|
|
|
|
eapply HtWeaken.
|
|
|
|
auto.
|
|
|
|
unfold himp; simplify.
|
|
|
|
propositional; subst.
|
|
|
|
apply H5.
|
|
|
|
invert H1.
|
|
|
|
invert H4; simp.
|
|
|
|
invert H6.
|
|
|
|
invert H8.
|
|
|
|
invert H6.
|
|
|
|
invert H8; simp.
|
|
|
|
invert H9.
|
|
|
|
exists x1.
|
|
|
|
apply split_empty_fwd' in H1; subst.
|
|
|
|
exists $0, (x3 $+ (a, (v, tv))); propositional; eauto.
|
|
|
|
constructor; auto.
|
|
|
|
exists v, x2, tv.
|
|
|
|
exists (heap1 x1 (v, tv)), x6; propositional; eauto.
|
|
|
|
unfold split, heap1.
|
|
|
|
unfold split, heap1 in H6.
|
|
|
|
subst.
|
|
|
|
apply fmap_ext; simplify.
|
|
|
|
cases (weq k x1); subst.
|
|
|
|
replace x1 with a by equality.
|
|
|
|
repeat (rewrite lookup_join1 by (simplify; sets); simplify).
|
|
|
|
auto.
|
|
|
|
simplify.
|
|
|
|
repeat (rewrite lookup_join2 by (simplify; sets); simplify).
|
|
|
|
auto.
|
|
|
|
unfold disjoint, heap1 in *.
|
|
|
|
intros.
|
|
|
|
apply H8 with a0.
|
|
|
|
cases (weq x1 a0); subst; simplify.
|
|
|
|
equality.
|
|
|
|
assumption.
|
|
|
|
assumption.
|
|
|
|
constructor.
|
|
|
|
unfold split in H6; subst.
|
|
|
|
replace x1 with a in * by equality.
|
|
|
|
unfold heap1 in H2.
|
|
|
|
rewrite lookup_join1 in H2 by (simplify; sets).
|
|
|
|
simplify.
|
|
|
|
equality.
|
|
|
|
simplify; auto.
|
|
|
|
|
|
|
|
apply invert_WriteTail in H3; simp.
|
|
|
|
eapply preservation_exp in H1; eauto.
|
|
|
|
simplify.
|
|
|
|
eapply HtWeaken.
|
|
|
|
auto.
|
|
|
|
unfold himp; simplify.
|
|
|
|
propositional; subst.
|
|
|
|
apply H5.
|
|
|
|
invert H1.
|
|
|
|
invert H4; simp.
|
|
|
|
invert H6.
|
|
|
|
invert H8.
|
|
|
|
invert H6.
|
|
|
|
invert H8; simp.
|
|
|
|
invert H9.
|
|
|
|
exists x1.
|
|
|
|
apply split_empty_fwd' in H1; subst.
|
|
|
|
exists $0, (x3 $+ (a, (hv, v))); propositional; eauto.
|
|
|
|
constructor; auto.
|
|
|
|
exists v, hv, x4.
|
|
|
|
exists (heap1 x1 (hv, v)), x6; propositional; eauto.
|
|
|
|
unfold split, heap1.
|
|
|
|
unfold split, heap1 in H6.
|
|
|
|
subst.
|
|
|
|
apply fmap_ext; simplify.
|
|
|
|
cases (weq k x1); subst.
|
|
|
|
replace x1 with a by equality.
|
|
|
|
repeat (rewrite lookup_join1 by (simplify; sets); simplify).
|
|
|
|
auto.
|
|
|
|
simplify.
|
|
|
|
repeat (rewrite lookup_join2 by (simplify; sets); simplify).
|
|
|
|
auto.
|
|
|
|
unfold disjoint, heap1 in *.
|
|
|
|
intros.
|
|
|
|
apply H8 with a0.
|
|
|
|
cases (weq x1 a0); subst; simplify.
|
|
|
|
equality.
|
|
|
|
assumption.
|
|
|
|
assumption.
|
|
|
|
constructor.
|
|
|
|
unfold split in H6; subst.
|
|
|
|
replace x1 with a in * by equality.
|
|
|
|
unfold heap1 in H2.
|
|
|
|
rewrite lookup_join1 in H2 by (simplify; sets).
|
|
|
|
simplify.
|
|
|
|
equality.
|
|
|
|
simplify; auto.
|
|
|
|
|
|
|
|
apply invert_Seq in H; first_order.
|
|
|
|
eapply HtWeaken.
|
|
|
|
eauto.
|
|
|
|
simplify.
|
|
|
|
eapply invert_Skip in H; eassumption.
|
|
|
|
|
|
|
|
apply invert_Seq in H1; first_order.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
apply invert_IfThenElse in H; first_order.
|
|
|
|
eapply HtWeaken; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold himp; propositional; subst.
|
|
|
|
eapply preservation_exp in H0; eauto.
|
|
|
|
exists n, H', $0; propositional; eauto.
|
2018-04-29 01:23:41 +00:00
|
|
|
invert H0; simp.
|
|
|
|
invert H7.
|
|
|
|
invert H6.
|
|
|
|
apply split_empty_fwd in H4; subst.
|
|
|
|
auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
constructor; auto.
|
|
|
|
simplify; auto.
|
|
|
|
|
|
|
|
apply invert_IfThenElse in H; first_order.
|
|
|
|
eapply HtWeaken; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold himp; propositional; subst.
|
|
|
|
eapply preservation_exp in H0; eauto.
|
2018-04-29 01:23:41 +00:00
|
|
|
eapply HtExpConsequence.
|
|
|
|
eauto.
|
|
|
|
simplify.
|
|
|
|
instantiate (1 := fun V H'0 => H'0 = H' /\ V = V').
|
|
|
|
simplify.
|
|
|
|
reflexivity.
|
|
|
|
simplify.
|
|
|
|
unfold himp; simplify.
|
|
|
|
invert H3; simp.
|
|
|
|
invert H7.
|
|
|
|
invert H6.
|
|
|
|
apply split_empty_fwd in H4; subst.
|
|
|
|
auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify; auto.
|
|
|
|
|
|
|
|
apply invert_WhileLoop in H; first_order.
|
|
|
|
eapply HtSeq.
|
|
|
|
eapply HtWeaken; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold himp; propositional; subst.
|
|
|
|
eapply preservation_exp in H0; eauto.
|
|
|
|
exists n, H', $0; propositional; eauto.
|
2018-04-29 01:23:41 +00:00
|
|
|
invert H0; simp.
|
|
|
|
invert H8.
|
|
|
|
invert H7.
|
|
|
|
apply split_empty_fwd in H5; subst.
|
|
|
|
auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
constructor; auto.
|
|
|
|
apply H; simplify; auto.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
eauto.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
apply invert_WhileLoop in H; first_order.
|
|
|
|
eapply HtWeaken; eauto.
|
|
|
|
simplify.
|
|
|
|
unfold himp; propositional; subst.
|
|
|
|
eapply preservation_exp in H0; eauto.
|
|
|
|
apply H3; auto.
|
2018-04-29 01:23:41 +00:00
|
|
|
simplify.
|
|
|
|
invert H0; simp.
|
|
|
|
invert H7.
|
|
|
|
invert H6.
|
|
|
|
apply split_empty_fwd in H4; subst.
|
|
|
|
auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
apply H; simplify; auto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma hoare_triple_sound' : forall P s Q,
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> forall H V, P V H
|
|
|
|
-> invariantFor (trsys_of H V s)
|
|
|
|
(fun p => hoare_triple (fun V' H' => H' = fst (fst p) /\ V' = snd (fst p))
|
|
|
|
(snd p)
|
|
|
|
Q).
|
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
|
|
|
|
apply invariant_induction; simplify.
|
|
|
|
|
|
|
|
propositional; subst; simplify.
|
|
|
|
eapply HtWeaken.
|
|
|
|
eauto.
|
|
|
|
unfold himp; simplify; equality.
|
|
|
|
|
|
|
|
cases s0.
|
|
|
|
cases p.
|
|
|
|
cases s'.
|
|
|
|
cases p.
|
|
|
|
simplify.
|
|
|
|
eapply preservation; eauto.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 01:23:41 +00:00
|
|
|
Lemma progress_exp : forall P e Q,
|
|
|
|
hoare_triple_exp P e Q
|
|
|
|
-> forall V H H1 H2, split H H1 H2
|
|
|
|
-> disjoint H1 H2
|
|
|
|
-> P V H1
|
|
|
|
-> exists v, eval H V e v.
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify; eauto.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
invert H5.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
invert H5.
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
invert H5; simp.
|
|
|
|
invert H6.
|
|
|
|
apply split_empty_fwd' in H4; subst.
|
|
|
|
invert H8.
|
|
|
|
invert H1; simp.
|
|
|
|
invert H6.
|
|
|
|
cases x1.
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
unfold heap1, split in *; subst.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify.
|
|
|
|
eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
eapply lookup_Some_dom; simplify.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify; eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
invert H5; simp.
|
|
|
|
invert H6.
|
|
|
|
apply split_empty_fwd' in H4; subst.
|
|
|
|
invert H8.
|
|
|
|
invert H1; simp.
|
|
|
|
invert H6.
|
|
|
|
cases x1.
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
unfold heap1, split in *; subst.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify.
|
|
|
|
eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
eapply lookup_Some_dom; simplify.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify; eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
invert H5.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
eapply IHhoare_triple_exp; eauto.
|
|
|
|
apply H0; auto.
|
|
|
|
|
|
|
|
invert H5; simp.
|
|
|
|
eapply IHhoare_triple_exp in H7; eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma progress : forall P s Q,
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> forall V H H1 H2, split H H1 H2
|
|
|
|
-> disjoint H1 H2
|
|
|
|
-> P V H1
|
|
|
|
-> s = Skip \/ (exists H' V' s', step (H, V, s) (H', V', s')).
|
|
|
|
Proof.
|
|
|
|
induct 1; simplify; eauto.
|
|
|
|
|
|
|
|
eapply (progress_exp _ _ _ H) in H5; eauto.
|
|
|
|
simp.
|
|
|
|
right; do 3 eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
|
|
|
|
pose proof (progress_exp _ _ _ H _ _ _ _ H3 H4 H5) as Hprog.
|
|
|
|
invert Hprog.
|
|
|
|
assert (Hdropped : eval H1 V e x0).
|
|
|
|
eapply drop_cells; eauto.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1; auto.
|
|
|
|
eapply lookup_Some_dom; eauto.
|
|
|
|
pose proof (preservation_exp _ _ _ H _ _ _ H5 Hdropped) as Hpres.
|
|
|
|
simplify.
|
|
|
|
invert Hpres.
|
|
|
|
invert H7; simp.
|
|
|
|
invert H9.
|
|
|
|
apply split_empty_fwd' in H8; subst.
|
|
|
|
invert H11.
|
|
|
|
invert H1.
|
|
|
|
invert H8; simp.
|
|
|
|
invert H9.
|
|
|
|
right; do 3 eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
eauto.
|
|
|
|
unfold heap1, split in *; subst.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify.
|
|
|
|
eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
eapply lookup_Some_dom; simplify.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify; eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
|
|
|
|
pose proof (progress_exp _ _ _ H _ _ _ _ H3 H4 H5) as Hprog.
|
|
|
|
invert Hprog.
|
|
|
|
assert (Hdropped : eval H1 V e x0).
|
|
|
|
eapply drop_cells; eauto.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1; auto.
|
|
|
|
eapply lookup_Some_dom; eauto.
|
|
|
|
pose proof (preservation_exp _ _ _ H _ _ _ H5 Hdropped) as Hpres.
|
|
|
|
simplify.
|
|
|
|
invert Hpres.
|
|
|
|
invert H7; simp.
|
|
|
|
invert H9.
|
|
|
|
apply split_empty_fwd' in H8; subst.
|
|
|
|
invert H11.
|
|
|
|
invert H1.
|
|
|
|
invert H8; simp.
|
|
|
|
invert H9.
|
|
|
|
right; do 3 eexists.
|
|
|
|
econstructor.
|
|
|
|
eauto.
|
|
|
|
eauto.
|
|
|
|
unfold heap1, split in *; subst.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify.
|
|
|
|
eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
eapply lookup_Some_dom; simplify.
|
|
|
|
rewrite lookup_join1.
|
|
|
|
simplify; eauto.
|
|
|
|
eapply lookup_Some_dom; simplify; sets.
|
|
|
|
|
|
|
|
specialize (IHhoare_triple1 _ _ _ _ H4 H5 H6); simp; eauto 6.
|
|
|
|
|
|
|
|
pose proof (progress_exp _ _ _ H _ _ _ _ H5 H6 H7) as Hprog.
|
|
|
|
invert Hprog.
|
|
|
|
assert (Hdropped : eval H3 V e x).
|
|
|
|
eapply drop_cells; eauto.
|
|
|
|
unfold split in H5; subst.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1; auto.
|
|
|
|
eapply lookup_Some_dom; eauto.
|
|
|
|
pose proof (preservation_exp _ _ _ H _ _ _ H7 Hdropped) as Hpres.
|
|
|
|
simplify.
|
|
|
|
invert Hpres; simp.
|
|
|
|
invert H13.
|
|
|
|
invert H12.
|
|
|
|
cases (weq x2 (^0)); subst; eauto 10.
|
|
|
|
|
|
|
|
pose proof (progress_exp _ _ _ H _ _ _ _ H4 H5 H6) as Hprog.
|
|
|
|
invert Hprog.
|
|
|
|
assert (Hdropped : eval H2 V e x).
|
|
|
|
eapply drop_cells; eauto.
|
|
|
|
unfold split in H4; subst.
|
|
|
|
simplify.
|
|
|
|
rewrite lookup_join1; auto.
|
|
|
|
eapply lookup_Some_dom; eauto.
|
|
|
|
pose proof (preservation_exp _ _ _ H _ _ _ H6 Hdropped) as Hpres.
|
|
|
|
simplify.
|
|
|
|
invert Hpres; simp.
|
|
|
|
invert H12.
|
|
|
|
invert H11.
|
|
|
|
cases (weq x2 (^0)); subst; eauto 10.
|
|
|
|
|
|
|
|
apply H0 in H7.
|
|
|
|
eapply IHhoare_triple in H7; eauto.
|
|
|
|
|
|
|
|
invert H6; simp.
|
|
|
|
eapply IHhoare_triple in H8; eauto.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 00:31:01 +00:00
|
|
|
Theorem hoare_triple_sound : forall P s Q,
|
|
|
|
hoare_triple P s Q
|
|
|
|
-> forall H V, P V H
|
|
|
|
-> invariantFor (trsys_of H V s)
|
|
|
|
(fun p => (snd p = Skip /\ Q (snd (fst p)) (fst (fst p)))
|
|
|
|
\/ exists p', step p p').
|
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
eapply invariant_weaken.
|
|
|
|
eapply hoare_triple_sound'; eauto.
|
|
|
|
simplify.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
|
|
|
cases s0.
|
|
|
|
cases p.
|
|
|
|
simplify.
|
|
|
|
pose proof (progress _ _ _ H2 v h h $0) as Hprog; simplify.
|
|
|
|
cases Hprog; eauto.
|
|
|
|
subst.
|
|
|
|
eapply invert_Skip in H2.
|
|
|
|
left; propositional.
|
|
|
|
apply H2; auto.
|
|
|
|
first_order.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
End DeeplyEmbedded.
|