Theory AlternativeSmallStep

(*
    Author:      Norbert Schirmer
    Maintainer:  Norbert Schirmer, norbert.schirmer at web de

Copyright (C) 2006-2008 Norbert Schirmer
*)

section  ‹Alternative Small Step Semantics›

theory AlternativeSmallStep imports HoareTotalDef
begin


text ‹
This is the small-step semantics, which is described and used in my PhD-thesis cite"Schirmer-PhD".
It decomposes the statement into a list of statements and finally executes the head.
So the redex is always the head of the list. The equivalence between termination
(based on the big-step semantics) and the absence of infinite computations in
this small-step semantics follows the same lines of reasoning as for
the new small-step semantics. However, it is technically more involved since
the configurations are more complicated. Thats why I switched to the new small-step
semantics in the "main trunk". I keep this alternative version and the important
proofs in this theory, so that one can compare both approaches.
›


subsection ‹Small-Step Computation: Γ⊢(cs, css, s) → (cs', css', s')›

type_synonym ('s,'p,'f) continuation = "('s,'p,'f) com list × ('s,'p,'f) com list"

type_synonym ('s,'p,'f) config =
  "('s,'p,'f)com list × ('s,'p,'f)continuation list × ('s,'f) xstate"



inductive "step"::"[('s,'p,'f) body,('s,'p,'f) config,('s,'p,'f) config]  bool"
                                (‹_ (_ / _) [81,81,81] 100)
  for Γ::"('s,'p,'f) body"
where
  Skip: "Γ(Skip#cs,css,Normal s)  (cs,css,Normal s)"
| Guard: "sg  Γ(Guard f g c#cs,css,Normal s)  (c#cs,css,Normal s)"

| GuardFault: "sg  Γ(Guard f g c#cs,css,Normal s)  (cs,css,Fault f)"

| FaultProp: "Γ(c#cs,css,Fault f)  (cs,css,Fault f)"
| FaultPropBlock: "Γ([],(nrms,abrs)#css,Fault f)  (nrms,css,Fault f)"
  (* FaultPropBlock: "Γ⊢([],cs#css,Fault) → ([],css,Fault)"*)

| AbruptProp:  "Γ(c#cs,css,Abrupt s)  (cs,css,Abrupt s)"

| ExitBlockNormal:
    "Γ([],(nrms,abrs)#css,Normal s)  (nrms,css,Normal s)"
| ExitBlockAbrupt:
    "Γ([],(nrms,abrs)#css,Abrupt s)  (abrs,css,Normal s)"

| Basic: "Γ(Basic f#cs,css,Normal s)  (cs,css,Normal (f s))"

| Spec: "(s,t)  r  Γ(Spec r#cs,css,Normal s)  (cs,css,Normal t)"
| SpecStuck: "t. (s,t)  r  Γ(Spec r#cs,css,Normal s)  (cs,css,Stuck)"

| Seq: "Γ(Seq c1 c2#cs,css,Normal s)  (c1#c2#cs,css,Normal s)"

| CondTrue:  "sb  Γ(Cond b c1 c2#cs,css,Normal s)  (c1#cs,css,Normal s)"
| CondFalse: "sb  Γ(Cond b c1 c2#cs,css,Normal s)  (c2#cs,css,Normal s)"

| WhileTrue: "sb
              
   Γ(While b c#cs,css,Normal s)  (c#While b c#cs,css,Normal s)"
| WhileFalse: "sb
               
               Γ(While b c#cs,css,Normal s)  (cs,css,Normal s)"

| Call: "Γ p=Some bdy 
         Γ(Call p#cs,css,Normal s)  ([bdy],(cs,Throw#cs)#css,Normal s)"

| CallUndefined: "Γ p=None 
         Γ(Call p#cs,css,Normal s)  (cs,css,Stuck)"

| StuckProp: "Γ(c#cs,css,Stuck)  (cs,css,Stuck)"
| StuckPropBlock: "Γ([],(nrms,abrs)#css,Stuck)  (nrms,css,Stuck)"

| DynCom: "Γ(DynCom c#cs,css,Normal s)  (c s#cs,css,Normal s)"

| Throw: "Γ(Throw#cs,css,Normal s)  (cs,css,Abrupt s)"
| Catch: "Γ(Catch c1 c2#cs,css,Normal s)  ([c1],(cs,c2#cs)#css,Normal s)"

lemmas step_induct = step.induct [of _ "(c,css,s)" "(c',css',s')", split_format (complete),
case_names
Skip Guard GuardFault FaultProp FaultPropBlock AbruptProp ExitBlockNormal ExitBlockAbrupt
Basic Spec SpecStuck Seq CondTrue CondFalse WhileTrue WhileFalse Call CallUndefined
StuckProp StuckPropBlock DynCom Throw Catch, induct set]

inductive_cases step_elim_cases [cases set]:
 "Γ(c#cs,css,Fault f)  u"
 "Γ([],css,Fault f)  u"
 "Γ(c#cs,css,Stuck)  u"
 "Γ([],css,Stuck)  u"
 "Γ(c#cs,css,Abrupt s)  u"
 "Γ([],css,Abrupt s)  u"
 "Γ([],css,Normal s)  u"
 "Γ(Skip#cs,css,s)  u"
 "Γ(Guard f g c#cs,css,s)  u"
 "Γ(Basic f#cs,css,s)  u"
 "Γ(Spec r#cs,css,s)  u"
 "Γ(Seq c1 c2#cs,css,s)  u"
 "Γ(Cond b c1 c2#cs,css,s)  u"
 "Γ(While b c#cs,css,s)  u"
 "Γ(Call p#cs,css,s)  u"
 "Γ(DynCom c#cs,css,s)  u"
 "Γ(Throw#cs,css,s)  u"
 "Γ(Catch c1 c2#cs,css,s)  u"

inductive_cases step_Normal_elim_cases [cases set]:
 "Γ(c#cs,css,Fault f)  u"
 "Γ([],css,Fault f)  u"
 "Γ(c#cs,css,Stuck)  u"
 "Γ([],css,Stuck)  u"
 "Γ([],(nrms,abrs)#css,Normal s)  u"
 "Γ([],(nrms,abrs)#css,Abrupt s)  u"
 "Γ(Skip#cs,css,Normal s)  u"
 "Γ(Guard f g c#cs,css,Normal s)  u"
 "Γ(Basic f#cs,css,Normal s)  u"
 "Γ(Spec r#cs,css,Normal s)  u"
 "Γ(Seq c1 c2#cs,css,Normal s)  u"
 "Γ(Cond b c1 c2#cs,css,Normal s)  u"
 "Γ(While b c#cs,css,Normal s)  u"
 "Γ(Call p#cs,css,Normal s)  u"
 "Γ(DynCom c#cs,css,Normal s)  u"
 "Γ(Throw#cs,css,Normal s)  u"
 "Γ(Catch c1 c2#cs,css,Normal s)  u"

abbreviation
 "step_rtrancl" :: "[('s,'p,'f) body,('s,'p,'f) config,('s,'p,'f) config]  bool"
                                (‹_ (_ */ _) [81,81,81] 100)
  where
  "Γcs0 * cs1     == (step Γ)** cs0 cs1"

abbreviation

 "step_trancl" :: "[('s,'p,'f) body,('s,'p,'f) config,('s,'p,'f) config]  bool"
                                (‹_ (_ +/ _) [81,81,81] 100)
  where
  "Γcs0 + cs1     == (step Γ)++ cs0 cs1"


subsubsection ‹Structural Properties of Small Step Computations›

lemma Fault_app_steps: "Γ(cs@xs,css,Fault f) * (xs,css,Fault f)"
proof (induct cs)
  case Nil thus ?case by simp
next
  case (Cons c cs)
  have "Γ(c#cs@xs, css, Fault f) * (xs, css, Fault f)"
  proof -
    have "Γ(c#cs@xs, css, Fault f)  (cs@xs, css, Fault f)"
      by (rule step.FaultProp)
    also
    have "Γ(cs@xs, css, Fault f) * (xs, css, Fault f)"
      by (rule Cons.hyps)
    finally show ?thesis .
  qed
  thus ?case
    by simp
qed

lemma Stuck_app_steps: "Γ(cs@xs,css,Stuck) * (xs,css,Stuck)"
proof (induct cs)
  case Nil thus ?case by simp
next
  case (Cons c cs)
  have "Γ(c#cs@xs, css, Stuck) * (xs, css, Stuck)"
  proof -
    have "Γ(c#cs@xs, css, Stuck)  (cs@xs, css, Stuck)"
      by (rule step.StuckProp)
    also
    have "Γ(cs@xs, css, Stuck) * (xs, css, Stuck)"
      by (rule Cons.hyps)
    finally show ?thesis .
  qed
  thus ?case
    by simp
qed

text ‹We can only append commands inside a block, if execution does not
        enter or exit a block.
›
lemma app_step:
  assumes step: "Γ(cs,css,s)  (cs',css',t)"
  shows "css=css'  Γ(cs@xs,css,s)  (cs'@xs,css',t)"
using step
apply induct
apply (simp_all del: fun_upd_apply,(blast intro: step.intros)+)
done

text ‹We can append whole blocks, without interfering with the actual
        block. Outer blocks do not influence execution of
        inner blocks.›
lemma app_css_step:
  assumes step: "Γ(cs,css,s)  (cs',css',t)"
  shows "Γ(cs,css@xs,s)  (cs',css'@xs,t)"
using step
apply induct
apply (simp_all del: fun_upd_apply,(blast intro: step.intros)+)
done

ML ML_Thms.bind_thm ("trancl_induct3", Split_Rule.split_rule @{context}
    (Rule_Insts.read_instantiate @{context}
      [((("a", 0), Position.none), "(ax, ay, az)"),
       ((("b", 0), Position.none), "(bx, by, bz)")] []
      @{thm tranclp_induct}));

lemma app_css_steps:
  assumes step: "Γ(cs,css,s) + (cs',css',t)"
  shows "Γ(cs,css@xs,s) + (cs',css'@xs,t)"
apply(rule trancl_induct3 [OF step])
 apply (rule app_css_step [THEN tranclp.r_into_trancl [of "step Γ"]],assumption)
apply(blast intro:app_css_step tranclp_trans)
done

lemma step_Cons':
  assumes step: "Γ(ccs,css,s)  (cs',css',t)"
  shows
  "c cs. ccs=c#cs  css''. css'=css''@css 
      (if css''=[] then p. cs'=p@cs
       else (pnorm pabr. css''=[(pnorm@cs,pabr@cs)]))"
using step
by induct force+

lemma step_Cons:
  assumes step: "Γ(c#cs,css,s)  (cs',css',t)"
  shows "pcss. css'=pcss@css 
         (if pcss=[] then ps. cs'=ps@cs
          else (pcs_normal pcs_abrupt. pcss=[(pcs_normal@cs,pcs_abrupt@cs)]))"
using step_Cons' [OF step]
by blast


lemma step_Nil':
  assumes step: "Γ(cs,asscss,s)  (cs',css',t)"
  shows
  "ass. cs=[]; asscss=ass@css; assNil 
          css'=tl ass@css 
          (case s of
             Abrupt s'  cs'=snd (hd ass)  t=Normal s'
           |  _  cs'=fst (hd ass)  t=s)"
using step
by (induct) (fastforce simp add: neq_Nil_conv)+

lemma step_Nil:
  assumes step: "Γ([],ass@css,s)  (cs',css',t)"
  assumes ass_not_Nil: "ass[]"
  shows "css'=tl ass@css 
          (case s of
             Abrupt s'  cs'=snd (hd ass)  t=Normal s'
           |  _  cs'=fst (hd ass)  t=s)"
  using step_Nil' [OF step _ _ ass_not_Nil]
  by simp

lemma step_Nil'':
  assumes step: "Γ([],(pcs_normal,pcs_abrupt)#pcss@css,s)  (cs',pcss@css,t)"
  shows "(case s of
             Abrupt s'  cs'=pcs_abrupt  t=Normal s'
           |  _  cs'=pcs_normal  t=s)"
  using step_Nil' [OF step, where ass ="(pcs_normal,pcs_abrupt)#pcss" and css="css"]
  by (auto split: xstate.splits)

lemma drop_suffix_css_step':
assumes step: "Γ(cs,cssxs,s)  (cs',css'xs,t)"
shows "css css' xs. cssxs = css@xs; css'xs=css'@xs
      Γ(cs,css,s)  (cs',css',t)"
using step
apply induct
apply (fastforce intro: step.intros)+
done

lemma drop_suffix_css_step:
assumes step: "Γ(cs,pcss@css,s)  (cs',pcss'@css,t)"
shows "Γ(cs,pcss,s)  (cs',pcss',t)"
using step by (blast intro: drop_suffix_css_step')

lemma drop_suffix_hd_css_step':
  assumes step: "Γ (pcs,css,s)  (cs',css'css,t)"
  shows "p ps cs pnorm pabr. pcs=p#ps@cs; css'css=(pnorm@cs,pabr@cs)#css
          Γ (p#ps,css,s)  (cs',(pnorm,pabr)#css,t)"
using step
by induct (force intro: step.intros)+

lemma drop_suffix_hd_css_step'':
  assumes step: "Γ (p#ps@cs,css,s)  (cs',(pnorm@cs,pabr@cs)#css,t)"
  shows  "Γ (p#ps,css,s)  (cs',(pnorm,pabr)#css,t)"
using drop_suffix_hd_css_step' [OF step]
by auto

lemma drop_suffix_hd_css_step:
  assumes step: "Γ (p#ps@cs,css,s)  (cs',[(pnorm@ps@cs,pabr@ps@cs)]@css,t)"
  shows  "Γ (p#ps,css,s)  (cs',[(pnorm@ps,pabr@ps)]@css,t)"
proof -
  from step drop_suffix_hd_css_step'' [of _ p ps cs css s cs' "pnorm@ps" "pabr@ps" t]
  show ?thesis
    by auto
qed

lemma drop_suffix':
  assumes step: "Γ(csxs,css,s)  (cs'xs,css',t)"
  shows "xs cs cs'. css=css'; csxs=cs@xs; cs'xs = cs'@xs; cs[] 
          Γ(cs,css,s)  (cs',css,t)"
using step
apply induct
apply (fastforce intro: step.intros simp add: neq_Nil_conv)+
done

lemma drop_suffix:
  assumes step: "Γ(c#cs@xs,css,s)  (cs'@xs,css,t)"
  shows "Γ(c#cs,css,s)  (cs',css,t)"
  by(rule drop_suffix' [OF step _ _ _]) auto

lemma drop_suffix_same_css_step:
  assumes step: "Γ(cs@xs,css,s)  (cs'@xs,css,t)"
  assumes not_Nil: "cs[]"
  shows "Γ(cs,xss,s)  (cs',xss,t)"
proof-
  from drop_suffix' [OF step _ _ _ not_Nil]
  have "Γ(cs,css,s)  (cs',css,t)"
    by auto
  with drop_suffix_css_step [of _ cs "[]" css s cs' "[]" t]
  have "Γ (cs, [], s)  (cs', [], t)"
    by auto
  from app_css_step [OF this]
  show ?thesis
    by auto
qed

lemma Cons_change_css_step:
  assumes step: "Γ (cs,css,s)  (cs',css'@css,t)"
  shows "Γ (cs,xss,s)  (cs',css'@xss,t)"
proof -
  from step
    drop_suffix_css_step [where cs=cs and pcss="[]" and css=css and s=s
                             and cs'=cs' and pcss'=css' and t=t]
  have "Γ (cs, [], s)  (cs', css', t)"
    by auto
  from app_css_step [where xs=xss, OF this]
  show ?thesis
    by auto
qed

lemma Nil_change_css_step:
  assumes step: "Γ([],ass@css,s)  (cs',ass'@css,t)"
  assumes ass_not_Nil: "ass[]"
  shows "Γ([],ass@xss,s)  (cs',ass'@xss,t)"
proof -
  from step drop_suffix_css_step [of _ "[]" ass css s cs' ass' t]
  have "Γ ([], ass, s)  (cs', ass', t)"
    by auto
  from app_css_step [where xs=xss, OF this]
  show ?thesis
    by auto
qed

subsubsection ‹Equivalence between Big and Small-Step Semantics›

lemma exec_impl_steps:
  assumes exec: "Γc,s  t"
  shows "cs css. Γ(c#cs,css,s) * (cs,css,t)"
using exec
proof (induct)
  case Skip thus ?case by (blast intro: step.Skip)
next
  case Guard thus ?case by (blast intro: step.Guard rtranclp_trans)
next
  case GuardFault thus ?case by (blast intro: step.GuardFault)
next
  case FaultProp thus ?case by (blast intro: step.FaultProp)
next
  case Basic thus ?case by (blast intro: step.Basic)
next
  case Spec thus ?case by (blast intro: step.Spec)
next
  case SpecStuck thus ?case by (blast intro: step.SpecStuck)
next
  case Seq thus ?case by (blast intro: step.Seq rtranclp_trans)
next
  case CondTrue thus ?case by (blast intro: step.CondTrue rtranclp_trans)
next
  case CondFalse thus ?case by (blast intro: step.CondFalse rtranclp_trans)
next
  case WhileTrue thus ?case by (blast intro: step.WhileTrue rtranclp_trans)
next
  case WhileFalse thus ?case by (blast intro: step.WhileFalse)
next
  case (Call p bdy s s' cs css)
  have bdy: "Γ p = Some bdy" by fact
  have steps_body: "Γ([bdy],(cs,Throw#cs)#css,Normal s) *
                       ([],(cs,Throw#cs)#css, s')" by fact
  show ?case
  proof (cases s')
    case (Normal s'')
    note steps_body
    also from Normal have "Γ([],(cs,Throw#cs)#css, s')  (cs,css,s')"
      by (auto intro: step.intros)
    finally show ?thesis
      using bdy
      by (blast intro: step.Call rtranclp_trans)
  next
    case (Abrupt s'')
    with steps_body
    have "Γ([bdy],(cs,Throw#cs)#css,Normal s) *
             ([],(cs,Throw#cs)#css, Abrupt s'')" by simp
    also have "Γ([],(cs,Throw#cs)#css, Abrupt s'')  (Throw#cs,css,Normal s'')"
      by (rule ExitBlockAbrupt)
    also have "Γ(Throw#cs,css,Normal s'')  (cs,css,Abrupt s'')"
      by (rule Throw)
    finally show ?thesis
      using bdy Abrupt
      by (auto intro: step.Call rtranclp_trans)
  next
    case Fault
    note steps_body
    also from Fault have "Γ([],(cs,Throw#cs)#css, s')  (cs,css,s')"
      by (auto intro: step.intros)
    finally show ?thesis
      using bdy
      by (blast intro: step.Call rtranclp_trans)
  next
    case Stuck
    note steps_body
    also from Stuck have "Γ([],(cs,Throw#cs)#css, s')  (cs,css,s')"
      by (auto intro: step.intros)
    finally show ?thesis
      using bdy
      by (blast intro: step.Call rtranclp_trans)
  qed
next
  case (CallUndefined p s cs css)
  have undef: "Γ p = None" by fact
  hence "Γ(Call p # cs, css, Normal s)  (cs, css, Stuck)"
    by (rule step.CallUndefined)
  thus ?case ..
next
  case StuckProp thus ?case by (blast intro: step.StuckProp rtrancl_trans)
next
  case DynCom thus ?case by (blast intro: step.DynCom rtranclp_trans)
next
   case Throw thus ?case by (blast intro: step.Throw)
next
  case AbruptProp thus ?case by (blast intro: step.AbruptProp)
next
  case (CatchMatch c1 s s' c2 s'' cs css)
  have steps_c1: "Γ([c1],(cs,c2#cs)#css,Normal s) *
                    ([],(cs,c2#cs)#css,Abrupt s')" by fact
  also
  have "Γ([],(cs,c2#cs)#css,Abrupt s')  (c2#cs,css,Normal s')"
    by (rule ExitBlockAbrupt)
  also
  have steps_c2: "Γ(c2#cs,css,Normal s') * (cs,css,s'')"  by fact
  finally
  show "Γ(Catch c1 c2 # cs, css, Normal s) * (cs, css, s'')"
    by (blast intro: step.Catch rtranclp_trans)
next
  case (CatchMiss c1 s s' c2 cs css)
  assume notAbr: "¬ isAbr s'"
  have steps_c1: "Γ([c1],(cs,c2#cs)#css,Normal s) * ([],(cs,c2#cs)#css,s')" by fact
  show "Γ(Catch c1 c2 # cs, css, Normal s) * (cs, css, s')"
  proof (cases s')
    case (Normal w)
    with steps_c1
    have "Γ([c1],(cs,c2#cs)#css,Normal s) * ([],(cs,c2#cs)#css,Normal w)"
      by simp
    also
    have "Γ([],(cs,c2#cs)#css,Normal w)  (cs,css,Normal w)"
      by (rule ExitBlockNormal)
    finally show ?thesis using Normal
      by (auto intro: step.Catch rtranclp_trans)
  next
    case Abrupt with notAbr show ?thesis by simp
  next
    case (Fault f)
    with steps_c1
    have "Γ([c1],(cs,c2#cs)#css,Normal s) * ([],(cs,c2#cs)#css,Fault f)"
      by simp
    also
    have "Γ([],(cs,c2#cs)#css,Fault f)  (cs,css,Fault f)"
      by (rule FaultPropBlock)
    finally show ?thesis using Fault
      by (auto intro: step.Catch rtranclp_trans)
  next
    case Stuck
    with steps_c1
    have "Γ([c1],(cs,c2#cs)#css,Normal s) * ([],(cs,c2#cs)#css,Stuck)"
      by simp
    also
    have "Γ([],(cs,c2#cs)#css,Stuck)  (cs,css,Stuck)"
      by (rule StuckPropBlock)
    finally show ?thesis using Stuck
      by (auto intro: step.Catch rtranclp_trans)
  qed
qed


inductive "execs"::"[('s,'p,'f) body,('s,'p,'f) com list,
                      ('s,'p,'f) continuation list,
                      ('s,'f) xstate,('s,'f) xstate]  bool"
                   (‹_ _,_,_  _› [50,50,50,50,50] 50)
  for Γ:: "('s,'p,'f) body"
where
  Nil: "Γ[],[],s  s"

| ExitBlockNormal: "Γnrms,css,Normal s  t
                    
                    Γ[],(nrms,abrs)#css,Normal s  t"

| ExitBlockAbrupt: "Γabrs,css,Normal s  t
                    
                    Γ[],(nrms,abrs)#css,Abrupt s  t"

| ExitBlockFault: "Γnrms,css,Fault f  t
                    
                    Γ[],(nrms,abrs)#css,Fault f  t"

| ExitBlockStuck: "Γnrms,css,Stuck  t
                    
                    Γ[],(nrms,abrs)#css,Stuck  t"

| Cons: "Γc,s  t; Γcs,css,t  u
         
         Γc#cs,css,s  u"


inductive_cases execs_elim_cases [cases set]:
 "Γ[],css,s  t"
 "Γc#cs,css,s  t"

ML ML_Thms.bind_thm ("converse_rtrancl_induct3", Split_Rule.split_rule @{context}
    (Rule_Insts.read_instantiate @{context}
      [((("a", 0), Position.none), "(cs, css, s)"),
       ((("b", 0), Position.none), "(cs', css', t)")] []
      @{thm converse_rtranclp_induct}));

lemma execs_Fault_end:
  assumes execs: "Γcs,css,s  t" shows "s=Fault f t=Fault f"
  using execs
  by (induct) (auto dest: Fault_end)

lemma execs_Stuck_end:
  assumes execs: "Γcs,css,s  t" shows "s=Stuck  t=Stuck"
  using execs
  by (induct) (auto dest: Stuck_end)


theorem steps_impl_execs:
  assumes steps: "Γ(cs,css,s) * ([],[],t)"
  shows "Γcs,css,s  t"
using steps
proof (induct rule: converse_rtrancl_induct3 [consumes 1])
  show "Γ[],[],t  t" by (rule execs.Nil)
next
  fix cs css s cs' css' w
  assume step: "Γ(cs,css, s)  (cs',css', w)"
  assume execs: "Γcs',css',w  t"
  from step
  show "Γcs,css,s  t"
  proof (cases)
    case (Catch c1 c2 cs s)
    with execs obtain t' where
      exec_c1: "Γc1,Normal s  t'" and
      execs_rest: "Γ[],(cs, c2 # cs) # css,t'  t"
      by (clarsimp elim!: execs_elim_cases)
    have  "ΓCatch c1 c2 # cs,css,Normal s  t"
    proof (cases t')
      case (Normal t'')
      with exec_c1 have "ΓCatch c1 c2,Normal s  t'"
        by (auto intro: exec.CatchMiss)
      moreover
      from execs_rest Normal have "Γcs,css,t'  t"
        by (cases) auto
      ultimately show ?thesis
        by (rule execs.Cons)
    next
      case (Abrupt t'')
      from execs_rest Abrupt have "Γc2#cs,css,Normal t''  t"
        by (cases) auto
      then obtain v where
          exec_c2: "Γc2,Normal t''  v" and
          rest: "Γcs,css,v  t"
        by cases
      from exec_c1 Abrupt exec_c2
      have "ΓCatch c1 c2,Normal s  v"
        by  - (rule exec.CatchMatch, auto)
      from this rest
      show ?thesis
        by (rule execs.Cons)
    next
      case (Fault f)
      with exec_c1 have "ΓCatch c1 c2,Normal s  Fault f"
        by (auto intro: exec.intros)
      moreover from execs_rest Fault have "Γcs,css,Fault f  t"
        by (cases) auto
      ultimately show ?thesis
        by (rule execs.Cons)
    next
      case Stuck
      with exec_c1 have "ΓCatch c1 c2,Normal s  Stuck"
        by (auto intro: exec.intros)
      moreover from execs_rest Stuck have "Γcs,css,Stuck  t"
        by (cases) auto
      ultimately show ?thesis
        by (rule execs.Cons)
    qed
    with Catch show ?thesis by simp
  next
    case (Call p bdy cs s)
    have bdy: "Γ p = Some bdy" by fact
    from Call execs obtain t' where
      exec_body: "Γbdy,Normal s  t'" and
      execs_rest:
            "Γ[],(cs,Throw#cs)#css ,t'  t"
       by (clarsimp elim!: execs_elim_cases)
    have "ΓCall p # cs,css,Normal s  t"
    proof (cases t')
      case (Normal t'')
      with exec_body bdy
      have "ΓCall p ,Normal s  Normal t''"
        by (auto intro: exec.intros)
      moreover
      from execs_rest Normal
      have "Γcs,css ,Normal t''  t"
        by cases auto
      ultimately show ?thesis by (rule execs.Cons)
    next
      case (Abrupt t'')
      with exec_body bdy
      have "ΓCall p,Normal s  Abrupt t''"
        by (auto intro: exec.intros)
      moreover
      from execs_rest Abrupt have
        "ΓThrow # cs,css,Normal t''  t"
        by (cases) auto
      then obtain v where v: "ΓThrow,Normal t''  v" "Γcs,css,v  t"
        by (clarsimp elim!: execs_elim_cases)
      moreover from v have "v=Abrupt t''"
        by (auto elim: exec_Normal_elim_cases)
      ultimately
      show ?thesis by (auto intro: execs.Cons)
    next
      case (Fault f)
      with exec_body bdy have "ΓCall p,Normal s  Fault f"
        by (auto intro: exec.intros)
      moreover from execs_rest Fault have "Γcs,css,Fault f  t"
        by (cases) (auto elim: execs_elim_cases dest: Fault_end)
      ultimately
      show ?thesis by (rule execs.Cons)
    next
      case Stuck
      with exec_body bdy have "ΓCall p,Normal s  Stuck"
        by (auto intro: exec.intros)
      moreover from execs_rest Stuck have "Γcs,css,Stuck  t"
        by (cases) (auto elim: execs_elim_cases dest: Stuck_end)
      ultimately
      show ?thesis by (rule execs.Cons)
    qed
    with Call show ?thesis by simp
  qed (insert execs,
      (blast intro:execs.intros exec.intros elim!: execs_elim_cases)+)
qed

theorem steps_impl_exec:
  assumes steps: "Γ([c],[],s) * ([],[],t)"
  shows "Γc,s  t"
using steps_impl_execs [OF steps]
by (blast elim: execs_elim_cases)

corollary steps_eq_exec: "Γ([c],[],s) * ([],[],t) = Γc,s  t"
  by (blast intro: steps_impl_exec exec_impl_steps)


subsection ‹Infinite Computations: inf Γ cs css s›

definition inf ::
 "[('s,'p,'f) body,('s,'p,'f) com list,('s,'p,'f) continuation list,('s,'f) xstate]
   bool"
where "inf Γ cs css s = (f. f 0 = (cs,css,s)  (i. Γf i  f(Suc i)))"

lemma not_infI: "f. f 0 = (cs,css,s); i. Γf i  f (Suc i)  False
                 ¬inf Γ cs css s"
  by (auto simp add: inf_def)

subsection ‹Equivalence of Termination and Absence of Infinite Computations›


inductive "terminatess":: "[('s,'p,'f) body,('s,'p,'f) com list,
                            ('s,'p,'f) continuation list,('s,'f) xstate]  bool"
                (‹__,_  _› [60,20,60] 89)
  for  Γ::"('s,'p,'f) body"
where
   Nil: "Γ[],[]s"

|  ExitBlockNormal: "Γnrms,cssNormal s
                     
                     Γ[],(nrms,abrs)#cssNormal s"

|  ExitBlockAbrupt: "Γabrs,cssNormal s
                     
                     Γ[],(nrms,abrs)#cssAbrupt s"

|  ExitBlockFault: "Γnrms,cssFault f
                    
                    Γ[],(nrms,abrs)#cssFault f"

|  ExitBlockStuck: "Γnrms,cssStuck
                    
                    Γ[],(nrms,abrs)#cssStuck"


|  Cons: "Γcs; (t. Γc,s  t  Γcs,csst)
          
          Γc#cs,csss"

inductive_cases terminatess_elim_cases [cases set]:
 "Γ[],csst"
 "Γc#cs,csst"

lemma terminatess_Fault: "cs. Γcs,cssFault f"
proof (induct css)
  case Nil
  show "Γcs,[]Fault f"
  proof (induct cs)
    case Nil show "Γ[],[]Fault f" by (rule terminatess.Nil)
  next
    case (Cons c cs)
    thus ?case
      by (auto intro: terminatess.intros terminates.intros dest: Fault_end)
  qed
next
  case (Cons d css)
  have hyp: "cs. Γcs,cssFault f" by fact
  obtain nrms abrs where d: "d=(nrms,abrs)"  by (cases d) auto
  have "Γcs,(nrms,abrs)#cssFault f"
  proof (induct cs)
    case Nil
    show "Γ[],(nrms, abrs) # cssFault f"
      by (rule terminatess.ExitBlockFault) (rule hyp)
  next
    case (Cons c cs)
    have hyp1: "Γcs,(nrms, abrs) # cssFault f" by fact
    show "Γc#cs,(nrms, abrs)#cssFault f"
      by (auto intro: hyp1 terminatess.Cons terminates.intros dest: Fault_end)
  qed
  with d show ?case by simp
qed

lemma terminatess_Stuck: "cs. Γcs,cssStuck"
proof (induct css)
  case Nil
  show "Γcs,[]Stuck"
  proof (induct cs)
    case Nil show "Γ[],[]Stuck" by (rule terminatess.Nil)
  next
    case (Cons c cs)
    thus ?case
      by (auto intro: terminatess.intros terminates.intros dest: Stuck_end)
  qed
next
  case (Cons d css)
  have hyp: "cs. Γcs,cssStuck" by fact
  obtain nrms abrs where d: "d=(nrms,abrs)" by (cases d) auto
  have "Γcs,(nrms,abrs)#cssStuck"
  proof (induct cs)
    case Nil
    show "Γ[],(nrms, abrs) # cssStuck"
      by (rule terminatess.ExitBlockStuck) (rule hyp)
  next
    case (Cons c cs)
    have hyp1: "Γcs,(nrms, abrs) # cssStuck" by fact
    show "Γc#cs,(nrms, abrs)#cssStuck"
      by (auto intro: hyp1 terminatess.Cons terminates.intros dest: Stuck_end)
  qed
  with d show ?case by simp
qed


lemma Basic_terminates: "ΓBasic f  t"
  by (cases t) (auto intro: terminates.intros)

lemma step_preserves_terminations:
  assumes step: "Γ(cs,css,s)  (cs',css',t)"
  shows "Γcs,csss  Γcs',css't"
using step
proof (induct)
  case Skip thus ?case
    by (auto elim: terminates_Normal_elim_cases terminatess_elim_cases
             intro: exec.intros)
next
  case Guard thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
             intro: terminatess.intros terminates.intros exec.intros)
next
  case GuardFault thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case FaultProp show ?case by (rule terminatess_Fault)
next
  case FaultPropBlock show ?case by (rule terminatess_Fault)
next
  case AbruptProp thus ?case
    by (blast elim: terminatess_elim_cases
              intro: terminatess.intros)
next
  case ExitBlockNormal thus ?case
    by (blast elim: terminatess_elim_cases
              intro: terminatess.intros )
next
  case ExitBlockAbrupt thus ?case
    by (blast elim: terminatess_elim_cases
              intro: terminatess.intros )
next
  case Basic thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case Spec thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case SpecStuck thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case Seq thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case CondTrue thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case CondFalse thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case WhileTrue thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case WhileFalse thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case (Call p bdy cs css s)
  have bdy: "Γ p = Some bdy" by fact
  from Call obtain
    term_body: "Γbdy  Normal s" and
    term_rest: "t. ΓCall p,Normal s  t  Γcs,csst"
    by (fastforce elim!: terminatess_elim_cases terminates_Normal_elim_cases)
  show "Γ[bdy],(cs,Throw # cs)#cssNormal s"
  proof (rule terminatess.Cons [OF term_body],clarsimp)
    fix t
    assume exec_body: "Γbdy,Normal s  t"
    show "Γ[],(cs,Throw # cs) # csst"
    proof (cases t)
      case (Normal t')
      with exec_body bdy
      have "ΓCall p,Normal s  Normal t'"
        by (auto intro: exec.intros)
      with term_rest have "Γcs,cssNormal t'"
        by iprover
      with Normal show ?thesis
        by (auto intro: terminatess.intros terminates.intros
                 elim: exec_Normal_elim_cases)
    next
      case (Abrupt t')
      with exec_body bdy
      have "ΓCall p,Normal s  Abrupt t'"
        by (auto intro: exec.intros)
      with term_rest have "Γcs,cssAbrupt t'"
        by iprover
      with Abrupt show ?thesis
        by (fastforce intro: terminatess.intros terminates.intros
                     elim: exec_Normal_elim_cases)
    next
      case Fault
      thus ?thesis
        by (iprover intro: terminatess_Fault)
    next
      case Stuck
      thus ?thesis
        by (iprover intro: terminatess_Stuck)
    qed
  qed
next
  case CallUndefined thus ?case
    by (iprover intro: terminatess_Stuck)
next
  case StuckProp show ?case by (rule terminatess_Stuck)
next
  case StuckPropBlock show ?case by (rule terminatess_Stuck)
next
  case DynCom thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case Throw thus ?case
    by (blast elim: terminatess_elim_cases terminates_Normal_elim_cases
              intro: terminatess.intros terminates.intros exec.intros)
next
  case (Catch c1 c2 cs css s)
  then obtain
    term_c1: "Γc1  Normal s" and
    term_c2: "s'. Γc1,Normal s  Abrupt s'  Γc2  Normal s'"and
    term_rest: "t. ΓCatch c1 c2,Normal s  t  Γcs,csst"
    by (clarsimp elim!: terminatess_elim_cases terminates_Normal_elim_cases)
  show "Γ[c1],(cs, c2 # cs) # cssNormal s"
  proof (rule terminatess.Cons [OF term_c1],clarsimp)
    fix t
    assume exec_c1: "Γc1,Normal s  t"
    show "Γ[],(cs, c2 # cs) # csst"
    proof (cases t)
      case (Normal t')
      with exec_c1 have "ΓCatch c1 c2,Normal s  t"
        by (auto intro: exec.intros)
      with term_rest have "Γcs,csst"
        by iprover
      with Normal show ?thesis
        by (iprover intro: terminatess.intros)
    next
      case (Abrupt t')
      with exec_c1 term_c2 have "Γc2  Normal t'"
        by auto
      moreover
      {
        fix w
        assume exec_c2: "Γc2,Normal t'  w"
        have "Γcs,cssw"
        proof -
          from exec_c1 Abrupt exec_c2
          have "ΓCatch c1 c2,Normal s  w"
            by (auto intro: exec.intros)
          with term_rest show ?thesis by simp
        qed
      }
      ultimately
      show ?thesis using Abrupt
        by (auto intro: terminatess.intros)
    next
      case Fault thus ?thesis
        by (iprover intro: terminatess_Fault)
    next
      case Stuck thus ?thesis
        by (iprover intro: terminatess_Stuck)
    qed
  qed
qed


ML ML_Thms.bind_thm ("rtrancl_induct3", Split_Rule.split_rule @{context}
    (Rule_Insts.read_instantiate @{context}
      [((("a", 0), Position.none), "(ax, ay, az)"),
       ((("b", 0), Position.none), "(bx, by, bz)")] []
      @{thm rtranclp_induct}));

lemma steps_preserves_terminations:
  assumes steps: "Γ(cs,css,s) * (cs',css',t)"
  shows "Γcs,csss  Γcs',css't"
using steps
proof (induct rule: rtrancl_induct3 [consumes 1])
  assume  "Γcs,csss" then show "Γcs,csss".
next
  fix cs'' css'' w cs' css' t
  assume "Γ(cs'',css'', w)  (cs',css', t)" "Γcs,csss  Γcs'',css''w"
         "Γcs,csss"
  then show "Γcs',css't"
    by (blast dest: step_preserves_terminations)
qed

theorem steps_preserves_termination:
  assumes steps: "Γ([c],[],s) * (c'#cs',css',t)"
  assumes term_c: "Γcs"
  shows "Γc't"
proof -
  from term_c have "Γ[c],[]s"
    by (auto intro: terminatess.intros)
  from steps this
  have "Γc'#cs',css't"
    by (rule steps_preserves_terminations)
  thus "Γc't"
    by (auto elim: terminatess_elim_cases)
qed





lemma renumber':
  assumes f: "i. (a,f i)  r*  (f i,f(Suc i))  r"
  assumes a_b: "(a,b)  r*"
  shows "b = f 0  (f. f 0 = a  (i. (f i, f(Suc i))  r))"
using a_b
proof (induct rule: converse_rtrancl_induct [consumes 1])
  assume "b = f 0"
  with f show "f. f 0 = b  (i. (f i, f (Suc i))  r)"
    by blast
next
  fix a z
  assume a_z: "(a, z)  r" and "(z, b)  r*"
  assume "b = f 0  f. f 0 = z  (i. (f i, f (Suc i))  r)"
         "b = f 0"
  then obtain f where f0: "f 0 = z" and seq: "i. (f i, f (Suc i))  r"
    by iprover
  {
    fix i have "((λi. case i of 0  a | Suc i  f i) i, f i)  r"
      using seq a_z f0
      by (cases i) auto
  }
  then
  show "f. f 0 = a  (i. (f i, f (Suc i))  r)"
    by - (rule exI [where x="λi. case i of 0  a | Suc i  f i"],simp)
qed

lemma renumber:
 "i. (a,f i)  r*  (f i,f(Suc i))  r
  f. f 0 = a  (i. (f i, f(Suc i))  r)"
  by(blast dest:renumber')

lemma not_inf_Fault':
  assumes enum_step: "i. Γf i  f (Suc i)"
  shows "k cs. f k = (cs,css,Fault m)  False"
proof (induct css)
  case Nil
  have f_k: "f k = (cs,[],Fault m)" by fact
  have "k. f k = (cs,[],Fault m)  False"
  proof (induct cs)
    case Nil
    have "f k = ([], [], Fault m)" by fact
    moreover
    from enum_step have "Γf k  f (Suc k)"..
    ultimately show "False"
      by (fastforce elim: step_elim_cases)
  next
    case (Cons c cs)
    have fk: "f k = (c # cs, [], Fault m)" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (cs,[],Fault m)"
      by (fastforce elim: step_elim_cases)
    with enum_step Cons.hyps
    show False
      by blast
  qed
  from this f_k show False by blast
next
  case (Cons ds css)
  then obtain nrms abrs where ds: "ds=(nrms,abrs)" by (cases ds) auto
  have hyp: "k cs. f k = (cs,css,Fault m)  False" by fact
  have "k. f k = (cs,(nrms,abrs)#css,Fault m)  False"
  proof (induct cs)
    case Nil
    have fk: "f k = ([], (nrms, abrs) # css, Fault m)" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (nrms,css,Fault m)"
      by (fastforce elim: step_elim_cases)
    thus ?case
      by (rule hyp)
  next
    case (Cons c cs)
    have fk: "f k = (c#cs, (nrms, abrs) # css, Fault m)" by fact
    have hyp1: "k. f k = (cs, (nrms, abrs) # css, Fault m)  False" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (cs,(nrms,abrs)#css,Fault m)"
      by (fastforce elim: step_elim_cases)
    thus ?case
      by (rule hyp1)
  qed
  with ds Cons.prems show False by auto
qed

lemma not_inf_Fault:
  "¬ inf Γ cs css (Fault m)"
apply (rule not_infI)
apply (rule_tac f=f in not_inf_Fault' )
by auto

lemma not_inf_Stuck':
  assumes enum_step: "i. Γf i  f (Suc i)"
  shows "k cs. f k = (cs,css,Stuck)  False"
proof (induct css)
  case Nil
  have f_k: "f k = (cs,[],Stuck)" by fact
  have "k. f k = (cs,[],Stuck)  False"
  proof (induct cs)
    case Nil
    have "f k = ([], [], Stuck)" by fact
    moreover
    from enum_step have "Γf k  f (Suc k)"..
    ultimately show "False"
      by (fastforce elim: step_elim_cases)
  next
    case (Cons c cs)
    have fk: "f k = (c # cs, [], Stuck)" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (cs,[],Stuck)"
      by (fastforce elim: step_elim_cases)
    with enum_step Cons.hyps
    show False
      by blast
  qed
  from this f_k show False .
next
  case (Cons ds css)
  then obtain nrms abrs where ds: "ds=(nrms,abrs)" by (cases ds) auto
  have hyp: "k cs. f k = (cs,css,Stuck)  False" by fact
  have "k. f k = (cs,(nrms,abrs)#css,Stuck)  False"
  proof (induct cs)
    case Nil
    have fk: "f k = ([], (nrms, abrs) # css, Stuck)" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (nrms,css,Stuck)"
      by (fastforce elim: step_elim_cases)
    thus ?case
      by (rule hyp)
  next
    case (Cons c cs)
    have fk: "f k = (c#cs, (nrms, abrs) # css, Stuck)" by fact
    have hyp1: "k. f k = (cs, (nrms, abrs) # css, Stuck)  False" by fact
    from enum_step have "Γf k  f (Suc k)"..
    with fk have "f (Suc k) = (cs,(nrms,abrs)#css,Stuck)"
      by (fastforce elim: step_elim_cases)
    thus ?case
      by (rule hyp1)
  qed
  with ds Cons.prems show False by auto
qed

lemma not_inf_Stuck:
  "¬ inf Γ cs css Stuck"
apply (rule not_infI)
apply (rule_tac f=f in not_inf_Stuck')
by auto

lemma last_butlast_app:
assumes butlast: "butlast as = xs @ butlast bs"
assumes not_Nil: "bs  []" "as  []"
assumes last: "fst (last as) = fst (last bs)" "snd (last as) = snd (last bs)"
shows "as = xs @ bs"
proof -
  from last have "last as = last bs"
    by (cases "last as",cases "last bs") simp
  moreover
  from not_Nil have "as = butlast as @ [last as]" "bs = butlast bs @ [last bs]"
    by auto
  ultimately show ?thesis
    using butlast
    by simp
qed


lemma last_butlast_tl:
assumes butlast: "butlast bs = x # butlast as"
assumes not_Nil: "bs  []" "as  []"
assumes last: "fst (last as) = fst (last bs)" "snd (last as) = snd (last bs)"
shows "as = tl bs"
proof -
  from last have "last as = last bs"
    by (cases "last as",cases "last bs") simp
  moreover
  from not_Nil have "as = butlast as @ [last as]" "bs = butlast bs @ [last bs]"
    by auto
  ultimately show ?thesis
    using butlast
    by simp
qed

locale inf =
fixes CS:: "('s,'p,'f) config  ('s, 'p,'f) com list"
  and CSS:: "('s,'p,'f) config  ('s, 'p,'f) continuation list"
  and S:: "('s,'p,'f) config  ('s,'f) xstate"
  defines CS_def : "CS  fst"
  defines CSS_def : "CSS  λc. fst (snd c)"
  defines S_def: "S  λc. snd (snd c)"

lemma (in inf) steps_hd_drop_suffix:
assumes f_0: "f 0 = (c#cs,css,s)"
assumes f_step: "i. Γ f(i)  f(Suc i)"
assumes not_finished: "i < k. ¬ (CS (f i) = cs  CSS (f i) = css)"
assumes simul: "ik.
        (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                 else CS (f i)=pcs i 
                      CSS (f i)= butlast (pcss i)@
                              [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                              css)"
defines "pλi. (pcs i, pcss i, S (f i))"
shows "i<k. Γ p i  p (Suc i)"
using not_finished simul
proof (induct k)
  case 0
  thus ?case by simp
next
  case (Suc k)
  have simul: "iSuc k.
        (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                 else CS (f i)=pcs i 
                      CSS (f i)= butlast (pcss i)@
                              [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                              css)" by fact
  have not_finished': "i < Suc k. ¬ (CS (f i) = cs  CSS (f i) = css)" by fact
  with simul
  have not_finished: "i<Suc k. ¬ (pcs i = []  pcss i = [])"
    by (auto simp add: CS_def CSS_def S_def split: if_split_asm)
  show ?case
  proof (clarify)
    fix i
    assume i_le_Suc_k: "i < Suc k"
    show "Γ p i  p (Suc i)"
    proof (cases "i < k")
      case True
      with not_finished' simul Suc.hyps
      show ?thesis
        by auto
    next
      case False
      with i_le_Suc_k
      have eq_i_k: "i=k"
        by simp
      show "Γp i  p (Suc i)"
      proof -
        obtain cs' css' t' where
          f_Suc_i: "f (Suc i) = (cs', css', t')"
          by (cases "f (Suc i)")
        obtain cs'' css'' t'' where
          f_i: "f i = (cs'',css'',t'')"
          by (cases "f i")
        from not_finished eq_i_k
        have pcs_pcss_not_Nil: "¬ (pcs i = []  pcss i = [])"
          by auto
        from simul [rule_format, of i] i_le_Suc_k f_i
        have pcs_pcss_i:
          "if pcss i = [] then css''=css  cs''=pcs i@cs
           else cs''=pcs i 
           css''= butlast (pcss i)@
                       [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                       css"
          by (simp add: CS_def CSS_def S_def cong: if_cong)
        from simul [rule_format, of "Suc i"] i_le_Suc_k f_Suc_i
        have pcs_pcss_Suc_i:
        "if pcss (Suc i) = [] then css' = css  cs' = pcs (Suc i) @ cs
         else cs' = pcs (Suc i) 
              css' = butlast (pcss (Suc i)) @
               [(fst (last (pcss (Suc i))) @ cs, snd (last (pcss (Suc i))) @ cs)] @
               css"
          by (simp add: CS_def CSS_def S_def cong: if_cong)
        show ?thesis
        proof (cases "pcss i = []")
          case True
          note pcss_Nil = this
          with pcs_pcss_i pcs_pcss_not_Nil obtain p ps where
            pcs_i: "pcs i = p#ps" and
            css'': "css''=css" and
            cs'': "cs''=(p#ps)@cs"
            by (auto simp add: neq_Nil_conv)
          with f_i have "f i = (p#(ps@cs),css,t'')"
            by simp
          with f_Suc_i f_step [rule_format, of i]
          have step_css: "Γ (p#(ps@cs),css,t'')  (cs',css',t')"
            by simp
          from step_Cons' [OF this, of p "ps@cs"]
          obtain css''' where
            css''': "css' = css''' @ css"
            "if css''' = [] then p. cs' = p @ ps @ cs
            else (pnorm pabr. css'''=[(pnorm @ ps @ cs,pabr @ ps @ cs)])"
            by auto
          show ?thesis
          proof (cases "css''' = []")
            case True
            with css'''
            obtain p' where
              css': "css' = css" and
              cs': "cs' = p' @ ps @ cs"
              by auto
                (*from cs' css' f_Suc_i f_i [rule_format, of "Suc k"]
                have p_ps_not_Nil: "p'@ps ≠ Nil"
                by auto*)
            from css' cs' step_css
            have step: "Γ (p#(ps@cs),css,t'')  (p'@ps@cs,css,t')"
              by simp
            hence "Γ ((p#ps)@cs,css,t'')  ((p'@ps)@cs,css,t')"
              by simp
            from drop_suffix_css_step' [OF drop_suffix_same_css_step [OF this],
              where xs="css" and css="[]" and css'="[]"]
            have  "Γ (p#ps,[],t'')  (p'@ps,[],t')"
              by simp
            moreover
            from css' cs' pcs_pcss_Suc_i
            obtain "pcs (Suc i) = p'@ps" and "pcss (Suc i) = []"
              by (simp split: if_split_asm)
            ultimately show ?thesis
              using pcs_i pcss_Nil f_i f_Suc_i
              by (simp add: CS_def CSS_def S_def p_def)
          next
            case False
            with css'''
            obtain pnorm pabr where
              css': "css'=css'''@css"
              "css'''=[(pnorm @ ps @ cs,pabr @ ps @ cs)]"
              by auto
            with css''' step_css
            have "Γ (p#ps@cs,css,t'')  (cs',[(pnorm@ps@cs,pabr@ps@cs)]@css,t')"
              by simp
            then
            have "Γ(p#ps, css, t'')  (cs', [(pnorm@ps, pabr@ps)] @ css, t')"
              by (rule drop_suffix_hd_css_step)
            from drop_suffix_css_step' [OF this,
              where css="[]" and xs="css" and css'="[(pnorm@ps, pabr@ps)]"]
            have "Γ (p#ps,[],t'')  (cs',[(pnorm@ps, pabr@ps)],t')"
              by simp
            moreover
            from css' pcs_pcss_Suc_i
            obtain "pcs (Suc i) = cs'" "pcss (Suc i) = [(pnorm@ps, pabr@ps)]"
              apply (cases "pcss (Suc i)")
              apply (auto split: if_split_asm)
              done
            ultimately show ?thesis
              using pcs_i pcss_Nil f_i f_Suc_i
              by (simp add: p_def CS_def CSS_def S_def)
          qed
        next
          case False
          note pcss_i_not_Nil = this
          with pcs_pcss_i obtain
            cs'': "cs''=pcs i" and
            css'': "css''= butlast (pcss i)@
                            [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                            css"
            by auto
          from f_Suc_i f_i f_step [rule_format, of i]
          have step_i_full: "Γ (cs'',css'',t'')  (cs',css',t')"
            by simp
          show ?thesis
          proof (cases cs'')
            case (Cons c' cs)
            with step_Cons' [OF step_i_full]
            obtain css''' where css': "css' = css'''@css''"
              by auto
            with step_i_full
            have "Γ (cs'',css'',t'')  (cs',css'''@css'',t')"
              by simp
            from Cons_change_css_step [OF this, where xss="pcss i"] Cons cs''
            have "Γ (pcs i, pcss i,t'')  (cs',css'''@pcss i,t')"
              by simp
            moreover
            from cs'' css'' css' False pcs_pcss_Suc_i
            obtain "pcs (Suc i) = cs'" "pcss (Suc i) = css'''@pcss i"
              apply (auto  split: if_split_asm)
              apply (drule (4) last_butlast_app)
              by simp
            ultimately show ?thesis
              using f_i f_Suc_i
              by (simp add: p_def CS_def CSS_def S_def)
          next
            case Nil
            note cs''_Nil = this
            show ?thesis
            proof (cases "butlast (pcss i)")
              case (Cons bpcs bpcss)
              with cs''_Nil step_i_full css''
              have *: "Γ ([],[hd css'']@tl css'',t'')  (cs',css',t')"
                by simp
              moreover
              from step_Nil [OF *]
              have css': "css'=tl css''"
                by simp
              ultimately have
                step_i_full: "Γ ([],[hd css'']@tl css'',t'')  (cs',tl css'',t')"
                by simp
              from css'' Cons pcss_i_not_Nil
              have "hd css'' = hd (pcss i)"
                by (auto simp add: neq_Nil_conv split: if_split_asm)
              with cs'' cs''_Nil
                Nil_change_css_step [where ass="[hd css'']" and
                css="tl css''" and ass'="[]" and
                xss="tl (pcss i)", simplified, OF step_i_full [simplified]]
              have "Γ (pcs i,[hd (pcss i)]@tl (pcss i),t'')  (cs',tl (pcss i),t')"
                by simp
              with pcss_i_not_Nil
              have "Γ (pcs i,pcss i,t'')  (cs',tl (pcss i),t')"
                by simp
              moreover
              from css' css'' cs''_Nil Cons pcss_i_not_Nil pcs_pcss_Suc_i
              obtain "pcs (Suc i) = cs'" "pcss (Suc i) = tl (pcss i)"
                apply (clarsimp  split: if_split_asm)
                apply (drule (4) last_butlast_tl)
                by simp
              ultimately show ?thesis
                using f_i f_Suc_i
                by (simp add: p_def CS_def CSS_def S_def)
            next
              case Nil
              with css'' pcss_i_not_Nil
              obtain pnorm pabr
                where css'': "css''= [(pnorm@cs,pabr@cs)]@css" and
                pcss_i: "pcss i = [(pnorm,pabr)]"
                by (force simp add: neq_Nil_conv split: if_split_asm)
              with cs''_Nil step_i_full
              have "Γ([],[(pnorm@cs,pabr@cs)]@css,t'')  (cs',css',t')"
                by simp
              from step_Nil [OF this]
              obtain
                css': "css'=css" and
                cs': "(case t'' of
                         Abrupt s'  cs' = pabr @ cs  t' = Normal s'
                       | _  cs' = pnorm @ cs  t' = t'')"
                by (simp cong: xstate.case_cong)
              let "?pcs_Suc_i " = "(case t'' of Abrupt s'  pabr | _  pnorm)"
              from cs'
              have "Γ([],[(pnorm,pabr)],t'')  (?pcs_Suc_i,[],t')"
                by (auto intro: step.intros split: xstate.splits)
              moreover
              from css'' css' cs' pcss_i pcs_pcss_Suc_i
              obtain "pcs (Suc i) = ?pcs_Suc_i" "pcss (Suc i) = []"
                by (simp split: if_split_asm xstate.splits)
              ultimately
              show ?thesis
                using pcss_i cs'' cs''_Nil f_i f_Suc_i
                by (simp add: p_def CS_def CSS_def S_def)
            qed
          qed
        qed
      qed
    qed
  qed
qed

lemma k_steps_to_rtrancl:
  assumes steps: "i<k. Γ p i  p (Suc i)"
  shows "Γp 0* p k"
using steps
proof (induct k)
  case 0 thus ?case by auto
next
  case (Suc k)
  have "i<Suc k. Γ p i  p (Suc i)" by fact
  then obtain
  step_le_k: "i<k. Γ p i  p (Suc i)" and step_k: "Γ p k  p (Suc k)"
    by auto
  from Suc.hyps [OF step_le_k]
  have "Γ p 0 * p k".
  also note step_k
  finally show ?case .
qed



lemma (in inf) steps_hd_drop_suffix_finite:
assumes f_0: "f 0 = (c#cs,css,s)"
assumes f_step: "i. Γ f(i)  f(Suc i)"
assumes not_finished: "i < k. ¬ (CS (f i) = cs  CSS (f i) = css)"
assumes simul: "ik.
        (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                 else CS (f i)=pcs i 
                      CSS (f i)= butlast (pcss i)@
                              [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                              css)"
shows "Γ([c],[],s) * (pcs k, pcss k, S (f k))"
proof -
  from steps_hd_drop_suffix [OF f_0 f_step not_finished simul]
  have "i<k. Γ (pcs i, pcss i, S (f i)) 
                  (pcs (Suc i), pcss (Suc i), S (f (Suc i)))".
  from k_steps_to_rtrancl [OF this]
  have "Γ (pcs 0, pcss 0, S (f 0)) * (pcs k, pcss k, S (f k))".
  moreover from f_0 simul [rule_format, of 0]
  have "(pcs 0, pcss 0, S (f 0)) = ([c],[],s)"
    by (auto split: if_split_asm simp add: CS_def CSS_def S_def)
  ultimately show ?thesis by simp
qed

lemma (in inf) steps_hd_drop_suffix_infinite:
assumes f_0: "f 0 = (c#cs,css,s)"
assumes f_step: "i. Γ f(i)  f(Suc i)"
assumes not_finished: "i. ¬ (CS (f i) = cs  CSS (f i) = css)"
(*assumes not_finished: "∀i. ¬ (pcs i = [] ∧ pcss i = [])"*)
assumes simul: "i.
        (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                 else CS (f i)=pcs i 
                      CSS (f i)= butlast (pcss i)@
                              [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                              css)"
defines "pλi. (pcs i, pcss i, S (f i))"
shows "Γ p i  p (Suc i)"
proof -
  from steps_hd_drop_suffix [OF f_0 f_step, of "Suc i" pcss pcs] not_finished simul
  show ?thesis
    by (auto simp add: p_def)
qed

lemma (in inf) steps_hd_progress:
assumes f_0: "f 0 = (c#cs,css,s)"
assumes f_step: "i. Γ f(i)  f(Suc i)"
assumes c_unfinished: "i < k. ¬ (CS (f i) = cs  CSS (f i) = css)"
shows "i  k. (pcs pcss.
          (if pcss = [] then CSS (f i)=css  CS (f i)=pcs@cs
           else CS (f i)=pcs  
                CSS (f i)= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css))"
using c_unfinished
proof (induct k)
  case 0
  with f_0 show ?case
    by (simp add: CSS_def CS_def)
next
  case (Suc k)
  have c_unfinished: "i<Suc k. ¬ (CS (f i) = cs  CSS (f i) = css)" by fact
  hence c_unfinished': "i< k. ¬ (CS (f i) = cs  CSS (f i) = css)" by simp
  show ?case
  proof (clarify)
    fix i
    assume i_le_Suc_k: "i  Suc k"
    show "pcs pcss.
          (if pcss = [] then CSS (f i)=css  CS (f i)=pcs@cs
           else CS (f i)=pcs  
                CSS (f i)= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css)"
    proof (cases "i < Suc k")
      case True
      with Suc.hyps [OF c_unfinished', rule_format, of i] c_unfinished
      show ?thesis
        by auto
    next
      case False
      with i_le_Suc_k have eq_i_Suc_k: "i=Suc k"
        by auto
      obtain cs' css' t' where
        f_Suc_k: "f (Suc k) = (cs', css', t')"
        by (cases "f (Suc k)")
      obtain cs'' css'' t'' where
        f_k: "f k = (cs'',css'',t'')"
        by (cases "f k")
      with Suc.hyps [OF c_unfinished',rule_format, of k]
      obtain pcs pcss where
        pcs_pcss_k:
        "if pcss = [] then css'' = css  cs'' = pcs @ cs
         else cs'' = pcs 
              css'' = butlast pcss @
                           [(fst (last pcss) @ cs, snd (last pcss) @ cs)] @
                           css"
        by (auto simp add: CSS_def CS_def cong: if_cong)
      from c_unfinished [rule_format, of k] f_k pcs_pcss_k
      have pcs_pcss_empty: "¬ (pcs = []  pcss = [])"
        by (auto simp add: CS_def CSS_def S_def split: if_split_asm)
      show ?thesis
      proof (cases "pcss = []")
        case True
        note pcss_Nil = this
        with pcs_pcss_k pcs_pcss_empty obtain p ps where
          pcs_i: "pcs = p#ps" and
          css'': "css''=css" and
          cs'': "cs''=(p#ps)@cs"
          by (cases "pcs") auto
        with f_k have "f k = (p#(ps@cs),css,t'')"
          by simp
        with f_Suc_k f_step [rule_format, of k]
        have step_css: "Γ (p#(ps@cs),css,t'')  (cs',css',t')"
          by simp
        from step_Cons' [OF this, of p "ps@cs"]
        obtain css''' where
          css''': "css' = css''' @ css"
          "if css''' = [] then p. cs' = p @ ps @ cs
          else (pnorm pabr. css'''=[(pnorm @ ps @ cs,pabr @ ps @ cs)])"
          by auto
        show ?thesis
        proof (cases "css''' = []")
          case True
          with css'''
          obtain p' where
            css': "css' = css" and
            cs': "cs' = p' @ ps @ cs"
            by auto
          from css' cs' f_Suc_k
          show ?thesis
            apply (rule_tac x="p'@ps" in exI)
            apply (rule_tac x="[]" in exI)
            apply (simp add: CSS_def CS_def eq_i_Suc_k)
            done
        next
          case False
          with css'''
          obtain pnorm pabr where
            css': "css'=css'''@css"
            "css'''=[(pnorm @ ps @ cs,pabr @ ps @ cs)]"
            by auto
          with f_Suc_k eq_i_Suc_k
          show ?thesis
            apply (rule_tac x="cs'" in exI)
            apply (rule_tac x="[(pnorm@ps, pabr@ps)]" in exI)
            by (simp add: CSS_def CS_def)
        qed
      next
        case False
        note pcss_k_not_Nil = this
        with pcs_pcss_k obtain
          cs'': "cs''=pcs" and
          css'': "css''= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css"
          by auto
        from f_Suc_k f_k f_step [rule_format, of k]
        have step_i_full: "Γ (cs'',css'',t'')  (cs',css',t')"
          by simp
        show ?thesis
        proof (cases cs'')
          case (Cons c' cs)
          with step_Cons' [OF step_i_full]
          obtain css''' where css': "css' = css'''@css''"
            by auto
          with cs'' css'' f_Suc_k eq_i_Suc_k pcss_k_not_Nil
          show ?thesis
            apply (rule_tac x="cs'" in exI)
            apply (rule_tac x="css'''@pcss" in exI)
            by (clarsimp simp add: CSS_def CS_def butlast_append)
        next
          case Nil
          note cs''_Nil = this
          show ?thesis
          proof (cases "butlast pcss")
            case (Cons bpcs bpcss)
            with cs''_Nil step_i_full css''
            have *: "Γ ([],[hd css'']@tl css'',t'')  (cs',css',t')"
              by simp
            moreover
            from step_Nil [OF *]
            obtain css': "css'=tl css''" and
                   cs': "cs' = (case t'' of Abrupt s'  snd (hd css'')
                                 | _  fst (hd css''))"
              by (auto split: xstate.splits)
            from css'' Cons pcss_k_not_Nil
            have "hd css'' = hd pcss"
              by (auto simp add: neq_Nil_conv split: if_split_asm)
            with css' cs' css'' cs''_Nil Cons pcss_k_not_Nil f_Suc_k eq_i_Suc_k
            show ?thesis
              apply (rule_tac x="cs'" in exI)
              apply (rule_tac x="tl pcss" in exI)
              apply (clarsimp split: xstate.splits
                       simp add: CS_def CSS_def neq_Nil_conv split: if_split_asm)
              done
          next
            case Nil
            with css'' pcss_k_not_Nil
            obtain pnorm pabr
              where css'': "css''= [(pnorm@cs,pabr@cs)]@css" and
              pcss_k: "pcss = [(pnorm,pabr)]"
              by (force simp add: neq_Nil_conv split: if_split_asm)
            with cs''_Nil step_i_full
            have "Γ([],[(pnorm@cs,pabr@cs)]@css,t'')  (cs',css',t')"
              by simp
            from step_Nil [OF this]
            obtain
              css': "css'=css" and
              cs': "(case t'' of
              Abrupt s'  cs' = pabr @ cs  t' = Normal s'
              | _  cs' = pnorm @ cs  t' = t'')"
              by (simp cong: xstate.case_cong)
            let "?pcs_Suc_k " = "(case t'' of Abrupt s'  pabr | _  pnorm)"
            from css'' css' cs' pcss_k f_Suc_k eq_i_Suc_k
            show ?thesis
              apply (rule_tac x="?pcs_Suc_k" in exI)
              apply (rule_tac x="[]" in exI)
              apply (simp split: xstate.splits add: CS_def CSS_def)
              done
          qed
        qed
      qed
    qed
  qed
qed

lemma (in inf) inf_progress:
assumes f_0: "f 0 = (c#cs,css,s)"
assumes f_step: "i. Γ f(i)  f(Suc i)"
assumes unfinished: "i. ¬ ((CS (f i) = cs)  (CSS (f i) = css))"
shows "pcs pcss.
          (if pcss = [] then CSS (f i)=css  CS (f i)=pcs@cs
           else CS (f i)=pcs  
                CSS (f i)= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css)"
proof -
  from steps_hd_progress [OF f_0 f_step, of "i"] unfinished
  show ?thesis
    by auto
qed

lemma skolemize1: "x. P x  (y. Q x y)  f.x. P x  Q x (f x)"
  by (rule choice) blast

lemma skolemize2: "x. P x  (y z. Q x y z)  f g.x. P x  Q x (f x) (g x)"
apply (drule skolemize1)
apply (erule exE)
apply (drule skolemize1)
apply fast
done

lemma skolemize2': "x.y z. P x y z  f g.x. P x (f x) (g x)"
apply (drule choice)
apply (erule exE)
apply (drule choice)
apply fast
done

theorem (in inf) inf_cases:
  fixes c::"('s,'p,'f) com"
  assumes inf: "inf Γ (c#cs) css s"
  shows "inf Γ [c] [] s  (t. Γc,s  t  inf Γ cs css t)"
proof -
  from inf obtain f where
    f_0: "f 0 = (c#cs,css,s)" and
    f_step: "(i. Γf i  f (Suc i))"
    by (auto simp add: inf_def)
  show ?thesis
  proof (cases "i. CS (f i) = cs  CSS (f i) = css")
    case True
    define k where "k = (LEAST i. CS (f i) = cs  CSS (f i) = css)"
    from True
    obtain CS_f_k: "CS (f k) = cs" and CSS_f_k: "CSS (f k) = css"
      apply -
      apply (erule exE)
      apply (drule LeastI)
      apply (simp add: k_def)
      done
    have less_k_prop: "i<k. ¬ (CS (f i) = cs  CSS (f i) = css)"
      apply (intro allI impI)
      apply (unfold k_def)
      apply (drule not_less_Least)
      apply simp
      done
    have "Γ([c], [], s) * ([],[],S (f k))"
    proof -
      have "ik. pcs pcss.
        (if pcss = [] then CSS (f i)=css  CS (f i)=pcs@cs
           else CS (f i)=pcs  
                CSS (f i)= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css)"
        by (rule steps_hd_progress
        [OF f_0 f_step, where k=k, OF less_k_prop])
      from skolemize2 [OF this] obtain pcs pcss where
        pcs_pcss:
            "ik.
               (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                else CS (f i)=pcs i 
                     CSS (f i)= butlast (pcss i)@
                           [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                           css)"
        by iprover
      from pcs_pcss [rule_format, of k] CS_f_k CSS_f_k
      have finished: "pcs k = []" "pcss k = []"
        by (auto simp add: CS_def CSS_def S_def split: if_split_asm)
      from pcs_pcss
      have simul: "ik. (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
                   else CS (f i)=pcs i 
                     CSS (f i)= butlast (pcss i)@
                           [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                            css)"
        by auto
      from steps_hd_drop_suffix_finite [OF f_0 f_step less_k_prop simul] finished
      show ?thesis
        by simp
    qed
    hence "Γc,s  S (f k)"
      by (rule steps_impl_exec)
    moreover
    from CS_f_k CSS_f_k f_step
    have "inf Γ cs css (S (f k))"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (i + k)" in exI)
      apply simp
      apply (auto simp add: CS_def CSS_def S_def)
      done
    ultimately
    have "(t. Γc,s  t  inf Γ cs css t)"
      by blast
    thus ?thesis
      by simp
  next
    case False
    hence unfinished: "i. ¬ ((CS (f i) = cs)  (CSS (f i) = css))"
      by simp
    from inf_progress [OF f_0 f_step this]
    have "i. pcs pcss.
          (if pcss = [] then CSS (f i)=css  CS (f i)=pcs@cs
           else CS (f i)=pcs  
                CSS (f i)= butlast pcss@
                           [(fst (last pcss)@cs,(snd (last pcss))@cs)]@
                           css)"
      by auto
    from skolemize2' [OF this] obtain pcs pcss where
      pcs_pcss: "i.
          (if pcss i = [] then CSS (f i)=css  CS (f i)=pcs i@cs
           else CS (f i)=pcs i  
                CSS (f i)= butlast (pcss i)@
                           [(fst (last (pcss i))@cs,(snd (last (pcss i)))@cs)]@
                           css)"
      by iprover
    define g where "g i = (pcs i, pcss i, S (f i))" for i
    from pcs_pcss [rule_format, of 0] f_0
    have "g 0 = ([c],[],s)"
      by (auto split: if_split_asm simp add: CS_def CSS_def S_def g_def)
    moreover
    from steps_hd_drop_suffix_infinite [OF f_0 f_step unfinished pcs_pcss]
    have "i. Γg i  g (Suc i)"
      by (simp add: g_def)
    ultimately
    have "inf Γ [c] [] s"
      by (auto simp add: inf_def)
    thus ?thesis
      by simp
  qed
qed

lemma infE [consumes 1]:
  assumes inf: "inf Γ (c#cs) css s"
  assumes cases: "inf Γ [c] [] s  P"
                 "t. Γc,s  t; inf Γ cs css t  P"
  shows P
using inf cases
apply -
apply (drule inf.inf_cases)
apply auto
done

lemma inf_Seq:
  "inf Γ (Seq c1 c2#cs) css (Normal s) = inf Γ (c1#c2#cs) css (Normal s)"
proof
  assume "inf Γ (Seq c1 c2 # cs) css (Normal s)"
  then obtain f where
    f_0: "f 0 = (Seq c1 c2#cs,css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  from f_step [rule_format, of 0] f_0
  have "f 1 = (c1#c2#cs,css,Normal s)"
    by (auto elim: step_Normal_elim_cases)
  with f_step show "inf Γ (c1#c2#cs) css (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x="λi. f (Suc i)" in exI)
    apply simp
    done
next
  assume "inf Γ (c1 # c2 # cs) css (Normal s)"
  then obtain f where
    f_0: "f 0 = (c1# c2#cs,css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  define g where "g i = (case i of 0  (Seq c1 c2#cs,css,Normal s) | Suc j  f j)" for i
  with f_0 have
    "Γg 0  g (Suc 0)"
    by (auto intro: step.intros)
  moreover
  from f_step have "i. i0  Γg i  g (Suc i)"
    by (auto simp add: g_def split: nat.splits)
  ultimately
  show "inf Γ (Seq c1 c2 # cs) css (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x=g in exI)
    apply (simp add: g_def split: nat.splits)
    done
qed

lemma inf_WhileTrue:
  assumes b: "s  b"
  shows "inf Γ (While b c#cs) css (Normal s) =
          inf Γ (c#While b c#cs) css (Normal s)"
proof
  assume "inf Γ (While b c # cs) css (Normal s)"
  then obtain f where
    f_0: "f 0 = (While b c#cs,css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  from b f_step [rule_format, of 0] f_0
  have "f 1 = (c#While b c#cs,css,Normal s)"
    by (auto elim: step_Normal_elim_cases)
  with f_step show "inf Γ (c # While b c # cs) css (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x="λi. f (Suc i)" in exI)
    apply simp
    done
next
  assume "inf Γ (c # While b c # cs) css (Normal s)"
  then obtain f where
    f_0: "f 0 = (c # While b c #cs,css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  define h where "h i = (case i of 0  (While b c#cs,css,Normal s) | Suc j  f j)"  for i
  with b f_0 have
    "Γh 0  h (Suc 0)"
    by (auto intro: step.intros)
  moreover
  from f_step have "i. i0  Γh i  h (Suc i)"
    by (auto simp add: h_def split: nat.splits)
  ultimately
  show "inf Γ (While b c # cs) css (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x=h in exI)
    apply (simp add: h_def split: nat.splits)
    done
qed

lemma inf_Catch:
"inf Γ (Catch c1 c2#cs) css (Normal s) = inf Γ [c1] ((cs,c2#cs)#css) (Normal s)"
proof
  assume "inf Γ (Catch c1 c2#cs) css (Normal s)"
  then obtain f where
    f_0: "f 0 = (Catch c1 c2#cs,css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  from f_step [rule_format, of 0] f_0
  have "f 1 = ([c1],(cs,c2#cs)#css,Normal s)"
    by (auto elim: step_Normal_elim_cases)
  with f_step show "inf Γ [c1] ((cs,c2#cs)#css) (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x="λi. f (Suc i)" in exI)
    apply simp
    done
next
  assume "inf Γ [c1] ((cs,c2#cs)#css) (Normal s)"
  then obtain f where
    f_0: "f 0 = ([c1],(cs,c2#cs)#css,Normal s)" and
    f_step: "i. Γf i  f (Suc i)"
    by (auto simp add: inf_def)
  define h where "h i = (case i of 0  (Catch c1 c2#cs,css,Normal s) | Suc j  f j)"  for i
  with f_0 have
    "Γh 0  h (Suc 0)"
    by (auto intro: step.intros)
  moreover
  from f_step have "i. i0  Γh i  h (Suc i)"
    by (auto simp add: h_def split: nat.splits)
  ultimately
  show "inf Γ (Catch c1 c2 # cs) css (Normal s)"
    apply (simp add: inf_def)
    apply (rule_tac x=h in exI)
    apply (simp add: h_def split: nat.splits)
    done
qed

theorem terminates_impl_not_inf:
  assumes termi: "Γc  s"
  shows "¬inf Γ [c] [] s"
using termi
proof induct
  case (Skip s) thus ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Skip], [], Normal s)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Basic g s)
  thus ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Basic g], [], Normal s)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Normal (g s))"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Spec r s)
  thus ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Spec r], [], Normal s)"
    with f_step [of 0]
    have "Γ([Spec r], [], Normal s)  f (Suc 0)"
      by simp
    then show False
    proof (cases)
      fix t
      assume "(s, t)  r" "f (Suc 0) = ([], [], Normal t)"
      with f_step [of 1]
      show False
        by (auto elim: step_elim_cases)
    next
      assume "t. (s, t)  r" "f (Suc 0) = ([], [], Stuck)"
      with f_step [of 1]
      show False
        by (auto elim: step_elim_cases)
    qed
  qed
next
  case (Guard s g c m)
  have g: "s  g" by fact
  have hyp: "¬ inf Γ [c] [] (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Guard m g c], [], Normal s)"
    from g f_step [of 0] f_0
    have "f (Suc 0) = ([c],[],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step
    have "inf Γ [c] [] (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp show False ..
  qed
next
  case (GuardFault s g m c)
  have g: "s  g" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Guard m g c], [], Normal s)"
    from g f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Fault m)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Fault c m)
  thus ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([c], [], Fault m)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Fault m)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Seq c1 s c2)
  have hyp_c1: "¬ inf Γ [c1] [] (Normal s)" by fact
  have hyp_c2: "s'. Γc1,Normal s  s'  Γc2  s'  ¬ inf Γ [c2] [] s'" by fact
  have "¬ inf Γ ([c1,c2]) [] (Normal s)"
  proof
    assume "inf Γ [c1, c2] [] (Normal s)"
    then show False
    proof (cases rule: infE)
      assume "inf Γ [c1] [] (Normal s)"
      with hyp_c1 show ?thesis by simp
    next
      fix t
      assume "Γc1,Normal s  t" "inf Γ [c2] [] t"
      with hyp_c2 show ?thesis by simp
    qed
  qed
  thus ?case
    by (simp add: inf_Seq)
next
  case (CondTrue s b c1 c2)
  have b: "s  b" by fact
  have hyp_c1: "¬ inf Γ [c1] [] (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Cond b c1 c2], [], Normal s)"
    from b f_step [of 0] f_0
    have "f 1 = ([c1],[],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step
    have "inf Γ [c1] [] (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp_c1 show False by simp
  qed
next
  case (CondFalse s b c2 c1)
  have b: "s  b" by fact
  have hyp_c2: "¬ inf Γ [c2] [] (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Cond b c1 c2], [], Normal s)"
    from b f_step [of 0] f_0
    have "f 1 = ([c2],[],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step
    have "inf Γ [c2] [] (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp_c2 show False by simp
  qed
next
  case (WhileTrue s b c)
  have b: "s  b" by fact
  have hyp_c: "¬ inf Γ [c] [] (Normal s)" by fact
  have hyp_w: "s'. Γc,Normal s  s' 
                      ΓWhile b c  s'  ¬ inf Γ [While b c] [] s'" by fact
  have "¬ inf Γ [c,While b c] [] (Normal s)"
  proof
    assume "inf Γ [c,While b c] [] (Normal s)"
    from this hyp_c hyp_w show False
      by (cases rule: infE) auto
  qed
  with b show ?case
    by (simp add: inf_WhileTrue)
next
  case (WhileFalse s b c)
  have b: "s  b" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([While b c], [], Normal s)"
    from b f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Call p bdy s)
  have bdy: "Γ p = Some bdy" by fact
  have hyp: "¬ inf Γ [bdy] [] (Normal s)" by fact
  have not_inf_bdy:
    "¬ inf Γ [bdy] [([],[Throw])] (Normal s)"
  proof
    assume "inf Γ [bdy] [([],[Throw])] (Normal s)"
    then show False
    proof (rule infE)
      assume "inf Γ [bdy] [] (Normal s)"
      with hyp show False by simp
    next
      fix t
      assume "Γbdy,Normal s  t"
      assume inf: "inf Γ [] [([], [Throw])] t"
      then obtain f where
        f_0: "f 0 = ([],[([], [Throw])],t)" and
        f_step: "i. Γf i  f (Suc i)"
        by (auto simp add: inf_def)
      show False
      proof (cases t)
        case (Normal t')
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],(Normal t'))"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of "Suc 0"]
        show False
          by (auto elim: step.cases)
      next
        case (Abrupt t')
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([Throw],[],(Normal t'))"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of "Suc 0"]
        have "f (Suc (Suc 0)) = ([],[],(Abrupt t'))"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of "Suc(Suc 0)"]
        show False
          by (auto elim: step.cases)
      next
        case (Fault m)
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],Fault m)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of 1]
        have "f (Suc (Suc 0)) = ([],[],Fault m)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of "Suc (Suc 0)"]
        show False
          by (auto elim: step.cases)
      next
        case Stuck
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],Stuck)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of 1]
        have "f (Suc (Suc 0)) = ([],[],Stuck)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of "Suc (Suc 0)"]
        show False
          by (auto elim: step.cases)
      qed
    qed
  qed
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Call p], [], Normal s)"
    from bdy f_step [of 0] f_0
    have "f (Suc 0) =
              ([bdy],[([],[Throw])],Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step
    have "inf Γ [bdy] [([],[Throw])] (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with not_inf_bdy
    show False by simp
  qed
next
  case (CallUndefined p s)
  have undef: "Γ p = None" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Call p], [], Normal s)"
    from undef f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Stuck)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [rule_format, of "Suc 0"]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Stuck c)
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([c], [], Stuck)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Stuck)"
      by (auto elim: step_elim_cases)
    with f_step [rule_format, of "Suc 0"]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (DynCom c s)
  have hyp: "¬ inf Γ [(c s)] [] (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([DynCom c], [], Normal s)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([(c s)], [], Normal s)"
      by (auto elim: step_elim_cases)
    with f_step have "inf Γ [(c s)] [] (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp
    show False by simp
  qed
next
  case (Throw s)
  thus ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([Throw], [], Normal s)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Abrupt s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step [of 1]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Abrupt c s)
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f_0: "f 0 = ([c], [], Abrupt s)"
    from f_step [of 0] f_0
    have "f (Suc 0) = ([],[],Abrupt s)"
      by (auto elim: step_elim_cases)
    with f_step [rule_format, of "Suc 0"]
    show False
      by (auto elim: step_elim_cases)
  qed
next
  case (Catch c1 s c2)
  have hyp_c1: "¬ inf Γ [c1] [] (Normal s)" by fact
  have hyp_c2: "s'. Γc1,Normal s  Abrupt s' 
                   Γc2  Normal s'  ¬ inf Γ [c2] [] (Normal s')" by fact
  have "¬ inf Γ [c1] [([],[c2])] (Normal s)"
  proof
    assume "inf Γ [c1] [([],[c2])] (Normal s)"
    then show False
    proof (rule infE)
      assume "inf Γ [c1] [] (Normal s)"
      with hyp_c1 show False by simp
    next
      fix t
      assume eval: "Γc1,Normal s  t"
      assume inf: "inf Γ [] [([], [c2])] t"
      then obtain f where
        f_0: "f 0 = ([],[([], [c2] )],t)" and
        f_step: "i. Γf i  f (Suc i)"
        by (auto simp add: inf_def)
      show False
      proof (cases t)
        case (Normal t')
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],Normal t')"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of 1]
        show False
          by (auto elim: step_elim_cases)
      next
        case (Abrupt t')
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([c2],[],Normal t')"
          by (auto elim: step_Normal_elim_cases)
        with f_step eval Abrupt
        have "inf Γ [c2] [] (Normal t')"
          apply (simp add: inf_def)
          apply (rule_tac x="λi. f (Suc i)" in exI)
          by simp
        with eval hyp_c2 Abrupt show False by simp
      next
        case (Fault m)
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],Fault m)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of 1]
        show False
          by (auto elim: step_elim_cases)
      next
        case Stuck
        with f_0 f_step [rule_format, of 0]
        have "f (Suc 0) = ([],[],Stuck)"
          by (auto elim: step_Normal_elim_cases)
        with f_step [rule_format, of 1]
        show False
          by (auto elim: step_elim_cases)
      qed
    qed
  qed
  thus ?case
    by (simp add: inf_Catch)
qed

lemma terminatess_impl_not_inf:
 assumes termi: "Γcs,csss"
  shows "¬inf Γ cs css s"
using termi
proof (induct)
  case (Nil s)
  show ?case
  proof (rule not_infI)
    fix f
    assume "i. Γf i  f (Suc i)"
    hence "Γf 0  f (Suc 0)"
      by simp
    moreover
    assume "f 0 = ([], [], s)"
    ultimately show False
      by (fastforce elim: step.cases)
  qed
next
  case (ExitBlockNormal nrms css s abrs)
  have hyp: "¬ inf Γ nrms css (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f0: "f 0 = ([], (nrms, abrs) # css, Normal s)"
    with f_step [of 0] have "f (Suc 0) = (nrms,css,Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step have "inf Γ nrms css (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp show False ..
  qed
next
  case (ExitBlockAbrupt abrs css s nrms)
  have hyp: "¬ inf Γ abrs css (Normal s)" by fact
  show ?case
  proof (rule not_infI)
    fix f
    assume f_step: "i. Γf i  f (Suc i)"
    assume f0: "f 0 = ([], (nrms, abrs) # css, Abrupt s)"
    with f_step [of 0] have "f (Suc 0) = (abrs,css,Normal s)"
      by (auto elim: step_Normal_elim_cases)
    with f_step have "inf Γ abrs css (Normal s)"
      apply (simp add: inf_def)
      apply (rule_tac x="λi. f (Suc i)" in exI)
      by simp
    with hyp show False ..
  qed
next
  case (ExitBlockFault nrms css f abrs)
  show ?case
    by (rule not_inf_Fault)
next
  case (ExitBlockStuck nrms css abrs)
  show ?case
    by (rule not_inf_Stuck)
next
  case (Cons c s cs css)
  have termi_c: "Γc  s" by fact
  have hyp: "t. Γc,s  t  Γcs,csst  ¬ inf Γ cs css t"  by fact
  show "¬ inf Γ (c # cs) css s"
  proof
    assume "inf Γ (c # cs) css s"
    thus False
    proof (rule infE)
      assume "inf Γ [c] [] s"
      with terminates_impl_not_inf [OF termi_c]
      show False ..
    next
      fix t
      assume "Γc,s  t" "inf Γ cs css t"
      with hyp show False by simp
    qed
  qed
qed

lemma lem:
  "y. r++ a y  P a  P y
    ((b,a)  {(y,x). P x  r x y}+) = ((b,a)  {(y,x). P x  r++ x y})"
apply(rule iffI)
 apply clarify
 apply(erule trancl_induct)
  apply blast
 apply(blast intro:tranclp_trans)
apply clarify
apply(erule tranclp_induct)
 apply blast
apply(blast intro:trancl_trans)
done

corollary terminatess_impl_no_inf_chain:
 assumes terminatess: "Γcs,csss"
 shows "¬(f. f 0 = (cs,css,s)  (i::nat. Γf i + f(Suc i)))"
proof -
  have "wf({(y,x). Γ(cs,css,s) * x  Γx  y}+)"
  proof (rule wf_trancl)
    show "wf {(y, x). Γ(cs, css, s) * x  Γx  y}"
    proof (simp only: wf_iff_no_infinite_down_chain,clarify,simp)
      fix f
      assume "i. Γ(cs, css, s) * f i  Γf i  f (Suc i)"
      hence "f. f 0 = (cs, css, s)  (i. Γf i  f (Suc i))"
        by (rule renumber [to_pred])
      moreover from terminatess
      have "¬ (f. f 0 = (cs, css, s)  (i. Γf i  f (Suc i)))"
        by (rule terminatess_impl_not_inf [unfolded inf_def])
      ultimately show False
        by simp
    qed
  qed
  hence "¬ (f. i. (f (Suc i), f i)
                  {(y, x). Γ(cs, css, s) * x  Γx  y}+)"
    by (simp add: wf_iff_no_infinite_down_chain)
  thus ?thesis
  proof (rule contrapos_nn)
    assume "f. f 0 = (cs, css, s)  (i. Γf i + f (Suc i))"
    then obtain f where
      f0: "f 0 = (cs, css, s)" and
      seq: "i. Γf i + f (Suc i)"
      by iprover
    show
      "f. i. (f (Suc i), f i)  {(y, x). Γ(cs, css, s) * x  Γx  y}+"
    proof (rule exI [where x=f],rule allI)
      fix i
      show "(f (Suc i), f i)  {(y, x). Γ(cs, css, s) * x  Γx  y}+"
      proof -
        {
          fix i have "Γ(cs,css,s) * f i"
          proof (induct i)
            case 0 show "Γ(cs, css, s) * f 0"
              by (simp add: f0)
          next
            case (Suc n)
            have "Γ(cs, css, s) * f n"  by fact
            with seq show "Γ(cs, css, s) * f (Suc n)"
              by (blast intro: tranclp_into_rtranclp rtranclp_trans)
          qed
        }
        hence "Γ(cs,css,s) * f i"
          by iprover
        with seq have
          "(f (Suc i), f i)  {(y, x). Γ(cs, css, s) * x  Γx + y}"
          by clarsimp
        moreover
        have "y. Γf i + yΓ(cs, css, s) * f iΓ(cs, css, s) * y"
          by (blast intro: tranclp_into_rtranclp rtranclp_trans)
        ultimately
        show ?thesis
          by (subst lem)
      qed
    qed
  qed
qed

corollary terminates_impl_no_inf_chain:
 "Γcs  ¬(f. f 0 = ([c],[],s)  (i::nat. Γf i + f(Suc i)))"
  by (rule terminatess_impl_no_inf_chain) (iprover intro: terminatess.intros)


definition
 termi_call_steps :: "('s,'p,'f) body  (('s × 'p) × ('s × 'p))set"
where
"termi_call_steps Γ =
 {((t,q),(s,p)). Γthe (Γ p)Normal s 
       (css. Γ([the (Γ p)],[],Normal s) + ([the (Γ q)],css,Normal t))}"

text ‹Sequencing computations, or more exactly continuation stacks›
primrec seq:: "(nat  'a list)  nat  'a list"
where
"seq css 0 = []" |
"seq css (Suc i) = css i@seq css i"


theorem wf_termi_call_steps: "wf (termi_call_steps Γ)"
proof (simp only: termi_call_steps_def wf_iff_no_infinite_down_chain,
       clarify,simp)
  fix S
  assume inf:
     "i. (λ(t,q) (s,p). Γ(the (Γ p))  Normal s 
                 (css. Γ([the (Γ p)],[],Normal s) + ([the (Γ q)],css,Normal t)))
           (S (Suc i)) (S i)"
  obtain s p where "s = (λi. fst (S i))" and "p = (λi. snd (S i))"
    by auto
  with inf
  have inf':
     "i. Γ(the (Γ (p i)))  Normal (s i) 
                 (css. Γ([the (Γ (p i))],[],Normal (s i)) +
                           ([the (Γ (p (Suc i)))],css,Normal (s (Suc i))))"
    apply -
    apply (rule allI)
    apply (erule_tac x=i in allE)
    apply auto
    done
  show False
  proof -
    from inf' ― ‹Skolemization of css with axiom of choice›
    have "css. i. Γ(the (Γ (p i)))  Normal (s i) 
                 Γ([the (Γ (p i))],[],Normal (s i)) +
                           ([the (Γ (p (Suc i)))],css i,Normal (s (Suc i)))"
      apply -
      apply (rule choice)
      by blast
    then obtain css where
      termi_css: "i. Γ(the (Γ (p i)))  Normal (s i)" and
      step_css: "i. Γ([the (Γ (p i))],[],Normal (s i)) +
                         ([the (Γ (p (Suc i)))],css i,Normal (s (Suc i)))"
      by blast
    define f where "f i = ([the (Γ (p i))], seq css i,Normal (s i)::('a,'c) xstate)" for i
    have "f 0 = ([the (Γ (p 0))],[],Normal (s 0))"
      by (simp add: f_def)
    moreover
    have "i. Γ (f i) + (f (i+1))"
    proof
      fix i
      from step_css [rule_format, of i]
      have "Γ([the (Γ (p i))], [], Normal (s i)) +
              ([the (Γ (p (Suc i)))], css i, Normal (s (Suc i)))".
      from app_css_steps [OF this,simplified]
      have "Γ([the (Γ (p i))], seq css i, Normal (s i)) +
              ([the (Γ (p (Suc i)))], css i@seq css i, Normal (s (Suc i)))".
      thus "Γ (f i) + (f (i+1))"
        by (simp add: f_def)
    qed
    moreover from termi_css [rule_format, of 0]
    have "¬ (f. (f 0 = ([the (Γ (p 0))],[],Normal (s 0)) 
                 (i. Γ(f i) + f(Suc i))))"
      by (rule terminates_impl_no_inf_chain)
    ultimately show False
      by auto
  qed
qed

text ‹An alternative proof using Hilbert-choice instead of axiom of choice.›
theorem "wf (termi_call_steps Γ)"
proof (simp only: termi_call_steps_def wf_iff_no_infinite_down_chain,
       clarify,simp)
  fix S
  assume inf:
     "i. (λ(t,q) (s,p). Γ(the (Γ p))  Normal s 
                 (css. Γ([the (Γ p)],[],Normal s) + ([the (Γ q)],css,Normal t)))
           (S (Suc i)) (S i)"
  obtain s p where "s = (λi. fst (S i))" and "p = (λi. snd (S i))"
    by auto
  with inf
  have inf':
     "i. Γ(the (Γ (p i)))  Normal (s i) 
                 (css. Γ([the (Γ (p i))],[],Normal (s i)) +
                           ([the (Γ (p (Suc i)))],css,Normal (s (Suc i))))"
    apply -
    apply (rule allI)
    apply (erule_tac x=i in allE)
    apply auto
    done
  show "False"
  proof -
    define CSS where "CSS i = (SOME css.
                      Γ([the (Γ (p i))],[], Normal (s i)) +
                      ([the (Γ (p (i+1)))],css,Normal (s (i+1))))" for i
    define f where "f i = ([the (Γ (p i))], seq CSS i,Normal (s i)::('a,'c) xstate)" for i
    have "f 0 = ([the (Γ (p 0))],[],Normal (s 0))"
      by (simp add: f_def)
    moreover
    have "i. Γ (f i) + (f (i+1))"
    proof
      fix i
      from inf' [rule_format, of i] obtain css where
         css: "Γ([the (Γ (p i))],[],Normal (s i)) +
                ([the (Γ (p (i+1)))],css,Normal (s (i+1)))"
        by fastforce
      hence "Γ([the (Γ (p i))], seq CSS i, Normal (s i)) +
                  ([the (Γ (p (i+1)))], CSS i @ seq CSS i, Normal (s (i+1)))"
        apply -
        apply (unfold CSS_def)
        apply (rule someI2
              [where P="λcss.
                    Γ([the (Γ (p i))],[],Normal (s i))+
                         ([the (Γ (p (i+1)))],css, Normal (s (i+1)))"])
        apply (rule css)
        apply (fastforce dest: app_css_steps)
        done
      thus "Γ (f i) + (f (i+1))"
        by (simp add: f_def)
    qed
    moreover from inf' [rule_format, of 0]
    have "Γthe (Γ (p 0))  Normal (s 0)"
      by iprover
    then have "¬ (f. (f 0 = ([the (Γ (p 0))],[],Normal (s 0)) 
                 (i. Γ(f i) + f(Suc i))))"
      by (rule terminates_impl_no_inf_chain)
    ultimately show False
      by auto
  qed
qed

lemma not_inf_implies_wf: assumes not_inf: "¬ inf Γ cs css s"
  shows "wf {(c2,c1). Γ  (cs,css,s) * c1  Γ  c1  c2}"
proof (simp only: wf_iff_no_infinite_down_chain,clarify, simp)
  fix f
  assume "i. Γ(cs, css, s) * f i  Γf i  f (Suc i)"
  hence "f. f 0 = (cs, css, s)  (i. Γf i  f (Suc i))"
    by (rule renumber [to_pred])
  moreover from not_inf
  have "¬ (f. f 0 = (cs, css, s)  (i. Γf i  f (Suc i)))"
    by (unfold inf_def)
  ultimately show False
    by simp
qed

lemma wf_implies_termi_reach:
assumes wf: "wf {(c2,c1). Γ  (cs,css,s) * c1  Γ  c1  c2}"
shows "cs1 css1 s1. Γ  (cs,css,s) * c1;  c1=(cs1,css1,s1) Γcs1,css1s1"
using wf
proof (induct c1, simp)
  fix cs1 css1 s1
  assume reach: "Γ(cs, css, s) * (cs1, css1, s1)"
  assume hyp_raw: "y cs2 css2 s2. Γ  (cs1,css1,s1)  (cs2,css2,s2);
                 Γ  (cs,css,s) * (cs2,css2,s2); y=(cs2,css2,s2) 
                 Γcs2,css2s2"
  have hyp: "cs2 css2 s2. Γ  (cs1,css1,s1)  (cs2,css2,s2) 
                 Γcs2,css2s2"
    apply -
    apply (rule hyp_raw)
    apply   assumption
    using reach
    apply  simp
    apply (rule refl)
    done
  show "Γcs1,css1s1"
  proof (cases s1)
    case (Normal s1')
    show ?thesis
    proof (cases cs1)
      case Nil
      note cs1_Nil = this
      show ?thesis
      proof (cases css1)
        case Nil
        with cs1_Nil show ?thesis
          by (auto intro: terminatess.intros)
      next
        case (Cons nrms_abrs css1')
        then obtain nrms abrs where nrms_abrs: "nrms_abrs=(nrms,abrs)"
          by (cases "nrms_abrs")
        have "Γ  ([],(nrms,abrs)#css1',Normal s1')  (nrms,css1',Normal s1')"
          by (rule step.intros)
        from hyp [simplified cs1_Nil Cons nrms_abrs Normal, OF this]
        have "Γnrms,css1'Normal s1'".
        from ExitBlockNormal [OF this] cs1_Nil Cons nrms_abrs Normal
        show ?thesis
          by auto
      qed
    next
      case (Cons c1 cs1')
      have "Γc1#cs1',css1Normal s1'"
      proof (cases c1)
        case Skip
        have "Γ  (Skip#cs1',css1,Normal s1')  (cs1',css1,Normal s1')"
          by (rule step.intros)
        from hyp [simplified Cons Skip Normal, OF this]
        have "Γcs1',css1Normal s1'".
        with Normal Skip show ?thesis
          by (auto intro: terminatess.intros terminates.intros
                  elim: exec_Normal_elim_cases)
      next
        case (Basic f)
        have "Γ  (Basic f#cs1',css1,Normal s1')  (cs1',css1,Normal (f s1'))"
          by (rule step.intros)
        from hyp [simplified Cons Basic Normal, OF this]
        have "Γcs1',css1Normal (f s1')".
        with Normal Basic show ?thesis
          by (auto intro: terminatess.intros terminates.intros
                  elim: exec_Normal_elim_cases)
      next
        case (Spec r)
        with Normal show ?thesis
          apply simp
          apply (rule terminatess.Cons)
          apply  (fastforce intro: terminates.intros)
          apply (clarify)
          apply (erule exec_Normal_elim_cases)
          apply  clarsimp
          apply  (rule hyp)
          apply  (fastforce intro: step.intros simp add: Cons Spec Normal )
          apply (fastforce intro: terminatess_Stuck)
          done
      next
        case (Seq c1 c2)
        have "Γ  (Seq c1 c2#cs1',css1,Normal s1')  (c1#c2#cs1',css1,Normal s1')"
          by (rule step.intros)
        from hyp [simplified Cons Seq Normal, OF this]
        have "Γc1 # c2 # cs1',css1Normal s1'".
        with Normal Seq show ?thesis
          by (fastforce intro: terminatess.intros terminates.intros
                   elim: terminatess_elim_cases exec_Normal_elim_cases)
      next
        case (Cond b c1 c2)
        show ?thesis
        proof (cases "s1'  b")
          case True
          hence "Γ(Cond b c1 c2#cs1',css1,Normal s1')  (c1#cs1',css1,Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons Cond Normal, OF this]
          have "Γc1 # cs1',css1Normal s1'".
          with Normal Cond True show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros
              elim: terminatess_elim_cases exec_Normal_elim_cases)
        next
          case False
          hence "Γ(Cond b c1 c2#cs1',css1,Normal s1')  (c2#cs1',css1,Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons Cond Normal, OF this]
          have "Γc2 # cs1',css1Normal s1'".
          with Normal Cond False show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros
              elim: terminatess_elim_cases exec_Normal_elim_cases)
        qed
      next
        case (While b c')
        show ?thesis
        proof (cases "s1'  b")
          case True
          then have "Γ(While b c' # cs1', css1, Normal s1') 
                       (c' # While b c' # cs1', css1, Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons While Normal, OF this]
          have "Γc' # While b c' # cs1',css1Normal s1'".
          with Cons While True Normal
          show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
        next
          case False
          then
          have "Γ(While b c' # cs1', css1, Normal s1')  (cs1', css1, Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons While Normal, OF this]
          have "Γcs1',css1Normal s1'".
          with Cons While False Normal
          show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
        qed
      next
        case (Call p)
        show ?thesis
        proof (cases "Γ p")
          case None
          with Call Normal show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros terminatess_Stuck
                 elim: exec_Normal_elim_cases)
        next
          case (Some bdy)
          then
          have "Γ  (Call p#cs1',css1,Normal s1') 
                    ([bdy],(cs1',Throw#cs1')#css1,Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons Call Normal Some, OF this]
          have "Γ[bdy],(cs1', Throw # cs1') # css1Normal s1'".
          with Some Call Normal show ?thesis
            apply simp
            apply (rule terminatess.intros)
            apply (blast elim: terminatess_elim_cases intro: terminates.intros)
            apply clarify
            apply (erule terminatess_elim_cases)
            apply (erule exec_Normal_elim_cases)
            prefer 2
            apply  simp
            apply (erule_tac x=t in allE)
            apply (case_tac t)
            apply (auto intro: terminatess_Stuck terminatess_Fault exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
            done
        qed
      next
        case (DynCom c')
        have "Γ  (DynCom c'#cs1',css1,Normal s1')  (c' s1'#cs1',css1,Normal s1')"
          by (rule step.intros)
        from hyp [simplified Cons DynCom Normal, OF this]
        have "Γc' s1'#cs1',css1Normal s1'".
        with Normal DynCom show ?thesis
          by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
      next
        case (Guard f g c')
        show ?thesis
        proof (cases "s1'  g")
          case True
          then have "Γ  (Guard f g c'#cs1',css1,Normal s1')  (c'#cs1',css1,Normal s1')"
            by (rule step.intros)
          from hyp [simplified Cons Guard Normal, OF this]
          have "Γc'#cs1',css1Normal s1'".
          with Normal Guard True show ?thesis
            by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
        next
          case False
          with Guard Normal show ?thesis
            by (fastforce intro: terminatess.intros terminatess_Fault
                                terminates.intros
                 elim:  exec_Normal_elim_cases)
        qed
      next
        case Throw
        have "Γ  (Throw#cs1',css1,Normal s1')  (cs1',css1,Abrupt s1')"
          by (rule step.intros)
        from hyp [simplified Cons Throw Normal, OF this]
        have "Γcs1',css1Abrupt s1'".
        with Normal Throw show ?thesis
          by (auto intro: terminatess.intros terminates.intros
                  elim: exec_Normal_elim_cases)
      next
        case (Catch c1 c2)
        have "Γ  (Catch c1 c2#cs1',css1,Normal s1') 
                  ([c1], (cs1',c2#cs1')# css1,Normal s1')"
          by (rule step.intros)
        from hyp [simplified Cons Catch Normal, OF this]
        have "Γ[c1],(cs1', c2 # cs1') # css1Normal s1'".
        with Normal Catch show ?thesis
          by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
      qed
      with Cons Normal show ?thesis
        by simp
    qed
  next
    case (Abrupt s1')
    show ?thesis
    proof (cases cs1)
      case Nil
      note cs1_Nil = this
      show ?thesis
      proof (cases css1)
        case Nil
        with cs1_Nil show ?thesis by (auto intro: terminatess.intros)
      next
        case (Cons nrms_abrs css1')
        then obtain nrms abrs where nrms_abrs: "nrms_abrs=(nrms,abrs)"
          by (cases "nrms_abrs")
        have "Γ  ([],(nrms,abrs)#css1',Abrupt s1')  (abrs,css1',Normal s1')"
          by (rule step.intros)
        from hyp [simplified cs1_Nil Cons nrms_abrs Abrupt, OF this]
        have "Γabrs,css1'Normal s1'".
        from ExitBlockAbrupt [OF this] cs1_Nil Cons nrms_abrs Abrupt
        show ?thesis
          by auto
      qed
    next
      case (Cons c1 cs1')
      have "Γc1#cs1',css1Abrupt s1'"
      proof -
        have "Γ  (c1#cs1',css1,Abrupt s1')  (cs1',css1,Abrupt s1')"
          by (rule step.intros)
        from hyp [simplified Cons Abrupt, OF this]
        have "Γcs1',css1Abrupt s1'".
        with Cons Abrupt
        show ?thesis
          by (fastforce intro: terminatess.intros terminates.intros exec.intros
                    elim: terminatess_elim_cases exec_Normal_elim_cases)
      qed
      with Cons Abrupt show ?thesis by simp
    qed
  next
    case (Fault f)
    thus ?thesis by (auto intro: terminatess_Fault)
  next
    case Stuck
    thus ?thesis by (auto intro: terminatess_Stuck)
  qed
qed

lemma not_inf_impl_terminatess:
  assumes not_inf: "¬ inf Γ cs css s"
  shows "Γcs,csss"
proof -
  from not_inf_implies_wf [OF not_inf]
  have wf: "wf {(c2, c1). Γ(cs, css, s) * c1  Γc1  c2}".
  show ?thesis
    by (rule wf_implies_termi_reach [OF wf]) auto
qed

lemma not_inf_impl_terminates:
  assumes not_inf: "¬ inf Γ [c] [] s"
  shows "Γcs"
proof -
  from not_inf_impl_terminatess [OF not_inf]
  have "Γ[c],[]s".
  thus ?thesis
    by (auto elim: terminatess_elim_cases)
qed

theorem terminatess_iff_not_inf:
  "Γcs,csss = (¬ inf Γ cs css s)"
  apply rule
  apply  (erule terminatess_impl_not_inf)
  apply (erule not_inf_impl_terminatess)
  done

corollary terminates_iff_not_inf:
  "Γcs = (¬ inf Γ [c] [] s)"
  apply (rule)
  apply  (erule terminates_impl_not_inf)
  apply (erule not_inf_impl_terminates)
  done

subsection ‹Completeness of Total Correctness Hoare Logic›

lemma ConseqMGT:
  assumes modif: "Z::'a. Γ,Θt⇘/F(P' Z::'a assn) c (Q' Z),(A' Z)"
  assumes impl: "s. s  P  s  P' s  (t. t  Q' s  t  Q) 
                                            (t. t  A' s  t  A)"
  shows "Γ,Θt⇘/FP c Q,A"
using impl
by - (rule conseq [OF modif],blast)

lemma conseq_extract_state_indep_prop:
  assumes state_indep_prop:"s  P. R"
  assumes to_show: "R  Γ,Θt⇘/FP c Q,A"
  shows "Γ,Θt⇘/FP c Q,A"
  apply (rule Conseq)
  apply (clarify)
  apply (rule_tac x="P" in exI)
  apply (rule_tac x="Q" in exI)
  apply (rule_tac x="A" in exI)
  using state_indep_prop to_show
  by blast

lemma Call_lemma':
 assumes Call_hyp:
 "qdom Γ. Z. Γ,Θt⇘/F{s. s=Z  ΓCall q,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                       ΓCall qNormal s  ((s,q),(σ,p))  termi_call_steps Γ}
                 (Call q)
                {t. ΓCall q,Normal Z  Normal t},
                {t. ΓCall q,Normal Z  Abrupt t}"
 shows "Z. Γ,Θt⇘/F{s. s=Z  Γc,Normal s ⇒∉({Stuck}  Fault ` (-F))  Γthe (Γ p)Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (c#cs,css,Normal s))}
              c
      {t. Γc,Normal Z  Normal t},
      {t. Γc,Normal Z  Abrupt t}"
proof (induct c)
  case Skip
  show "Γ,Θt⇘/F{s. s = Z  ΓSkip,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                 Γthe (Γ p)  Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (Skip # cs,css,Normal s))}
               Skip
              {t. ΓSkip,Normal Z  Normal t},
              {t. ΓSkip,Normal Z  Abrupt t}"
    by (rule hoaret.Skip [THEN conseqPre]) (blast intro: exec.Skip)
next
  case (Basic f)
  show "Γ,Θt⇘/F{s. s=Z  ΓBasic f,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                   Γthe (Γ p)Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (Basic f#cs,css,Normal s))}
               Basic f
              {t. ΓBasic f,Normal Z  Normal t},
              {t. ΓBasic f,Normal Z  Abrupt t}"
    by (rule hoaret.Basic [THEN conseqPre]) (blast intro: exec.Basic)
next
  case (Spec r)
  show "Γ,Θt⇘/F{s. s=Z  ΓSpec r,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                   Γthe (Γ p)Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (Spec r#cs,css,Normal s))}
               Spec r
              {t. ΓSpec r,Normal Z  Normal t},
              {t. ΓSpec r,Normal Z  Abrupt t}"
    apply (rule hoaret.Spec [THEN conseqPre])
    apply (clarsimp)
    apply (case_tac "t. (Z,t)  r")
    apply (auto elim: exec_elim_cases simp add: final_notin_def intro: exec.intros)
    done
next
  case (Seq c1 c2)
  have hyp_c1:
    "Z. Γ,Θt⇘/F{s. s=Z  Γc1,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                     Γthe (Γ p)Normal σ 
                 (cs css. Γ([the (Γ p)],[],Normal σ) * (c1#cs,css,Normal s))}
                c1
               {t. Γc1,Normal Z  Normal t},
               {t. Γc1,Normal Z  Abrupt t}"
    using Seq.hyps by iprover
  have hyp_c2:
    "Z. Γ,Θt⇘/F{s. s=Z  Γc2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    Γthe (Γ p)Normal σ 
                 (cs css. Γ([the (Γ p)],[],Normal σ) * (c2#cs,css,Normal s))}
                c2
               {t. Γc2,Normal Z  Normal t},
               {t. Γc2,Normal Z  Abrupt t}"
    using Seq.hyps by iprover
  have c1: "Γ,Θt⇘/F{s. s=Z  ΓSeq c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    Γthe (Γ p)Normal σ 
              (cs css. Γ([the (Γ p)],[],Normal σ) * (Seq c1 c2#cs,css,Normal s))}
               c1
               {t. Γc1,Normal Z  Normal t 
                   Γc2,Normal t ⇒∉({Stuck}  Fault ` (-F)) 
                   Γthe (Γ p)Normal σ 
                  (cs css. Γ([the (Γ p)],[],Normal σ) * (c2#cs,css,Normal t))},
               {t. ΓSeq c1 c2,Normal Z  Abrupt t}"
  proof (rule ConseqMGT [OF hyp_c1],clarify,safe)
    assume "ΓSeq c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
    thus "Γc1,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by (blast dest: Seq_NoFaultStuckD1)
  next
    fix cs css
    assume "Γ([the (Γ p)],[],Normal σ) * (Seq c1 c2 # cs,css,Normal Z)"
    thus "cs css. Γ([the (Γ p)],[],Normal σ) * (c1 # cs,css, Normal Z)"
      by (blast intro: rtranclp_into_tranclp1 [THEN tranclp_into_rtranclp]
                 step.Seq)
  next
    fix t
    assume "ΓSeq c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
            "Γc1,Normal Z  Normal t"
    thus "Γc2,Normal t ⇒∉({Stuck}  Fault ` (-F))"
      by (blast dest: Seq_NoFaultStuckD2)
  next
    fix cs css t
    assume "Γ([the (Γ p)],[],Normal σ) * (Seq c1 c2#cs,css,Normal Z)"
    also have "Γ(Seq c1 c2 # cs,css,Normal Z)  (c1#c2#cs,css,Normal Z)"
      by (rule step.Seq)
    also assume "Γc1,Normal Z  Normal t"
    hence "Γ (c1#c2#cs,css,Normal Z) * (c2#cs,css,Normal t)"
      by (rule exec_impl_steps)
    finally
    show "cs css. Γ([the (Γ p)],[],Normal σ) * (c2 # cs,css, Normal t)"
      by iprover
  next
    fix t
    assume "Γc1,Normal Z  Abrupt t"
    thus "ΓSeq c1 c2,Normal Z  Abrupt t"
      by (blast intro: exec.intros)
  qed
  show "Γ,Θt⇘/F{s. s=Z  ΓSeq c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                  Γthe (Γ p)Normal σ 
              (cs css. Γ([the (Γ p)],[],Normal σ) * (Seq c1 c2#cs,css,Normal s))}
              Seq c1 c2
              {t. ΓSeq c1 c2,Normal Z  Normal t},
              {t. ΓSeq c1 c2,Normal Z  Abrupt t}"
  by (rule hoaret.Seq [OF c1 ConseqMGT [OF hyp_c2]])
     (blast intro: exec.intros)
next
  case (Cond b c1 c2)
  have hyp_c1:
       "Z. Γ,Θt⇘/F{s. s=Z  Γc1,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                        Γthe (Γ p)Normal σ 
                    (cs css. Γ([the (Γ p)],[], Normal σ) * (c1#cs,css,Normal s))}
                   c1
                  {t. Γc1,Normal Z  Normal t},
                  {t. Γc1,Normal Z  Abrupt t}"
    using Cond.hyps by iprover
  have
  "Γ,Θt⇘/F({s. s=Z  ΓCond b c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
           Γthe (Γ p)Normal σ 
           (cs css. Γ([the (Γ p)],[],Normal σ) * (Cond b c1 c2#cs,css,Normal s))}
            b)
           c1
          {t. ΓCond b c1 c2,Normal Z  Normal t},
          {t. ΓCond b c1 c2,Normal Z  Abrupt t}"
  proof (rule ConseqMGT [OF hyp_c1],safe)
    assume "Z  b" "ΓCond b c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
    thus "Γc1,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by (auto simp add: final_notin_def intro: exec.CondTrue)
  next
    fix cs css
    assume "Z  b"
      "Γ([the (Γ p)],[], Normal σ) * (Cond b c1 c2 # cs,css, Normal Z)"
    thus "cs css. Γ([the (Γ p)],[], Normal σ) * (c1 # cs,css, Normal Z)"
      by (blast intro: rtranclp_into_tranclp1 [THEN tranclp_into_rtranclp]
          step.CondTrue)
  next
    fix t assume "Z  b" "Γc1,Normal Z  Normal t"
    thus "ΓCond b c1 c2,Normal Z  Normal t"
      by (blast intro: exec.CondTrue)
  next
    fix t assume "Z  b" "Γc1,Normal Z  Abrupt t"
    thus "ΓCond b c1 c2,Normal Z  Abrupt t"
      by (blast intro: exec.CondTrue)
  qed
  moreover
  have hyp_c2:
       "Z. Γ,Θt⇘/F{s. s=Z  Γc2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                     Γthe (Γ p)Normal σ 
                    (cs css. Γ([the (Γ p)],[],Normal σ) * (c2#cs,css,Normal s))}
                   c2
                  {t. Γc2,Normal Z  Normal t},
                  {t. Γc2,Normal Z  Abrupt t}"
    using Cond.hyps by iprover
  have
  "Γ,Θt⇘/F({s. s=Z  ΓCond b c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
              Γthe (Γ p)Normal σ 
           (cs css. Γ([the (Γ p)],[],Normal σ) *(Cond b c1 c2#cs,css, Normal s))}
            -b)
           c2
          {t. ΓCond b c1 c2,Normal Z  Normal t},
          {t. ΓCond b c1 c2,Normal Z  Abrupt t}"
  proof (rule ConseqMGT [OF hyp_c2],safe)
    assume "Z  b" "ΓCond b c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
    thus "Γc2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by (auto simp add: final_notin_def intro: exec.CondFalse)
  next
    fix cs css
    assume "Z  b"
      "Γ([the (Γ p)],[], Normal σ) * (Cond b c1 c2 # cs,css, Normal Z)"
    thus "cs css. Γ([the (Γ p)],[], Normal σ) * (c2 # cs,css,Normal Z)"
      by (blast intro: rtranclp_into_tranclp1 [THEN tranclp_into_rtranclp]
          step.CondFalse)
  next
    fix t assume "Z  b" "Γc2,Normal Z  Normal t"
    thus "ΓCond b c1 c2,Normal Z  Normal t"
      by (blast intro: exec.CondFalse)
  next
    fix t assume "Z  b" "Γc2,Normal Z  Abrupt t"
    thus "ΓCond b c1 c2,Normal Z  Abrupt t"
      by (blast intro: exec.CondFalse)
  qed
  ultimately
  show
   "Γ,Θt⇘/F{s. s=Z  ΓCond b c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
              Γthe (Γ p)Normal σ 
           (cs css. Γ([the (Γ p)],[],Normal σ) * (Cond b c1 c2#cs,css,Normal s))}
           (Cond b c1 c2)
          {t. ΓCond b c1 c2,Normal Z  Normal t},
          {t. ΓCond b c1 c2,Normal Z  Abrupt t}"
    by (rule hoaret.Cond)
next
  case (While b c)
  let ?unroll = "({(s,t). sb  Γc,Normal s  Normal t})*"
  let ?P' = "λZ. {t. (Z,t)?unroll 
                    (e. (Z,e)?unroll  eb
                          Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
                             (u. Γc,Normal e Abrupt u 
                                  ΓWhile b c,Normal Z  Abrupt u)) 
                    Γthe (Γ p)Normal σ 
                  (cs css. Γ([the (Γ p)],[],Normal σ) *
                               (While b c#cs,css,Normal t))}"
  let ?A = "λZ. {t. ΓWhile b c,Normal Z  Abrupt t}"
  let ?r = "{(t,s). Γ(While b c)Normal s  sb 
                    Γc,Normal s  Normal t}"
  show "Γ,Θt⇘/F{s. s=Z  ΓWhile b c,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                 Γthe (Γ p)Normal σ 
          (cs css. Γ([the (Γ p)],[],Normal σ)*(While b c#cs,css,Normal s))}
         (While b c)
       {t. ΓWhile b c,Normal Z  Normal t},
       {t. ΓWhile b c,Normal Z  Abrupt t}"
  proof (rule ConseqMGT [where ?P'="λ Z. ?P' Z"
                         and ?Q'="λ Z. ?P' Z  - b"])
    have wf_r: "wf ?r" by (rule wf_terminates_while)
    show " Z. Γ,Θt⇘/F(?P' Z) (While b c) (?P' Z  - b),(?A Z)"
    proof (rule allI, rule hoaret.While [OF wf_r])
      fix Z
      from While
      have hyp_c: "Z. Γ,Θt⇘/F{s. s=Z  Γc,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                Γthe (Γ p)Normal σ 
               (cs css. Γ([the (Γ p)],[],Normal σ) * (c # cs,css,Normal s))}
              c
            {t. Γc,Normal Z  Normal t},
            {t. Γc,Normal Z  Abrupt t}" by iprover
      show "σ. Γ,Θt⇘/F({σ}  ?P' Z   b) c
                       ({t. (t, σ)  ?r}  ?P' Z),(?A Z)"
      proof (rule allI, rule ConseqMGT [OF hyp_c])
        fix τ s
        assume  asm: "s {τ} 
                   {t. (Z, t)  ?unroll 
                      (e. (Z,e)?unroll  eb
                            Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
                               (u. Γc,Normal e Abrupt u 
                                    ΓWhile b c,Normal Z  Abrupt u)) 
                     Γthe (Γ p) Normal σ 
                     (cs css. Γ([the (Γ p)],[],Normal σ) *
                                  (While b c#cs,css,Normal t))}
                    b"
        then obtain cs css where
          s_eq_τ: "s=τ" and
          Z_s_unroll: "(Z,s)  ?unroll" and
          noabort:"e. (Z,e)?unroll  eb
                         Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
                            (u. Γc,Normal e Abrupt u 
                                  ΓWhile b c,Normal Z  Abrupt u)" and
          termi:  "Γthe (Γ p)  Normal σ" and
          reach: "Γ([the (Γ p)],[],Normal σ) *
                    (While b c#cs,css,Normal s)"and
          s_in_b: "sb"
          by blast
        have reach_c:
          "Γ([the (Γ p)],[],Normal σ) * (c#While b c#cs,css,Normal s)"
        proof -
          note reach
          also from s_in_b
          have "Γ(While b c#cs,css,Normal s)
                  (c#While b c#cs,css,Normal s)"
            by (rule step.WhileTrue)
          finally
          show ?thesis .
        qed
        from reach termi have
          termi_while: "ΓWhile b c  Normal s"
          by (rule steps_preserves_termination)
        show "s  {t. t = s  Γc,Normal t ⇒∉({Stuck}  Fault ` (-F)) 
                      Γthe (Γ p)  Normal σ 
                   (cs css. Γ([the (Γ p)],[],Normal σ) * (c#cs,css,Normal t))} 
        (t. t  {t. Γc,Normal s  Normal t} 
             t  {t. (t,τ)  ?r} 
                 {t. (Z, t)  ?unroll 
                     (e. (Z,e)?unroll   eb
                            Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
                              (u. Γc,Normal e Abrupt u 
                                  ΓWhile b c,Normal Z  Abrupt u)) 
                      Γthe (Γ p)  Normal σ 
                    (cs css. Γ([the (Γ p)],[],Normal σ) *
                                 (While b c # cs,css,Normal t))}) 
         (t. t  {t. Γc,Normal s  Abrupt t} 
             t  {t. ΓWhile b c,Normal Z  Abrupt t})"
          (is "?C1  ?C2  ?C3")
        proof (intro conjI)
          from Z_s_unroll noabort s_in_b termi reach_c show ?C1
            by blast
        next
          {
            fix t
            assume s_t: "Γc,Normal s  Normal t"
            with s_eq_τ termi_while s_in_b have "(t,τ)  ?r"
              by blast
            moreover
            from Z_s_unroll s_t s_in_b
            have "(Z, t)  ?unroll"
              by (blast intro: rtrancl_into_rtrancl)
            moreover
            have "Γ([the (Γ p)],[],Normal σ) * (While b c#cs,css,Normal t)"
            proof -
              note reach_c
              also from s_t
              have "Γ(c#While b c#cs,css,Normal s)*
                      (While b c#cs,css, Normal t)"
                by (rule exec_impl_steps)
              finally show ?thesis .
            qed
            moreover note noabort termi
            ultimately
            have "(t,τ)  ?r  (Z, t)  ?unroll 
                  (e. (Z,e)?unroll  eb
                         Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
                            (u. Γc,Normal e Abrupt u 
                                  ΓWhile b c,Normal Z  Abrupt u)) 
                  Γthe (Γ p)  Normal σ 
                    (cs css. Γ([the (Γ p)],[],Normal σ) *
                                 (While b c # cs,css, Normal t))"
              by iprover
          }
          then show ?C2 by blast
        next
          {
            fix t
            assume s_t:  "Γc,Normal s  Abrupt t"
            from Z_s_unroll noabort s_t s_in_b
            have "ΓWhile b c,Normal Z  Abrupt t"
              by blast
          } thus ?C3 by simp
        qed
      qed
    qed
  next
    fix s
    assume P: "s  {s. s=Z  ΓWhile b c,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                       Γthe (Γ p)Normal σ 
                   (cs css. Γ([the (Γ p)],[],Normal σ) *
                                (While b c#cs,css,Normal s))}"
    hence WhileNoFault: "ΓWhile b c,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by auto
    show "s  ?P' s 
     (t. t(?P' s  - b)
          t{t. ΓWhile b c,Normal Z  Normal t})
     (t. t?A s  t?A Z)"
    proof (intro conjI)
      {
        fix e
        assume "(Z,e)  ?unroll" "e  b"
        from this WhileNoFault
        have "Γc,Normal e ⇒∉({Stuck}  Fault ` (-F)) 
               (u. Γc,Normal e Abrupt u 
                    ΓWhile b c,Normal Z  Abrupt u)" (is "?Prop Z e")
        proof (induct rule: converse_rtrancl_induct [consumes 1])
          assume e_in_b: "e  b"
          assume WhileNoFault: "ΓWhile b c,Normal e ⇒∉({Stuck}  Fault ` (-F))"
          with e_in_b WhileNoFault
          have cNoFault: "Γc,Normal e ⇒∉({Stuck}  Fault ` (-F))"
            by (auto simp add: final_notin_def intro: exec.intros)
          moreover
          {
            fix u assume "Γc,Normal e  Abrupt u"
            with e_in_b have "ΓWhile b c,Normal e  Abrupt u"
              by (blast intro: exec.intros)
          }
          ultimately
          show "?Prop e e"
            by iprover
        next
          fix Z r
          assume e_in_b: "eb"
          assume WhileNoFault: "ΓWhile b c,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
          assume hyp: "eb;ΓWhile b c,Normal r ⇒∉({Stuck}  Fault ` (-F))
                        ?Prop r e"
          assume Z_r:
            "(Z, r)  {(Z, r). Z  b  Γc,Normal Z  Normal r}"
          with WhileNoFault
          have "ΓWhile b c,Normal r ⇒∉({Stuck}  Fault ` (-F))"
            by (auto simp add: final_notin_def intro: exec.intros)
          from hyp [OF e_in_b this] obtain
            cNoFault: "Γc,Normal e ⇒∉({Stuck}  Fault ` (-F))" and
            Abrupt_r: "u. Γc,Normal e  Abrupt u 
                            ΓWhile b c,Normal r  Abrupt u"
            by simp

           {
            fix u assume "Γc,Normal e  Abrupt u"
            with Abrupt_r have "ΓWhile b c,Normal r  Abrupt u" by simp
            moreover from  Z_r obtain
              "Z  b"  "Γc,Normal Z  Normal r"
              by simp
            ultimately have "ΓWhile b c,Normal Z  Abrupt u"
              by (blast intro: exec.intros)
          }
          with cNoFault show "?Prop Z e"
            by iprover
        qed
      }
      with P show "s  ?P' s"
        by blast
    next
      {
        fix t
        assume "termination": "t  b"
        assume "(Z, t)  ?unroll"
        hence "ΓWhile b c,Normal Z  Normal t"
        proof (induct rule: converse_rtrancl_induct [consumes 1])
          from "termination"
          show "ΓWhile b c,Normal t  Normal t"
            by (blast intro: exec.WhileFalse)
        next
          fix Z r
          assume first_body:
                 "(Z, r)  {(s, t). s  b  Γc,Normal s  Normal t}"
          assume "(r, t)  ?unroll"
          assume rest_loop: "ΓWhile b c, Normal r  Normal t"
          show "ΓWhile b c,Normal Z  Normal t"
          proof -
            from first_body obtain
              "Z  b" "Γc,Normal Z  Normal r"
              by fast
            moreover
            from rest_loop have
              "ΓWhile b c,Normal r  Normal t"
              by fast
            ultimately show "ΓWhile b c,Normal Z  Normal t"
              by (rule exec.WhileTrue)
          qed
        qed
      }
      with P
      show "t. t(?P' s  - b)
            t{t. ΓWhile b c,Normal Z  Normal t}"
        by blast
    next
      from P show "t. t?A s  t?A Z"
        by simp
    qed
  qed
next
  case (Call q)
  let ?P = "{s. s=Z  ΓCall q ,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
               Γthe (Γ p)Normal σ 
              (cs css. Γ([the (Γ p)],[],Normal σ) *
                  (Call q # cs,css,Normal s))}"
  from noStuck_Call
  have "s  ?P. q  dom Γ"
    by (fastforce simp add: final_notin_def)
  then show ?case
  proof (rule conseq_extract_state_indep_prop)
    assume q_defined: "q  dom Γ"
    from Call_hyp have
      "qdom Γ. Z.
        Γ,Θt⇘/F{s. s=Z  Γthe (Γ q),Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                        Γ(the (Γ q))Normal s  ((s,q),(σ,p))  termi_call_steps Γ}
                 (Call q)
                {t. Γthe (Γ q),Normal Z  Normal t},
                {t. Γthe (Γ q),Normal Z  Abrupt t}"
      by (simp add: exec_Call_body' noFaultStuck_Call_body' [simplified]
         terminates_Normal_Call_body)
    from Call_hyp q_defined have Call_hyp':
    "Z. Γ,Θt⇘/F{s. s=Z  ΓCall q,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                     ΓCall qNormal s  ((s,q),(σ,p))  termi_call_steps Γ}
                  (Call q)
                 {t. ΓCall q,Normal Z  Normal t},
                 {t. ΓCall q,Normal Z  Abrupt t}"
      by auto
    show
     "Γ,Θt⇘/F?P
           (Call q)
          {t. ΓCall q ,Normal Z  Normal t},
          {t. ΓCall q ,Normal Z  Abrupt t}"
    proof (rule ConseqMGT [OF Call_hyp'],safe)
      fix cs css
      assume
        "Γ([the (Γ p)],[],Normal σ)* (Call q # cs,css,Normal Z)"
        "Γthe (Γ p)  Normal σ"
      hence "ΓCall q  Normal Z"
        by (rule steps_preserves_termination)
      with q_defined show "ΓCall q  Normal Z"
        by (auto elim: terminates_Normal_elim_cases)
    next
      fix cs css
      assume reach:
        "Γ([the (Γ p)],[],Normal σ) * (Call q#cs,css,Normal Z)"
      moreover have "Γ(Call q # cs,css, Normal Z) 
                        ([the (Γ q)],(cs,Throw#cs)#css, Normal Z)"
        by (rule step.Call) (insert q_defined,auto)
      ultimately
      have "Γ([the (Γ p)],[],Normal σ) + ([the (Γ q)],(cs,Throw#cs)#css,Normal Z)"
        by (rule rtranclp_into_tranclp1)
      moreover
      assume termi: "Γthe (Γ p)  Normal σ"
      ultimately
      show "((Z,q), σ,p)  termi_call_steps Γ"
        by (auto simp add: termi_call_steps_def)
    qed
  qed
next
  case (DynCom c)
  have hyp:
    "s'. Z. Γ,Θt⇘/F{s. s = Z  Γc s',Normal s ⇒∉({Stuck}  Fault ` (-F)) 
            Γthe (Γ p)  Normal σ 
          (cs css. Γ([the (Γ p)],[],Normal σ) * (c s'#cs,css,Normal s))}
        (c s')
       {t. Γc s',Normal Z  Normal t},{t. Γc s',Normal Z  Abrupt t}"
    using DynCom by simp
  have hyp':
    "Γ,Θt⇘/F{s. s=Z  ΓDynCom c,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                 Γthe (Γ p)  Normal σ 
               (cs css. Γ([the (Γ p)],[],Normal σ) * (DynCom c#cs,css,Normal s))}
        (c Z)
       {t. ΓDynCom c,Normal Z  Normal t},{t. ΓDynCom c,Normal Z  Abrupt t}"
  proof (rule ConseqMGT [OF hyp],safe)
    assume "ΓDynCom c,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
    then show "Γc Z,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by (fastforce simp add: final_notin_def intro: exec.intros)
  next
    fix cs css
    assume "Γ([the (Γ p)], [], Normal σ) * (DynCom c # cs, css, Normal Z)"
    also have "Γ(DynCom c # cs, css, Normal Z)  (c Z#cs,css,Normal Z)"
      by (rule step.DynCom)
    finally
    show "cs css. Γ([the (Γ p)], [], Normal σ) * (c Z # cs, css, Normal Z)"
      by blast
  next
    fix t
    assume "Γc Z,Normal Z  Normal t"
    thus "ΓDynCom c,Normal Z  Normal t"
      by (auto intro: exec.intros)
  next
    fix t
    assume "Γc Z,Normal Z  Abrupt t"
    thus "ΓDynCom c,Normal Z  Abrupt t"
      by (auto intro: exec.intros)
  qed
  show ?case
    apply (rule hoaret.DynCom)
    apply safe
    apply (rule hyp')
    done
next
  case (Guard f g c)
  have hyp_c: "Z. Γ,Θt⇘/F{s. s=Z  Γc,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
              Γthe (Γ p)Normal σ 
            (cs css. Γ([the (Γ p)],[],Normal σ) * (c#cs,css,Normal s))}
          c
         {t. Γc,Normal Z  Normal t},
         {t. Γc,Normal Z  Abrupt t}"
    using Guard.hyps by iprover
  show "Γ,Θt⇘/F{s. s=Z  ΓGuard f g c ,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                  Γthe (Γ p)Normal σ 
            (cs css. Γ([the (Γ p)],[],Normal σ) * (Guard f g c#cs,css,Normal s))}
              Guard f g c
              {t. ΓGuard f g c ,Normal Z  Normal t},
              {t. ΓGuard f g c ,Normal Z  Abrupt t}"
  proof (cases "f  F")
    case True
    have "Γ,Θt⇘/F(g  {s. s=Z 
                     ΓGuard f g c ,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                 Γthe (Γ p)Normal σ 
            (cs css. Γ([the (Γ p)],[],Normal σ) * (Guard f g c#cs,css,Normal s))})
              c
              {t. ΓGuard f g c ,Normal Z  Normal t},
              {t. ΓGuard f g c ,Normal Z  Abrupt t}"
    proof (rule ConseqMGT [OF hyp_c], safe)
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))" "Zg"
      thus "Γc,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
        by (auto simp add: final_notin_def intro: exec.intros)
    next
      fix cs css
      assume "Γ([the (Γ p)],[],Normal σ) * (Guard f g c#cs,css,Normal Z)"
      also
      assume "Z  g"
      hence "Γ(Guard f g c#cs,css,Normal Z)  (c#cs,css,Normal Z)"
        by (rule step.Guard)
      finally show "cs css. Γ([the (Γ p)],[],Normal σ) * (c#cs,css,Normal Z)"
        by iprover
    next
      fix t
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
             "Γc,Normal Z  Normal t" "Z  g"
      thus "ΓGuard f g c ,Normal Z  Normal t"
        by (auto simp add: final_notin_def intro: exec.intros )
    next
      fix t
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
              "Γc,Normal Z  Abrupt t" "Z  g"
      thus "ΓGuard f g c ,Normal Z  Abrupt t"
        by (auto simp add: final_notin_def intro: exec.intros )
    qed
    from True this show ?thesis
      by (rule conseqPre [OF Guarantee]) auto
  next
    case False
    have "Γ,Θt⇘/F(g  {s. s=Z 
                     ΓGuard f g c ,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                 Γthe (Γ p)Normal σ 
            (cs css. Γ([the (Γ p)],[],Normal σ) * (Guard f g c#cs,css,Normal s))})
              c
              {t. ΓGuard f g c ,Normal Z  Normal t},
              {t. ΓGuard f g c ,Normal Z  Abrupt t}"
    proof (rule ConseqMGT [OF hyp_c], safe)
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      thus "Γc,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
        using False
        by (cases "Z g") (auto simp add: final_notin_def intro: exec.intros)
    next
      fix cs css
      assume "Γ([the (Γ p)],[],Normal σ) * (Guard f g c#cs,css,Normal Z)"
      also assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      hence "Z  g"
        using False by (auto simp add: final_notin_def intro: exec.GuardFault)
      hence "Γ(Guard f g c#cs,css,Normal Z)  (c#cs,css,Normal Z)"
        by (rule step.Guard)
      finally show "cs css. Γ([the (Γ p)],[],Normal σ) * (c#cs,css,Normal Z)"
        by iprover
    next
      fix t
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
        "Γc,Normal Z  Normal t"
      thus "ΓGuard f g c ,Normal Z  Normal t"
        using False
        by (cases "Z g") (auto simp add: final_notin_def intro: exec.intros )
    next
      fix t
      assume "ΓGuard f g c ,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
             "Γc,Normal Z  Abrupt t"
      thus "ΓGuard f g c ,Normal Z  Abrupt t"
        using False
        by (cases "Z g") (auto simp add: final_notin_def intro: exec.intros )
    qed
    then show ?thesis
      apply (rule conseqPre [OF hoaret.Guard])
      apply clarify
      apply (frule Guard_noFaultStuckD [OF _ False])
      apply auto
      done
  qed
next
  case Throw
  show "Γ,Θt⇘/F{s. s=Z  ΓThrow,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                  Γthe (Γ p)Normal σ 
                (cs css. Γ([the (Γ p)],[], Normal σ) * (Throw#cs,css,Normal s))}
              Throw
              {t. ΓThrow,Normal Z  Normal t},
              {t. ΓThrow,Normal Z  Abrupt t}"
    by (rule conseqPre [OF hoaret.Throw])
       (blast intro: exec.intros terminates.intros)
next
  case (Catch c1 c2)
  have hyp_c1:
   "Z. Γ,Θt⇘/F{s. s= Z  Γc1,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    Γthe (Γ p)  Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (c1# cs, css,Normal s))}
               c1
              {t. Γc1,Normal Z  Normal t},{t. Γc1,Normal Z  Abrupt t}"
    using Catch.hyps by iprover
  have hyp_c2:
   "Z. Γ,Θt⇘/F{s. s= Z  Γc2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                     Γthe (Γ p)  Normal σ 
                (cs css. Γ([the (Γ p)],[],Normal σ) * (c2# cs, css,Normal s))}
               c2
              {t. Γc2,Normal Z  Normal t},{t. Γc2,Normal Z  Abrupt t}"
    using Catch.hyps by iprover
  have
    "Γ,Θt⇘/F{s. s = Z  ΓCatch c1 c2,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
               Γthe (Γ p)  Normal σ 
            (cs css. Γ([the (Γ p)],[],Normal σ)*(Catch c1 c2 #cs,css,Normal s))}
            c1
           {t. ΓCatch c1 c2,Normal Z  Normal t},
           {t. Γc1,Normal Z  Abrupt t 
               Γc2,Normal t ⇒∉({Stuck}  Fault`(-F))  Γthe (Γ p)  Normal σ 
               (cs css. Γ([the (Γ p)],[],Normal σ) * (c2# cs, css,Normal t))}"
  proof (rule ConseqMGT [OF hyp_c1],clarify,safe)
    assume "ΓCatch c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
    thus "Γc1,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      by (fastforce simp add: final_notin_def intro: exec.intros)
  next
    fix cs css
    assume "Γ([the (Γ p)], [], Normal σ) * (Catch c1 c2 # cs, css, Normal Z)"
    also have
      "Γ(Catch c1 c2 # cs, css, Normal Z)  ([c1],(cs,c2#cs)#css,Normal Z)"
      by (rule step.Catch)
    finally
    show "cs css. Γ([the (Γ p)], [], Normal σ) * (c1 # cs, css, Normal Z)"
      by iprover
  next
    fix t
    assume "Γc1,Normal Z  Normal t"
    thus "ΓCatch c1 c2,Normal Z  Normal t"
      by (auto intro: exec.intros)
  next
    fix t
    assume "ΓCatch c1 c2,Normal Z ⇒∉({Stuck}  Fault ` (-F))"
      "Γc1,Normal Z  Abrupt t"
    thus "Γc2,Normal t ⇒∉({Stuck}  Fault ` (-F))"
      by (auto simp add: final_notin_def intro: exec.intros)
  next
    fix cs css t
    assume "Γ([the (Γ p)], [], Normal σ) * (Catch c1 c2 # cs, css, Normal Z)"
    also have
      "Γ(Catch c1 c2 # cs, css, Normal Z)  ([c1],(cs,c2#cs)#css,Normal Z)"
      by (rule step.Catch)
    also
    assume "Γc1,Normal Z  Abrupt t"
    hence "Γ([c1],(cs,c2#cs)#css,Normal Z) * ([],(cs,c2#cs)#css,Abrupt t)"
      by (rule exec_impl_steps)
    also
    have "Γ([],(cs,c2#cs)#css,Abrupt t)  (c2#cs,css,Normal t)"
      by (rule step.intros)
    finally
    show "cs css. Γ([the (Γ p)], [], Normal σ) * (c2 # cs, css, Normal t)"
      by iprover
  qed
  moreover
  have "Γ,Θt⇘/F{t. Γc1,Normal Z  Abrupt t 
                  Γc2,Normal t ⇒∉({Stuck}  Fault ` (-F)) 
                  Γthe (Γ p)  Normal σ 
                  (cs css. Γ([the (Γ p)],[],Normal σ) * (c2# cs, css,Normal t))}
               c2
              {t. ΓCatch c1 c2,Normal Z  Normal t},
              {t. ΓCatch c1 c2,Normal Z  Abrupt t}"
    by (rule ConseqMGT [OF hyp_c2]) (fastforce intro: exec.intros)
  ultimately show ?case
    by (rule hoaret.Catch)
qed


text ‹To prove a procedure implementation correct it suffices to assume
       only the procedure specifications of procedures that actually
       occur during evaluation of the body.
›
lemma Call_lemma:
 assumes
 Call: "q  dom Γ. Z. Γ,Θt⇘/F{s. s=Z  ΓCall q,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    ΓCall qNormal s  ((s,q),(σ,p))  termi_call_steps Γ}
                 (Call q)
                {t. ΓCall q,Normal Z  Normal t},
                {t. ΓCall q,Normal Z  Abrupt t}"
 shows "Z. Γ,Θt⇘/F({σ}  {s. s=Z  Γthe (Γ p),Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                                 Γthe (Γ p)Normal s})
                 the (Γ p)
              {t. Γthe (Γ p),Normal Z  Normal t},
              {t. Γthe (Γ p),Normal Z  Abrupt t}"
apply (rule conseqPre)
apply (rule Call_lemma')
apply (rule Call)
apply blast
done

lemma Call_lemma_switch_Call_body:
 assumes
 call: "q  dom Γ. Z. Γ,Θt⇘/F{s. s=Z  ΓCall q,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    ΓCall qNormal s  ((s,q),(σ,p))  termi_call_steps Γ}
                 (Call q)
                {t. ΓCall q,Normal Z  Normal t},
                {t. ΓCall q,Normal Z  Abrupt t}"
 assumes p_defined: "p  dom Γ"
 shows "Z. Γ,Θt⇘/F({σ}  {s. s=Z  ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                                 ΓCall pNormal s})
                 the (Γ p)
              {t. ΓCall p,Normal Z  Normal t},
              {t. ΓCall p,Normal Z  Abrupt t}"
apply (simp only: exec_Call_body' [OF p_defined] noFaultStuck_Call_body' [OF p_defined] terminates_Normal_Call_body [OF p_defined])
apply (rule conseqPre)
apply (rule Call_lemma')
apply (rule call)
apply blast
done


lemma MGT_Call:
"p  dom Γ. Z.
  Γ,Θt⇘/F{s. s=Z  ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
             Γ(Call p)Normal s}
           (Call p)
          {t. ΓCall p,Normal Z  Normal t},
          {t. ΓCall p,Normal Z  Abrupt t}"
apply (intro ballI allI)
apply (rule CallRec' [where Procs="dom Γ" and
    P="λp Z. {s. s=Z  ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                    ΓCall pNormal s}" and
    Q="λp Z. {t. ΓCall p,Normal Z  Normal t}" and
    A="λp Z. {t. ΓCall p,Normal Z  Abrupt t}" and
    r="termi_call_steps Γ"
    ])
apply    simp
apply   simp
apply  (rule wf_termi_call_steps)
apply (intro ballI allI)
apply simp
apply (rule Call_lemma_switch_Call_body [rule_format, simplified])
apply  (rule hoaret.Asm)
apply  fastforce
apply assumption
done


lemma CollInt_iff: "{s. P s}  {s. Q s} = {s. P s  Q s}"
  by auto

lemma image_Un_conv: "f ` (pdom Γ. Z. {x p Z}) =  (pdom Γ. Z. {f (x p Z)})"
  by (auto iff: not_None_eq)


text ‹Another proof of MGT_Call›, maybe a little more readable›
lemma
"p  dom Γ. Z.
  Γ,{}t⇘/F{s. s=Z  ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
             Γ(Call p)Normal s}
           (Call p)
          {t. ΓCall p,Normal Z  Normal t},
          {t. ΓCall p,Normal Z  Abrupt t}"
proof -
  {
    fix p Z σ
    assume defined: "p  dom Γ"
    define Specs where "Specs = (pdom Γ. Z.
            {({s. s=Z 
              ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
              ΓCall pNormal s},
             p,
             {t. ΓCall p,Normal Z  Normal t},
             {t. ΓCall p,Normal Z  Abrupt t})})"
    define Specs_wf where "Specs_wf p σ = (λ(P,q,Q,A).
                       (P  {s. ((s,q),σ,p)  termi_call_steps Γ}, q, Q, A)) ` Specs" for p σ
    have "Γ,Specs_wf p σt⇘/F({σ} 
                 {s. s = Z  Γthe (Γ p),Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                  Γthe (Γ p)Normal s})
                (the (Γ p))
               {t. Γthe (Γ p),Normal Z  Normal t},
               {t. Γthe (Γ p),Normal Z  Abrupt t}"
      apply (rule Call_lemma [rule_format])
      apply (rule hoaret.Asm)
      apply (clarsimp simp add: Specs_wf_def Specs_def image_Un_conv)
      apply (rule_tac x=q in bexI)
      apply (rule_tac x=Z in exI)
      apply (clarsimp simp add: CollInt_iff)
      apply auto
      done
    hence "Γ,Specs_wf p σt⇘/F({σ} 
                 {s. s = Z  ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
                  ΓCall pNormal s})
                (the (Γ p))
               {t. ΓCall p,Normal Z  Normal t},
               {t. ΓCall p,Normal Z  Abrupt t}"
      by (simp only: exec_Call_body' [OF defined]
                   noFaultStuck_Call_body' [OF defined]
                  terminates_Normal_Call_body [OF defined])
  } note bdy=this
  show ?thesis
    apply (intro ballI allI)
    apply (rule hoaret.CallRec [where Specs="(pdom Γ. Z.
            {({s. s=Z 
              ΓCall p,Normal s ⇒∉({Stuck}  Fault ` (-F)) 
              ΓCall pNormal s},
             p,
             {t. ΓCall p,Normal Z  Normal t},
             {t. ΓCall p,Normal Z  Abrupt t})})",
             OF _ wf_termi_call_steps [of Γ] refl])
    apply fastforce
    apply clarify
    apply (rule conjI)
    apply  fastforce
    apply (rule allI)
    apply (simp (no_asm_use) only : Un_empty_left)
    apply (rule bdy)
    apply auto
    done
qed

end