Theory AxSem

(*  Title:      HOL/Bali/AxSem.thy
    Author:     David von Oheimb
*)

subsection ‹Axiomatic semantics of Java expressions and statements 
          (see also Eval.thy)
›
theory AxSem imports Evaln TypeSafe begin

text ‹
design issues:
\begin{itemize}
\item a strong version of validity for triples with premises, namely one that 
      takes the recursive depth needed to complete execution, enables 
      correctness proof
\item auxiliary variables are handled first-class (-> Thomas Kleymann)
\item expressions not flattened to elementary assignments (as usual for 
      axiomatic semantics) but treated first-class => explicit result value 
      handling
\item intermediate values not on triple, but on assertion level 
      (with result entry)
\item multiple results with semantical substitution mechnism not requiring a 
      stack 
\item because of dynamic method binding, terms need to be dependent on state.
  this is also useful for conditional expressions and statements
\item result values in triples exactly as in eval relation (also for xcpt 
      states)
\item validity: additional assumption of state conformance and well-typedness,
  which is required for soundness and thus rule hazard required of completeness
\end{itemize}

restrictions:
\begin{itemize}
\item all triples in a derivation are of the same type (due to weak 
      polymorphism)
\end{itemize}
›

type_synonym  res = vals ― ‹result entry›

abbreviation (input)
  Val where "Val x == In1 x"

abbreviation (input)
  Var where "Var x == In2 x"

abbreviation (input)
  Vals where "Vals x == In3 x"

syntax
  "_Val"    :: "[pttrn] => pttrn"     ("Val:_"  [951] 950)
  "_Var"    :: "[pttrn] => pttrn"     ("Var:_"  [951] 950)
  "_Vals"   :: "[pttrn] => pttrn"     ("Vals:_" [951] 950)

translations
  "λVal:v . b"  == "(λv. b)  CONST the_In1"
  "λVar:v . b"  == "(λv. b)  CONST the_In2"
  "λVals:v. b"  == "(λv. b)  CONST the_In3"

  ― ‹relation on result values, state and auxiliary variables›
type_synonym 'a assn = "res  state  'a  bool"
translations
  (type) "'a assn" <= (type) "vals  state  'a  bool"

definition
  assn_imp :: "'a assn  'a assn  bool" (infixr "" 25)
  where "(P  Q) = (Y s Z. P Y s Z  Q Y s Z)"
  
lemma assn_imp_def2 [iff]: "(P  Q) = (Y s Z. P Y s Z  Q Y s Z)"
apply (unfold assn_imp_def)
apply (rule HOL.refl)
done


subsubsection "assertion transformers"

subsection "peek-and"

definition
  peek_and :: "'a assn  (state   bool)  'a assn" (infixl "∧." 13)
  where "(P ∧. p) = (λY s Z. P Y s Z  p s)"

lemma peek_and_def2 [simp]: "peek_and P p Y s = (λZ. (P Y s Z  p s))"
apply (unfold peek_and_def)
apply (simp (no_asm))
done

lemma peek_and_Not [simp]: "(P ∧. (λs. ¬ f s)) = (P ∧. Not  f)"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_and_and [simp]: "peek_and (peek_and P p) p = peek_and P p"
apply (unfold peek_and_def)
apply (simp (no_asm))
done

lemma peek_and_commut: "(P ∧. p ∧. q) = (P ∧. q ∧. p)"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply auto
done

abbreviation
  Normal :: "'a assn  'a assn"
  where "Normal P == P ∧. normal"

lemma peek_and_Normal [simp]: "peek_and (Normal P) p = Normal (peek_and P p)"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply auto
done

subsection "assn-supd"

definition
  assn_supd :: "'a assn  (state  state)  'a assn" (infixl ";." 13)
  where "(P ;. f) = (λY s' Z. s. P Y s Z  s' = f s)"

lemma assn_supd_def2 [simp]: "assn_supd P f Y s' Z = (s. P Y s Z  s' = f s)"
apply (unfold assn_supd_def)
apply (simp (no_asm))
done

subsection "supd-assn"

definition
  supd_assn :: "(state  state)  'a assn  'a assn" (infixr ".;" 13)
  where "(f .; P) = (λY s. P Y (f s))"


lemma supd_assn_def2 [simp]: "(f .; P) Y s = P Y (f s)"
apply (unfold supd_assn_def)
apply (simp (no_asm))
done

lemma supd_assn_supdD [elim]: "((f .; Q) ;. f) Y s Z  Q Y s Z"
apply auto
done

lemma supd_assn_supdI [elim]: "Q Y s Z  (f .; (Q ;. f)) Y s Z"
apply (auto simp del: split_paired_Ex)
done

subsection "subst-res"

definition
  subst_res :: "'a assn  res  'a assn" ("__"  [60,61] 60)
  where "Pw = (λY. P w)"

lemma subst_res_def2 [simp]: "(Pw) Y = P w"
apply (unfold subst_res_def)
apply (simp (no_asm))
done

lemma subst_subst_res [simp]: "Pwv = Pw"
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_and_subst_res [simp]: "(P ∧. p)w = (Pw ∧. p)"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

(*###Do not work for some strange (unification?) reason
lemma subst_res_Val_beta [simp]: "(λY. P (the_In1 Y))←Val v = (λY. P v)"
apply (rule ext)
by simp

lemma subst_res_Var_beta [simp]: "(λY. P (the_In2 Y))←Var vf = (λY. P vf)";
apply (rule ext)
by simp

lemma subst_res_Vals_beta [simp]: "(λY. P (the_In3 Y))←Vals vs = (λY. P vs)";
apply (rule ext)
by simp
*)

subsection "subst-Bool"

definition
  subst_Bool :: "'a assn  bool  'a assn" ("_←=_" [60,61] 60)
  where "P←=b = (λY s Z. v. P (Val v) s Z  (normal s  the_Bool v=b))"

