Theory Correctness

(*  Title:      JinjaThreads/Compiler/Correctness.thy
    Author:     Andreas Lochbihler
*)

section ‹Correctness of both stages›

theory Correctness 
imports
  J0Bisim
  J1Deadlock 
  "../Framework/FWBisimDeadlock"
  Correctness2
  Correctness1Threaded
  Correctness1 
  JJ1WellForm
  Compiler
begin

locale J_JVM_heap_conf_base = 
  J0_J1_heap_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
  +
  J1_JVM_heap_conf_base 
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf "compP1 P"
  for addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
  and hconf :: "'heap  bool"
  and P :: "'addr J_prog"
begin

definition bisimJ2JVM :: 
  "(('addr,'thread_id,'addr expr×'addr locals,'heap,'addr) state, 
    ('addr,'thread_id,'addr option × 'addr frame list,'heap,'addr) state) bisim"
where "bisimJ2JVM = red_red0.mbisim B red0_Red1'.mbisim B mbisim_Red1'_Red1 B Red1_execd.mbisim"

definition tlsimJ2JVM ::
  "('thread_id × ('addr, 'thread_id, 'heap) J_thread_action,
    'thread_id × ('addr, 'thread_id, 'heap) jvm_thread_action) bisim"
where "tlsimJ2JVM = red_red0.mta_bisim B red0_Red1'.mta_bisim B (=) B Red1_execd.mta_bisim"

end

lemma compP2_has_method [simp]: "compP2 P  C has M  P  C has M"
by(auto simp add: compP2_def compP_has_method)

locale J_JVM_conf_read = 
  J1_JVM_conf_read
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf "compP1 P"
  for addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
  and hconf :: "'heap  bool"
  and P :: "'addr J_prog"
begin

sublocale J_JVM_heap_conf_base by(unfold_locales)

theorem bisimJ2JVM_weak_bisim:
  assumes wf: "wf_J_prog P"
  shows "delay_bisimulation_diverge_final (mredT P) (execd_mthr.redT (J2JVM P)) bisimJ2JVM tlsimJ2JVM 
            (red_mthr.mτmove P) (execd_mthr.mτmove (J2JVM P)) red_mthr.mfinal exec_mthr.mfinal"
unfolding bisimJ2JVM_def tlsimJ2JVM_def J2JVM_def o_apply
apply(rule delay_bisimulation_diverge_final_compose)
 apply(rule FWdelay_bisimulation_diverge.mthr_delay_bisimulation_diverge_final)
 apply(rule red_red0_FWbisim[OF wf_prog_wwf_prog[OF wf]])
