theory CSLsound
imports Main VHelper Lang
begin

This file contains a soundness proof for CSL (with multiple resources) as presented by O'Hearn and Brookes including the data-race freedom property of CSL. For simplicity, there is a slight difference regarding variable side-conditions: we do not allow resource-owned variables.

(Adapted to Isabelle 2016-1 by Qin Yu and James Brotherston)

Separation logic assertions

A deep embedding of separation logic assertions.

datatype assn =
    Aemp — Empty heap
  | Apointsto exp exp (infixl ⟼ 200) — Singleton heap
  | Astar assn assn (infixl ** 100) — Separating conjunction
  | Awand assn assn — Separating implication
  | Apure bexp — Pure assertion
  | Aconj assn assn — Conjunction
  | Adisj assn assn — Disjunction
  | Aex (nat ⇒ assn) — Existential quantification

Separating conjunction of a finite list of assertions is just a derived assertion.

primrec
  Aistar :: assn list ⇒ assn
where
  Aistar [] = Aemp
| Aistar (P # Ps) = Astar P (Aistar Ps)

primrec
  sat :: state ⇒ assn ⇒ bool (infixl ⊨ 60)
where
  (σ ⊨ Aemp) = (snd σ = empty)
| (σ ⊨ E ⟼ E') = (dom (snd σ) = { edenot E (fst σ) } ∧ (snd σ) (edenot E (fst σ)) = Some (edenot E' (fst σ)))
| (σ ⊨ P ** Q) = (∃h1 h2. (fst σ, h1) ⊨ P ∧ (fst σ, h2) ⊨ Q ∧ snd σ = (h1 ++ h2) ∧ disjoint (dom h1) (dom h2))
| (σ ⊨ Awand P Q) = (∀h. disjoint (dom (snd σ)) (dom h) ∧ (fst σ, h) ⊨ P ⟶ (fst σ, snd σ ++ h) ⊨ Q)
| (σ ⊨ Apure B) = bdenot B (fst σ)
| (σ ⊨ Aconj P Q) = (σ ⊨ P ∧ σ ⊨ Q)
| (σ ⊨ Adisj P Q) = (σ ⊨ P ∨ σ ⊨ Q)
| (σ ⊨ Aex PP) = (∃v. σ ⊨ PP v)

definition
  implies :: assn ⇒ assn ⇒ bool (infixl ⊑ 60)
where
  P ⊑ Q ≜ (∀σ. σ ⊨ P ⟶ σ ⊨ Q)

lemma sat_istar_map_expand:
r ∈ set l
σ ⊨ Aistar (map f l)
⟷ (∃h1 h2. (fst σ, h1) ⊨ f r
∧ (fst σ, h2) ⊨ Aistar (map f (remove1 r l))
∧ snd σ = (h1 ++ h2)
∧ disjoint (dom h1) (dom h2))
apply (case_tac σ, rename_tac s h, clarify)
apply (induction l arbitrary: σ, auto)
apply (intro exI conjI, (simp add: hsimps)+)+
done

Precision

We say that an assertion is precise if for any given heap, there is at most one subheap that satisfies the formula. (The formal definition below says that if there are two such subheaps, they must be equal.)

definition
  precise :: assn ⇒ bool