lemma subst_Bool_def2 [simp]: 
"(P←=b) Y s Z = (v. P (Val v) s Z  (normal s  the_Bool v=b))"
apply (unfold subst_Bool_def)
apply (simp (no_asm))
done

lemma subst_Bool_the_BoolI: "P (Val b) s Z  (P←=the_Bool b) Y s Z"
apply auto
done

subsection "peek-res"

definition
  peek_res :: "(res  'a assn)  'a assn"
  where "peek_res Pf = (λY. Pf Y Y)"

syntax
  "_peek_res" :: "pttrn  'a assn  'a assn"            ("λ_:. _" [0,3] 3)
translations
  "λw:. P"   == "CONST peek_res (λw. P)"

lemma peek_res_def2 [simp]: "peek_res P Y = P Y Y"
apply (unfold peek_res_def)
apply (simp (no_asm))
done

lemma peek_res_subst_res [simp]: "peek_res Pw = P ww"
apply (rule ext)
apply (simp (no_asm))
done

(* unused *)
lemma peek_subst_res_allI: 
 "(a. T a (P (f a)f a))  a. T a (peek_res Pf a)"
apply (rule allI)
apply (simp (no_asm))
apply fast
done

subsection "ign-res"

definition
  ign_res :: "'a assn  'a assn" ("_" [1000] 1000)
  where "P = (λY s Z. Y. P Y s Z)"

lemma ign_res_def2 [simp]: "P Y s Z = (Y. P Y s Z)"
apply (unfold ign_res_def)
apply (simp (no_asm))
done

lemma ign_ign_res [simp]: "P = P"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma ign_subst_res [simp]: "Pw = P"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_and_ign_res [simp]: "(P ∧. p) = (P ∧. p)"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

subsection "peek-st"

definition
  peek_st :: "(st  'a assn)  'a assn"
  where "peek_st P = (λY s. P (store s) Y s)"

syntax
  "_peek_st"   :: "pttrn  'a assn  'a assn"            ("λ_.. _" [0,3] 3)
translations
  "λs.. P"   == "CONST peek_st (λs. P)"

lemma peek_st_def2 [simp]: "(λs.. Pf s) Y s = Pf (store s) Y s"
apply (unfold peek_st_def)
apply (simp (no_asm))
done

lemma peek_st_triv [simp]: "(λs.. P) = P"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_st_st [simp]: "(λs.. λs'.. P s s') = (λs.. P s s)"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_st_split [simp]: "(λs.. λY s'. P s Y s') = (λY s. P (store s) Y s)"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_st_subst_res [simp]: "(λs.. P s)w = (λs.. P sw)"
apply (rule ext)
apply (simp (no_asm))
done

lemma peek_st_Normal [simp]: "(λs..(Normal (P s))) = Normal (λs.. P s)"
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

subsection "ign-res-eq"

definition
  ign_res_eq :: "'a assn  res  'a assn" ("_↓=_"  [60,61] 60)
  where "P↓=w  (λY:. P ∧. (λs. Y=w))"

lemma ign_res_eq_def2 [simp]: "(P↓=w) Y s Z = ((Y. P Y s Z)  Y=w)"
apply (unfold ign_res_eq_def)
apply auto
done

lemma ign_ign_res_eq [simp]: "(P↓=w) = P"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

(* unused *)
lemma ign_res_eq_subst_res: "P↓=ww = P"
apply (rule ext)
apply (rule ext)
apply (rule ext)
apply (simp (no_asm))
done

(* unused *)
lemma subst_Bool_ign_res_eq: "((P←=b)↓=x) Y s Z = ((P←=b) Y s Z   Y=x)"
apply (simp (no_asm))
done

subsection "RefVar"

definition
  RefVar :: "(state  vvar × state)  'a assn  'a assn" (infixr "..;" 13)
  where "(vf ..; P) = (λY s. let (v,s') = vf s in P (Var v) s')"
 
lemma RefVar_def2 [simp]: "(vf ..; P) Y s =  
  P (Var (fst (vf s))) (snd (vf s))"
apply (unfold RefVar_def Let_def)
apply (simp (no_asm) add: split_beta)
done

subsection "allocation"

definition
  Alloc :: "prog  obj_tag  'a assn  'a assn"
  where "Alloc G otag P = (λY s Z. s' a. Gs ─halloc otaga s' P (Val (Addr a)) s' Z)"

definition
  SXAlloc :: "prog  'a assn  'a assn"
  where "SXAlloc G P = (λY s Z. s'. Gs ─sxalloc→ s'  P Y s' Z)"


