Theory OG_Hoare

(*
 * Copyright 2016, Data61, CSIRO
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 *)
section ‹ Owicki-Gries for Partial Correctness ›
theory OG_Hoare
imports OG_Annotations 
begin

subsection ‹Validity of Hoare Tuples: Γ⊨/F P c Q,A›

definition
  valid :: "[('s,'p,'f) body,'f set,'s assn,('s,'p,'f) com,'s assn,'s assn] => bool"
                ("_ ⊨⇘'/_/ _ _ _, _"  [61,60,1000, 20, 1000,1000] 60)
where
  "Γ ⊨⇘/FP c Q,A  s t c'. Γ(c,s) * (c', t)  final (c', t )  s  Normal ` P  t  Fault ` F  
                        c' = Skip  t  Normal ` Q  c' = Throw  t  Normal ` A"

subsection ‹Interference Freedom›

inductive
 atomicsR :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  ('s, 'p, 'f) ann  ('s,'p,'f) com  ('s assn × ('s, 'p, 'f) com)  bool"
  for Γ::"('s,'p,'f) body"
  and Θ :: " ('s,'p,'f) proc_assns"
where
  AtBasic: "atomicsR Γ Θ (AnnExpr p) (Basic f) (p, Basic f)"
| AtSpec: "atomicsR Γ Θ (AnnExpr p) (Spec r) (p, Spec r)"
| AtAwait: "atomicsR Γ Θ (AnnRec r ae) (Await b e) (r  b, Await b e)"
| AtWhileExpr: "atomicsR Γ Θ p e a  atomicsR Γ Θ (AnnWhile r i p) (While b e) a"
| AtGuardExpr: "atomicsR Γ Θ p e a  atomicsR Γ Θ (AnnRec r p) (Guard f b e) a" 
| AtDynCom: "x  r  atomicsR Γ Θ ad (f x) a  atomicsR Γ Θ (AnnRec r ad) (DynCom f) a" 
| AtCallExpr: "Γ f = Some b  Θ f = Some as 
                n < length as 
                atomicsR Γ Θ  (as!n) b a 
               atomicsR Γ Θ (AnnCall r n) (Call f) a"
| AtSeqExpr1: "atomicsR Γ Θ  a1 c1 a 
               atomicsR Γ Θ (AnnComp a1 a2) (Seq c1 c2) a" 
| AtSeqExpr2: "atomicsR Γ Θ  a2 c2 a 
               atomicsR Γ Θ (AnnComp a1 a2) (Seq c1 c2) a" 
| AtCondExpr1: "atomicsR Γ Θ  a1 c1 a 
               atomicsR Γ Θ (AnnBin r a1 a2) (Cond b c1 c2) a" 
| AtCondExpr2: "atomicsR Γ Θ  a2 c2 a 
               atomicsR Γ Θ (AnnBin r a1 a2) (Cond b c1 c2) a" 
| AtCatchExpr1: "atomicsR Γ Θ  a1 c1 a 
               atomicsR Γ Θ (AnnComp a1 a2) (Catch c1 c2) a" 
| AtCatchExpr2: "atomicsR Γ Θ  a2 c2 a 
               atomicsR Γ Θ (AnnComp a1 a2) (Catch c1 c2) a" 
| AtParallelExprs: "i < length cs  atomicsR Γ Θ (fst (as!i)) (cs!i) a 
    atomicsR Γ Θ (AnnPar as) (Parallel cs) a"

lemma atomicsR_Skip[simp]:
  "atomicsR Γ Θ a Skip r = False"
 by (auto elim: atomicsR.cases)

lemma atomicsR_Throw[simp]:
  "atomicsR Γ Θ a Throw r = False"
 by (auto elim: atomicsR.cases)

inductive
 assertionsR :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  's assn  's assn  ('s, 'p, 'f) ann  ('s,'p,'f) com  's assn  bool"
  for Γ::"('s,'p,'f) body"
  and Θ :: " ('s,'p,'f) proc_assns"
where
  AsSkip: "assertionsR Γ Θ Q A (AnnExpr p) Skip p"
| AsThrow: "assertionsR Γ Θ Q A (AnnExpr p) Throw p"
| AsBasic: "assertionsR Γ Θ Q A (AnnExpr p) (Basic f) p"
| AsBasicSkip: "assertionsR Γ Θ Q A (AnnExpr p) (Basic f) Q"
| AsSpec: "assertionsR Γ Θ Q A (AnnExpr p) (Spec r) p"
| AsSpecSkip: "assertionsR Γ Θ Q A (AnnExpr p) (Spec r) Q"
| AsAwaitSkip: "assertionsR Γ Θ Q A (AnnRec r ae) (Await b e) Q"
| AsAwaitThrow: "assertionsR Γ Θ Q A (AnnRec r ae) (Await b e) A"
| AsAwait: "assertionsR Γ Θ Q A (AnnRec r ae) (Await b e) r"
| AsWhileExpr: "assertionsR Γ Θ i A p e a  assertionsR Γ Θ Q A (AnnWhile r i p) (While b e) a" 
| AsWhileAs: "assertionsR Γ Θ Q A (AnnWhile r i p) (While b e) r"
| AsWhileInv: "assertionsR Γ Θ Q A (AnnWhile r i p) (While b e) i"
| AsWhileSkip: "assertionsR Γ Θ Q A (AnnWhile r i p) (While b e) Q"
| AsGuardExpr: "assertionsR Γ Θ Q A p e a  assertionsR Γ Θ Q A (AnnRec r p) (Guard f b e) a" 
| AsGuardAs: "assertionsR Γ Θ Q A (AnnRec r p) (Guard f b e) r" 
| AsDynComExpr: "x  r  assertionsR Γ Θ Q A ad (f x) a  assertionsR Γ Θ Q A (AnnRec r ad) (DynCom f) a" 
| AsDynComAs: "assertionsR Γ Θ Q A (AnnRec r p) (DynCom f) r" 
| AsCallAs: "assertionsR Γ Θ Q A (AnnCall r n) (Call f) r" 
| AsCallExpr: "Γ f = Some b  Θ f = Some as 
                n < length as 
                assertionsR Γ Θ Q A (as!n) b a 
               assertionsR Γ Θ Q A (AnnCall r n) (Call f) a" 
| AsSeqExpr1: "assertionsR Γ Θ (pre a2) A a1 c1 a 
               assertionsR Γ Θ Q A (AnnComp a1 a2) (Seq c1 c2) a" 
| AsSeqExpr2: "assertionsR Γ Θ Q A a2 c2 a 
               assertionsR Γ Θ Q A (AnnComp a1 a2) (Seq c1 c2) a" 
| AsCondExpr1: "assertionsR Γ Θ Q A a1 c1 a 
               assertionsR Γ Θ Q A (AnnBin r a1 a2) (Cond b c1 c2) a" 
| AsCondExpr2: "assertionsR Γ Θ Q A a2 c2 a 
               assertionsR Γ Θ Q A (AnnBin r a1 a2) (Cond b c1 c2) a" 
| AsCondAs: "assertionsR Γ Θ Q A (AnnBin r a1 a2) (Cond b c1 c2) r" 
| AsCatchExpr1: "assertionsR Γ Θ Q (pre a2) a1 c1 a 
               assertionsR Γ Θ Q A (AnnComp a1 a2) (Catch c1 c2) a" 
| AsCatchExpr2: "assertionsR Γ Θ Q A a2 c2 a 
               assertionsR Γ Θ Q A (AnnComp a1 a2) (Catch c1 c2) a" 

| AsParallelExprs: "i < length cs  assertionsR Γ Θ (postcond (as!i)) (abrcond (as!i)) (pres (as!i)) (cs!i) a 
    assertionsR Γ Θ Q A (AnnPar as) (Parallel cs) a" 
| AsParallelSkips: "Qs =  (set (map postcond as)) 
  assertionsR Γ Θ Q A (AnnPar as) (Parallel cs) (Qs)" 

definition
  interfree_aux :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  'f set  (('s,'p,'f) com × ('s, 'p, 'f) ann_triple × ('s,'p,'f) com × ('s, 'p, 'f) ann)  bool"
where
  "interfree_aux Γ Θ F  λ(c1, (P1, Q1, A1), c2, P2).
                              (p c .atomicsR Γ Θ P2 c2 (p,c)  
                               Γ⊨⇘/F(Q1  p) c Q1,Q1   Γ⊨⇘/F(A1  p) c A1,A1  
                                (a. assertionsR Γ Θ Q1 A1 P1 c1 a  Γ⊨⇘/F(a  p) c a,a))"

definition
  interfree :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  'f set  (('s, 'p, 'f) ann_triple) list  ('s,'p,'f) com list   bool"
where 
  "interfree Γ Θ F Ps Ts  i j. i < length Ts  j < length Ts  i  j  
                         interfree_aux Γ Θ F (Ts!i, Ps!i, Ts!j, fst (Ps!j))"

subsection ‹The Owicki-Gries Logic for COMPLX›

inductive
  oghoare :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  'f set
               ('s, 'p, 'f) ann  ('s,'p,'f) com  's assn  's assn  bool"
    ("(4_, _/ ⊢⇘'/_ (_/ (_)/ _, _))" [60,60,60,1000,1000,1000,1000]60)
and
  oghoare_seq :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  'f set
               's assn  ('s, 'p, 'f) ann  ('s,'p,'f) com  's assn  's assn  bool"
    ("(4_, _/ ⊩⇘'/_ (_/ _/ (_)/ _, _))" [60,60,60,1000,1000,1000,1000]60)

where
 Skip: " Γ, Θ ⊢⇘/F(AnnExpr Q) Skip Q,A"

| Throw: "Γ, Θ ⊢⇘/F(AnnExpr A) Throw Q,A"

| Basic: "Γ, Θ ⊢⇘/F(AnnExpr {s. f s  Q}) (Basic f) Q,A"

| Spec: "Γ, Θ ⊢⇘/F(AnnExpr {s. (t. (s,t)  rel  t  Q)  (t. (s,t)  rel)}) (Spec rel) Q,A"

| Seq: "Γ, Θ ⊢⇘/FP1 c1 (pre P2),A;
         Γ, Θ ⊢⇘/FP2 c2 Q,A 
          Γ, Θ ⊢⇘/F(AnnComp P1 P2) (Seq c1 c2) Q,A"

| Catch: "Γ, Θ ⊢⇘/FP1 c1 Q,(pre P2);
           Γ, Θ ⊢⇘/FP2 c2 Q,A  
        Γ, Θ ⊢⇘/F(AnnComp P1 P2) (Catch c1 c2) Q,A"
  
| Cond: " Γ, Θ ⊢⇘/FP1 c1 Q,A;
           Γ, Θ ⊢⇘/FP2 c2 Q,A;
          r  b  pre P1;
          r  -b  pre P2 
          
         Γ, Θ ⊢⇘/F(AnnBin r P1 P2) (Cond b c1 c2) Q,A"

| While: " Γ, Θ ⊢⇘/FP c i,A;
            i  b  pre P;
            i  -b  Q;
            r  i  
          
          Γ, Θ ⊢⇘/F(AnnWhile r i P) (While b c) Q,A"

| Guard: " Γ, Θ ⊢⇘/FP c Q,A;
            r  g  pre P;
            r  -g  {}  f  F 
          Γ, Θ ⊢⇘/F(AnnRec r P) (Guard f g c) Q,A"

| Call: "  Θ p = Some as;
          (as ! n) = P;
          r  pre P;
          Γ p = Some b;
          n < length as;
          Γ,Θ ⊢⇘/FP b Q,A
           
          
         Γ, Θ ⊢⇘/F(AnnCall r n) (Call p) Q,A"

| DynCom:
      "r  pre a  sr. Γ, Θ ⊢⇘/Fa (c s) Q,A 
       
      Γ, Θ ⊢⇘/F(AnnRec r a) (DynCom c) Q,A"

| Await: "Γ, Θ ⊩⇘/F(r  b) P c Q,A; atom_com c  
  Γ, Θ ⊢⇘/F(AnnRec r P) (Await b c) Q,A"

| Parallel: " length as = length cs;
               i < length cs. Γ,Θ⊢⇘/F(pres (as!i)) (cs!i) (postcond (as!i)),(abrcond (as!i));
               interfree Γ Θ F as cs;
                (set (map postcond as))  Q;
                (set (map abrcond as))  A
              
         Γ,Θ⊢⇘/F(AnnPar as) (Parallel cs) Q,A"

| Conseq: "P' Q' A'. Γ,Θ⊢⇘/F(weaken_pre P P') c Q',A'  Q'  Q  A'  A 
            Γ,Θ⊢⇘/FP c Q,A"

| SeqSkip:   "Γ, Θ ⊩⇘/FQ (AnnExpr x) Skip Q,A"

| SeqThrow:   "Γ, Θ ⊩⇘/FA (AnnExpr x) Throw Q,A"

| SeqBasic:   "Γ, Θ ⊩⇘/F{s. f s  Q} (AnnExpr x) (Basic f) Q,A"

| SeqSpec:   "Γ, Θ ⊩⇘/F{s. (t. (s,t)  r  t  Q)  (t. (s,t)  r)} (AnnExpr x) (Spec r) Q,A"

| SeqSeq:    " Γ, Θ ⊩⇘/FR P2 c2 Q,A ; Γ, Θ ⊩⇘/FP P1 c1 R,A
          Γ, Θ ⊩⇘/FP (AnnComp P1 P2) (Seq c1 c2) Q,A"

| SeqCatch:  "Γ, Θ ⊩⇘/FR P2 c2 Q,A ; Γ, Θ ⊩⇘/FP P1 c1 Q,R  
    Γ, Θ ⊩⇘/FP (AnnComp P1 P2) (Catch c1 c2) Q,A"

| SeqCond: " Γ, Θ ⊩⇘/F(P  b) P1 c1 Q,A;
           Γ, Θ ⊩⇘/F(P  -b) P2 c2 Q,A 
          
         Γ, Θ ⊩⇘/FP (AnnBin r P1 P2) (Cond b c1 c2) Q,A"

| SeqWhile: " Γ, Θ ⊩⇘/F(Pb) a c P,A 
          
          Γ, Θ ⊩⇘/FP (AnnWhile r i a) (While b c) (P  -b),A"

| SeqGuard: " Γ, Θ ⊩⇘/F(Pg) a c Q,A;
            P  -g  {}  f  F 
          Γ, Θ ⊩⇘/FP (AnnRec r a) (Guard f g c) Q,A"

| SeqCall: "  Θ p = Some as;
          (as ! n) = P'';
          Γ p = Some b;
          n < length as;
          Γ,Θ ⊩⇘/FP P'' b Q,A
           
          
         Γ, Θ ⊩⇘/FP (AnnCall r n) (Call p) Q,A"

| SeqDynCom:
      "r  pre a 
      sr. Γ, Θ ⊩⇘/FP a (c s) Q,A 
      Pr
       
      Γ, Θ ⊩⇘/FP (AnnRec r a) (DynCom c) Q,A"

| SeqConseq: " P  P'; Γ,Θ⊩⇘/FP' a c Q',A'; Q'  Q; A'  A 
            Γ,Θ⊩⇘/FP a c Q,A"

| SeqParallel: "P  pre (AnnPar as)  Γ,Θ⊢⇘/F(AnnPar as) (Parallel cs) Q,A
   Γ,Θ⊩⇘/FP (AnnPar as) (Parallel cs) Q,A"

lemmas oghoare_intros = "oghoare_oghoare_seq.intros"

lemmas oghoare_inducts = oghoare_oghoare_seq.inducts

lemmas oghoare_induct = oghoare_oghoare_seq.inducts(1)

lemmas oghoare_seq_induct = oghoare_oghoare_seq.inducts(2)

end