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/ *)
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Require Import Frap SepCancel ModelCheck Classes.Morphisms.
|
|
|
|
Require Import Arith.Div2 Eqdep.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
(** * Some odds and ends from past chapters *)
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Definition weq : forall {sz} (x y : word sz), sumbool (x = y) (x <> y).
|
|
|
|
refine (fix weq sz (x : word sz) : forall y : word sz, sumbool (x = y) (x <> y) :=
|
|
|
|
match x in word sz return forall y : word sz, sumbool (x = y) (x <> y) with
|
2018-04-29 00:31:01 +00:00
|
|
|
| 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.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma mod2_2times : forall n,
|
|
|
|
mod2 (2 * n) = false.
|
|
|
|
Proof.
|
|
|
|
induct n; simplify; auto.
|
|
|
|
replace (n + S (n + 0)) with (S (2 * n)) by linear_arithmetic.
|
|
|
|
assumption.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma mod2_plus1_2times : forall n,
|
|
|
|
mod2 (1 + 2 * n) = true.
|
|
|
|
Proof.
|
|
|
|
induct n; simplify; auto.
|
|
|
|
replace (n + S (n + 0)) with (S (2 * n)) by linear_arithmetic.
|
|
|
|
assumption.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem adding_one_changes : forall sz (w : word sz),
|
|
|
|
sz > 0
|
|
|
|
-> w ^+ ^1 <> w.
|
|
|
|
Proof.
|
|
|
|
propositional.
|
|
|
|
cases sz; try linear_arithmetic.
|
|
|
|
pose proof (shatter_word_S w); first_order; subst.
|
|
|
|
unfold wplus in H0.
|
|
|
|
simplify.
|
|
|
|
invert H0.
|
|
|
|
clear H3.
|
|
|
|
cases x.
|
|
|
|
replace (S (wordToNat x0 + (wordToNat x0 + 0)) + S (wordToNat (^ 0) + (wordToNat (^ 0) + 0)))
|
|
|
|
with (2 * (1 + wordToNat x0 + @wordToNat sz (^0))) in H2 by linear_arithmetic.
|
|
|
|
rewrite mod2_2times in H2; equality.
|
|
|
|
replace (wordToNat x0 + (wordToNat x0 + 0) + S (wordToNat (^ 0) + (wordToNat (^ 0) + 0)))
|
|
|
|
with (1 + 2 * (wordToNat x0 + @wordToNat sz (^0))) in H2 by linear_arithmetic.
|
|
|
|
rewrite mod2_plus1_2times in H2.
|
|
|
|
equality.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
Module Type BIT_WIDTH.
|
|
|
|
Parameter bit_width : nat.
|
2018-04-29 20:57:47 +00:00
|
|
|
Axiom bit_width_nonzero : bit_width > 0.
|
2018-04-29 00:31:01 +00:00
|
|
|
End BIT_WIDTH.
|
|
|
|
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(** * A modification of last chapter's language, to use words instead of naturals *)
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Module MixedEmbedded(Import BW : BIT_WIDTH).
|
|
|
|
Definition wrd := word bit_width.
|
|
|
|
Definition heap := fmap wrd wrd.
|
|
|
|
|
|
|
|
Ltac simp := repeat (simplify; subst; propositional;
|
|
|
|
try match goal with
|
|
|
|
| [ H : ex _ |- _ ] => invert H
|
|
|
|
end).
|
|
|
|
|
|
|
|
|
|
|
|
Inductive loop_outcome {acc} :=
|
|
|
|
| Done (a : acc)
|
|
|
|
| Again (a : acc).
|
|
|
|
|
|
|
|
Arguments loop_outcome : clear implicits.
|
|
|
|
|
|
|
|
Inductive cmd : Set -> Type :=
|
|
|
|
| Return {result : Set} (r : result) : cmd result
|
|
|
|
| Bind {result result'} (c1 : cmd result') (c2 : result' -> cmd result) : cmd result
|
|
|
|
| Read (a : wrd) : cmd wrd
|
|
|
|
| Write (a v : wrd) : cmd unit
|
|
|
|
| Loop {acc : Set} (init : acc) (body : acc -> cmd (loop_outcome acc)) : cmd acc
|
|
|
|
| Fail {result} : cmd result.
|
|
|
|
|
|
|
|
(* We're leaving out allocation and deallocation, to avoid distraction from
|
|
|
|
* the main point of the examples to follow. *)
|
|
|
|
|
|
|
|
Notation "x <- c1 ; c2" := (Bind c1 (fun x => c2)) (right associativity, at level 80).
|
|
|
|
Notation "'for' x := i 'loop' c1 'done'" := (Loop i (fun x => c1)) (right associativity, at level 80).
|
|
|
|
|
|
|
|
Inductive step : forall {A}, heap * cmd A -> heap * cmd A -> Prop :=
|
|
|
|
| StepBindRecur : forall result result' (c1 c1' : cmd result') (c2 : result' -> cmd result) h h',
|
|
|
|
step (h, c1) (h', c1')
|
|
|
|
-> step (h, Bind c1 c2) (h', Bind c1' c2)
|
|
|
|
| StepBindProceed : forall (result result' : Set) (v : result') (c2 : result' -> cmd result) h,
|
|
|
|
step (h, Bind (Return v) c2) (h, c2 v)
|
|
|
|
|
|
|
|
| StepLoop : forall (acc : Set) (init : acc) (body : acc -> cmd (loop_outcome acc)) h,
|
|
|
|
step (h, Loop init body) (h, o <- body init; match o with
|
|
|
|
| Done a => Return a
|
|
|
|
| Again a => Loop a body
|
|
|
|
end)
|
|
|
|
|
|
|
|
| StepRead : forall h a v,
|
|
|
|
h $? a = Some v
|
|
|
|
-> step (h, Read a) (h, Return v)
|
|
|
|
| StepWrite : forall h a v v',
|
|
|
|
h $? a = Some v
|
|
|
|
-> step (h, Write a v') (h $+ (a, v'), Return tt).
|
|
|
|
|
|
|
|
|
|
|
|
Definition trsys_of (h : heap) {result} (c : cmd result) := {|
|
|
|
|
Initial := {(h, c)};
|
|
|
|
Step := step (A := result)
|
|
|
|
|}.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Definition multistep_trsys_of (h : heap) {result} (c : cmd result) := {|
|
|
|
|
Initial := {(h, c)};
|
|
|
|
Step := (step (A := result))^*
|
|
|
|
|}.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Now let's get into the first distinctive feature of separation logic: an
|
|
|
|
* assertion language that takes advantage of *partiality* of heaps. We give our
|
|
|
|
* definitions inside a module, which will shortly be used as a parameter to
|
|
|
|
* another module (from the book library), to get some free automation for
|
|
|
|
* implications between these assertions. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Module Import S <: SEP.
|
|
|
|
Definition hprop := heap -> Prop.
|
2018-04-29 20:57:47 +00:00
|
|
|
(* A [hprop] is a regular old assertion over heaps. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Implication *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Definition himp (p q : hprop) := forall h, p h -> q h.
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
(* Equivalence *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Definition heq (p q : hprop) := forall h, p h <-> q h.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Lifting a pure proposition: it must hold, and the heap must be empty. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Definition lift (P : Prop) : hprop :=
|
|
|
|
fun h => P /\ h = $0.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Separating conjunction, one of the two big ideas of separation logic.
|
|
|
|
* When does [star p q] apply to [h]? When [h] can be partitioned into two
|
|
|
|
* subheaps [h1] and [h2], respectively compatible with [p] and [q]. See book
|
|
|
|
* module [Map] for definitions of [split] and [disjoint]. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Definition star (p q : hprop) : hprop :=
|
|
|
|
fun h => exists h1 h2, split h h1 h2 /\ disjoint h1 h2 /\ p h1 /\ q h2.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Existential quantification *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Definition exis {A} (p : A -> hprop) : hprop :=
|
|
|
|
fun h => exists x, p x h.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Convenient notations *)
|
2018-04-29 00:31:01 +00:00
|
|
|
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.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* And now we prove some key algebraic properties, whose details aren't so
|
|
|
|
* important. The library automation uses these properties. *)
|
|
|
|
|
2018-04-29 00:31:01 +00:00
|
|
|
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
|
2018-04-29 20:57:47 +00:00
|
|
|
| [ H : ex _ |- _ ] => destruct H
|
2018-04-29 00:31:01 +00:00
|
|
|
| [ 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.
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Instantiate our big automation engine to these definitions. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
Module Import Se := SepCancel.Make(S).
|
2018-04-29 20:57:47 +00:00
|
|
|
Export Se.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* ** Predicates *)
|
|
|
|
|
|
|
|
Definition heap1 (a v : wrd) : heap := $0 $+ (a, v).
|
|
|
|
Definition ptsto (a v : wrd) : hprop :=
|
|
|
|
fun h => h = heap1 a v.
|
|
|
|
|
2018-04-29 00:31:01 +00:00
|
|
|
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.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Fixpoint multi_ptsto (a : wrd) (vs : list wrd) : hprop :=
|
|
|
|
match vs with
|
|
|
|
| nil => emp
|
|
|
|
| v :: vs' => a |-> v * multi_ptsto (a ^+ ^1) vs'
|
|
|
|
end%sep.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Infix "|-->" := multi_ptsto (at level 30) : sep_scope.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(** * Finally, the Hoare logic *)
|
|
|
|
|
|
|
|
Inductive hoare_triple : forall {result}, hprop -> cmd result -> (result -> hprop) -> Prop :=
|
|
|
|
| HtReturn : forall P {result : Set} (v : result),
|
|
|
|
hoare_triple P (Return v) (fun r => P * [| r = v |])%sep
|
|
|
|
| HtBind : forall P {result' result} (c1 : cmd result') (c2 : result' -> cmd result) Q R,
|
|
|
|
hoare_triple P c1 Q
|
|
|
|
-> (forall r, hoare_triple (Q r) (c2 r) R)
|
|
|
|
-> hoare_triple P (Bind c1 c2) R
|
|
|
|
| HtLoop : forall {acc : Set} (init : acc) (body : acc -> cmd (loop_outcome acc)) I,
|
|
|
|
(forall acc, hoare_triple (I (Again acc)) (body acc) I)
|
|
|
|
-> hoare_triple (I (Again init)) (Loop init body) (fun r => I (Done r))
|
|
|
|
| HtFail : forall {result},
|
|
|
|
hoare_triple (fun _ => False) (Fail (result := result)) (fun _ _ => False)
|
|
|
|
|
|
|
|
| HtRead : forall a R,
|
|
|
|
hoare_triple (exists v, a |-> v * R v)%sep (Read a) (fun r => a |-> r * R r)%sep
|
|
|
|
| HtWrite : forall a v',
|
|
|
|
hoare_triple (exists v, a |-> v)%sep (Write a v') (fun _ => a |-> v')%sep
|
|
|
|
|
|
|
|
| HtConsequence : forall {result} (c : cmd result) P Q (P' : hprop) (Q' : _ -> hprop),
|
|
|
|
hoare_triple P c Q
|
|
|
|
-> P' ===> P
|
|
|
|
-> (forall r, Q r ===> Q' r)
|
|
|
|
-> hoare_triple P' c Q'
|
|
|
|
|
|
|
|
| HtFrame : forall {result} (c : cmd result) P Q R,
|
|
|
|
hoare_triple P c Q
|
|
|
|
-> hoare_triple (P * R)%sep c (fun r => Q r * R)%sep.
|
|
|
|
|
|
|
|
|
|
|
|
Notation "{{ P }} c {{ r ~> Q }}" :=
|
|
|
|
(hoare_triple P%sep c (fun r => Q%sep)) (at level 90, c at next level).
|
|
|
|
|
|
|
|
Lemma HtStrengthen : forall {result} (c : cmd result) P Q (Q' : _ -> hprop),
|
|
|
|
hoare_triple P c Q
|
|
|
|
-> (forall r, Q r ===> Q' r)
|
|
|
|
-> hoare_triple P c Q'.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma HtWeaken : forall {result} (c : cmd result) P Q (P' : hprop),
|
|
|
|
hoare_triple P c Q
|
|
|
|
-> P' ===> P
|
|
|
|
-> hoare_triple P' c Q.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
|
|
|
simplify.
|
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
reflexivity.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Now, we carry out a moderately laborious soundness proof! It's safe to skip
|
|
|
|
* ahead to the text "Examples", but a few representative lemma highlights
|
|
|
|
* include [invert_Read], [preservation], [progress], and the main theorem
|
|
|
|
* [hoare_triple_sound]. *)
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Return : forall {result : Set} (r : result) P Q,
|
|
|
|
hoare_triple P (Return r) Q
|
|
|
|
-> forall h, P h -> Q r h.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
induct 1; propositional; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
exists h, $0; propositional; eauto.
|
|
|
|
unfold lift; propositional.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
unfold himp in *; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
unfold star, himp in *; simp; eauto 7.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Hint Constructors hoare_triple.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Bind : forall {result' result} (c1 : cmd result') (c2 : result' -> cmd result) P Q,
|
|
|
|
hoare_triple P (Bind c1 c2) Q
|
|
|
|
-> exists R, hoare_triple P c1 R
|
|
|
|
/\ forall r, hoare_triple (R r) (c2 r) Q.
|
|
|
|
Proof.
|
|
|
|
induct 1; propositional; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
invert IHhoare_triple; propositional.
|
|
|
|
eexists; propositional.
|
|
|
|
eapply HtWeaken.
|
2018-04-29 00:31:01 +00:00
|
|
|
eassumption.
|
|
|
|
auto.
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply HtStrengthen.
|
|
|
|
apply H4.
|
2018-04-29 00:31:01 +00:00
|
|
|
auto.
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
simp.
|
|
|
|
exists (fun r => x r * R)%sep.
|
|
|
|
propositional.
|
|
|
|
eapply HtFrame; eauto.
|
|
|
|
eapply HtFrame; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Loop : forall {acc : Set} (init : acc) (body : acc -> cmd (loop_outcome acc)) P Q,
|
|
|
|
hoare_triple P (Loop init body) Q
|
|
|
|
-> exists I, (forall acc, hoare_triple (I (Again acc)) (body acc) I)
|
|
|
|
/\ (forall h, P h -> I (Again init) h)
|
|
|
|
/\ (forall r h, I (Done r) h -> Q r h).
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
induct 1; propositional; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
invert IHhoare_triple; propositional.
|
|
|
|
exists x; propositional; eauto.
|
|
|
|
unfold himp in *; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
|
|
|
simp.
|
2018-04-29 20:57:47 +00:00
|
|
|
exists (fun o => x o * R)%sep; propositional; eauto.
|
|
|
|
unfold star in *; simp; eauto 7.
|
|
|
|
unfold star in *; simp; eauto 7.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Fail : forall result P Q,
|
|
|
|
hoare_triple P (Fail (result := result)) Q
|
|
|
|
-> forall h, P h -> False.
|
|
|
|
Proof.
|
|
|
|
induct 1; propositional; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
unfold star in *; simp; eauto.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Now that we proved enough basic facts, let's hide the definitions of all
|
|
|
|
* these predicates, so that we reason about them only through automation. *)
|
|
|
|
Opaque heq himp lift star exis ptsto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma unit_not_wrd : unit = wrd -> False.
|
|
|
|
Proof.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
assert (exists x : unit, forall y : unit, x = y).
|
|
|
|
exists tt; simplify.
|
|
|
|
cases y; reflexivity.
|
|
|
|
rewrite H in H0.
|
|
|
|
invert H0.
|
|
|
|
specialize (H1 (x ^+ ^1)).
|
|
|
|
eapply adding_one_changes.
|
|
|
|
apply bit_width_nonzero.
|
|
|
|
symmetry; eassumption.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Read : forall a P Q,
|
|
|
|
hoare_triple P (Read a) Q
|
|
|
|
-> exists R, (P ===> exists v, a |-> v * R v)%sep
|
|
|
|
/\ forall r, a |-> r * R r ===> Q r.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
induct 1; simp; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
exists R; simp.
|
|
|
|
cancel; auto.
|
|
|
|
cancel; auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply unit_not_wrd in x0; simp.
|
|
|
|
|
|
|
|
specialize (IHhoare_triple _ _ eq_refl JMeq.JMeq_refl JMeq.JMeq_refl); first_order.
|
|
|
|
exists x.
|
|
|
|
propositional.
|
|
|
|
etransitivity; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
etransitivity; eauto.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
specialize (IHhoare_triple _ _ eq_refl JMeq.JMeq_refl JMeq.JMeq_refl); first_order.
|
|
|
|
exists (fun n => x n * R)%sep; simp.
|
|
|
|
rewrite H0.
|
|
|
|
cancel.
|
|
|
|
|
|
|
|
rewrite <- H1.
|
|
|
|
cancel.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma invert_Write : forall a v' P Q,
|
|
|
|
hoare_triple P (Write a v') Q
|
|
|
|
-> exists R, (P ===> (exists v, a |-> v) * R)%sep
|
|
|
|
/\ a |-> v' * R ===> Q tt.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
induct 1; simp; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
symmetry in x0.
|
|
|
|
apply unit_not_wrd in x0; simp.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
exists emp; simp.
|
|
|
|
cancel; auto.
|
|
|
|
cancel; auto.
|
|
|
|
|
|
|
|
eexists; split.
|
|
|
|
etransitivity; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
etransitivity; eauto.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
exists (x * R)%sep; simp.
|
|
|
|
rewrite H1.
|
|
|
|
cancel.
|
|
|
|
|
2018-04-29 00:31:01 +00:00
|
|
|
cancel.
|
|
|
|
rewrite <- H2.
|
|
|
|
cancel.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma HtReturn' : forall P {result : Set} (v : result) Q,
|
|
|
|
P ===> Q v
|
|
|
|
-> hoare_triple P (Return v) Q.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
simp.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
constructor.
|
|
|
|
simp.
|
2018-04-29 00:31:01 +00:00
|
|
|
cancel.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Temporarily transparent again! *)
|
|
|
|
Transparent heq himp lift star exis ptsto.
|
|
|
|
|
|
|
|
Lemma preservation : forall {result} (c : cmd result) h c' h',
|
|
|
|
step (h, c) (h', c')
|
|
|
|
-> forall Q, hoare_triple (fun h' => h' = h) c Q
|
|
|
|
-> hoare_triple (fun h'' => h'' = h') c' Q.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
|
|
|
induct 1; simplify.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply invert_Bind in H0; simp.
|
|
|
|
eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply invert_Bind in H; simp.
|
|
|
|
specialize (invert_Return _ _ _ H); eauto using HtWeaken.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply invert_Loop in H; simp.
|
|
|
|
econstructor.
|
|
|
|
eapply HtWeaken.
|
|
|
|
eauto.
|
|
|
|
assumption.
|
|
|
|
simp.
|
|
|
|
cases r.
|
|
|
|
apply HtReturn'.
|
|
|
|
unfold himp; simp; eauto.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
eauto.
|
|
|
|
unfold himp; simp; eauto.
|
|
|
|
|
|
|
|
apply invert_Read in H0; simp.
|
|
|
|
apply HtReturn'.
|
|
|
|
assert ((exists v, a |-> v * x v)%sep h') by auto.
|
|
|
|
unfold exis, star in H1; simp.
|
|
|
|
unfold ptsto in H4; subst.
|
|
|
|
unfold split in H1; subst.
|
|
|
|
unfold heap1 in H.
|
|
|
|
rewrite lookup_join1 in H by (simp; sets).
|
|
|
|
unfold himp; simp.
|
|
|
|
invert H.
|
|
|
|
apply H2.
|
|
|
|
unfold star.
|
|
|
|
exists (heap1 a v), x2; propositional.
|
|
|
|
unfold split; reflexivity.
|
|
|
|
unfold ptsto; reflexivity.
|
|
|
|
|
|
|
|
apply invert_Write in H0; simp.
|
|
|
|
apply HtReturn'.
|
|
|
|
simp.
|
|
|
|
assert (((exists v : wrd, a |-> v) * x)%sep h) by auto.
|
|
|
|
unfold star in H1; simp.
|
|
|
|
invert H4.
|
|
|
|
unfold ptsto in H5; subst.
|
|
|
|
unfold split in H3; subst.
|
|
|
|
unfold heap1 in H.
|
|
|
|
rewrite lookup_join1 in H by (simp; sets).
|
|
|
|
unfold himp; simp.
|
|
|
|
invert H.
|
|
|
|
apply H2.
|
|
|
|
unfold star.
|
|
|
|
exists ($0 $+ (a, v')), x1; propositional.
|
|
|
|
unfold split.
|
|
|
|
unfold heap1.
|
|
|
|
maps_equal.
|
|
|
|
rewrite lookup_join1 by (simp; sets).
|
|
|
|
simp.
|
|
|
|
repeat rewrite lookup_join2 by (simp; sets); reflexivity.
|
|
|
|
unfold disjoint in *; simp.
|
|
|
|
cases (weq a0 a); simp.
|
|
|
|
apply H1 with (a0 := a).
|
|
|
|
unfold heap1; simp.
|
|
|
|
equality.
|
|
|
|
assumption.
|
|
|
|
unfold ptsto; reflexivity.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Hint Constructors step.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma progress : forall {result} (c : cmd result) P Q,
|
|
|
|
hoare_triple P c Q
|
|
|
|
-> forall h h1 h2, split h h1 h2
|
|
|
|
-> disjoint h1 h2
|
|
|
|
-> P h1
|
|
|
|
-> (exists r, c = Return r)
|
|
|
|
\/ (exists h' c', step (h, c) (h', c')).
|
|
|
|
Proof.
|
|
|
|
induct 1; simp;
|
|
|
|
repeat match goal with
|
|
|
|
| [ H : forall _ h1 _, _ -> _ -> ?P h1 -> _, H' : ?P _ |- _ ] => eapply H in H'; clear H; try eassumption; simp
|
|
|
|
end; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
invert H1.
|
|
|
|
right; exists h, (Return x).
|
|
|
|
constructor.
|
|
|
|
unfold split, ptsto, heap1 in *; simp.
|
|
|
|
unfold star in H2; simp.
|
|
|
|
unfold split in H; simp.
|
|
|
|
rewrite lookup_join1; simp.
|
|
|
|
rewrite lookup_join1; simp.
|
|
|
|
sets.
|
|
|
|
eapply lookup_Some_dom.
|
|
|
|
rewrite lookup_join1; simp.
|
|
|
|
sets.
|
|
|
|
|
|
|
|
right; exists (h $+ (a, v')), (Return tt).
|
|
|
|
unfold split, exis, ptsto, heap1 in *; simp.
|
|
|
|
econstructor.
|
|
|
|
rewrite lookup_join1; simp.
|
|
|
|
sets.
|
|
|
|
|
|
|
|
unfold star in H2; simp.
|
|
|
|
apply IHhoare_triple with (h := h) (h1 := x) (h2 := h2 $++ x0); eauto.
|
|
|
|
unfold split in *; simp.
|
|
|
|
rewrite (@join_comm _ _ h2 x0).
|
|
|
|
apply join_assoc.
|
|
|
|
sets.
|
|
|
|
cases (h2 $? x1).
|
|
|
|
cases (x0 $? x1).
|
|
|
|
specialize (H2 x1).
|
|
|
|
specialize (H1 x1).
|
|
|
|
rewrite lookup_join2 in H1.
|
|
|
|
apply H1; equality.
|
|
|
|
unfold not.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
cases (x $? x1).
|
|
|
|
exfalso; apply H2; equality.
|
|
|
|
apply lookup_None_dom in Heq1; propositional.
|
|
|
|
apply lookup_None_dom in Heq0; propositional.
|
|
|
|
apply lookup_None_dom in Heq; propositional.
|
|
|
|
|
|
|
|
unfold split, disjoint in *; simp.
|
|
|
|
cases (h2 $? a).
|
|
|
|
rewrite lookup_join1 in H7.
|
|
|
|
apply H1 with (a := a); auto.
|
|
|
|
rewrite lookup_join1; auto.
|
|
|
|
cases (x $? a); try equality.
|
|
|
|
eauto using lookup_Some_dom.
|
|
|
|
eauto using lookup_Some_dom.
|
|
|
|
rewrite lookup_join2 in H7.
|
|
|
|
eapply H2; eassumption.
|
|
|
|
eauto using lookup_None_dom.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Lemma hoare_triple_sound' : forall P {result} (c : cmd result) Q,
|
|
|
|
hoare_triple P c Q
|
2018-04-29 21:25:03 +00:00
|
|
|
-> forall h, P h
|
|
|
|
-> invariantFor (trsys_of h c)
|
2018-04-29 20:57:47 +00:00
|
|
|
(fun p =>
|
|
|
|
hoare_triple (fun h' => h' = fst p)
|
|
|
|
(snd p)
|
|
|
|
Q).
|
|
|
|
Proof.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
apply invariant_induction; simplify.
|
|
|
|
|
|
|
|
propositional; subst; simplify.
|
|
|
|
eapply HtWeaken; eauto.
|
|
|
|
unfold himp; simplify; equality.
|
|
|
|
|
|
|
|
cases s.
|
|
|
|
cases s'.
|
|
|
|
simp.
|
|
|
|
eauto using preservation.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem hoare_triple_sound : forall P {result} (c : cmd result) Q,
|
|
|
|
hoare_triple P c Q
|
2018-04-29 21:25:03 +00:00
|
|
|
-> forall h, P h
|
|
|
|
-> invariantFor (trsys_of h c)
|
2018-04-29 20:57:47 +00:00
|
|
|
(fun p => (exists r, snd p = Return r)
|
|
|
|
\/ (exists p', step p p')).
|
|
|
|
Proof.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
eapply invariant_weaken.
|
|
|
|
eapply hoare_triple_sound'; eauto.
|
|
|
|
simp.
|
|
|
|
specialize (progress _ _ _ H1); simplify.
|
|
|
|
specialize (H2 (fst s) (fst s) $0).
|
|
|
|
assert (split (fst s) (fst s) $0) by auto.
|
|
|
|
assert (disjoint (fst s) $0) by auto.
|
|
|
|
cases s; simp; eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
(* Fancy theorem to help us rewrite within preconditions and postconditions *)
|
|
|
|
Instance hoare_triple_morphism : forall A,
|
|
|
|
Proper (heq ==> eq ==> (eq ==> heq) ==> iff) (@hoare_triple A).
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
Transparent himp.
|
|
|
|
repeat (hnf; intros).
|
|
|
|
unfold pointwise_relation in *; intuition subst.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
rewrite H; reflexivity.
|
|
|
|
intros.
|
|
|
|
hnf in H1.
|
|
|
|
specialize (H1 r _ eq_refl).
|
|
|
|
rewrite H1; reflexivity.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply HtConsequence; eauto.
|
|
|
|
rewrite H; reflexivity.
|
|
|
|
intros.
|
|
|
|
hnf in H1.
|
|
|
|
specialize (H1 r _ eq_refl).
|
|
|
|
rewrite H1; reflexivity.
|
|
|
|
Opaque himp.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Examples *)
|
|
|
|
|
|
|
|
Global Opaque heq himp lift star exis ptsto.
|
|
|
|
|
|
|
|
Theorem use_lemma : forall result P' (c : cmd result) (Q : result -> hprop) P R,
|
|
|
|
hoare_triple P' c Q
|
|
|
|
-> P ===> P' * R
|
|
|
|
-> hoare_triple P c (fun r => Q r * R)%sep.
|
|
|
|
Proof.
|
|
|
|
simp.
|
2018-04-29 00:31:01 +00:00
|
|
|
eapply HtWeaken.
|
|
|
|
eapply HtFrame.
|
|
|
|
eassumption.
|
2018-04-29 20:57:47 +00:00
|
|
|
eauto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem HtRead' : forall a v,
|
|
|
|
hoare_triple (a |-> v)%sep (Read a) (fun r => a |-> v * [| r = v |])%sep.
|
|
|
|
Proof.
|
|
|
|
simp.
|
|
|
|
apply HtWeaken with (exists r, a |-> r * [| r = v |])%sep.
|
|
|
|
eapply HtStrengthen.
|
|
|
|
apply HtRead.
|
|
|
|
simp.
|
|
|
|
cancel; auto.
|
|
|
|
subst; cancel.
|
|
|
|
cancel; auto.
|
|
|
|
Qed.
|
|
|
|
|
|
|
|
Theorem HtRead'' : forall p P R,
|
|
|
|
P ===> (exists v, p |-> v * R v)
|
|
|
|
-> hoare_triple P (Read p) (fun r => p |-> r * R r)%sep.
|
|
|
|
Proof.
|
|
|
|
simp.
|
|
|
|
eapply HtWeaken.
|
|
|
|
apply HtRead.
|
2018-04-29 00:31:01 +00:00
|
|
|
assumption.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Ltac basic := apply HtReturn' || eapply HtWrite.
|
|
|
|
|
|
|
|
Ltac step0 := basic || eapply HtBind || (eapply use_lemma; [ basic | cancel; auto ])
|
|
|
|
|| (eapply use_lemma; [ eapply HtRead' | solve [ cancel; auto ] ])
|
|
|
|
|| (eapply HtRead''; solve [ cancel ])
|
|
|
|
|| (eapply HtStrengthen; [ eapply use_lemma; [ basic | cancel; auto ] | ])
|
|
|
|
|| (eapply HtConsequence; [ apply HtFail | .. ]).
|
|
|
|
Ltac step := step0; simp.
|
|
|
|
Ltac ht := simp; repeat step.
|
|
|
|
Ltac conseq := simplify; eapply HtConsequence.
|
|
|
|
Ltac use_IH H := conseq; [ apply H | .. ]; ht.
|
|
|
|
Ltac loop_inv0 Inv := (eapply HtWeaken; [ apply HtLoop with (I := Inv) | .. ])
|
|
|
|
|| (eapply HtConsequence; [ apply HtLoop with (I := Inv) | .. ]).
|
|
|
|
Ltac loop_inv Inv := loop_inv0 Inv; ht.
|
|
|
|
Ltac use H := (eapply use_lemma; [ eapply H | cancel; auto ])
|
|
|
|
|| (eapply HtStrengthen; [ eapply use_lemma; [ eapply H | cancel; auto ] | ]).
|
|
|
|
|
|
|
|
Ltac heq := intros; apply himp_heq; split.
|
|
|
|
|
|
|
|
|
|
|
|
(** * List-reverse example *)
|
|
|
|
|
|
|
|
Fixpoint linkedList (p : wrd) (ls : list wrd) :=
|
|
|
|
match ls with
|
|
|
|
| nil => [| p = ^0 |]
|
|
|
|
| x :: ls' => [| p <> ^0 |]
|
|
|
|
* exists p', p |--> [x; p'] * linkedList p' ls'
|
|
|
|
end%sep.
|
|
|
|
|
|
|
|
Theorem linkedList_null : forall ls,
|
|
|
|
linkedList (^0) ls === [| ls = nil |].
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
heq; cases ls; cancel.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Theorem linkedList_nonnull : forall p ls,
|
|
|
|
p <> ^0
|
|
|
|
-> linkedList p ls === exists x ls' p', [| ls = x :: ls' |] * p |--> [x; p'] * linkedList p' ls'.
|
|
|
|
Proof.
|
|
|
|
heq; cases ls; cancel; match goal with
|
|
|
|
| [ H : _ = _ :: _ |- _ ] => invert H
|
|
|
|
end; cancel.
|
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Hint Rewrite <- rev_alt.
|
|
|
|
Hint Rewrite rev_involutive.
|
|
|
|
|
|
|
|
Opaque linkedList.
|
|
|
|
|
|
|
|
Definition reverse p :=
|
|
|
|
pr <- for pr := (p, ^0) loop
|
|
|
|
let (p, r) := pr in
|
|
|
|
if weq p (^0) then
|
|
|
|
Return (Done pr)
|
|
|
|
else
|
|
|
|
tmp <- Read (p ^+ ^1);
|
|
|
|
_ <- Write (p ^+ ^1) r;
|
|
|
|
Return (Again (tmp, p))
|
|
|
|
done;
|
|
|
|
Return (snd pr).
|
|
|
|
|
|
|
|
Definition valueOf {A} (o : loop_outcome A) :=
|
|
|
|
match o with
|
|
|
|
| Done v => v
|
|
|
|
| Again v => v
|
|
|
|
end.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Theorem reverse_ok : forall p ls,
|
|
|
|
{{linkedList p ls}}
|
|
|
|
reverse p
|
|
|
|
{{r ~> linkedList r (rev ls)}}.
|
|
|
|
Proof.
|
|
|
|
unfold reverse.
|
|
|
|
simp.
|
|
|
|
step.
|
|
|
|
loop_inv (fun o => exists ls1 ls2, [| ls = rev_append ls1 ls2 |]
|
|
|
|
* linkedList (fst (valueOf o)) ls2
|
|
|
|
* linkedList (snd (valueOf o)) ls1
|
|
|
|
* [| match o with
|
|
|
|
| Done (p, _) => p = ^0
|
|
|
|
| _ => True
|
|
|
|
end |])%sep.
|
|
|
|
cases (weq a (^0)); simp.
|
|
|
|
step.
|
2018-04-29 01:23:41 +00:00
|
|
|
cancel.
|
2018-04-29 20:57:47 +00:00
|
|
|
step.
|
|
|
|
setoid_rewrite (linkedList_nonnull _ _ n).
|
|
|
|
step.
|
|
|
|
simp.
|
|
|
|
step.
|
|
|
|
step.
|
|
|
|
simp.
|
|
|
|
step.
|
|
|
|
setoid_rewrite (linkedList_nonnull _ _ n).
|
|
|
|
cancel.
|
|
|
|
simp.
|
|
|
|
setoid_rewrite linkedList_null.
|
|
|
|
cancel.
|
|
|
|
equality.
|
|
|
|
simp.
|
|
|
|
step.
|
|
|
|
cancel.
|
|
|
|
simp.
|
|
|
|
setoid_rewrite linkedList_null.
|
|
|
|
cancel.
|
|
|
|
simp.
|
2018-04-29 00:31:01 +00:00
|
|
|
cancel.
|
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Opaque reverse.
|
|
|
|
End MixedEmbedded.
|
|
|
|
|
|
|
|
|
|
|
|
(** * A simple C-like language with just two data types *)
|
|
|
|
|
|
|
|
Module DeeplyEmbedded(Import BW : BIT_WIDTH).
|
|
|
|
Definition wrd := word bit_width.
|
|
|
|
|
|
|
|
Inductive exp :=
|
|
|
|
| Var (x : var)
|
|
|
|
| Const (n : wrd)
|
|
|
|
| Add (e1 e2 : exp)
|
|
|
|
| Head (e : exp)
|
|
|
|
| Tail (e : exp)
|
|
|
|
| NotNull (e : exp).
|
|
|
|
|
|
|
|
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, sumbool (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 e1 e2 => match expType e1, expType e2 with
|
|
|
|
| Some Scalar, Some Scalar => Some Scalar
|
|
|
|
| _, _ => None
|
|
|
|
end
|
|
|
|
| Head x => match expType x with
|
|
|
|
| Some (ListPointer t) => Some t
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
| Tail x => match expType x with
|
|
|
|
| Some (ListPointer t) => Some (ListPointer t)
|
|
|
|
| _ => None
|
|
|
|
end
|
|
|
|
| NotNull e1 => match expType e1 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.
|
|
|
|
|
|
|
|
Definition heap := fmap (wrd) (wrd * wrd).
|
|
|
|
Definition valuation := fmap var wrd.
|
|
|
|
|
|
|
|
Inductive eval : heap -> valuation -> exp -> wrd -> 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) n
|
|
|
|
| VAdd : forall H V e1 e2 n1 n2,
|
|
|
|
eval H V e1 n1
|
|
|
|
-> eval H V e2 n2
|
|
|
|
-> eval H V (Add e1 e2) (n1 ^+ n2)
|
|
|
|
| VHead : forall H V e1 p ph pt,
|
|
|
|
eval H V e1 p
|
|
|
|
-> H $? p = Some (ph, pt)
|
|
|
|
-> eval H V (Head e1) ph
|
|
|
|
| VTail : forall H V e1 p ph pt,
|
|
|
|
eval H V e1 p
|
|
|
|
-> H $? p = Some (ph, pt)
|
|
|
|
-> eval H V (Tail e1) pt
|
|
|
|
| VNotNull : forall H V e1 p,
|
|
|
|
eval H V e1 p
|
|
|
|
-> eval H V (NotNull e1) (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 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 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 n
|
|
|
|
-> n <> ^0
|
|
|
|
-> step (H, V, IfThenElse e s1 s2) (H, V, s1)
|
|
|
|
| StIfElse : forall H V e s1 s2,
|
|
|
|
eval H V e (^0)
|
|
|
|
-> step (H, V, IfThenElse e s1 s2) (H, V, s2)
|
|
|
|
| StWhileTrue : forall H V e s1 n,
|
|
|
|
eval H V e 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 (^0)
|
|
|
|
-> step (H, V, WhileLoop e s1) (H, V, Skip).
|
|
|
|
|
|
|
|
Definition trsys_of (H : heap) (V : valuation) (s : stmt) := {|
|
|
|
|
Initial := {(H, V, s)};
|
|
|
|
Step := step
|
|
|
|
|}.
|
|
|
|
End DeeplyEmbedded.
|
|
|
|
|
|
|
|
|
|
|
|
(** * Connecting the two *)
|
|
|
|
|
|
|
|
Module MixedToDeep(Import BW : BIT_WIDTH).
|
|
|
|
Module Import DE := DeeplyEmbedded(BW).
|
|
|
|
Module Import ME := MixedEmbedded(BW).
|
|
|
|
|
|
|
|
Inductive translate_exp (V : valuation) : forall {A}, A -> exp -> Prop :=
|
|
|
|
| TrAdd : forall (v1 v2 : wrd) e1 e2,
|
|
|
|
translate_exp V v1 e1
|
|
|
|
-> translate_exp V v2 e2
|
|
|
|
-> translate_exp V (v1 ^+ v2) (Add e1 e2)
|
|
|
|
| TrVar : forall x v,
|
|
|
|
V $? x = Some v
|
|
|
|
-> translate_exp V v (Var x)
|
|
|
|
| TrConst : forall v,
|
|
|
|
translate_exp V v (Const v).
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Fixpoint couldWrite (x : var) (s : stmt) : bool :=
|
|
|
|
match s with
|
|
|
|
| Assign y _ => if x ==v y then true else false
|
|
|
|
| Skip
|
|
|
|
| WriteHead _ _
|
|
|
|
| WriteTail _ _ => false
|
|
|
|
| Seq s1 s2
|
|
|
|
| IfThenElse _ s1 s2 => couldWrite x s1 || couldWrite x s2
|
|
|
|
| WhileLoop _ s1 => couldWrite x s1
|
|
|
|
end.
|
|
|
|
|
2018-04-30 00:33:51 +00:00
|
|
|
Inductive translate_result (out : var) (V : valuation) (v : wrd) : stmt -> Prop :=
|
|
|
|
| TrReturn : forall e,
|
2018-04-29 20:57:47 +00:00
|
|
|
translate_exp V v e
|
2018-04-30 00:33:51 +00:00
|
|
|
-> translate_result out V v (Assign out e)
|
|
|
|
| TrReturned :
|
2018-04-29 20:57:47 +00:00
|
|
|
V $? out = Some v
|
2018-04-30 00:33:51 +00:00
|
|
|
-> translate_result out V v Skip.
|
|
|
|
|
|
|
|
Inductive translate {RT : Set} (translate_return : valuation -> RT -> stmt -> Prop)
|
|
|
|
: valuation -> forall {A}, cmd A -> stmt -> Prop :=
|
|
|
|
| TrDone : forall V (v : RT) s,
|
|
|
|
translate_return V v s
|
|
|
|
-> translate translate_return V (Return v) s
|
2018-04-29 20:57:47 +00:00
|
|
|
| TrAssign : forall V (B : Set) (v : wrd) (c : wrd -> cmd B) e x s1,
|
|
|
|
translate_exp V v e
|
2018-04-30 00:33:51 +00:00
|
|
|
-> (forall w, translate translate_return (V $+ (x, w)) (c w) s1)
|
|
|
|
-> translate translate_return V (Bind (Return v) c) (Seq (Assign x e) s1)
|
2018-04-29 20:57:47 +00:00
|
|
|
| TrAssigned : forall V (B : Set) (v : wrd) (c : wrd -> cmd B) x s1,
|
|
|
|
V $? x = Some v
|
2018-04-30 00:33:51 +00:00
|
|
|
-> translate translate_return (V $+ (x, v)) (c v) s1
|
|
|
|
-> translate translate_return V (Bind (Return v) c) (Seq Skip s1).
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
Example adder (a b c : wrd) :=
|
|
|
|
Bind (Return (a ^+ b)) (fun ab => Return (ab ^+ c)).
|
|
|
|
|
|
|
|
Ltac freshFor vm k :=
|
|
|
|
let rec keepTrying x :=
|
|
|
|
let H := fresh in
|
|
|
|
(assert (H : vm $? x = None) by (simplify; equality);
|
|
|
|
clear H; k x)
|
|
|
|
|| let x' := eval simpl in (x ++ "'")%string in keepTrying x' in
|
|
|
|
keepTrying "tmp".
|
|
|
|
|
|
|
|
Ltac translate :=
|
|
|
|
match goal with
|
|
|
|
| [ |- translate_exp _ (_ ^+ _) _ ] => eapply TrAdd
|
|
|
|
| [ |- translate_exp ?V ?v _ ] =>
|
|
|
|
match V with
|
|
|
|
| context[add _ ?y v] => apply TrVar with (x := y); simplify; equality
|
|
|
|
end
|
|
|
|
|
2018-04-30 00:33:51 +00:00
|
|
|
| [ |- translate _ _ (Return _) _ ] => apply TrDone; apply TrReturn
|
2018-04-29 20:57:47 +00:00
|
|
|
| [ |- translate _ ?V (Bind (Return _) _) _ ] =>
|
|
|
|
freshFor V ltac:(fun y =>
|
|
|
|
eapply TrAssign with (x := y); [ | intro ])
|
|
|
|
end.
|
|
|
|
|
|
|
|
Lemma translate_adder : sig (fun s =>
|
2018-04-30 00:33:51 +00:00
|
|
|
forall a b c, translate (translate_result "result") ($0 $+ ("a", a) $+ ("b", b) $+ ("c", c)) (adder a b c) s).
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
eexists; simplify.
|
|
|
|
unfold adder.
|
|
|
|
repeat translate.
|
|
|
|
Defined.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Definition adder_compiled := Eval simpl in proj1_sig translate_adder.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 21:25:03 +00:00
|
|
|
Record heaps_compat (H : DE.heap) (h : ME.heap) : Prop := {
|
|
|
|
DeepToMixedHd : forall a v1 v2, H $? a = Some (v1, v2) -> h $? a = Some v1;
|
|
|
|
DeepToMixedTl : forall a v1 v2, H $? a = Some (v1, v2) -> h $? (a ^+ ^1) = Some v2;
|
|
|
|
MixedToDeep : forall a v1 v2, h $? a = Some v1 -> h $? (a ^+ ^1) = Some v2
|
|
|
|
-> H $? a = Some (v1, v2)
|
|
|
|
}.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Inductive translated : forall {A}, DE.heap * valuation * stmt -> ME.heap * cmd A -> Prop :=
|
|
|
|
| Translated : forall A H h V s (c : cmd A),
|
2018-04-30 00:33:51 +00:00
|
|
|
translate (translate_result "result") V c s
|
2018-04-29 21:25:03 +00:00
|
|
|
-> heaps_compat H h
|
2018-04-29 20:57:47 +00:00
|
|
|
-> translated (H, V, s) (h, c).
|
|
|
|
|
|
|
|
Lemma eval_translate : forall H V e v,
|
|
|
|
eval H V e v
|
|
|
|
-> forall (v' : wrd), translate_exp V v' e
|
|
|
|
-> v = v'.
|
|
|
|
Proof.
|
|
|
|
induct 1; invert 1; simplify.
|
|
|
|
|
|
|
|
apply inj_pair2 in H2; subst.
|
2018-04-29 00:31:01 +00:00
|
|
|
equality.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply inj_pair2 in H1; subst.
|
2018-04-29 00:31:01 +00:00
|
|
|
equality.
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
apply inj_pair2 in H1; subst.
|
|
|
|
erewrite IHeval1 by eauto.
|
|
|
|
erewrite IHeval2 by eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
equality.
|
2018-04-29 20:57:47 +00:00
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma multistep_bind : forall A h (c1 : cmd A) h' c1',
|
|
|
|
step^* (h, c1) (h', c1')
|
|
|
|
-> forall B (c2 : A -> cmd B), step^* (h, Bind c1 c2) (h', Bind c1' c2).
|
|
|
|
Proof.
|
|
|
|
induct 1; eauto.
|
|
|
|
cases y; simplify.
|
|
|
|
specialize (IHtrc _ _ _ _ _ eq_refl JMeq.JMeq_refl JMeq.JMeq_refl JMeq.JMeq_refl _ c2).
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
2018-04-29 20:57:47 +00:00
|
|
|
Qed.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Lemma step_translate : forall H V s H' V' s',
|
|
|
|
DE.step (H, V, s) (H', V', s')
|
|
|
|
-> forall h (c : cmd wrd) out,
|
2018-04-30 00:33:51 +00:00
|
|
|
translate (translate_result out) V c s
|
2018-04-29 21:25:03 +00:00
|
|
|
-> heaps_compat H h
|
|
|
|
-> exists c' h', ME.step^* (h, c) (h', c')
|
2018-04-30 00:33:51 +00:00
|
|
|
/\ translate (translate_result out) V' c' s'
|
2018-04-29 21:25:03 +00:00
|
|
|
/\ heaps_compat H' h'.
|
2018-04-29 20:57:47 +00:00
|
|
|
Proof.
|
|
|
|
induct 1; invert 1; simplify.
|
|
|
|
|
2018-04-30 00:33:51 +00:00
|
|
|
invert H3.
|
2018-04-29 20:57:47 +00:00
|
|
|
apply inj_pair2 in H1; subst.
|
2018-04-30 00:33:51 +00:00
|
|
|
eapply eval_translate in H4; eauto; subst.
|
2018-04-29 21:25:03 +00:00
|
|
|
do 2 eexists; propositional.
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
2018-04-30 00:33:51 +00:00
|
|
|
apply TrDone; apply TrReturned; simplify; auto.
|
2018-04-29 21:25:03 +00:00
|
|
|
assumption.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-30 00:33:51 +00:00
|
|
|
invert H6.
|
|
|
|
|
|
|
|
invert H6.
|
|
|
|
|
|
|
|
invert H2.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply inj_pair2 in H0; subst.
|
2018-04-29 21:25:03 +00:00
|
|
|
do 2 eexists; propositional.
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply TrcFront.
|
|
|
|
eauto.
|
|
|
|
eauto.
|
|
|
|
replace V' with (V' $+ (x, v)).
|
|
|
|
assumption.
|
|
|
|
maps_equal.
|
|
|
|
symmetry; assumption.
|
2018-04-29 21:25:03 +00:00
|
|
|
assumption.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-30 00:33:51 +00:00
|
|
|
invert H4.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
apply inj_pair2 in H2; subst.
|
|
|
|
invert H0.
|
2018-04-29 21:25:03 +00:00
|
|
|
do 2 eexists; propositional.
|
2018-04-29 01:23:41 +00:00
|
|
|
eauto.
|
2018-04-30 00:33:51 +00:00
|
|
|
eapply TrAssigned.
|
|
|
|
instantiate (1 := x).
|
2018-04-29 01:23:41 +00:00
|
|
|
simplify.
|
2018-04-30 00:33:51 +00:00
|
|
|
eapply eval_translate in H7; eauto.
|
2018-04-29 20:57:47 +00:00
|
|
|
subst.
|
2018-04-29 01:23:41 +00:00
|
|
|
reflexivity.
|
2018-04-29 20:57:47 +00:00
|
|
|
match goal with
|
|
|
|
| [ |- translate _ ?V' _ _ ] => replace V' with (V $+ (x, v)) by (maps_equal; equality)
|
|
|
|
end.
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
2018-04-29 21:25:03 +00:00
|
|
|
assumption.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
invert H0.
|
2018-04-30 00:33:51 +00:00
|
|
|
|
|
|
|
invert H4.
|
|
|
|
|
|
|
|
invert H3.
|
|
|
|
|
|
|
|
invert H4.
|
|
|
|
|
|
|
|
invert H3.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Theorem translated_simulates : forall H V c h s,
|
2018-04-30 00:33:51 +00:00
|
|
|
translate (translate_result "result") V c s
|
2018-04-29 21:25:03 +00:00
|
|
|
-> heaps_compat H h
|
2018-04-29 20:57:47 +00:00
|
|
|
-> simulates (translated (A := wrd)) (DE.trsys_of H V s) (ME.multistep_trsys_of h c).
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
constructor; simplify.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
propositional; subst.
|
|
|
|
eexists; split.
|
|
|
|
econstructor.
|
|
|
|
eassumption.
|
2018-04-29 00:31:01 +00:00
|
|
|
eauto.
|
2018-04-29 21:25:03 +00:00
|
|
|
auto.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 21:25:03 +00:00
|
|
|
invert H2.
|
|
|
|
apply inj_pair2 in H5; subst.
|
2018-04-29 20:57:47 +00:00
|
|
|
cases st1'.
|
2018-04-29 00:31:01 +00:00
|
|
|
cases p.
|
2018-04-29 21:25:03 +00:00
|
|
|
eapply step_translate in H6; eauto.
|
|
|
|
simp.
|
2018-04-29 20:57:47 +00:00
|
|
|
eexists; split; [ | eassumption ].
|
|
|
|
econstructor.
|
|
|
|
assumption.
|
2018-04-29 21:25:03 +00:00
|
|
|
eauto.
|
2018-04-29 00:31:01 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Hint Constructors eval DE.step.
|
|
|
|
|
|
|
|
Lemma translate_exp_sound : forall V v e,
|
|
|
|
translate_exp V v e
|
|
|
|
-> forall H, eval H V e v.
|
2018-04-29 01:23:41 +00:00
|
|
|
Proof.
|
|
|
|
induct 1; simplify; eauto.
|
2018-04-29 20:57:47 +00:00
|
|
|
Qed.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Hint Resolve translate_exp_sound.
|
|
|
|
|
|
|
|
Lemma not_stuck : forall A h (c : cmd A) h' c',
|
|
|
|
step (h, c) (h', c')
|
2018-04-30 00:33:51 +00:00
|
|
|
-> forall out V s, translate (translate_result out) V c s
|
2018-04-29 20:57:47 +00:00
|
|
|
-> forall H, exists p', DE.step (H, V, s) p'.
|
|
|
|
Proof.
|
|
|
|
induct 1; invert 1; simplify.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
2018-04-29 20:57:47 +00:00
|
|
|
econstructor.
|
2018-04-29 01:23:41 +00:00
|
|
|
eauto.
|
|
|
|
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
|
|
|
|
|
|
|
eexists.
|
|
|
|
econstructor.
|
2018-04-29 20:57:47 +00:00
|
|
|
econstructor.
|
2018-04-29 01:23:41 +00:00
|
|
|
eauto.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
eexists.
|
|
|
|
econstructor.
|
2018-04-29 01:23:41 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 21:25:03 +00:00
|
|
|
Theorem hoare_triple_sound : forall P (c : cmd wrd) Q V s h H,
|
2018-04-29 20:57:47 +00:00
|
|
|
hoare_triple P c Q
|
2018-04-29 21:25:03 +00:00
|
|
|
-> P h
|
|
|
|
-> heaps_compat H h
|
2018-04-30 00:33:51 +00:00
|
|
|
-> translate (translate_result "result") V c s
|
2018-04-29 20:57:47 +00:00
|
|
|
-> V $? "result" = None
|
2018-04-29 21:25:03 +00:00
|
|
|
-> invariantFor (DE.trsys_of H V s)
|
2018-04-29 20:57:47 +00:00
|
|
|
(fun p => snd p = Skip
|
|
|
|
\/ exists p', DE.step p p').
|
2018-04-29 01:23:41 +00:00
|
|
|
Proof.
|
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply invariant_weaken.
|
|
|
|
eapply invariant_simulates.
|
|
|
|
apply translated_simulates.
|
|
|
|
eassumption.
|
2018-04-29 21:25:03 +00:00
|
|
|
eassumption.
|
|
|
|
apply invariant_multistepify with (sys := trsys_of h c).
|
2018-04-29 20:57:47 +00:00
|
|
|
eauto using hoare_triple_sound.
|
2018-04-29 21:25:03 +00:00
|
|
|
invert 1; simp.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
cases st2; simplify; subst.
|
2018-04-29 21:25:03 +00:00
|
|
|
invert H6; simplify.
|
|
|
|
apply inj_pair2 in H8; subst.
|
|
|
|
invert H11.
|
|
|
|
apply inj_pair2 in H6; subst.
|
2018-04-30 00:33:51 +00:00
|
|
|
invert H8.
|
2018-04-29 20:57:47 +00:00
|
|
|
right; eexists.
|
|
|
|
econstructor; eauto.
|
|
|
|
auto.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
2018-04-29 21:25:03 +00:00
|
|
|
invert H6; simp.
|
|
|
|
apply inj_pair2 in H8; subst; simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
cases x.
|
2018-04-29 21:25:03 +00:00
|
|
|
eapply not_stuck in H7; eauto.
|
2018-04-29 01:23:41 +00:00
|
|
|
Qed.
|
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Theorem adder_ok : forall a b c,
|
|
|
|
{{emp}}
|
|
|
|
adder a b c
|
|
|
|
{{r ~> [| r = a ^+ b ^+ c |]}}.
|
2018-04-29 00:31:01 +00:00
|
|
|
Proof.
|
2018-04-29 20:57:47 +00:00
|
|
|
unfold adder.
|
2018-04-29 00:31:01 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
step.
|
|
|
|
step.
|
|
|
|
instantiate (1 := (fun r => [| r = a ^+ b |])%sep).
|
|
|
|
cancel.
|
|
|
|
simp.
|
|
|
|
step.
|
|
|
|
cancel.
|
|
|
|
equality.
|
|
|
|
Qed.
|
2018-04-29 01:23:41 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
Theorem adder_compiled_ok : forall a b c,
|
|
|
|
invariantFor (DE.trsys_of $0 ($0 $+ ("a", a) $+ ("b", b) $+ ("c", c)) adder_compiled)
|
|
|
|
(fun p => snd p = Skip
|
|
|
|
\/ exists p', DE.step p p').
|
|
|
|
Proof.
|
2018-04-29 01:23:41 +00:00
|
|
|
simplify.
|
2018-04-29 20:57:47 +00:00
|
|
|
eapply hoare_triple_sound.
|
|
|
|
apply adder_ok.
|
|
|
|
constructor; auto.
|
2018-04-29 21:25:03 +00:00
|
|
|
constructor; simplify; equality.
|
2018-04-29 20:57:47 +00:00
|
|
|
apply (proj2_sig translate_adder).
|
|
|
|
simplify; equality.
|
2018-04-29 01:23:41 +00:00
|
|
|
Qed.
|
2018-04-29 20:57:47 +00:00
|
|
|
End MixedToDeep.
|
2018-04-29 00:31:01 +00:00
|
|
|
|
2018-04-29 20:57:47 +00:00
|
|
|
|
|
|
|
(** * Getting concrete *)
|
|
|
|
|
|
|
|
Module Bw64.
|
|
|
|
Definition bit_width := 64.
|
|
|
|
Theorem bit_width_nonzero : bit_width > 0.
|
|
|
|
Proof.
|
|
|
|
unfold bit_width; linear_arithmetic.
|
|
|
|
Qed.
|
|
|
|
End Bw64.
|
|
|
|
|
|
|
|
Module MixedEmbedded64.
|
|
|
|
Module Import ME := MixedEmbedded(Bw64).
|
|
|
|
End MixedEmbedded64.
|