Theory OG_Annotations

(*
 * 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 ‹Annotations, assertions and associated operations›

theory OG_Annotations
imports SmallStep
begin

type_synonym 's assn = "'s set"

datatype ('s, dead 'p, dead 'f) ann =
    AnnExpr "'s assn" 
  | AnnRec "'s assn" "('s, 'p, 'f) ann"
  | AnnWhile "'s assn" "'s assn" "('s, 'p, 'f) ann"
  | AnnComp "('s, 'p, 'f) ann" "('s, 'p, 'f) ann"
  | AnnBin "'s assn" "('s, 'p, 'f) ann" "('s, 'p, 'f) ann"
  | AnnPar "(('s, 'p, 'f) ann × 's assn × 's assn) list"
  | AnnCall "'s assn" nat

type_synonym ('s, 'p, 'f) ann_triple = "('s, 'p, 'f) ann × 's assn × 's assn"

text ‹
 The list of ann_triple› is useful if the code calls the same function multiple times
 and require different annotations for the function body each time.
›
type_synonym ('s,'p,'f) proc_assns = "'p  (('s, 'p, 'f) ann) list option"

abbreviation  (input) pres:: "('s, 'p, 'f) ann_triple  ('s, 'p, 'f) ann"
where "pres a  fst a"

abbreviation (input) postcond :: "('s, 'p, 'f) ann_triple  's assn"
where "postcond a  fst (snd a)"

abbreviation (input) abrcond :: "('s, 'p, 'f) ann_triple  's assn"
where "abrcond a  snd (snd a)"

fun pre :: "('s, 'p, 'f) ann  's assn" where
  "pre (AnnExpr r)      = r"                                                                                               
| "pre (AnnRec r e)     = r"
| "pre (AnnWhile r i e) = r"
| "pre (AnnComp e1 e2)   =  pre e1"
| "pre (AnnBin r e1 e2)  = r"
| "pre (AnnPar as)      =  (pre ` set (map pres (as)))"
| "pre (AnnCall r n)    = r"

fun pre_par :: "('s, 'p, 'f) ann  bool" where
  "pre_par (AnnComp e1 e2) =  pre_par e1"
| "pre_par (AnnPar as)  = True"
| "pre_par _    = False"

fun pre_set :: "('s, 'p, 'f) ann  ('s assn) set" where
  "pre_set (AnnExpr r)      = {r}"
| "pre_set (AnnRec r e)     = {r}"
| "pre_set (AnnWhile r i e) = {r}"
| "pre_set (AnnComp e1 e2)   =  pre_set e1"
| "pre_set (AnnBin r e1 e2)  = {r}"
| "pre_set (AnnPar as)       =  (pre_set ` set (map pres (as)))"
(*| "pre_set (AnnPar e1 e2)    = pre_set (pres e1) ∪ pre_set (pres e2)" *)
| "pre_set (AnnCall r n)    = {r}"

lemma fst_BNFs[simp]:
  "a  Basic_BNFs.fsts (a,b)"
   using fsts.intros by auto

lemma "¬pre_par c   pre c  pre_set c"
  by (induct c; simp)

lemma pre_set:
  "pre c =  (pre_set c)"
  by (induct c; fastforce)

lemma pre_imp_pre_set:
  "s  pre c  a  pre_set c  s  a"
  by (simp add: pre_set)

abbreviation precond :: "('s, 'p, 'f) ann_triple  's assn"
where "precond a  pre (fst a)"

fun strengthen_pre :: "('s, 'p, 'f) ann  's assn  ('s, 'p, 'f) ann" where
  "strengthen_pre (AnnExpr r)      r' = AnnExpr (r  r')"                                                                                               
| "strengthen_pre (AnnRec r e)     r' = AnnRec (r  r') e"
| "strengthen_pre (AnnWhile r i e) r' = AnnWhile (r  r') i e"
| "strengthen_pre (AnnComp e1 e2)   r' = AnnComp (strengthen_pre e1 r') e2"
| "strengthen_pre (AnnBin r e1 e2) r' = AnnBin (r  r') e1 e2"
| "strengthen_pre (AnnPar as)    r' = (AnnPar as)"
| "strengthen_pre (AnnCall r n)    r' = AnnCall (r  r') n"

fun weaken_pre :: "('s, 'p, 'f) ann  's assn  ('s, 'p, 'f) ann" where
  "weaken_pre (AnnExpr r)      r' = AnnExpr (r  r')"                                                                                               
| "weaken_pre (AnnRec r e)     r' = AnnRec (r  r') e"
| "weaken_pre (AnnWhile r i e) r' = AnnWhile (r  r') i e"
| "weaken_pre (AnnComp e1 e2)   r' = AnnComp (weaken_pre e1 r') e2"
| "weaken_pre (AnnBin r e1 e2) r' = AnnBin (r  r') e1 e2"
| "weaken_pre (AnnPar as)   r' = AnnPar as"
| "weaken_pre (AnnCall r n)    r' = AnnCall (r  r') n"

lemma weaken_pre_empty[simp]:
  "weaken_pre r {} = r"
  by (induct r) auto

text ‹Annotations for call definition (see Language.thy)›
definition
 ann_call :: "'s assn  's assn  nat   's assn 's assn   's assn  's assn  ('s,'p,'f) ann"
where
 "ann_call init r n restoreq return restorea A  
  AnnRec init (AnnComp (AnnComp (AnnComp (AnnExpr init) (AnnCall r n)) (AnnComp (AnnExpr restorea) (AnnExpr A)))
          (AnnRec restoreq (AnnComp (AnnExpr restoreq) (AnnExpr return))))"


inductive ann_matches :: "('s,'p,'f) body  ('s,'p,'f) proc_assns  ('s, 'p, 'f) ann  ('s, 'p, 'f) com  bool" where
  ann_skip: "ann_matches Γ Θ (AnnExpr a) Skip"
| ann_basic: "ann_matches Γ Θ (AnnExpr a) (Basic f)"
| ann_spec: "ann_matches Γ Θ (AnnExpr a) (Spec r)"
| ann_throw: "ann_matches Γ Θ (AnnExpr a) (Throw)"
| ann_await: "ann_matches Γ Θ a e 
               ann_matches Γ Θ (AnnRec r a) (Await b e)"
| ann_seq: " ann_matches Γ Θ a1 p1; ann_matches Γ Θ a2 p2  
               ann_matches Γ Θ (AnnComp a1 a2) (Seq p1 p2)"
| ann_cond: " ann_matches Γ Θ a1 c1; ann_matches Γ Θ a2 c2  
               ann_matches Γ Θ (AnnBin a a1 a2) (Cond b c1 c2)"
| ann_catch: " ann_matches Γ Θ a1 c1; ann_matches Γ Θ a2 c2  
                ann_matches Γ Θ (AnnComp a1 a2) (Catch c1 c2)"
| ann_while: "ann_matches Γ Θ a' e 
                ann_matches Γ Θ (AnnWhile a i a') (While b e)"
| ann_guard: " ann_matches Γ Θ a' e   
                ann_matches Γ Θ (AnnRec a a') (Guard f b e)"
| ann_call: " Θ f = Some as; Γ f = Some b; n < length as;
               ann_matches Γ Θ (as!n) b 
   ann_matches Γ Θ (AnnCall a n) (Call f)"
| ann_dyncom: "sr. ann_matches Γ Θ a (c s) 
               ann_matches Γ Θ (AnnRec r a) (DynCom c)"
| ann_parallel: " length as = length cs;
                   i<length cs. ann_matches Γ Θ (pres (as!i)) (cs!i)  
   ann_matches Γ Θ (AnnPar as) (Parallel cs)"

primrec ann_guards:: "'s assn  ('f × 's bexp ) list 
                  ('s,'p,'f) ann  ('s,'p,'f) ann"
where
  "ann_guards _ [] c = c" |
  "ann_guards r (g#gs) c = AnnRec r (ann_guards (r  snd g) gs c)"

end