where
  precise P ≜ ∀h1 h2 h1' h2' s. disjoint (dom h1) (dom h2) ∧ disjoint (dom h1') (dom h2')
                   ∧ h1 ++ h2 = h1' ++ h2' ∧ (s, h1) ⊨ P ∧ (s, h1') ⊨ P
               ⟶ h1 = h1'

A direct consequence of the definition that is more useful in Isabelle, because unfolding the definition slows down Isabelle's simplifier dramatically.

lemma preciseD:
precise P; (s, x) ⊨ P; (s, x') ⊨ P; x ++ y = x' ++ y';
disjoint (dom x) (dom y); disjoint (dom x') (dom y')
x = x' ∧ y = y'
unfolding precise_def
by (drule all5_impD, (erule conjI)+, simp_all, rule map_add_cancel)
   (subst (1 2) map_add_comm, auto simp add: disjoint_def)

The separating conjunction of precise assertions is precise:

lemma precise_istar:
∀x ∈ set l. precise x
precise (Aistar l)
apply (induct l, simp_all (no_asm) add: precise_def)
apply (clarsimp simp add: map_add_assoc [THEN sym])
apply (drule (3) preciseD, simp_all, clarsimp?)+
done

Auxiliary definition for resource environments

definition
  envs :: ('a ⇒ assn) ⇒ 'a list ⇒ 'a list ⇒ assn
where
  envs Γ l l' ≜ Aistar (map Γ (list_minus l l'))

lemma sat_envs_expand:
r ∈ set l; r ∉ set l'; distinct l
σ ⊨ envs Γ l l'
⟷ (∃h1 h2. (fst σ, h1) ⊨ Γ r
∧ (fst σ, h2) ⊨ envs Γ (removeAll r l) l'
∧ snd σ = h1 ++ h2 ∧ disjoint (dom h1) (dom h2))
apply (simp add: envs_def distinct_remove1_removeAll [THEN sym] add: list_minus_remove1)
apply (subst sat_istar_map_expand [where f=Γ and r=r], simp_all)
done

lemma envs_upd:
r ∉ set l
envs (Γ(r := R)) l l' = envs Γ l l'
r ∈ set l'
envs (Γ(r := R)) l l' = envs Γ l l'
by (simp_all add: envs_def)

lemma envs_removeAll_irr:
r ∉ set l
envs Γ l (removeAll r l') = envs Γ l l'
by (simp add: envs_def list_minus_removeAll_irr)

lemma envs_removeAll2:
r ∈ set l'
envs Γ (removeAll r l) (removeAll r l') = envs Γ l l'
by (simp add: envs_def list_minus_removeAll2)

lemma envs_app:
disjoint (set x) (set z)
envs Γ (x @ z) (y @ z) = envs Γ x y
disjoint (set z) (set x)
envs Γ (z @ x) (z @ y) = envs Γ x y
by (simp_all add: envs_def list_minus_appl list_minus_appr)

Free variables, substitutions

primrec
  fvA :: assn ⇒ var set
where
  fvA (Aemp) = {}
| fvA (Apure B) = fvB B
| fvA (e1 ⟼ e2) = (fvE e1 ∪ fvE e2)
| fvA (P ** Q) = (fvA P ∪ fvA Q)
| fvA (Awand P Q) = (fvA P ∪ fvA Q)
| fvA (Aconj P Q) = (fvA P ∪ fvA Q)
| fvA (Adisj P Q) = (fvA P ∪ fvA Q)
| fvA (Aex P) = (x. fvA (P x))

definition
  fvAs :: ('a ⇒ assn) ⇒ var set
where
  fvAs Γ = (x. fvA (Γ x))

primrec
  subA :: var ⇒ exp ⇒ assn ⇒ assn
where
  subA x E (Aemp) = Aemp
| subA x E (Apure B) = Apure (subB x E B)
| subA x E (e1 ⟼ e2) = (subE x E e1 ⟼ subE x E e2)
| subA x E (P ** Q) = (subA x E P ** subA x E Q)
| subA x E (Awand P Q) = Awand (subA x E P) (subA x E Q)
| subA x E (Aconj P Q) = Aconj (subA x E P) (subA x E Q)
| subA x E (Adisj P Q) = Adisj (subA x E P) (subA x E Q)
| subA x E (Aex PP) = Aex (λn. subA x E (PP n))

lemma subA_assign:
(s,h) ⊨ subA x E P ⟷ (s(x := edenot E s), h) ⊨ P
by (induct P arbitrary: h, simp_all add: subE_assign subB_assign fun_upd_def)

lemma fvA_istar[simp]:
fvA (Aistar Ps) = (P ∈ set Ps. fvA P)
by (induct Ps, simp_all)

Proposition 4.2 for assertions

lemma assn_agrees:
agrees (fvA P) s s'
(s, h) ⊨ P ⟷ (s', h) ⊨ P
apply (induct P arbitrary: h, simp_all add: bexp_agrees)
apply (clarsimp, (subst exp_agrees, simp_all)+ )
apply (rule iff_exI, simp add: agrees_def)
done

Corollaries of Proposition 4.2, useful for automation.

lemma assns_agrees:
agrees (fvAs J) s s'
(s, h) ⊨ envs J l1 l2 ⟷ (s', h) ⊨ envs J l1 l2
apply (clarsimp simp add: envs_def, subst assn_agrees, simp_all)
apply (erule agrees_search, auto simp add: fvAs_def)
done

corollary assns_agreesE[elim]:
(s, h) ⊨ envs J l1 l2 ; agrees (fvAs J) s s'
(s',h) ⊨ envs J l1 l2
by (simp add: assns_agrees)

corollary assn_agrees2[simp]:
x ∉ fvA P
(s(x := v), h) ⊨ P ⟷ (s, h) ⊨ P
by (rule assn_agrees, simp add: agrees_def)

corollary assns_agrees2[simp]:
x ∉ fvAs J
(s(x := v), h) ⊨ envs J l l' ⟷ (s, h) ⊨ envs J l l'
by (rule assns_agrees, simp add: agrees_def)

Meaning of CSL judgments

Definition 5.1: Configuration safety.

primrec
  safe :: nat ⇒ cmd ⇒ stack ⇒ heap ⇒ (rname ⇒ assn) ⇒ assn ⇒ bool
where
  safe 0 C s h Γ Q = True
| safe (Suc n) C s h Γ Q = (
            (C = Cskip ⟶ (s, h) ⊨ Q)
          ∧ (∀hF. disjoint (dom h) (dom hF) ⟶ ¬ aborts C (s, h ++ hF))
          ∧ accesses C s ⊆ dom h
          ∧ (∀hJ hF C' σ'.
                  red C (s,h ++ hJ ++ hF) C' σ'
                 ⟶ (s, hJ) ⊨ envs Γ (llocked C') (llocked C)
                 ⟶ (disjoint (dom h) (dom hJ) ∧ disjoint (dom h) (dom hF) ∧ disjoint (dom hJ) (dom hF))
                 ⟶ (∃h' hJ'.
                         snd σ' = h' ++ hJ' ++ hF
                       ∧ disjoint (dom h') (dom hJ') ∧ disjoint (dom h') (dom hF) ∧ disjoint (dom hJ') (dom hF)
                       ∧ (fst σ', hJ') ⊨ envs Γ (llocked C) (llocked C')
                       ∧ safe n C' (fst σ') h' Γ Q)))

The predicate safe n C s h Γ Q says that the command C and the logical state (s, h) are safe with respect to the resource environment Γ and the postcondition Q for n execution steps. Intuitively, any configuration is safe for zero steps. For n + 1 steps, it must (i) satisfy the postcondition if it is a terminal configuration, (ii) not abort, (iii) access memory only inside its footprint, and (iv) after any step it does, re-establish the resource invariant and be safe for another n steps.

Definition 5.2: The meaning of CSL judgements.

definition
  CSL :: (rname ⇒ assn) ⇒ assn ⇒ cmd ⇒ assn ⇒ bool
  (_ ⊢ { _ } _ { _ })
where
  Γ ⊢ {P} C {Q} ≜ (user_cmd C ∧ (∀n s h. (s, h) ⊨ P ⟶ safe n C s h Γ Q))

Basic properties of Definition 5.1

Proposition 4.3: Monotonicity with respect to the step number.

lemma safe_mon:
safe n C s h J Q; m ≤ n
safe m C s h J Q
apply (induct m arbitrary: C s n h l, simp)
apply (case_tac n, clarify)
apply (simp only: safe.simps, clarsimp)
apply (drule all5D, drule (2) imp3D, simp, clarsimp)
apply (rule_tac x=h' in exI, rule_tac x=hJ' in exI, simp)
done

Proposition 4.4: Safety depends only the free variables of C, Q, and Γ.

lemma safe_agrees:
safe n C s h Γ Q ;
agrees (fvC C ∪ fvA Q ∪ fvAs Γ) s s'
safe n C s' h Γ Q
apply (induct n arbitrary: C s s' h bl, simp, simp only: safe.simps, clarify)
apply (rule conjI, clarsimp, subst assn_agrees, subst agreesC, assumption+)
apply (rule conjI, clarsimp)
 apply (drule_tac aborts_agrees, simp, fast, simp, simp)
apply (rule conjI, subst (asm) accesses_agrees, simp_all)
apply (clarify, drule_tac X=fvC C ∪ fvAs Γ ∪ fvA Q in red_agrees,
       simp (no_asm), fast, simp (no_asm), fast, clarify)
apply (drule (1) all5_impD, clarsimp)
apply (drule impD, erule assns_agreesE, simp add: agreesC, clarify)
apply (rule_tac x=h' and y=hJ' in ex2I, simp add: hsimps)
apply (rule conjI, erule assns_agreesE, subst agreesC, assumption)
apply (erule (1) mall4_imp2D, simp add: agreesC)
apply (drule red_properties, auto)
done

Soundness of the proof rules

Skip

lemma safe_skip[intro!]:
(s,h) ⊨ Q
safe n Cskip s h J Q
by (induct n, simp_all)

theorem rule_skip:
Γ ⊢ {P} Cskip {P}
by (auto simp add: CSL_def)

Parallel composition

lemma safe_par:
safe n C1 s h1 J Q1; safe n C2 s h2 J Q2;
wf_cmd (Cpar C1 C2);
disjoint (dom h1) (dom h2);
disjoint (fvC C1 ∪ fvA Q1 ∪ fvAs J) (wrC C2);
disjoint (fvC C2 ∪ fvA Q2 ∪ fvAs J) (wrC C1)
safe n (Cpar C1 C2) s (h1 ++ h2) J (Q1 ** Q2)
apply (induct n arbitrary: C1 C2 s h1 h2 bl1 bl2, simp, clarsimp)
apply (rule conjI, clarify)
 — no aborts
 apply (erule aborts.cases, simp_all add: hsimps)
    apply (clarify, drule_tac a=h2 ++ hF in all_impD, simp_all add: hsimps)
   apply (clarify, drule_tac allD, drule_tac a=h1 ++ hF in all_impD, simp_all add: hsimps)
 — no races
 apply (clarsimp, erule notE, erule disjoint_search [rotated], erule disjoint_search,
        erule order_trans [OF writes_accesses])+
— accesses
apply (rule conjI, erule order_trans, simp)+
— step
 apply (clarsimp, erule red_par_cases)
 — C1 does a step
  apply (clarify, drule_tac a=hJ and b=h2 ++ hF in all2D, drule all3_impD,
         simp_all add: hsimps envs_app locked_eq, clarsimp)
  apply (rule_tac x=h' ++ h2 in exI, rule_tac x=hJ' in exI, simp add: hsimps)
  apply (frule (1) red_wf_cmd, drule red_properties, clarsimp)
  apply (drule_tac a=C1' and b=C2 in mall2D, simp add: hsimps)
  apply (subst map_add_commute, simp add: hsimps)
  apply (drule mall3_imp2D, erule_tac[3] mimp3D, simp_all add: hsimps)
  apply (rule_tac s=s in safe_agrees)
  apply (rule_tac n=Suc n in safe_mon, simp add: hsimps, simp)
  apply (fastforce simp add: agreesC disjoint_commute)
  apply (intro conjI | erule (1) disjoint_search)+
 — C2 does a step
  apply (clarify, drule_tac a=hJ and b=h1 ++ hF in all2D, drule all3_imp2D,
         simp_all add: hsimps envs_app, clarsimp)
  apply (rule_tac x=h1 ++ h' in exI, rule_tac x=hJ' in exI, simp add: hsimps)
  apply (frule (1) red_wf_cmd, drule red_properties, clarsimp)
  apply (drule_tac a=C1 and b=C2' in mall2D, simp add: hsimps)
  apply (drule mall3_imp2D, erule_tac[3] mimp3D, simp_all add: hsimps)
  apply (rule_tac s=s in safe_agrees)
   apply (rule_tac n=Suc n in safe_mon, simp add: hsimps, simp)
  apply (subst agreesC, fastforce, fastforce, fastforce)
  — Par skip skip
  apply (clarify)
  apply (rule_tac x=h1 ++ h2 in exI, rule_tac x=hJ in exI, simp add: hsimps)
  apply (rule_tac safe_skip, simp, (rule exI, erule conjI)+, simp)
done

theorem rule_par:
Γ ⊢ {P1} C1 {Q1} ; Γ ⊢ {P2} C2 {Q2};
disjoint (fvC C1 ∪ fvA Q1 ∪ fvAs Γ) (wrC C2);
disjoint (fvC C2 ∪ fvA Q2 ∪ fvAs Γ) (wrC C1)
Γ ⊢ {P1 ** P2} (Cpar C1 C2) {Q1 ** Q2}
by (auto simp add: CSL_def intro!: safe_par)

Resource declaration

lemma safe_resource:
safe n C s h (Γ(r := R)) Q; wf_cmd C; disjoint (fvA R) (wrC C)
(∀hR. r ∉ locked C ⟶ disjoint (dom h) (dom hR) ⟶ (s,hR) ⊨ R ⟶ safe n (Cresource r C) s (h ++ hR) Γ (Q ** R))
∧ (r ∈ locked C ⟶ safe n (Cresource r C) s h Γ (Q ** R))
apply (induct n arbitrary: C s h, simp, clarsimp)
apply (rule conjI, clarify)
 apply (rule conjI, clarify)
  — no aborts
  apply (erule aborts.cases, simp_all, clarsimp)
  apply (drule_tac a=hR ++ hF in all_impD, simp, simp add: hsimps)
 — accesses
 apply (rule conjI, erule order_trans, simp)
 — step
 apply (clarify, frule red_properties, clarsimp)
 apply (erule red.cases, simp_all, clarsimp, rename_tac C s C' s' hh)
 — normal step
  apply (case_tac r ∈ set (llocked C'), simp_all add: locked_eq)
   apply (drule_tac a=hJ ++ hR and b=hF and c=C' and d=s' and e=hh in all5D, simp add: hsimps)
   apply (drule impD, subst sat_envs_expand [where r=r], simp_all)
     apply (rule wf_cmd_distinct_locked, erule (1) red_wf_cmd)
    apply (intro exI conjI, simp, simp_all add: envs_upd)
   apply (clarsimp simp add: envs_removeAll_irr)
   apply (drule (1) mall3_imp2D, erule (1) red_wf_cmd)
   apply (drule mimpD, fast, clarsimp)
   apply (intro exI conjI, simp+)
  r ∉ locked C'
  apply (drule_tac a=hJ and b=hR ++ hF and c=C' and d=s' and e=hh in all5D, simp add: hsimps)
  apply (clarsimp simp add: envs_upd)
  apply (drule (1) mall3_imp2D, erule (1) red_wf_cmd)
  apply (drule mimpD, fast, clarsimp)
  apply (rule_tac x=h' ++ hR and y=hJ' in ex2I, simp add: hsimps)
  apply (drule_tac a=hR in all_imp2D, simp_all add: hsimps)
  apply (subst assn_agrees, simp_all, fastforce)
 — skip
 apply (clarsimp simp add: envs_def)
 apply (rule_tac x=h ++ hR in exI, simp add: hsimps, rule safe_skip, simp, fast)
— not user cmd
apply (clarsimp)
apply (rule conjI, clarsimp, erule aborts.cases, simp_all, clarsimp, clarsimp)
apply (frule red_properties, clarsimp)
apply (erule red.cases, simp_all, clarsimp, rename_tac C s C' s' hh)
apply (drule_tac a=hJ and b=hF and c=C' and d=s' and e=hh in all5D, simp add: hsimps)
apply (clarsimp simp add: envs_upd envs_removeAll2)
apply (drule (1) mall3_imp2D, erule (1) red_wf_cmd)
apply (drule mimpD, fast, clarsimp)
apply (case_tac r ∈ set (llocked C'), simp_all add: locked_eq envs_removeAll2 envs_upd)
 apply (intro exI conjI, simp+)
apply (subst (asm) sat_envs_expand [where r=r], simp_all add: wf_cmd_distinct_locked,
       clarsimp, rename_tac hR' hJ')
apply (drule (2) all_imp2D, rule_tac x=h' ++ hR' and y=hJ' in ex2I, simp add: hsimps envs_upd)
done

theorem rule_resource:
Γ(r := R) ⊢ {P} C {Q} ; disjoint (fvA R) (wrC C)
Γ ⊢ {P ** R} (Cresource r C) {Q ** R}
by (clarsimp simp add: CSL_def, drule (1) all3_impD)
   (auto simp add: locked_eq dest!: safe_resource)

Frame rule

The safety of the frame rule can be seen as a special case of the parallel composition rule taking one thread to be the empty command.

lemma safe_frame:
safe n C s h J Q;
disjoint (dom h) (dom hR);
disjoint (fvA R) (wrC C);
(s,hR) ⊨ R
safe n C s (h ++ hR) J (Q ** R)
apply (induct n arbitrary: C s h hR, simp, clarsimp)
apply (rule conjI, clarify, fast)
apply (rule conjI, clarify)
 — no aborts
 apply (drule_tac a=hR ++ hF in all_impD, simp, simp add: hsimps)
— accesses
apply (rule conjI, erule order_trans, simp)
— step
apply (clarify, frule red_properties, clarsimp)
apply (drule_tac a=hJ and b=hR ++ hF in all3D, simp add: hsimps, drule (1) all2_impD, clarsimp)
apply (rule_tac y=hJ' and x=h' ++ hR in ex2I, clarsimp simp add: hsimps)
apply (subst map_add_commute, simp add: hsimps)
apply (drule mall4D, erule mimp4D, simp_all add: hsimps)
 apply (erule (1) disjoint_search)
apply (subst assn_agrees, simp_all, fastforce)
done

theorem rule_frame:
Γ ⊢ {P} C {Q} ; disjoint (fvA R) (wrC C)
Γ ⊢ {P ** R} C {Q ** R}
by (auto simp add: CSL_def intro: safe_frame)

Conditional critical regions

lemma safe_inwith:
safe n C s h Γ (Q ** Γ r); wf_cmd (Cinwith r C)
safe n (Cinwith r C) s h Γ Q
apply (induct n arbitrary: C s h, simp_all, clarify)
apply (rule conjI)
 apply (clarify, erule aborts.cases, simp_all, clarsimp)
apply (clarify, erule_tac red.cases, simp_all, clarify)
 apply (frule (1) red_wf_cmd)
 apply (drule (1) all5_imp2D, simp_all)
 apply (simp add: envs_def list_minus_removeAll [THEN sym] locked_eq)+
 apply fast
apply (clarsimp simp add: envs_def, rename_tac hQ hJ)
apply (rule_tac x=hQ and y=hJ in ex2I, simp add: hsimps, fast)
done

theorem rule_with:
Γ ⊢ {Aconj (P ** Γ r) (Apure B)} C {Q ** Γ r}
Γ ⊢ {P} Cwith r B C {Q}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI, clarify, erule aborts.cases, simp_all)
apply (clarify, erule red.cases, simp_all, clarsimp)
apply (simp add: envs_def, rule_tac x=h ++ hJ in exI, simp)
apply (rule safe_inwith, erule all3_impD, auto dest: user_cmdD)
done

Sequential composition

lemma safe_seq:
safe n C s h J Q; user_cmd C2;
∀m s' h'. m ≤ n ∧ (s', h') ⊨ Q ⟶ safe m C2 s' h' J R
safe n (Cseq C C2) s h J R
apply (induct n arbitrary: C s h l, simp, clarsimp)
apply (rule conjI, clarsimp)
 apply (erule aborts.cases, simp_all, clarsimp)
apply (clarsimp, erule red.cases, simp_all)
 — Seq1
 apply (clarify, rule_tac x=h and y=hJ in ex2I, simp)
— Seq2
apply (clarify, drule (1) all5_impD, clarsimp)
apply (drule (1) mall3_impD, rule_tac x=h' and y=hJ' in ex2I, simp)
done

theorem rule_seq:
Γ ⊢ {P} C1 {Q} ; Γ ⊢ {Q} C2 {R}
Γ ⊢ {P} Cseq C1 C2 {R}
by (auto simp add: CSL_def intro!: safe_seq)

Conditionals (if-then-else)

theorem rule_if:
Γ ⊢ {Aconj P (Apure B)} C1 {Q} ;
Γ ⊢ {Aconj P (Apure (Bnot B))} C2 {Q}
Γ ⊢ {P} Cif B C1 C2 {Q}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (intro conjI allI impI notI, erule aborts.cases, simp_all)
apply (elim conjE)
apply (erule red.cases, simp_all)
apply (clarsimp, intro exI, (rule conjI, simp)+, simp)+
done

While

lemma safe_while:
Γ ⊢ {Aconj P (Apure B)} C {P} ; (s, h) ⊨ P
safe n (Cwhile B C) s h Γ (Aconj P (Apure (Bnot B)))
apply (induct n arbitrary: s h, simp, clarsimp)
apply (intro conjI allI impI notI, erule aborts.cases, simp_all)
apply (elim conjE, erule red.cases, simp_all)
apply (clarsimp, intro exI, (rule conjI, simp)+)
apply (subgoal_tac ∀m s h. m ≤ n ∧ (s, h) ⊨ P ⟶ safe m (Cwhile B C) s h Γ (Aconj P (Apure (Bnot B))))
 apply (case_tac n, simp, clarsimp)
 apply (intro conjI allI impI notI, erule aborts.cases, simp_all)
 apply (elim conjE, erule red.cases, simp_all)
  apply (clarsimp, intro exI, (rule conjI, simp)+)
  apply (clarsimp simp add: CSL_def, rule safe_seq, blast, simp, clarsimp)
 apply (clarsimp, intro exI, (rule conjI, simp)+, rule safe_skip, simp)
apply (clarsimp, drule (1) mall2_impD, erule (1) safe_mon)
done

theorem rule_while:
Γ ⊢ {Aconj P (Apure B)} C {P}
Γ ⊢ {P} Cwhile B C {Aconj P (Apure (Bnot B))}
by (auto simp add: CSL_def intro: safe_while)

Local variable declaration

lemma safe_inlocal:
safe n C (s(x:=v)) h Γ Q ; x ∉ fvA Q ∪ fvAs Γ
safe n (Cinlocal x v C) s h Γ Q
apply (induct n arbitrary: s h v C, simp, clarsimp)
apply (intro conjI allI impI notI, erule aborts.cases, simp_all, clarsimp)
apply (elim conjE, erule red.cases, simp_all)
 apply (clarsimp, drule (1) all5_imp2D, simp)
 apply (clarsimp, intro exI, (rule conjI, simp)+, simp)
apply (fastforce simp add: safe_skip)
done

theorem rule_local:
Γ ⊢ {Aconj P (Apure (Beq (Evar x) E))} C {Q} ;
x ∉ fvA P ∪ fvA Q ∪ fvAs Γ ∪ fvE E
Γ ⊢ {P} Clocal x E C {Q}
apply (auto simp add: CSL_def intro: safe_inlocal)
apply (case_tac n, simp_all)
apply (intro conjI allI impI notI, erule aborts.cases, simp_all)
apply (elim conjE, erule red.cases, simp_all, clarsimp)
apply (intro exI conjI, simp_all, rule safe_inlocal, simp_all)
done

Basic commands (Assign, Read, Write, Alloc, Free)

theorem rule_assign:
x ∉ fvAs Γ
Γ ⊢ {subA x E Q} Cassign x E {Q}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI, clarsimp, erule aborts.cases, simp_all)
apply (clarsimp, erule red.cases, simp_all)
apply (rule_tac x=h in exI, rule_tac x=hJ in exI,
       clarsimp simp add: subA_assign)
done

theorem rule_read:
x ∉ fvE E ∪ fvE E' ∪ fvAs Γ
Γ ⊢ {E ⟼ E'} Cread x E {Aconj (E ⟼ E') (Apure (Beq (Evar x) E'))}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI)
 apply (clarsimp, erule aborts.cases, simp_all, clarsimp simp add: dom_def)
apply (clarify, erule red.cases, simp_all, elim exE conjE, hypsubst)
apply (rule_tac x=h in exI, rule_tac x=hJ in exI, clarsimp)
apply (simp add: disjoint_def, clarsimp, elim disjE, clarsimp+)
done

theorem rule_write:
Γ ⊢ {E ⟼ E0} Cwrite E E' {E ⟼ E'}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI)
 apply (clarsimp, erule aborts.cases, simp_all, clarsimp simp add: dom_def)
apply (clarify, erule red.cases, simp_all, clarsimp)
apply (rule_tac x=h(edenot E sa ↦ edenot E' sa) in exI, rule_tac x=hJ in exI, simp)
apply (rule conjI [rotated], clarsimp)
apply (subst map_add_assoc [THEN sym], subst map_add_commute, simp add: hsimps)
apply (subst map_add_upd [THEN sym], simp add: hsimps del: map_add_upd)
done

theorem rule_alloc:
x ∉ fvE E ∪ fvAs Γ
Γ ⊢ {Aemp} Calloc x E {Evar x ⟼ E}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI, clarsimp, erule aborts.cases, simp_all)
apply (clarify)
apply (erule red.cases, simp_all)
apply (rule_tac x=Map.empty(v ↦ edenot E s) in exI, rule_tac x=hJ in exI, simp)
apply (elim conjE, hypsubst, simp, elim conjE)
apply (clarsimp simp add: map_add_upd_left disjoint_def)
done

theorem rule_free:
Γ ⊢ {E ⟼ E0} Cdispose E {Aemp}
apply (clarsimp simp add: CSL_def)
apply (case_tac n, simp, clarsimp)
apply (rule conjI)
 apply (clarsimp, erule aborts.cases, simp_all, clarsimp simp add: dom_def)
apply (clarify, erule red.cases, simp_all, clarsimp)
apply (rule_tac x=h(edenot E sa := None) in exI, rule_tac x=hJ in exI, simp)
apply (clarsimp, rule ext, simp, clarify, erule dom_eqD, simp)
done

Simple structural rules (Conseq, Disj, Ex)

lemma safe_conseq:
safe n C s h Γ Q ; Q ⊑ Q'
safe n C s h Γ Q'
apply (induct n arbitrary: C s h, simp, clarsimp simp add: implies_def)
apply (drule (2) all5_imp2D, simp_all, clarsimp)
apply (drule (1) mall3_impD, rule_tac x=h' and y=hJ' in ex2I, simp)
done

theorem rule_conseq:
Γ ⊢ {P} C {Q} ; P' ⊑ P ; Q ⊑ Q'
Γ ⊢ {P'} C {Q'}
by (fastforce simp add: CSL_def implies_def elim!: safe_conseq)

theorem rule_disj:
Γ ⊢ {P1} C {Q1}; Γ ⊢ {P2} C {Q2}
Γ ⊢ {Adisj P1 P2} C {Adisj Q1 Q2}
by (clarsimp simp add: CSL_def, safe)
   (rule safe_conseq, simp_all add: implies_def, drule (2) all3_impD, force)+

theorem rule_ex:
∀n. (Γ ⊢ {P n} C {Q n})
Γ ⊢ {Aex P} C {Aex Q}
by (clarsimp simp add: CSL_def, rule_tac Q = Q v in safe_conseq,
    auto simp add: implies_def)

Conjunction rule

lemma safe_conj:
safe n C s h Γ Q1;
safe n C s h Γ Q2;
∀r. precise (Γ r)
safe n C s h Γ (Aconj Q1 Q2)
apply (induct n arbitrary: C s h, simp, clarsimp)
apply (drule (1) all5_impD, clarsimp)+
apply (rule_tac x=h' and y=hJ' in ex2I, simp)
apply (erule mall3_imp2D, simp_all, drule map_add_cancel, simp_all)
apply (drule_tac s=a and y=h' and y'=h'a in preciseD [rotated], simp_all add: hsimps)
apply (auto simp add: envs_def precise_istar)
done

theorem rule_conj:
Γ ⊢ {P1} C {Q1};
Γ ⊢ {P2} C {Q2};
∀r. precise (Γ r)
Γ ⊢ {Aconj P1 P2} C {Aconj Q1 Q2}
by (auto simp add: CSL_def intro: safe_conj)

Auxiliary variables

lemma safe_aux:
safe n C s h Γ Q; disjoint X (fvC (rem_vars X C) ∪ fvA Q ∪ fvAs Γ)
safe n (rem_vars X C) s h Γ Q
apply (induct n arbitrary: C s h, simp_all)
apply (intro conjI impI allI, clarsimp)
apply (fastforce intro: aborts_remvars)
apply (elim conjE, erule order_trans [OF accesses_remvars])
apply (clarsimp, frule red_properties, drule aux_red, simp_all)
apply (drule_tac a=hJ ++ hF in allD, simp add: hsimps)
apply (clarsimp, drule (2) all5_imp2D, clarsimp)
apply (intro exI conjI, simp+)
apply (fastforce simp add: disjoint_commute agreesC)
apply (drule (1) mall3_imp2D, fast)
apply (erule safe_agrees, fastforce simp add: disjoint_commute agreesC)
done

The proof rule for eliminating auxiliary variables. Note that a set of variables, X, is auxiliary for a command C iff it disjoint from fvC (rem_vars X C).

theorem rule_aux:
Γ ⊢ {P} C {Q} ;
disjoint X (fvA P ∪ fvA Q ∪ fvAs Γ ∪ fvC (rem_vars X C))
Γ ⊢ {P} rem_vars X C {Q}
by (auto simp add: CSL_def safe_aux disjoint_commute)

Alternative definition of configuration safety

Here is an alternative definition of safety monotonicity that does not quantify over the frame hF.

primrec
  safe_weak :: nat ⇒ cmd ⇒ stack ⇒ heap ⇒ (rname ⇒ assn) ⇒ assn ⇒ bool
where
  safe_weak 0 C s h Γ Q = True
| safe_weak (Suc n) C s h Γ Q = (
            (C = Cskip ⟶ (s, h) ⊨ Q)
          ∧ ¬ aborts C (s, h)
          ∧ accesses C s ⊆ dom h
          ∧ (∀hJ C' σ'.
                  red C (s,h ++ hJ) C' σ'
                 ⟶ (s, hJ) ⊨ envs Γ (llocked C') (llocked C)
                 ⟶ (disjoint (dom h) (dom hJ))
                 ⟶ (∃h' hJ'.
                         snd σ' = h' ++ hJ'
                       ∧ disjoint (dom h') (dom hJ')
                       ∧ (fst σ', hJ') ⊨ envs Γ (llocked C) (llocked C')
                       ∧ safe_weak n C' (fst σ') h' Γ Q)))

It is easy to show that the alternative definition is weaker than the one with the quantification:

lemma safe_weakI:
safe n C s h Γ Q
safe_weak n C s h Γ Q
apply (induct n arbitrary: C s h, simp, clarsimp)
apply (rule conjI, drule_tac a=empty in allD, simp)
apply (clarify, drule_tac b=empty in all5D, simp, drule (2) imp2D, fast)
done

If, however, the operational semantics satisfies the safety monotonicity and frame properties (which it does), then the two definitions are equivalent. We first prove that the operational semantics satisfies these two properties, and then using these properties, we show that the alternative definition of configuration safety implies the original one.

[A] Safety monotonicity:

lemma safety_monotonicity_helper[rule_format]:
  aborts C σ ⟹ ∀s h hF. σ = (s, h ++ hF) ⟶ disjoint (dom h) (dom hF) ⟶ aborts C (s, h)
by (erule aborts.induct, auto)

lemma safety_monotonicity:
aborts C (s, h ++ hF); disjoint (dom h) (dom hF)
aborts C (s, h)
by (erule safety_monotonicity_helper, simp_all)

[B] Frame property:

lemma frame_property_helper[rule_format]:
  red C σ C' σ' ⟹ ∀s h hF s' h''. σ = (s, h ++ hF) ⟶ σ' = (s', h'')
   ⟶ disjoint (dom h) (dom hF)
   ⟶ ¬ aborts C (s, h)
   ⟶ (∃h'. red C (s, h) C' (s', h') ∧ h'' = h' ++ hF ∧ disjoint (dom h') (dom hF))
apply (erule red.induct, fastforce+)
— Read
apply (clarsimp, rename_tac h hF)
apply (case_tac h (edenot E s), erule notE, fastforce)
apply (intro exI conjI red_Read, fast+, simp_all)
apply (fastforce simp add: disjoint_def)
— Write
apply (clarsimp, rename_tac h hF)
apply (case_tac h (edenot E s), erule notE, fastforce)
apply (rule_tac x=h(edenot E s ↦ edenot E' s) in exI, intro conjI, fast)
 apply (rule map_add_upd_left [THEN sym], fastforce simp add: disjoint_def)
apply (fastforce simp add: disjoint_def)
— Alloc
apply (clarsimp, rename_tac h hF)
apply (rule_tac x=h(v ↦ edenot E s) in exI, intro conjI)
  apply (rule_tac v=v in red_Alloc, fast+)
 apply (rule map_add_upd_left [THEN sym], fastforce simp add: disjoint_def)
apply (fastforce simp add: disjoint_def)
— Dispose
apply (clarsimp, rename_tac h hF)
apply (case_tac h (edenot E s), erule notE, fastforce)
  apply (rule_tac x=h(edenot E s := None) in exI, intro conjI, fast)
 apply (subgoal_tac hF(edenot E s := None) = hF, simp, rule ext, fastforce simp add: disjoint_def)
apply (fastforce simp add: disjoint_def)
done

lemma frame_property:
red C (s, h ++ hF) C' (s', h''); disjoint (dom h) (dom hF); ¬ aborts C (s, h)
∃h'. red C (s, h) C' (s', h') ∧ h'' = h' ++ hF ∧ disjoint (dom h') (dom hF)
by (erule frame_property_helper, simp_all)

Finally, using safety monotonicity and the frame property, we conclude that safe_weak n C s h Γ Q implies safe n C s h Γ Q.

lemma safe_weakE:
safe_weak n C s h Γ Q
safe n C s h Γ Q
apply (induct n arbitrary: C s h, simp, clarsimp)
apply (rule conjI, clarify)
 apply (erule notE, erule (1) safety_monotonicity)
apply (clarify, drule frame_property, simp)
 apply (erule contrapos_nn, erule (1) safety_monotonicity, clarify)
apply (drule (2) all4_imp2D, clarsimp, fast)
done

end
Imprint | Data protection | HTML version generated by isa2html.