lemma Alloc_def2 [simp]: "Alloc G otag P Y s Z =  
       (s' a. Gs ─halloc otaga s' P (Val (Addr a)) s' Z)"
apply (unfold Alloc_def)
apply (simp (no_asm))
done

lemma SXAlloc_def2 [simp]: 
  "SXAlloc G P Y s Z = (s'. Gs ─sxalloc→ s'  P Y s' Z)"
apply (unfold SXAlloc_def)
apply (simp (no_asm))
done

subsubsection "validity"

definition
  type_ok :: "prog  term  state  bool" where
  "type_ok G t s =
    (L T C A. (normal s  prg=G,cls=C,lcl=LtT  
                             prg=G,cls=C,lcl=Ldom (locals (store s))»t»A )
                s∷≼(G,L))"

datatype    'a triple = triple "('a assn)" "term" "('a assn)" (** should be
something like triple = ∀'a. triple ('a assn) term ('a assn)   **)
                                        ("{(1_)}/ _/ {(1_)}"     [3,65,3] 75)
type_synonym 'a triples = "'a triple set"

abbreviation
  var_triple   :: "['a assn, var         ,'a assn]  'a triple"
                                         ("{(1_)}/ _=≻/ {(1_)}"    [3,80,3] 75)
  where "{P} e=≻ {Q} == {P} In2 e {Q}"

abbreviation
  expr_triple  :: "['a assn, expr        ,'a assn]  'a triple"
                                         ("{(1_)}/ _-≻/ {(1_)}"    [3,80,3] 75)
  where "{P} e-≻ {Q} == {P} In1l e {Q}"

abbreviation
  exprs_triple :: "['a assn, expr list   ,'a assn]  'a triple"
                                         ("{(1_)}/ _≐≻/ {(1_)}"    [3,65,3] 75)
  where "{P} e≐≻ {Q} == {P} In3 e {Q}"

abbreviation
  stmt_triple  :: "['a assn, stmt,        'a assn]  'a triple"
                                         ("{(1_)}/ ._./ {(1_)}"     [3,65,3] 75)
  where "{P} .c. {Q} == {P} In1r c {Q}"

notation (ASCII)
  triple  ("{(1_)}/ _>/ {(1_)}"      [3,65,3]75) and
  var_triple  ("{(1_)}/ _=>/ {(1_)}"    [3,80,3] 75) and
  expr_triple  ("{(1_)}/ _->/ {(1_)}"    [3,80,3] 75) and
  exprs_triple  ("{(1_)}/ _#>/ {(1_)}"    [3,65,3] 75)

lemma inj_triple: "inj (λ(P,t,Q). {P} t {Q})"
apply (rule inj_onI)
apply auto
done

lemma triple_inj_eq: "({P} t {Q} = {P'} t' {Q'} ) = (P=P'  t=t'  Q=Q')"
apply auto
done

definition mtriples :: "('c  'sig  'a assn)  ('c  'sig  expr)  
                ('c  'sig  'a assn)  ('c ×  'sig) set  'a triples" ("{{(1_)}/ _-≻/ {(1_)} | _}"[3,65,3,65]75) where
 "{{P} tf-≻ {Q} | ms} = (λ(C,sig). {Normal(P C sig)} tf C sig-≻ {Q C sig})`ms"
  
definition
  triple_valid :: "prog  nat  'a triple   bool"  ("__:_" [61,0, 58] 57)
  where
    "Gn:t =
      (case t of {P} t {Q} 
        Y s Z. P Y s Z  type_ok G t s 
        (Y' s'. Gs t≻─n (Y',s')  Q Y' s' Z))"

abbreviation
  triples_valid:: "prog  nat  'a triples  bool"  ("_|⊨_:_" [61,0, 58] 57)
  where "G|⊨n:ts == Ball ts (triple_valid G n)"

notation (ASCII)
  triples_valid  (  "_||=_:_" [61,0, 58] 57)


definition
  ax_valids :: "prog  'b triples  'a triples  bool"  ("_,_|⊨_" [61,58,58] 57)
  where "(G,A|⊨ts) = (n. G|⊨n:A  G|⊨n:ts)"

abbreviation
  ax_valid :: "prog  'b triples  'a triple  bool"  ("_,__" [61,58,58] 57)
  where "G,A t == G,A|⊨{t}"

notation (ASCII)
  ax_valid  ( "_,_|=_"   [61,58,58] 57)


lemma triple_valid_def2: "Gn:{P} t {Q} =  
 (Y s Z. P Y s Z 
   (L. (normal s  ( C T A. prg=G,cls=C,lcl=LtT  
                   prg=G,cls=C,lcl=Ldom (locals (store s))»t»A))  
           s∷≼(G,L))
   (Y' s'. Gs t≻─n (Y',s') Q Y' s' Z))"
apply (unfold triple_valid_def type_ok_def)
apply (simp (no_asm))
done


declare split_paired_All [simp del] split_paired_Ex [simp del] 
declare if_split     [split del] if_split_asm     [split del] 
        option.split [split del] option.split_asm [split del]
setup map_theory_simpset (fn ctxt => ctxt delloop "split_all_tac")
setup map_theory_claset (fn ctxt => ctxt delSWrapper "split_all_tac")

inductive
  ax_derivs :: "prog  'a triples  'a triples  bool" ("_,_|⊢_" [61,58,58] 57)
  and ax_deriv :: "prog  'a triples  'a triple   bool" ("_,__" [61,58,58] 57)
  for G :: prog
where

  "G,A t  G,A|⊢{t}"

| empty: " G,A|⊢{}"
| insert:"G,At; G,A|⊢ts 
          G,A|⊢insert t ts"

| asm:   "tsA  G,A|⊢ts"

(* could be added for convenience and efficiency, but is not necessary
  cut:   "⟦G,A'|⊢ts; G,A|⊢A'⟧ ⟹
           G,A |⊢ts"
*)
| weaken:"G,A|⊢ts'; ts  ts'  G,A|⊢ts"

| conseq:"Y s Z . P  Y s Z   (P' Q'. G,A{P'} t {Q'}  (Y' s'. 
         (Y   Z'. P' Y s Z'  Q' Y' s' Z') 
                                 Q  Y' s' Z ))
                                          G,A{P } t {Q }"

| hazard:"G,A{P ∧. Not  type_ok G t} t {Q}"

| Abrupt:  "G,A{P(undefined3 t) ∧. Not  normal} t {P}"

  ― ‹variables›
| LVar:  " G,A{Normal (λs.. PVar (lvar vn s))} LVar vn=≻ {P}"

| FVar: "G,A{Normal P} .Init C. {Q};
          G,A{Q} e-≻ {λVal:a:. fvar C stat fn a ..; R} 
                                 G,A{Normal P} {accC,C,stat}e..fn=≻ {R}"

| AVar:  "G,A{Normal P} e1-≻ {Q};
          a. G,A{QVal a} e2-≻ {λVal:i:. avar G i a ..; R} 
                                 G,A{Normal P} e1.[e2]=≻ {R}"
  ― ‹expressions›

| NewC: "G,A{Normal P} .Init C. {Alloc G (CInst C) Q} 
                                 G,A{Normal P} NewC C-≻ {Q}"

| NewA: "G,A{Normal P} .init_comp_ty T. {Q};  G,A{Q} e-≻
          {λVal:i:. abupd (check_neg i) .; Alloc G (Arr T (the_Intg i)) R} 
                                 G,A{Normal P} New T[e]-≻ {R}"

| Cast: "G,A{Normal P} e-≻ {λVal:v:. λs..
          abupd (raise_if (¬G,sv fits T) ClassCast) .; QVal v} 
                                 G,A{Normal P} Cast T e-≻ {Q}"