apply(rule delay_bisimulation_diverge_final_compose)
 apply(rule FWdelay_bisimulation_diverge.mthr_delay_bisimulation_diverge_final)
 apply(rule red0_Red1'_FWweak_bisim[OF wf])
apply(rule delay_bisimulation_diverge_final_compose)
 apply(rule delay_bisimulation_diverge_final.intro)
  apply(rule bisimulation_into_delay.delay_bisimulation)
  apply(rule Red1'_Red1_bisim_into_weak[OF compP1_pres_wf[OF wf]])
 apply(rule bisimulation_final.delay_bisimulation_final_base)
 apply(rule Red1'_Red1_bisimulation_final[OF compP1_pres_wf[OF wf]])
apply(rule FWdelay_bisimulation_diverge.mthr_delay_bisimulation_diverge_final)
apply(rule Red1_exec1_FWwbisim[OF compP1_pres_wf[OF wf]])
done


lemma bisimJ2JVM_start:
  assumes wf: "wf_J_prog P"
  and start: "wf_start_state P C M vs"
  shows "bisimJ2JVM (J_start_state P C M vs) (JVM_start_state (J2JVM P) C M vs)"
using assms
unfolding bisimJ2JVM_def J2JVM_def o_def
apply(intro bisim_composeI)
   apply(erule (1) bisim_J_J0_start[OF wf_prog_wwf_prog])
  apply(erule (1) bisim_J0_J1_start)
 apply(erule bisim_J1_J1_start[OF compP1_pres_wf])
 apply simp
apply(erule bisim_J1_JVM_start[OF compP1_pres_wf])
apply simp
done

end

fun exception :: "'addr expr × 'addr locals  'addr option × 'addr frame list"
where "exception (Throw a, xs) = (a, [])"
| "exception _ = (None, [])"

definition mexception :: 
  "('addr,'thread_id,'addr expr×'addr locals,'heap,'addr) state  
   ('addr,'thread_id,'addr option×'addr frame list,'heap,'addr) state"
where
  "ln. mexception s  
  (locks s, (λt. case thr s t of (e, ln)  (exception e, ln) | None  None, shr s), wset s, interrupts s)"

declare compP1_def [simp del]

context J_JVM_heap_conf_base begin

lemma bisimJ2JVM_mfinal_mexception:
  assumes bisim: "bisimJ2JVM s s'"
  and fin: "exec_mthr.mfinal s'"
  and fin': "red_mthr.mfinal s"
  and tsNotEmpty: "thr s t  None"
  shows "s' = mexception s"
proof -
  obtain ls ts m ws "is" where s: "s = (ls, (ts, m), ws, is)" by(cases s) fastforce
  from bisim obtain s0 s1 where bisimJ0: "red_red0.mbisim s s0"
    and bisim01: "red0_Red1'.mbisim s0 s1"
    and bisim1JVM: "Red1_execd.mbisim s1 s'"
    unfolding bisimJ2JVM_def by(fastforce simp add: mbisim_Red1'_Red1_def)
  from bisimJ0 s have [simp]: "locks s0 = ls" "wset s0 = ws" "interrupts s0 = is"
    and tbisimJ0: "t. red_red0.tbisim (ws t = None) t (ts t) m (thr s0 t) (shr s0)"
    by(auto simp add: red_red0.mbisim_def)
  from bisim01 have [simp]: "locks s1 = ls" "wset s1 = ws" "interrupts s1 = is"
    and tbisim01: "t. red0_Red1'.tbisim (ws t = None) t (thr s0 t) (shr s0) (thr s1 t) (shr s1)"
    by(auto simp add: red0_Red1'.mbisim_def)
  from bisim1JVM have "locks s' = ls" "wset s' = ws" "interrupts s' = is"
    and tbisim1JVM: "t. Red1_execd.tbisim (ws t = None) t (thr s1 t) (shr s1) (thr s' t) (shr s')"
    by(auto simp add: Red1_execd.mbisim_def)
  then obtain ts' m' where s': "s' = (ls, (ts', m'), ws, is)" by(cases s') fastforce
  { fix t e x ln
    assume tst: "ts t = ((e, x), ln)"
    from tbisimJ0[of t] tst obtain e' exs' where ts0t: "thr s0 t = ((e', exs'), ln)"
      and bisimtJ0: "bisim_red_red0 ((e, x), m) ((e', exs'), shr s0)"
      by(auto simp add: red_red0.tbisim_def)
    from tbisim01[of t] ts0t obtain e'' xs'' exs''
      where ts1t: "thr s1 t = (((e'', xs''), exs''), ln)"
      and bisimt01: "bisim_red0_Red1 ((e', exs'), shr s0) (((e'', xs''), exs''), shr s1)"
      by(auto simp add: red0_Red1'.tbisim_def)
    from tbisim1JVM[of t] ts1t s' obtain xcp frs
      where ts't: "ts' t = ((xcp, frs), ln)" and [simp]: "m' = shr s1"
      and bisimt1JVM: "bisim1_list1 t m' (e'', xs'') exs'' xcp frs"
      by(fastforce simp add: Red1_execd.tbisim_def)

    from fin ts't s s' have [simp]: "frs = []" by(auto dest: exec_mthr.mfinalD)
    from bisimt1JVM have [simp]: "exs'' = []" by(auto elim: bisim1_list1.cases)
    from bisimt01 have [simp]: "exs' = []"
      by(auto simp add: bisim_red0_Red1_def elim!: bisim_list1E elim: bisim_list.cases)
    from tst fin' s have fine: "final e" by(auto dest: red_mthr.mfinalD)
    hence "exception (e, x) = (xcp, frs)"
    proof(cases)
      fix v
      assume [simp]: "e = Val v"
      from bisimtJ0 have "e' = Val v" by(auto elim!: bisim_red_red0.cases)
      with bisimt01 have "e'' = Val v" by(auto simp add: bisim_red0_Red1_def elim: bisim_list1E)
      with bisimt1JVM have "xcp = None" by(auto elim: bisim1_list1.cases)
      thus ?thesis by simp
    next
      fix a
      assume [simp]: "e = Throw a"
      from bisimtJ0 have "e' = Throw a" by(auto elim!: bisim_red_red0.cases)
      with bisimt01 have "e'' = Throw a" by(auto simp add: bisim_red0_Red1_def elim: bisim_list1E)
      with bisimt1JVM have "xcp = a" by(auto elim: bisim1_list1.cases)
      thus ?thesis by simp
    qed
    moreover from bisimtJ0 have "shr s0 = m" by(auto elim: bisim_red_red0.cases)
    moreover from bisimt01 have "shr s1 = shr s0" by(auto simp add: bisim_red0_Red1_def)
    ultimately have "ts' t = (exception (e, x), ln)" "m' = m" using ts't by simp_all }
  moreover {
    fix t
    assume "ts t = None"
    with red_red0.mbisim_thrNone_eq[OF bisimJ0, of t] s have "thr s0 t = None" by simp
    with bisim01 have "thr s1 t = None" by(auto simp add: red0_Red1'.mbisim_thrNone_eq)
    with bisim1JVM s' have "ts' t = None" by(simp add: Red1_execd.mbisim_thrNone_eq) }
  ultimately show ?thesis using s s' tsNotEmpty by(auto simp add: mexception_def fun_eq_iff)
qed

end

context J_JVM_conf_read begin

theorem J2JVM_correct1:
  fixes C M vs
  defines s: "s  J_start_state P C M vs"
  and comps: "cs  JVM_start_state (J2JVM P) C M vs"
  assumes wf: "wf_J_prog P"
  and wf_start: "wf_start_state P C M vs"
  and red: "red_mthr.mthr.τRuns P s ξ"
  obtains ξ' 
  where "execd_mthr.mthr.τRuns (J2JVM P) cs ξ'" "tllist_all2 tlsimJ2JVM (rel_option bisimJ2JVM) ξ ξ'"
  and "s'.  tfinite ξ; terminal ξ = s'; red_mthr.mfinal s' 
       tfinite ξ'  terminal ξ' = mexception s'"
  and "s'.  tfinite ξ; terminal ξ = s'; red_mthr.deadlock P s' 
       cs'. tfinite ξ'  terminal ξ' = cs'  execd_mthr.deadlock (J2JVM P) cs'  bisimJ2JVM s' cs'"
  and " tfinite ξ; terminal ξ = None   tfinite ξ'  terminal ξ' = None"
  and "¬ tfinite ξ  ¬ tfinite ξ'"
proof -
  from wf wf_start have bisim: "bisimJ2JVM s cs" unfolding s comps by(rule bisimJ2JVM_start)

  note divfin = delay_bisimulation_diverge_final.delay_bisimulation_diverge[OF bisimJ2JVM_weak_bisim[OF wf]]
  note divfin2 = delay_bisimulation_diverge_final.delay_bisimulation_final_base[OF bisimJ2JVM_weak_bisim[OF wf]]

  from delay_bisimulation_diverge.simulation_τRuns1[OF divfin, OF bisim red] obtain ξ' 
    where exec: "execd_mthr.mthr.τRuns (J2JVM P) cs ξ'" 
    and tlsim: "tllist_all2 tlsimJ2JVM (rel_option bisimJ2JVM) ξ ξ'" by blast
  moreover {
    fix s'
    assume fin: "tfinite ξ" and s': "terminal ξ = s'" and final: "red_mthr.mfinal s'"
    from delay_bisimulation_final_base.τRuns_terminate_final1[OF divfin2, OF red exec tlsim fin s' final]
    obtain cs' where fin': "tfinite ξ'" and cs': "terminal ξ' = cs'"
      and final': "exec_mthr.mfinal cs'" by blast
    from tlsim fin s' cs' have bisim': "bisimJ2JVM s' cs'" by(auto dest: tllist_all2_tfinite1_terminalD)
    from red_mthr.mthr.τRuns_into_τrtrancl3p[OF red fin s'] 
    have "thr s' start_tid  None" unfolding s
      by(rule red_mthr.τrtrancl3p_redT_thread_not_disappear)(simp add: start_state_def)
    with bisim' final final' have [simp]: "cs' = mexception s'"
      by(intro bisimJ2JVM_mfinal_mexception disjI1)
    with fin' cs' have "tfinite ξ'  terminal ξ' = mexception s'" by simp }
  moreover {
    fix s'
    assume fin: "tfinite ξ" and s': "terminal ξ = s'" and dead: "red_mthr.deadlock P s'"
    from tlsim fin s'
    obtain cs' where "tfinite ξ'" and cs': "terminal ξ' = cs'"
      and bisim': "bisimJ2JVM s' cs'"
      by(cases "terminal ξ'")(fastforce dest: tllist_all2_tfinite1_terminalD tllist_all2_tfiniteD)+
    from bisim' obtain s0' s1' S1' where bisim0: "red_red0.mbisim s' s0'"
      and bisim01: "red0_Red1'.mbisim s0' s1'"
      and bisim11: "mbisim_Red1'_Red1 s1' S1'"
      and bisim12: "Red1_execd.mbisim S1' cs'"
      unfolding bisimJ2JVM_def by auto

    note b0 = red_red0_FWbisim[OF wf_prog_wwf_prog[OF wf]]
    note b01 = red0_Red1'_FWweak_bisim[OF wf]
    note b01mthr = FWdelay_bisimulation_diverge.mbisim_delay_bisimulation[OF b01]
    note b11 = Red1'_Red1_bisim_into_weak[OF compP1_pres_wf[OF wf]]
    note b11delay = bisimulation_into_delay.delay_bisimulation[OF b11]
    note b12 = Red1_exec1_FWwbisim[OF compP1_pres_wf[OF wf]]
    note b12mthr = FWdelay_bisimulation_diverge.mbisim_delay_bisimulation[OF b12]

    from FWdelay_bisimulation_diverge.deadlock1_imp_τs_deadlock2[OF b0, OF bisim0 dead, of convert_RA]
    obtain s0'' where "red0_mthr.mthr.silent_moves P s0' s0''"
      and bisim0': "red_red0.mbisim s' s0''"
      and dead0: "red0_mthr.deadlock P s0''" by auto
    
    from delay_bisimulation_diverge.simulation_silents1[OF b01mthr, OF bisim01 red0_mthr.mthr.silent_moves P s0' s0'']
    obtain s1'' where "Red1_mthr.mthr.silent_moves False (compP1 P) s1' s1''"
      and "red0_Red1'.mbisim s0'' s1''" by auto
    from FWdelay_bisimulation_diverge.deadlock1_imp_τs_deadlock2[OF b01, OF red0_Red1'.mbisim s0'' s1'' dead0, of convert_RA]
    obtain s1''' where "Red1_mthr.mthr.silent_moves False (compP1 P) s1'' s1'''"
      and dead1: "Red1_mthr.deadlock False (compP1 P) s1'''"
      and bisim01': "red0_Red1'.mbisim s0'' s1'''" by auto
    from Red1_mthr.mthr.silent_moves False (compP1 P) s1' s1'' Red1_mthr.mthr.silent_moves False (compP1 P) s1'' s1'''
    have "Red1_mthr.mthr.silent_moves False (compP1 P) s1' s1'''" by(rule rtranclp_trans)

    from delay_bisimulation_diverge.simulation_silents1[OF b11delay, OF bisim11 this]
    obtain S1'' where "Red1_mthr.mthr.silent_moves True (compP1 P) S1' S1''"
      and bisim11': "mbisim_Red1'_Red1 s1''' S1''" by auto
    from bisim11' have "s1''' = S1''" by(simp add: mbisim_Red1'_Red1_def)
    with dead1 have dead1': "Red1_mthr.deadlock True (compP1 P) S1''"
      by(simp add: Red1_Red1'_deadlock_inv)

    from delay_bisimulation_diverge.simulation_silents1[OF b12mthr, OF bisim12 Red1_mthr.mthr.silent_moves True (compP1 P) S1' S1'']
    obtain cs'' where "execd_mthr.mthr.silent_moves (compP2 (compP1 P)) cs' cs''"
      and "Red1_execd.mbisim S1'' cs''" by auto
    from FWdelay_bisimulation_diverge.deadlock1_imp_τs_deadlock2[OF b12 Red1_execd.mbisim S1'' cs'' dead1', of convert_RA]
    obtain cs''' where "execd_mthr.mthr.silent_moves (compP2 (compP1 P)) cs'' cs'''"
      and bisim12': "Red1_execd.mbisim S1'' cs'''"
      and dead': "execd_mthr.deadlock (compP2 (compP1 P)) cs'''" by auto
    from execd_mthr.mthr.silent_moves (compP2 (compP1 P)) cs' cs'' execd_mthr.mthr.silent_moves (compP2 (compP1 P)) cs'' cs'''
    have "execd_mthr.mthr.silent_moves (compP2 (compP1 P)) cs' cs'''" by(rule rtranclp_trans)
    hence "cs''' = cs'" using execd_mthr.mthr.τRuns_terminal_stuck[OF exec tfinite ξ' terminal ξ' = cs']
      by(cases rule: converse_rtranclpE)(fastforce simp add: J2JVM_def)+
    with dead' have "execd_mthr.deadlock (J2JVM P) cs'" by(simp add: J2JVM_def)
    hence "cs'. tfinite ξ'  terminal ξ' = cs'  execd_mthr.deadlock (J2JVM P) cs'  bisimJ2JVM s' cs'"
      using tfinite ξ' terminal ξ' = cs' bisim' by blast }
  moreover {
    assume "tfinite ξ" and "terminal ξ = None"
    hence "tfinite ξ'  terminal ξ' = None" using tlsim tllist_all2_tfiniteD[OF tlsim]
      by(cases "terminal ξ'")(auto dest: tllist_all2_tfinite1_terminalD) }
  moreover {
    assume "¬ tfinite ξ"
      hence "¬ tfinite ξ'" using tlsim by(blast dest: tllist_all2_tfiniteD) }
  ultimately show thesis by(rule that)
qed

theorem J2JVM_correct2:
  fixes C M vs
  defines s: "s  J_start_state P C M vs"
  and comps: "cs  JVM_start_state (J2JVM P) C M vs"
  assumes wf: "wf_J_prog P"
  and wf_start: "wf_start_state P C M vs"
  and exec: "execd_mthr.mthr.τRuns (J2JVM P) cs ξ'"
  obtains ξ 
  where "red_mthr.mthr.τRuns P s ξ" "tllist_all2 tlsimJ2JVM (rel_option bisimJ2JVM) ξ ξ'"
  and "cs'.  tfinite ξ'; terminal ξ' = cs'; exec_mthr.mfinal cs' 
       s'. tfinite ξ  terminal ξ = s'  cs' = mexception s'  bisimJ2JVM s' cs'"
  and "cs'.  tfinite ξ'; terminal ξ' = cs'; execd_mthr.deadlock (J2JVM P) cs' 
       s'. tfinite ξ  terminal ξ = s'  red_mthr.deadlock P s'  bisimJ2JVM s' cs'"
  and " tfinite ξ'; terminal ξ' = None   tfinite ξ  terminal ξ = None"
  and "¬ tfinite ξ'  ¬ tfinite ξ"
proof -
  from wf wf_start have bisim: "bisimJ2JVM s cs" unfolding s comps by(rule bisimJ2JVM_start)

  note divfin = delay_bisimulation_diverge_final.delay_bisimulation_diverge[OF bisimJ2JVM_weak_bisim[OF wf]]
  note divfin2 = delay_bisimulation_diverge_final.delay_bisimulation_final_base[OF bisimJ2JVM_weak_bisim[OF wf]]

  from delay_bisimulation_diverge.simulation_τRuns2[OF divfin, OF bisim exec] obtain ξ
    where red: "red_mthr.mthr.τRuns P s ξ" 
    and tlsim: "tllist_all2 tlsimJ2JVM (rel_option bisimJ2JVM) ξ ξ'" by blast
  moreover {
    fix cs'
    assume fin: "tfinite ξ'" and cs': "terminal ξ' = cs'" and final: "exec_mthr.mfinal cs'"
    from delay_bisimulation_final_base.τRuns_terminate_final2[OF divfin2, OF red exec tlsim fin cs' final]
    obtain s' where fin': "tfinite ξ" and s': "terminal ξ = s'"
      and final': "red_mthr.mfinal s'" by blast
    from tlsim fin s' cs' have bisim': "bisimJ2JVM s' cs'" by(auto dest: tllist_all2_tfinite2_terminalD)
    from red_mthr.mthr.τRuns_into_τrtrancl3p[OF red fin' s'] 
    have "thr s' start_tid  None" unfolding s
      by(rule red_mthr.τrtrancl3p_redT_thread_not_disappear)(simp add: start_state_def)
    with bisim' final final' have [simp]: "cs' = mexception s'"
      by(intro bisimJ2JVM_mfinal_mexception)
    with fin' s' bisim' have "s'. tfinite ξ  terminal ξ = s'  cs' = mexception s'  bisimJ2JVM s' cs'" by simp }
  moreover {
    fix cs'
    assume fin: "tfinite ξ'" and cs': "terminal ξ' = cs'" and dead': "execd_mthr.deadlock (J2JVM P) cs'"
    from tlsim fin cs'
    obtain s' where "tfinite ξ" and s': "terminal ξ = s'"
      and bisim': "bisimJ2JVM s' cs'"
      by(cases "terminal ξ")(fastforce dest: tllist_all2_tfinite2_terminalD tllist_all2_tfiniteD)+
    from bisim' obtain s0' s1' S1' where bisim0: "red_red0.mbisim s' s0'"
      and bisim01: "red0_Red1'.mbisim s0' s1'"
      and bisim11: "mbisim_Red1'_Red1 s1' S1'"
      and bisim12: "Red1_execd.mbisim S1' cs'"
      unfolding bisimJ2JVM_def by auto

    note b0 = red_red0_FWbisim[OF wf_prog_wwf_prog[OF wf]]
    note b0mthr = FWdelay_bisimulation_diverge.mbisim_delay_bisimulation[OF b0]
    note b01 = red0_Red1'_FWweak_bisim[OF wf]
    note b01mthr = FWdelay_bisimulation_diverge.mbisim_delay_bisimulation[OF b01]
    note b11 = Red1'_Red1_bisim_into_weak[OF compP1_pres_wf[OF wf]]
    note b11delay = bisimulation_into_delay.delay_bisimulation[OF b11]
    note b12 = Red1_exec1_FWwbisim[OF compP1_pres_wf[OF wf]]

    from FWdelay_bisimulation_diverge.deadlock2_imp_τs_deadlock1[OF b12 bisim12, of convert_RA] dead'
    obtain S1'' where "Red1_mthr.mthr.silent_moves True (compP1 P) S1' S1''"
      and bisim12': "Red1_execd.mbisim S1'' cs'"
      and dead': "Red1_mthr.deadlock True (compP1 P) S1''" by(auto simp add: J2JVM_def)
    from delay_bisimulation_diverge.simulation_silents2[OF b11delay, OF bisim11 Red1_mthr.mthr.silent_moves True (compP1 P) S1' S1'']
    obtain s1'' where "Red1_mthr.mthr.silent_moves False (compP1 P) s1' s1''"
      and bisim11': "mbisim_Red1'_Red1 s1'' S1''" by blast
    from bisim11' have "s1'' = S1''" by(simp add: mbisim_Red1'_Red1_def)
    with dead' have dead1: "Red1_mthr.deadlock False (compP1 P) s1''"
      by(simp add: Red1_Red1'_deadlock_inv)
    from delay_bisimulation_diverge.simulation_silents2[OF b01mthr, OF bisim01 Red1_mthr.mthr.silent_moves False (compP1 P) s1' s1'']
    obtain s0'' where "red0_mthr.mthr.silent_moves P s0' s0''"
      and bisim01': "red0_Red1'.mbisim s0'' s1''" by auto
    from FWdelay_bisimulation_diverge.deadlock2_imp_τs_deadlock1[OF b01 bisim01' dead1, of convert_RA]
    obtain s0''' where "red0_mthr.mthr.silent_moves P s0'' s0'''"
      and bisim01'': "red0_Red1'.mbisim s0''' s1''"
      and dead0: "red0_mthr.deadlock P s0'''" by auto
    from red0_mthr.mthr.silent_moves P s0' s0'' red0_mthr.mthr.silent_moves P s0'' s0'''
    have "red0_mthr.mthr.silent_moves P s0' s0'''" by(rule rtranclp_trans)
    from delay_bisimulation_diverge.simulation_silents2[OF b0mthr, OF bisim0 this]
    obtain s'' where "red_mthr.mthr.silent_moves P s' s''" 
      and "red_red0.mbisim s'' s0'''" by blast
    from FWdelay_bisimulation_diverge.deadlock2_imp_τs_deadlock1[OF b0 red_red0.mbisim s'' s0''' dead0, of convert_RA]
    obtain s''' where "red_mthr.mthr.silent_moves P s'' s'''" 
      and "red_red0.mbisim s''' s0'''"
      and dead: "red_mthr.deadlock P s'''" by blast
    from red_mthr.mthr.silent_moves P s' s'' red_mthr.mthr.silent_moves P s'' s'''
    have "red_mthr.mthr.silent_moves P s' s'''" by(rule rtranclp_trans)
    hence "s''' = s'" using red_mthr.mthr.τRuns_terminal_stuck[OF red tfinite ξ terminal ξ = s']
      by(cases rule: converse_rtranclpE) fastforce+
    with dead have "red_mthr.deadlock P s'" by(simp)
    hence "s'. tfinite ξ  terminal ξ = s'  red_mthr.deadlock P s'  bisimJ2JVM s' cs'"
      using tfinite ξ terminal ξ = s' bisim' by blast }
  moreover {
    assume "tfinite ξ'" and "terminal ξ' = None"
    hence "tfinite ξ  terminal ξ = None" using tlsim tllist_all2_tfiniteD[OF tlsim]
      by(cases "terminal ξ")(auto dest: tllist_all2_tfinite2_terminalD) }
  moreover {
    assume "¬ tfinite ξ'"
      hence "¬ tfinite ξ" using tlsim by(blast dest: tllist_all2_tfiniteD) }
  ultimately show thesis by(rule that)
qed

end

declare compP1_def [simp]

theorem wt_J2JVM: "wf_J_prog P  wf_jvm_prog (J2JVM P)"
unfolding J2JVM_def o_def
by(rule wt_compP2)(rule compP1_pres_wf)

end