| Inst: "G,A{Normal P} e-≻ {λVal:v:. λs..
                  QVal (Bool (vNull  G,sv fits RefT T))} 
                                 G,A{Normal P} e InstOf T-≻ {Q}"

| Lit:                          "G,A{Normal (PVal v)} Lit v-≻ {P}"

| UnOp: "G,A{Normal P} e-≻ {λVal:v:. QVal (eval_unop unop v)}
          
          G,A{Normal P} UnOp unop e-≻ {Q}"

| BinOp:
   "G,A{Normal P} e1-≻ {Q};
     v1. G,A{QVal v1} 
               (if need_second_arg binop v1 then (In1l e2) else (In1r Skip))
               {λVal:v2:. RVal (eval_binop binop v1 v2)}
    
    G,A{Normal P} BinOp binop e1 e2-≻ {R}" 

| Super:" G,A{Normal (λs.. PVal (val_this s))} Super-≻ {P}"

| Acc:  "G,A{Normal P} va=≻ {λVar:(v,f):. QVal v} 
                                 G,A{Normal P} Acc va-≻ {Q}"

| Ass:  "G,A{Normal P} va=≻ {Q};
     vf. G,A{QVar vf} e-≻ {λVal:v:. assign (snd vf) v .; R} 
                                 G,A{Normal P} va:=e-≻ {R}"

| Cond: "G,A {Normal P} e0-≻ {P'};
          b. G,A{P'←=b} (if b then e1 else e2)-≻ {Q} 
                                 G,A{Normal P} e0 ? e1 : e2-≻ {Q}"

| Call: 
"G,A{Normal P} e-≻ {Q}; a. G,A{QVal a} args≐≻ {R a};
  a vs invC declC l. G,A{(R aVals vs ∧.
 (λs. declC=invocation_declclass G mode (store s) a statT name=mn,parTs=pTs 
      invC = invocation_class mode (store s) a statT 
         l = locals (store s)) ;.
      init_lvars G declC name=mn,parTs=pTs mode a vs) ∧.
      (λs. normal s  GmodeinvCstatT)}
 Methd declC name=mn,parTs=pTs-≻ {set_lvars l .; S} 
         G,A{Normal P} {accC,statT,mode}emn({pTs}args)-≻ {S}"

| Methd:"G,A {{P} Methd-≻ {Q} | ms} |⊢ {{P} body G-≻ {Q} | ms} 
                                 G,A|⊢{{P} Methd-≻  {Q} | ms}"

| Body: "G,A{Normal P} .Init D. {Q}; 
  G,A{Q} .c. {λs.. abupd (absorb Ret) .; R(In1 (the (locals s Result)))} 
    
                                 G,A{Normal P} Body D c-≻ {R}"
  
  ― ‹expression lists›

| Nil:                          "G,A{Normal (PVals [])} []≐≻ {P}"

| Cons: "G,A{Normal P} e-≻ {Q};
          v. G,A{QVal v} es≐≻ {λVals:vs:. RVals (v#vs)} 
                                 G,A{Normal P} e#es≐≻ {R}"

  ― ‹statements›

| Skip:                         "G,A{Normal (P)} .Skip. {P}"

| Expr: "G,A{Normal P} e-≻ {Q} 
                                 G,A{Normal P} .Expr e. {Q}"

| Lab: "G,A{Normal P} .c. {abupd (absorb l) .; Q} 
                           G,A{Normal P} .l c. {Q}"

| Comp: "G,A{Normal P} .c1. {Q};
          G,A{Q} .c2. {R} 
                                 G,A{Normal P} .c1;;c2. {R}"

| If:   "G,A {Normal P} e-≻ {P'};
          b. G,A{P'←=b} .(if b then c1 else c2). {Q} 
                                 G,A{Normal P} .If(e) c1 Else c2. {Q}"
(* unfolding variant of Loop, not needed here
  LoopU:"⟦G,A ⊢{Normal P} e-≻ {P'};
          ∀b. G,A⊢{P'←=b} .(if b then c;;While(e) c else Skip).{Q}⟧
         ⟹              G,A⊢{Normal P} .While(e) c. {Q}"
*)
| Loop: "G,A{P} e-≻ {P'}; 
          G,A{Normal (P'←=True)} .c. {abupd (absorb (Cont l)) .; P} 
                            G,A{P} .l While(e) c. {(P'←=False)↓=}"
  
| Jmp: "G,A{Normal (abupd (λa. (Some (Jump j))) .; P)} .Jmp j. {P}"

| Throw:"G,A{Normal P} e-≻ {λVal:a:. abupd (throw a) .; Q} 
                                 G,A{Normal P} .Throw e. {Q}"

| Try:  "G,A{Normal P} .c1. {SXAlloc G Q};
          G,A{Q ∧. (λs.  G,s⊢catch C) ;. new_xcpt_var vn} .c2. {R};
              (Q ∧. (λs. ¬G,s⊢catch C))  R 
                                 G,A{Normal P} .Try c1 Catch(C vn) c2. {R}"

| Fin:  "G,A{Normal P} .c1. {Q};
      x. G,A{Q ∧. (λs. x = fst s) ;. abupd (λx. None)}
              .c2. {abupd (abrupt_if (xNone) x) .; R} 
                                 G,A{Normal P} .c1 Finally c2. {R}"

| Done:                       "G,A{Normal (P ∧. initd C)} .Init C. {P}"

| Init: "the (class G C) = c;
          G,A{Normal ((P ∧. Not  initd C) ;. supd (init_class_obj G C))}
              .(if C = Object then Skip else Init (super c)). {Q};
      l. G,A{Q ∧. (λs. l = locals (store s)) ;. set_lvars Map.empty}
              .init c. {set_lvars l .; R} 
                               G,A{Normal (P ∧. Not  initd C)} .Init C. {R}"

― ‹Some dummy rules for the intermediate terms Callee›,
InsInitE›, InsInitV›, FinA› only used by the smallstep 
semantics.›
| InsInitV: " G,A{Normal P} InsInitV c v=≻ {Q}"
| InsInitE: " G,A{Normal P} InsInitE c e-≻ {Q}"
| Callee:    " G,A{Normal P} Callee l e-≻ {Q}"
| FinA:      " G,A{Normal P} .FinA a c. {Q}"
(*
axioms 
*)

definition
  adapt_pre :: "'a assn  'a assn  'a assn  'a assn"
  where "adapt_pre P Q Q' = (λY s Z. Y' s'. Z'. P Y s Z'  (Q Y' s' Z'  Q' Y' s' Z))"


subsubsection "rules derived by induction"

lemma cut_valid: "G,A'|⊨ts; G,A|⊨A'  G,A|⊨ts"
apply (unfold ax_valids_def)
apply fast
done

(*if cut is available
Goal "⟦G,A'|⊢ts; A' ⊆ A; ∀P Q t. {P} t≻ {Q} ∈ A' ⟶ (∃T. (G,L)⊢t∷T) ⟧ ⟹  
       G,A|⊢ts"
b y etac ax_derivs.cut 1;
b y eatac ax_derivs.asm 1 1;
qed "ax_thin";
*)
lemma ax_thin [rule_format (no_asm)]: 
  "G,(A'::'a triple set)|⊢(ts::'a triple set)  A. A'  A  G,A|⊢ts"
apply (erule ax_derivs.induct)
apply                (tactic "ALLGOALS (EVERY'[clarify_tac context, REPEAT o smp_tac context 1])")
apply                (rule ax_derivs.empty)
apply               (erule (1) ax_derivs.insert)
apply              (fast intro: ax_derivs.asm)
(*apply           (fast intro: ax_derivs.cut) *)
apply            (fast intro: ax_derivs.weaken)
apply           (rule ax_derivs.conseq, intro strip, tactic "smp_tac context 3 1",clarify,
  tactic "smp_tac context 1 1",rule exI, rule exI, erule (1) conjI) 
(* 37 subgoals *)
prefer 18 (* Methd *)
apply (rule ax_derivs.Methd, drule spec, erule mp, fast) 
apply (tactic TRYALL (resolve_tac context ((funpow 5 tl) @{thms ax_derivs.intros})))
apply auto
done

lemma ax_thin_insert: "G,(A::'a triple set)(t::'a triple)  G,insert x At"
apply (erule ax_thin)
apply fast
done

lemma subset_mtriples_iff: 
  "ts  {{P} mb-≻ {Q} | ms} = (ms'. ms'ms   ts = {{P} mb-≻ {Q} | ms'})"
apply (unfold mtriples_def)
apply (rule subset_image_iff)
done

lemma weaken: 
 "G,(A::'a triple set)|⊢(ts'::'a triple set)  ts. ts  ts'  G,A|⊢ts"
apply (erule ax_derivs.induct)
(*42 subgoals*)
apply       (tactic "ALLGOALS (strip_tac context)")
apply       (tactic ALLGOALS(REPEAT o (EVERY'[dresolve_tac context @{thms subset_singletonD},
         eresolve_tac context [disjE],
         fast_tac (context addSIs @{thms ax_derivs.empty})])))
apply       (tactic "TRYALL (hyp_subst_tac context)")
apply       (simp, rule ax_derivs.empty)
apply      (drule subset_insertD)
apply      (blast intro: ax_derivs.insert)
apply     (fast intro: ax_derivs.asm)
(*apply  (blast intro: ax_derivs.cut) *)
apply   (fast intro: ax_derivs.weaken)
apply  (rule ax_derivs.conseq, clarify, tactic "smp_tac context 3 1", blast(* unused *))
(*37 subgoals*)
apply (tactic TRYALL (resolve_tac context ((funpow 5 tl) @{thms ax_derivs.intros})
                   THEN_ALL_NEW fast_tac context))
(*1 subgoal*)
apply (clarsimp simp add: subset_mtriples_iff)
apply (rule ax_derivs.Methd)
apply (drule spec)
apply (erule impE)
apply  (rule exI)
apply  (erule conjI)
apply  (rule HOL.refl)
oops (* dead end, Methd is to blame *)


subsubsection "rules derived from conseq"

text ‹In the following rules we often have to give some type annotations like:
 termG,(A::'a triple set){P::'a assn} t {Q}.
Given only the term above without annotations, Isabelle would infer a more 
general type were we could have 
different types of auxiliary variables in the assumption set (termA) and 
in the triple itself (termP and termQ). But 
ax_derivs.Methd› enforces the same type in the inductive definition of
the derivation. So we have to restrict the types to be able to apply the
rules. 
›
lemma conseq12: "G,(A::'a triple set){P'::'a assn} t {Q'};  
 Y s Z. P Y s Z  (Y' s'. (Y Z'. P' Y s Z'  Q' Y' s' Z')   
  Q Y' s' Z)  
    G,A{P ::'a assn} t {Q }"
apply (rule ax_derivs.conseq)
apply clarsimp
apply blast
done

― ‹Nice variant, since it is so symmetric we might be able to memorise it.›
lemma conseq12': "G,(A::'a triple set){P'::'a assn} t {Q'}; s Y' s'.  
       (Y Z. P' Y s Z  Q' Y' s' Z)   
       (Y Z. P  Y s Z  Q  Y' s' Z)  
    G,A{P::'a assn } t {Q }"
apply (erule conseq12)
apply fast
done

lemma conseq12_from_conseq12': "G,(A::'a triple set){P'::'a assn} t {Q'};  
 Y s Z. P Y s Z  (Y' s'. (Y Z'. P' Y s Z'  Q' Y' s' Z')   
  Q Y' s' Z)  
    G,A{P::'a assn} t {Q }"
apply (erule conseq12')
apply blast
done

lemma conseq1: "G,(A::'a triple set){P'::'a assn} t {Q}; P  P' 
  G,A{P::'a assn} t {Q}"
apply (erule conseq12)
apply blast
done

lemma conseq2: "G,(A::'a triple set){P::'a assn} t {Q'}; Q'  Q 
 G,A{P::'a assn} t {Q}"
apply (erule conseq12)
apply blast
done

lemma ax_escape: 
 "Y s Z. P Y s Z 
    G,(A::'a triple set){λY' s' (Z'::'a). (Y',s') = (Y,s)} 
                             t 
                            {λY s Z'. Q Y s Z}
   G,A{P::'a assn} t {Q::'a assn}"
apply (rule ax_derivs.conseq)
apply force
done

(* unused *)
lemma ax_constant: " C  G,(A::'a triple set){P::'a assn} t {Q} 
 G,A{λY s Z. C  P Y s Z} t {Q}"
apply (rule ax_escape (* unused *))
apply clarify
apply (rule conseq12)
apply  fast
apply auto
done
(*alternative (more direct) proof:
apply (rule ax_derivs.conseq) *)(* unused *)(*
apply (fast)
*)


lemma ax_impossible [intro]: 
  "G,(A::'a triple set){λY s Z. False} t {Q::'a assn}"
apply (rule ax_escape)
apply clarify
done

(* unused *)
lemma ax_nochange_lemma: "P Y s; All ((=) w)  P w s"
apply auto
done

lemma ax_nochange:
 "G,(A::(res × state) triple set){λY s Z. (Y,s)=Z} t {λY s Z. (Y,s)=Z} 
   G,A{P::(res × state) assn} t {P}"
apply (erule conseq12)
apply auto
apply (erule (1) ax_nochange_lemma)
done

(* unused *)
lemma ax_trivial: "G,(A::'a triple set){P::'a assn}  t {λY s Z. True}"
apply (rule ax_derivs.conseq(* unused *))
apply auto
done

(* unused *)
lemma ax_disj: 
 "G,(A::'a triple set){P1::'a assn} t {Q1}; G,A{P2::'a assn} t {Q2} 
    G,A{λY s Z. P1 Y s Z  P2 Y s Z} t {λY s Z. Q1 Y s Z  Q2 Y s Z}"
apply (rule ax_escape (* unused *))
apply safe
apply  (erule conseq12, fast)+
done

(* unused *)
lemma ax_supd_shuffle: 
 "(Q. G,(A::'a triple set){P::'a assn} .c1. {Q}  G,A{Q ;. f} .c2. {R}) =  
       (Q'. G,A{P} .c1. {f .; Q'}  G,A{Q'} .c2. {R})"
apply (best elim!: conseq1 conseq2)
done

lemma ax_cases: "
 G,(A::'a triple set){P ∧.       C} t {Q::'a assn};  
                   G,A{P ∧. Not  C} t {Q}  G,A{P} t {Q}"
apply (unfold peek_and_def)
apply (rule ax_escape)
apply clarify
apply (case_tac "C s")
apply  (erule conseq12, force)+
done
(*alternative (more direct) proof:
apply (rule rtac ax_derivs.conseq) *)(* unused *)(*
apply clarify
apply (case_tac "C s")
apply  force+
*)

lemma ax_adapt: "G,(A::'a triple set){P::'a assn} t {Q} 
   G,A{adapt_pre P Q Q'} t {Q'}"
apply (unfold adapt_pre_def)
apply (erule conseq12)
apply fast
done

lemma adapt_pre_adapts: "G,(A::'a triple set){P::'a assn} t {Q} 
 G,A{adapt_pre P Q Q'} t {Q'}"
apply (unfold adapt_pre_def)
apply (simp add: ax_valids_def triple_valid_def2)
apply fast
done


lemma adapt_pre_weakest: 
"G (A::'a triple set) t. G,A{P} t {Q}  G,A{P'} t {Q'}   
  P'  adapt_pre P Q (Q'::'a assn)"
apply (unfold adapt_pre_def)
apply (drule spec)
apply (drule_tac x = "{}" in spec)
apply (drule_tac x = "In1r Skip" in spec)
apply (simp add: ax_valids_def triple_valid_def2)
oops

lemma peek_and_forget1_Normal: 
 "G,(A::'a triple set){Normal P} t {Q::'a assn} 
  G,A{Normal (P ∧. p)} t {Q}"
apply (erule conseq1)
apply (simp (no_asm))
done

lemma peek_and_forget1: 
"G,(A::'a triple set){P::'a assn} t {Q} 
  G,A{P ∧. p} t {Q}"
apply (erule conseq1)
apply (simp (no_asm))
done

lemmas ax_NormalD = peek_and_forget1 [of _ _ _ _ _ normal] 

lemma peek_and_forget2: 
"G,(A::'a triple set){P::'a assn} t {Q ∧. p} 
 G,A{P} t {Q}"
apply (erule conseq2)
apply (simp (no_asm))
done

lemma ax_subst_Val_allI: 
"v. G,(A::'a triple set){(P'               v )Val v} t {(Q v)::'a assn}
   v. G,A{(λw:. P' (the_In1 w))Val v} t {Q v}"
apply (force elim!: conseq1)
done

lemma ax_subst_Var_allI: 
"v. G,(A::'a triple set){(P'               v )Var v} t {(Q v)::'a assn}
   v. G,A{(λw:. P' (the_In2 w))Var v} t {Q v}"
apply (force elim!: conseq1)
done

lemma ax_subst_Vals_allI: 
"(v. G,(A::'a triple set){(     P'          v )Vals v} t {(Q v)::'a assn})
   v. G,A{(λw:. P' (the_In3 w))Vals v} t {Q v}"
apply (force elim!: conseq1)
done


subsubsection "alternative axioms"

lemma ax_Lit2: 
  "G,(A::'a triple set){Normal P::'a assn} Lit v-≻ {Normal (P↓=Val v)}"
apply (rule ax_derivs.Lit [THEN conseq1])
apply force
done
lemma ax_Lit2_test_complete: 
  "G,(A::'a triple set){Normal (PVal v)::'a assn} Lit v-≻ {P}"
apply (rule ax_Lit2 [THEN conseq2])
apply force
done

lemma ax_LVar2: "G,(A::'a triple set){Normal P::'a assn} LVar vn=≻ {Normal (λs.. P↓=Var (lvar vn s))}"
apply (rule ax_derivs.LVar [THEN conseq1])
apply force
done

lemma ax_Super2: "G,(A::'a triple set)
  {Normal P::'a assn} Super-≻ {Normal (λs.. P↓=Val (val_this s))}"
apply (rule ax_derivs.Super [THEN conseq1])
apply force
done

lemma ax_Nil2: 
  "G,(A::'a triple set){Normal P::'a assn} []≐≻ {Normal (P↓=Vals [])}"
apply (rule ax_derivs.Nil [THEN conseq1])
apply force
done


subsubsection "misc derived structural rules"

(* unused *)
lemma ax_finite_mtriples_lemma: "F  ms; finite ms; (C,sig)ms. 
    G,(A::'a triple set){Normal (P C sig)::'a assn} mb C sig-≻ {Q C sig}  
       G,A|⊢{{P} mb-≻ {Q} | F}"
apply (frule (1) finite_subset)
apply (erule rev_mp)
apply (erule thin_rl)
apply (erule finite_induct)
apply  (unfold mtriples_def)
apply  (clarsimp intro!: ax_derivs.empty ax_derivs.insert)+
apply force
done
lemmas ax_finite_mtriples = ax_finite_mtriples_lemma [OF subset_refl]

lemma ax_derivs_insertD: 
 "G,(A::'a triple set)|⊢insert (t::'a triple) ts  G,At  G,A|⊢ts"
apply (fast intro: ax_derivs.weaken)
done

lemma ax_methods_spec: 
"G,(A::'a triple set)|⊢case_prod f ` ms; (C,sig)  ms G,A((f C sig)::'a triple)"
apply (erule ax_derivs.weaken)
apply (force del: image_eqI intro: rev_image_eqI)
done

(* this version is used to avoid using the cut rule *)
lemma ax_finite_pointwise_lemma [rule_format]: "F  ms; finite ms   
  (((C,sig)F. G,(A::'a triple set)(f C sig::'a triple))  ((C,sig)ms. G,A(g C sig::'a triple)))   
      G,A|⊢case_prod f ` F  G,A|⊢case_prod g ` F"
apply (frule (1) finite_subset)
apply (erule rev_mp)
apply (erule thin_rl)
apply (erule finite_induct)
apply  clarsimp+
apply (drule ax_derivs_insertD)
apply (rule ax_derivs.insert)
apply  (simp (no_asm_simp) only: split_tupled_all)
apply  (auto elim: ax_methods_spec)
done
lemmas ax_finite_pointwise = ax_finite_pointwise_lemma [OF subset_refl]
 
lemma ax_no_hazard: 
  "G,(A::'a triple set){P ∧. type_ok G t} t {Q::'a assn}  G,A{P} t {Q}"
apply (erule ax_cases)
apply (rule ax_derivs.hazard [THEN conseq1])
apply force
done

lemma ax_free_wt: 
 "(T L C. prg=G,cls=C,lcl=LtT) 
   G,(A::'a triple set){Normal P} t {Q::'a assn}  
  G,A{Normal P} t {Q}"
apply (rule ax_no_hazard)
apply (rule ax_escape)
apply clarify
apply (erule mp [THEN conseq12])
apply  (auto simp add: type_ok_def)
done

ML ML_Thms.bind_thms ("ax_Abrupts", sum3_instantiate context @{thm ax_derivs.Abrupt})
declare ax_Abrupts [intro!]

lemmas ax_Normal_cases = ax_cases [of _ _ _ normal]

lemma ax_Skip [intro!]: "G,(A::'a triple set){P} .Skip. {P::'a assn}"
apply (rule ax_Normal_cases)
apply  (rule ax_derivs.Skip)
apply fast
done
lemmas ax_SkipI = ax_Skip [THEN conseq1]


subsubsection "derived rules for methd call"

lemma ax_Call_known_DynT: 
"GIntVirCstatT; 
  a vs l. G,A{(R aVals vs ∧. (λs. l = locals (store s)) ;.
  init_lvars G C name=mn,parTs=pTs IntVir a vs)} 
    Methd C name=mn,parTs=pTs-≻ {set_lvars l .; S}; 
  a. G,A{QVal a} args≐≻  
       {R a ∧. (λs. C = obj_class (the (heap (store s) (the_Addr a))) 
                     C = invocation_declclass 
                            G IntVir (store s) a statT name=mn,parTs=pTs )};  
       G,(A::'a triple set){Normal P} e-≻ {Q::'a assn}  
    G,A{Normal P} {accC,statT,IntVir}emn({pTs}args)-≻ {S}"
apply (erule ax_derivs.Call)
apply  safe
apply  (erule spec)
apply (rule ax_escape, clarsimp)
apply (drule spec, drule spec, drule spec,erule conseq12)
apply force
done


lemma ax_Call_Static: 
 "a vs l. G,A{R aVals vs ∧. (λs. l = locals (store s)) ;.  
               init_lvars G C name=mn,parTs=pTs Static any_Addr vs}  
              Methd C name=mn,parTs=pTs-≻ {set_lvars l .; S}; 
  G,A{Normal P} e-≻ {Q};
   a. G,(A::'a triple set){QVal a} args≐≻ {(R::val  'a assn)  a 
  ∧. (λ s. C=invocation_declclass 
                G Static (store s) a statT name=mn,parTs=pTs)}
    G,A{Normal P} {accC,statT,Static}emn({pTs}args)-≻ {S}"
apply (erule ax_derivs.Call)
apply  safe
apply  (erule spec)
apply (rule ax_escape, clarsimp)
apply (erule_tac V = "P  Q" for P Q in thin_rl)
apply (drule spec,drule spec,drule spec, erule conseq12)
apply (force simp add: init_lvars_def Let_def)
done

lemma ax_Methd1: 
 "G,A{{P} Methd-≻ {Q} | ms}|⊢ {{P} body G-≻ {Q} | ms}; (C,sig) ms  
       G,A{Normal (P C sig)} Methd C sig-≻ {Q C sig}"
apply (drule ax_derivs.Methd)
apply (unfold mtriples_def)
apply (erule (1) ax_methods_spec)
done

lemma ax_MethdN: 
"G,insert({Normal P} Methd  C sig-≻ {Q}) A 
          {Normal P} body G C sig-≻ {Q}   
      G,A{Normal P} Methd   C sig-≻ {Q}"
apply (rule ax_Methd1)
apply  (rule_tac [2] singletonI)
apply (unfold mtriples_def)
apply clarsimp
done

lemma ax_StatRef: 
  "G,(A::'a triple set){Normal (PVal Null)} StatRef rt-≻ {P::'a assn}"
apply (rule ax_derivs.Cast)
apply (rule ax_Lit2 [THEN conseq2])
apply clarsimp
done

subsubsection "rules derived from Init and Done"

  lemma ax_InitS: "the (class G C) = c; C  Object;  
     l. G,A{Q ∧. (λs. l = locals (store s)) ;. set_lvars Map.empty}  
            .init c. {set_lvars l .; R};   
         G,A{Normal ((P ∧. Not  initd C) ;. supd (init_class_obj G C))}  
  .Init (super c). {Q}   
  G,(A::'a triple set){Normal (P ∧. Not  initd C)} .Init C. {R::'a assn}"
apply (erule ax_derivs.Init)
apply  (simp (no_asm_simp))
apply assumption
done

lemma ax_Init_Skip_lemma: 
"l. G,(A::'a triple set){P ∧. (λs. l = locals (store s)) ;. set_lvars l'}
  .Skip. {(set_lvars l .; P)::'a assn}"
apply (rule allI)
apply (rule ax_SkipI)
apply clarsimp
done

lemma ax_triv_InitS: "the (class G C) = c;init c = Skip; C  Object; 
       P  (supd (init_class_obj G C) .; P);  
       G,A{Normal (P ∧. initd C)} .Init (super c). {(P ∧. initd C)}   
       G,(A::'a triple set){Normal P} .Init C. {(P ∧. initd C)::'a assn}"
apply (rule_tac C = "initd C" in ax_cases)
apply  (rule conseq1, rule ax_derivs.Done, clarsimp)
apply (simp (no_asm))
apply (erule (1) ax_InitS)
apply  simp
apply  (rule ax_Init_Skip_lemma)
apply (erule conseq1)
apply force
done

lemma ax_Init_Object: "wf_prog G  G,(A::'a triple set)
  {Normal ((supd (init_class_obj G Object) .; P) ∧. Not  initd Object)} 
       .Init Object. {(P ∧. initd Object)::'a assn}"
apply (rule ax_derivs.Init)
apply   (drule class_Object, force)
apply (simp_all (no_asm))
apply (rule_tac [2] ax_Init_Skip_lemma)
apply (rule ax_SkipI, force)
done

lemma ax_triv_Init_Object: "wf_prog G;  
       (P::'a assn)  (supd (init_class_obj G Object) .; P)   
  G,(A::'a triple set){Normal P} .Init Object. {P ∧. initd Object}"
apply (rule_tac C = "initd Object" in ax_cases)
apply  (rule conseq1, rule ax_derivs.Done, clarsimp)
apply (erule ax_Init_Object [THEN conseq1])
apply force
done


subsubsection "introduction rules for Alloc and SXAlloc"

lemma ax_SXAlloc_Normal: 
 "G,(A::'a triple set){P::'a assn} .c. {Normal Q} 
  G,A{P} .c. {SXAlloc G Q}"
apply (erule conseq2)
apply (clarsimp elim!: sxalloc_elim_cases simp add: split_tupled_all)
done

lemma ax_Alloc: 
  "G,(A::'a triple set){P::'a assn} t 
     {Normal (λY (x,s) Z. (a. new_Addr (heap s) = Some a   
      Q (Val (Addr a)) (Norm(init_obj G (CInst C) (Heap a) s)) Z)) ∧. 
      heap_free (Suc (Suc 0))}
    G,A{P} t {Alloc G (CInst C) Q}"
apply (erule conseq2)
apply (auto elim!: halloc_elim_cases)
done

lemma ax_Alloc_Arr: 
 "G,(A::'a triple set){P::'a assn} t 
   {λVal:i:. Normal (λY (x,s) Z. ¬the_Intg i<0   
    (a. new_Addr (heap s) = Some a   
    Q (Val (Addr a)) (Norm (init_obj G (Arr T (the_Intg i)) (Heap a) s)) Z)) ∧.
    heap_free (Suc (Suc 0))} 
   
 G,A{P} t {λVal:i:. abupd (check_neg i) .; Alloc G (Arr T(the_Intg i)) Q}"
apply (erule conseq2)
apply (auto elim!: halloc_elim_cases)
done

lemma ax_SXAlloc_catch_SXcpt: 
 "G,(A::'a triple set){P::'a assn} t 
     {(λY (x,s) Z. x=Some (Xcpt (Std xn))   
      (a. new_Addr (heap s) = Some a   
      Q Y (Some (Xcpt (Loc a)),init_obj G (CInst (SXcpt xn)) (Heap a) s) Z))  
      ∧. heap_free (Suc (Suc 0))} 
   
 G,A{P} t {SXAlloc G (λY s Z. Q Y s Z  G,s⊢catch SXcpt xn)}"
apply (erule conseq2)
apply (auto elim!: sxalloc_elim_cases halloc_elim_cases)
done

end