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

(*  Title:      Termination.thy
    Author:     Norbert Schirmer, TU Muenchen

Copyright (C) 2004-2008 Norbert Schirmer
Some rights reserved, TU Muenchen

This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*)
section \<open>Terminating Programs\<close>

theory Termination imports Semantic begin

subsection \<open>Inductive Characterisation: \<open>\<Gamma>\<turnstile>c\<down>s\<close>\<close>

inductive "terminates"::"('s,'p,'f) body \<Rightarrow> ('s,'p,'f) com \<Rightarrow> ('s,'f) xstate \<Rightarrow> bool"
  ("_\<turnstile>_ \<down> _" [60,20,60] 89)
  for  \<Gamma>::"('s,'p,'f) body"
where
  Skip: "\<Gamma>\<turnstile>Skip \<down>(Normal s)"

| Basic: "\<Gamma>\<turnstile>Basic f \<down>(Normal s)"

| Spec: "\<Gamma>\<turnstile>Spec r \<down>(Normal s)"

| Guard: "\<lbrakk>s\<in>g; \<Gamma>\<turnstile>c\<down>(Normal s)\<rbrakk>
          \<Longrightarrow>
          \<Gamma>\<turnstile>Guard f g c\<down>(Normal s)"

| GuardFault: "s\<notin>g
               \<Longrightarrow>
               \<Gamma>\<turnstile>Guard f g c\<down>(Normal s)"

| Fault [intro,simp]: "\<Gamma>\<turnstile>c\<down>Fault f"

| Seq: "\<lbrakk>\<Gamma>\<turnstile>c\<^sub>1\<down>Normal s; \<forall>s'. \<Gamma>\<turnstile>\<langle>c\<^sub>1,Normal s\<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>c\<^sub>2\<down>s'\<rbrakk>
        \<Longrightarrow>
        \<Gamma>\<turnstile>Seq c\<^sub>1 c\<^sub>2\<down>(Normal s)"

| CondTrue: "\<lbrakk>s \<in> b; \<Gamma>\<turnstile>c\<^sub>1\<down>(Normal s)\<rbrakk>
             \<Longrightarrow>
             \<Gamma>\<turnstile>Cond b c\<^sub>1 c\<^sub>2\<down>(Normal s)"

| CondFalse: "\<lbrakk>s \<notin> b; \<Gamma>\<turnstile>c\<^sub>2\<down>(Normal s)\<rbrakk>
             \<Longrightarrow>
             \<Gamma>\<turnstile>Cond b c\<^sub>1 c\<^sub>2\<down>(Normal s)"

| WhileTrue: "\<lbrakk>s \<in> b; \<Gamma>\<turnstile>c\<down>(Normal s);
               \<forall>s'. \<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>While b c\<down>s'\<rbrakk>
              \<Longrightarrow>
              \<Gamma>\<turnstile>While b c\<down>(Normal s)"

| WhileFalse: "\<lbrakk>s \<notin> b\<rbrakk>
               \<Longrightarrow>
               \<Gamma>\<turnstile>While b c\<down>(Normal s)"

| Call:  "\<lbrakk>\<Gamma> p=Some bdy;\<Gamma>\<turnstile>bdy\<down>(Normal s)\<rbrakk>
          \<Longrightarrow>
          \<Gamma>\<turnstile>Call p\<down>(Normal s)"

| CallUndefined:  "\<lbrakk>\<Gamma> p = None\<rbrakk>
                   \<Longrightarrow>
                   \<Gamma>\<turnstile>Call p\<down>(Normal s)"

| Stuck [intro,simp]: "\<Gamma>\<turnstile>c\<down>Stuck"

| DynCom:  "\<lbrakk>\<Gamma>\<turnstile>(c s)\<down>(Normal s)\<rbrakk>
             \<Longrightarrow>
             \<Gamma>\<turnstile>DynCom c\<down>(Normal s)"

| Throw: "\<Gamma>\<turnstile>Throw\<down>(Normal s)"

| Abrupt [intro,simp]: "\<Gamma>\<turnstile>c\<down>Abrupt s"

| Catch: "\<lbrakk>\<Gamma>\<turnstile>c\<^sub>1\<down>Normal s;
           \<forall>s'. \<Gamma>\<turnstile>\<langle>c\<^sub>1,Normal s \<rangle> \<Rightarrow> Abrupt s' \<longrightarrow> \<Gamma>\<turnstile>c\<^sub>2\<down>Normal s'\<rbrakk>
          \<Longrightarrow>
          \<Gamma>\<turnstile>Catch c\<^sub>1 c\<^sub>2\<down>Normal s"

inductive_cases terminates_elim_cases [cases set]:
  "\<Gamma>\<turnstile>Skip \<down> s"
  "\<Gamma>\<turnstile>Guard f g c \<down> s"
  "\<Gamma>\<turnstile>Basic f \<down> s"
  "\<Gamma>\<turnstile>Spec r \<down> s"
  "\<Gamma>\<turnstile>Seq c1 c2 \<down> s"
  "\<Gamma>\<turnstile>Cond b c1 c2 \<down> s"
  "\<Gamma>\<turnstile>While b c \<down> s"
  "\<Gamma>\<turnstile>Call p \<down> s"
  "\<Gamma>\<turnstile>DynCom c \<down> s"
  "\<Gamma>\<turnstile>Throw \<down> s"
  "\<Gamma>\<turnstile>Catch c1 c2 \<down> s"

inductive_cases terminates_Normal_elim_cases [cases set]:
  "\<Gamma>\<turnstile>Skip \<down> Normal s"
  "\<Gamma>\<turnstile>Guard f g c \<down> Normal s"
  "\<Gamma>\<turnstile>Basic f \<down> Normal s"
  "\<Gamma>\<turnstile>Spec r \<down> Normal s"
  "\<Gamma>\<turnstile>Seq c1 c2 \<down> Normal s"
  "\<Gamma>\<turnstile>Cond b c1 c2 \<down> Normal s"
  "\<Gamma>\<turnstile>While b c \<down> Normal s"
  "\<Gamma>\<turnstile>Call p \<down> Normal s"
  "\<Gamma>\<turnstile>DynCom c \<down> Normal s"
  "\<Gamma>\<turnstile>Throw \<down> Normal s"
  "\<Gamma>\<turnstile>Catch c1 c2 \<down> Normal s"

lemma terminates_Skip': "\<Gamma>\<turnstile>Skip \<down> s"
  by (cases s) (auto intro: terminates.intros)

lemma terminates_Call_body:
 "\<Gamma> p=Some bdy\<Longrightarrow>\<Gamma>\<turnstile>Call  p \<down>s = \<Gamma>\<turnstile>(the (\<Gamma> p))\<down>s"
  by (cases s)
     (auto elim: terminates_Normal_elim_cases intro: terminates.intros)

lemma terminates_Normal_Call_body:
 "p \<in> dom \<Gamma> \<Longrightarrow>
  \<Gamma>\<turnstile>Call p \<down>Normal s = \<Gamma>\<turnstile>(the (\<Gamma> p))\<down>Normal s"
  by (auto elim: terminates_Normal_elim_cases intro: terminates.intros)

lemma terminates_implies_exec:
  assumes terminates: "\<Gamma>\<turnstile>c\<down>s"
  shows "\<exists>t. \<Gamma>\<turnstile>\<langle>c,s\<rangle> \<Rightarrow> t"
using terminates
proof (induct)
  case Skip thus ?case by (iprover intro: exec.intros)
next
  case Basic thus ?case by (iprover intro: exec.intros)
next
  case (Spec r s) thus ?case
    by (cases "\<exists>t. (s,t)\<in> r") (auto intro: exec.intros)
next
  case Guard thus ?case by (iprover intro: exec.intros)
next
  case GuardFault thus ?case by (iprover intro: exec.intros)
next
  case Fault thus ?case by (iprover intro: exec.intros)
next
  case Seq thus ?case by (iprover intro: exec_Seq')
next
  case CondTrue thus ?case by (iprover intro: exec.intros)
next
  case CondFalse thus ?case by (iprover intro: exec.intros)
next
  case WhileTrue thus ?case by (iprover intro: exec.intros)
next
  case WhileFalse thus ?case by (iprover intro: exec.intros)
next
  case (Call p bdy s)
  then obtain s' where
    "\<Gamma>\<turnstile>\<langle>bdy,Normal s \<rangle> \<Rightarrow> s'"
    by iprover
  moreover have "\<Gamma> p = Some bdy" by fact
  ultimately show ?case
    by (cases s') (iprover intro: exec.intros)+
next
  case CallUndefined thus ?case by (iprover intro: exec.intros)
next
  case Stuck thus ?case by (iprover intro: exec.intros)
next
  case DynCom thus ?case by (iprover intro: exec.intros)
next
  case Throw thus ?case by (iprover intro: exec.intros)
next
  case Abrupt thus ?case by (iprover intro: exec.intros)
next
  case (Catch c1 s c2)
  then obtain s' where exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
    by iprover
  thus ?case
  proof (cases s')
    case (Normal s'')
    with exec_c1 show ?thesis by (auto intro!: exec.intros)
  next
    case (Abrupt s'')
    with exec_c1 Catch.hyps
    obtain t where "\<Gamma>\<turnstile>\<langle>c2,Normal s'' \<rangle> \<Rightarrow> t"
      by auto
    with exec_c1 Abrupt show ?thesis by (auto intro: exec.intros)
  next
    case Fault
    with exec_c1 show ?thesis by (auto intro!: exec.CatchMiss)
  next
    case Stuck
    with exec_c1 show ?thesis by (auto intro!: exec.CatchMiss)
  qed
qed

lemma terminates_block:
"\<lbrakk>\<Gamma>\<turnstile>bdy \<down> Normal (init s);
  \<forall>t. \<Gamma>\<turnstile>\<langle>bdy,Normal (init s)\<rangle> \<Rightarrow> Normal t \<longrightarrow> \<Gamma>\<turnstile>c s t \<down> Normal (return s t)\<rbrakk>
 \<Longrightarrow> \<Gamma>\<turnstile>block init bdy return c \<down> Normal s"
apply (unfold block_def)
apply (fastforce intro: terminates.intros elim!: exec_Normal_elim_cases
        dest!: not_isAbrD)
done

lemma terminates_block_elim [cases set, consumes 1]:
assumes termi: "\<Gamma>\<turnstile>block init bdy return c \<down> Normal s"
assumes e: "\<lbrakk>\<Gamma>\<turnstile>bdy \<down> Normal (init s);
          \<forall>t. \<Gamma>\<turnstile>\<langle>bdy,Normal (init s)\<rangle> \<Rightarrow> Normal t \<longrightarrow> \<Gamma>\<turnstile>c s t \<down> Normal (return s t)
         \<rbrakk> \<Longrightarrow> P"
shows P
proof -
  have "\<Gamma>\<turnstile>\<langle>Basic init,Normal s\<rangle> \<Rightarrow> Normal (init s)"
    by (auto intro: exec.intros)
  with termi
  have "\<Gamma>\<turnstile>bdy \<down> Normal (init s)"
    apply (unfold block_def)
    apply (elim terminates_Normal_elim_cases)
    by simp
  moreover
  {
    fix t
    assume exec_bdy: "\<Gamma>\<turnstile>\<langle>bdy,Normal (init s)\<rangle> \<Rightarrow> Normal t"
    have "\<Gamma>\<turnstile>c s t \<down> Normal (return s t)"
    proof -
      from exec_bdy
      have "\<Gamma>\<turnstile>\<langle>Catch (Seq (Basic init) bdy)
                               (Seq (Basic (return s)) Throw),Normal s\<rangle> \<Rightarrow> Normal t"
        by (fastforce intro: exec.intros)
      with termi have "\<Gamma>\<turnstile>DynCom (\<lambda>t. Seq (Basic (return s)) (c s t)) \<down> Normal t"
        apply (unfold block_def)
        apply (elim terminates_Normal_elim_cases)
        by simp
      thus ?thesis
        apply (elim terminates_Normal_elim_cases)
        apply (auto intro: exec.intros)
        done
    qed
  }
  ultimately show P by (iprover intro: e)
qed

lemma terminates_call:
"\<lbrakk>\<Gamma> p = Some bdy; \<Gamma>\<turnstile>bdy \<down> Normal (init s);
  \<forall>t. \<Gamma>\<turnstile>\<langle>bdy,Normal (init s)\<rangle> \<Rightarrow> Normal t \<longrightarrow> \<Gamma>\<turnstile>c s t \<down> Normal (return s t)\<rbrakk>
 \<Longrightarrow> \<Gamma>\<turnstile>call init p return c \<down> Normal s"
  apply (unfold call_def)
  apply (rule terminates_block)
  apply  (iprover intro: terminates.intros)
  apply (auto elim: exec_Normal_elim_cases)
  done

lemma terminates_callUndefined:
"\<lbrakk>\<Gamma> p = None\<rbrakk>
 \<Longrightarrow> \<Gamma>\<turnstile>call init p return result \<down> Normal s"
  apply (unfold call_def)
  apply (rule terminates_block)
  apply  (iprover intro: terminates.intros)
  apply (auto elim: exec_Normal_elim_cases)
  done

lemma terminates_call_elim [cases set, consumes 1]:
assumes termi: "\<Gamma>\<turnstile>call init p return c \<down> Normal s"
assumes bdy: "\<And>bdy. \<lbrakk>\<Gamma> p = Some bdy; \<Gamma>\<turnstile>bdy \<down> Normal (init s);
     \<forall>t. \<Gamma>\<turnstile>\<langle>bdy,Normal (init s)\<rangle> \<Rightarrow> Normal t \<longrightarrow> \<Gamma>\<turnstile>c s t \<down> Normal (return s t)\<rbrakk> \<Longrightarrow> P"
assumes undef: "\<lbrakk>\<Gamma> p = None\<rbrakk> \<Longrightarrow> P"
shows P
apply (cases "\<Gamma> p")
apply  (erule undef)
using termi
apply (unfold call_def)
apply (erule terminates_block_elim)
apply (erule terminates_Normal_elim_cases)
apply  simp
apply  (frule (1) bdy)
apply   (fastforce intro: exec.intros)
apply  assumption
apply simp
done

lemma terminates_dynCall:
"\<lbrakk>\<Gamma>\<turnstile>call init (p s) return c \<down> Normal s\<rbrakk>
 \<Longrightarrow> \<Gamma>\<turnstile>dynCall init p return c \<down> Normal s"
  apply (unfold dynCall_def)
  apply (auto intro: terminates.intros terminates_call)
  done

lemma terminates_dynCall_elim [cases set, consumes 1]:
assumes termi: "\<Gamma>\<turnstile>dynCall init p return c \<down> Normal s"
assumes "\<lbrakk>\<Gamma>\<turnstile>call init (p s) return c \<down> Normal s\<rbrakk> \<Longrightarrow> P"
shows P
using termi
apply (unfold dynCall_def)
apply (elim terminates_Normal_elim_cases)
apply fact
done

(* ************************************************************************* *)
subsection \<open>Lemmas about @{const "sequence"}, @{const "flatten"} and
 @{const "normalize"}\<close>
(* ************************************************************************ *)

lemma terminates_sequence_app:
  "\<And>s. \<lbrakk>\<Gamma>\<turnstile>sequence Seq xs \<down> Normal s;
        \<forall>s'. \<Gamma>\<turnstile>\<langle>sequence Seq xs,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>  \<Gamma>\<turnstile>sequence Seq ys \<down> s'\<rbrakk>
\<Longrightarrow> \<Gamma>\<turnstile>sequence Seq (xs @ ys) \<down> Normal s"
proof (induct xs)
  case Nil
  thus ?case by (auto intro: exec.intros)
next
  case (Cons x xs)
  have termi_x_xs: "\<Gamma>\<turnstile>sequence Seq (x # xs) \<down> Normal s" by fact
  have termi_ys: "\<forall>s'. \<Gamma>\<turnstile>\<langle>sequence Seq (x # xs),Normal s \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>sequence Seq ys \<down> s'" by fact
  show ?case
  proof (cases xs)
    case Nil
    with termi_x_xs termi_ys show ?thesis
      by (cases ys) (auto intro: terminates.intros)
  next
    case Cons
    from termi_x_xs Cons
    have "\<Gamma>\<turnstile>x \<down> Normal s"
      by (auto elim: terminates_Normal_elim_cases)
    moreover
    {
      fix s'
      assume exec_x: "\<Gamma>\<turnstile>\<langle>x,Normal s \<rangle> \<Rightarrow> s'"
      have "\<Gamma>\<turnstile>sequence Seq (xs @ ys) \<down> s'"
      proof -
        from exec_x termi_x_xs Cons
        have termi_xs: "\<Gamma>\<turnstile>sequence Seq xs \<down> s'"
          by (auto elim: terminates_Normal_elim_cases)
        show ?thesis
        proof (cases s')
          case (Normal s'')
          with exec_x termi_ys Cons
          have "\<forall>s'. \<Gamma>\<turnstile>\<langle>sequence Seq xs,Normal s'' \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>sequence Seq ys \<down> s'"
            by (auto intro: exec.intros)
          from Cons.hyps [OF termi_xs [simplified Normal] this]
          have "\<Gamma>\<turnstile>sequence Seq (xs @ ys) \<down> Normal s''".
          with Normal show ?thesis by simp
        next
          case Abrupt thus ?thesis by (auto intro: terminates.intros)
        next
          case Fault thus ?thesis by (auto intro: terminates.intros)
        next
          case Stuck thus ?thesis by (auto intro: terminates.intros)
        qed
      qed
    }
    ultimately show ?thesis
      using Cons
      by (auto intro: terminates.intros)
  qed
qed

lemma terminates_sequence_appD:
  "\<And>s. \<Gamma>\<turnstile>sequence Seq (xs @ ys) \<down> Normal s
   \<Longrightarrow> \<Gamma>\<turnstile>sequence Seq xs \<down> Normal s \<and>
       (\<forall>s'. \<Gamma>\<turnstile>\<langle>sequence Seq xs,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>  \<Gamma>\<turnstile>sequence Seq ys \<down> s')"
proof (induct xs)
  case Nil
  thus ?case
    by (auto elim: terminates_Normal_elim_cases exec_Normal_elim_cases
         intro: terminates.intros)
next
  case (Cons x xs)
  have termi_x_xs_ys: "\<Gamma>\<turnstile>sequence Seq ((x # xs) @ ys) \<down> Normal s" by fact
  show ?case
  proof (cases xs)
    case Nil
    with termi_x_xs_ys show ?thesis
      by (cases ys)
         (auto elim: terminates_Normal_elim_cases exec_Normal_elim_cases
           intro:  terminates_Skip')
  next
    case Cons
    with termi_x_xs_ys
    obtain termi_x: "\<Gamma>\<turnstile>x \<down> Normal s" and
           termi_xs_ys: "\<forall>s'. \<Gamma>\<turnstile>\<langle>x,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>  \<Gamma>\<turnstile>sequence Seq (xs@ys) \<down> s'"
      by (auto elim: terminates_Normal_elim_cases)

    have "\<Gamma>\<turnstile>Seq x (sequence Seq xs) \<down> Normal s"
    proof (rule terminates.Seq [rule_format])
      show "\<Gamma>\<turnstile>x \<down> Normal s" by (rule termi_x)
    next
      fix s'
      assume exec_x: "\<Gamma>\<turnstile>\<langle>x,Normal s \<rangle> \<Rightarrow> s'"
      show "\<Gamma>\<turnstile>sequence Seq xs \<down> s'"
      proof -
        from termi_xs_ys [rule_format, OF exec_x]
        have termi_xs_ys': "\<Gamma>\<turnstile>sequence Seq (xs@ys) \<down> s'" .
        show ?thesis
        proof (cases s')
          case (Normal s'')
          from Cons.hyps [OF termi_xs_ys' [simplified Normal]]
          show ?thesis
            using Normal by auto
        next
          case Abrupt thus ?thesis by (auto intro: terminates.intros)
        next
          case Fault thus ?thesis by (auto intro: terminates.intros)
        next
          case Stuck thus ?thesis by (auto intro: terminates.intros)
        qed
      qed
    qed
    moreover
    {
      fix s'
      assume exec_x_xs: "\<Gamma>\<turnstile>\<langle>Seq x (sequence Seq xs),Normal s \<rangle> \<Rightarrow> s'"
      have "\<Gamma>\<turnstile>sequence Seq ys \<down> s'"
      proof -
        from exec_x_xs obtain t where
          exec_x: "\<Gamma>\<turnstile>\<langle>x,Normal s \<rangle> \<Rightarrow> t" and
          exec_xs: "\<Gamma>\<turnstile>\<langle>sequence Seq xs,t \<rangle> \<Rightarrow> s'"
          by cases
        show ?thesis
        proof (cases t)
          case (Normal t')
          with exec_x termi_xs_ys have "\<Gamma>\<turnstile>sequence Seq (xs@ys) \<down> Normal t'"
            by auto
          from Cons.hyps [OF this] exec_xs Normal
          show ?thesis
            by auto
        next
          case (Abrupt t')
          with exec_xs have "s'=Abrupt t'"
            by (auto dest: Abrupt_end)
          thus ?thesis by (auto intro: terminates.intros)
        next
          case (Fault f)
          with exec_xs have "s'=Fault f"
            by (auto dest: Fault_end)
          thus ?thesis by (auto intro: terminates.intros)
        next
          case Stuck
          with exec_xs have "s'=Stuck"
            by (auto dest: Stuck_end)
          thus ?thesis by (auto intro: terminates.intros)
        qed
      qed
    }
    ultimately show ?thesis
      using Cons
      by auto
  qed
qed

lemma terminates_sequence_appE [consumes 1]:
  "\<lbrakk>\<Gamma>\<turnstile>sequence Seq (xs @ ys) \<down> Normal s;
    \<lbrakk>\<Gamma>\<turnstile>sequence Seq xs \<down> Normal s;
     \<forall>s'. \<Gamma>\<turnstile>\<langle>sequence Seq xs,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>  \<Gamma>\<turnstile>sequence Seq ys \<down> s'\<rbrakk> \<Longrightarrow> P\<rbrakk>
   \<Longrightarrow> P"
  by (auto dest: terminates_sequence_appD)

lemma terminates_to_terminates_sequence_flatten:
  assumes termi: "\<Gamma>\<turnstile>c\<down>s"
  shows "\<Gamma>\<turnstile>sequence Seq (flatten c)\<down>s"
using termi
by (induct)
   (auto intro: terminates.intros terminates_sequence_app
     exec_sequence_flatten_to_exec)

lemma terminates_to_terminates_normalize:
  assumes termi: "\<Gamma>\<turnstile>c\<down>s"
  shows "\<Gamma>\<turnstile>normalize c\<down>s"
using termi
proof induct
  case Seq
  thus ?case
    by (fastforce intro: terminates.intros terminates_sequence_app
                 terminates_to_terminates_sequence_flatten
        dest: exec_sequence_flatten_to_exec exec_normalize_to_exec)
next
  case WhileTrue
  thus ?case
    by (fastforce intro: terminates.intros terminates_sequence_app
                 terminates_to_terminates_sequence_flatten
        dest: exec_sequence_flatten_to_exec exec_normalize_to_exec)
next
  case Catch
  thus ?case
    by (fastforce intro: terminates.intros terminates_sequence_app
                 terminates_to_terminates_sequence_flatten
        dest: exec_sequence_flatten_to_exec exec_normalize_to_exec)
qed (auto intro: terminates.intros)

lemma terminates_sequence_flatten_to_terminates:
  shows "\<And>s. \<Gamma>\<turnstile>sequence Seq (flatten c)\<down>s \<Longrightarrow> \<Gamma>\<turnstile>c\<down>s"
proof (induct c)
  case (Seq c1 c2)
  have "\<Gamma>\<turnstile>sequence Seq (flatten (Seq c1 c2)) \<down> s" by fact
  hence termi_app: "\<Gamma>\<turnstile>sequence Seq (flatten c1 @ flatten c2) \<down> s" by simp
  show ?case
  proof (cases s)
    case (Normal s')
    have "\<Gamma>\<turnstile>Seq c1 c2 \<down> Normal s'"
    proof (rule terminates.Seq [rule_format])
      from termi_app [simplified Normal]
      have "\<Gamma>\<turnstile>sequence Seq (flatten c1) \<down> Normal s'"
        by (cases rule: terminates_sequence_appE)
      with Seq.hyps
      show "\<Gamma>\<turnstile>c1 \<down> Normal s'"
        by simp
    next
      fix s''
      assume "\<Gamma>\<turnstile>\<langle>c1,Normal s' \<rangle> \<Rightarrow> s''"
      from termi_app [simplified Normal] exec_to_exec_sequence_flatten [OF this]
      have "\<Gamma>\<turnstile>sequence Seq (flatten c2) \<down> s''"
        by (cases rule: terminates_sequence_appE) auto
      with Seq.hyps
      show "\<Gamma>\<turnstile>c2 \<down> s''"
        by simp
    qed
    with Normal show ?thesis
      by simp
  qed (auto intro: terminates.intros)
qed (auto intro: terminates.intros)

lemma terminates_normalize_to_terminates:
  shows "\<And>s. \<Gamma>\<turnstile>normalize c\<down>s \<Longrightarrow> \<Gamma>\<turnstile>c\<down>s"
proof (induct c)
  case Skip thus ?case by (auto intro:  terminates_Skip')
next
  case Basic thus ?case by (cases s) (auto intro: terminates.intros)
next
  case Spec thus ?case by (cases s) (auto intro: terminates.intros)
next
  case (Seq c1 c2)
  have "\<Gamma>\<turnstile>normalize (Seq c1 c2) \<down> s" by fact
  hence termi_app: "\<Gamma>\<turnstile>sequence Seq (flatten (normalize c1) @ flatten (normalize c2)) \<down> s"
    by simp
  show ?case
  proof (cases s)
    case (Normal s')
    have "\<Gamma>\<turnstile>Seq c1 c2 \<down> Normal s'"
    proof (rule terminates.Seq [rule_format])
      from termi_app [simplified Normal]
      have "\<Gamma>\<turnstile>sequence Seq (flatten (normalize c1))  \<down> Normal s'"
        by (cases rule: terminates_sequence_appE)
      from terminates_sequence_flatten_to_terminates [OF this] Seq.hyps
      show "\<Gamma>\<turnstile>c1 \<down> Normal s'"
        by simp
    next
      fix s''
      assume "\<Gamma>\<turnstile>\<langle>c1,Normal s' \<rangle> \<Rightarrow> s''"
      from exec_to_exec_normalize [OF this]
      have "\<Gamma>\<turnstile>\<langle>normalize c1,Normal s' \<rangle> \<Rightarrow> s''" .
      from termi_app [simplified Normal] exec_to_exec_sequence_flatten [OF this]
      have "\<Gamma>\<turnstile>sequence Seq (flatten (normalize c2))  \<down> s''"
        by (cases rule: terminates_sequence_appE) auto
      from terminates_sequence_flatten_to_terminates [OF this] Seq.hyps
      show "\<Gamma>\<turnstile>c2 \<down> s''"
        by simp
    qed
    with Normal show ?thesis by simp
  qed (auto intro: terminates.intros)
next
  case (Cond b c1 c2)
  thus ?case
    by (cases s)
       (auto intro: terminates.intros elim!: terminates_Normal_elim_cases)
next
  case (While b c)
  have "\<Gamma>\<turnstile>normalize (While b c) \<down> s" by fact
  hence termi_norm_w: "\<Gamma>\<turnstile>While b (normalize c) \<down> s" by simp
  {
    fix t w
    assume termi_w: "\<Gamma>\<turnstile> w \<down> t"
    have "w=While b (normalize c) \<Longrightarrow> \<Gamma>\<turnstile>While b c \<down> t"
      using termi_w
    proof (induct)
      case (WhileTrue t' b' c')
      from WhileTrue obtain
        t'_b: "t' \<in> b" and
        termi_norm_c: "\<Gamma>\<turnstile>normalize c \<down> Normal t'" and
        termi_norm_w': "\<forall>s'. \<Gamma>\<turnstile>\<langle>normalize c,Normal t' \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> s'"
        by auto
      from While.hyps [OF termi_norm_c]
      have "\<Gamma>\<turnstile>c \<down> Normal t'".
      moreover
      from termi_norm_w'
      have "\<forall>s'. \<Gamma>\<turnstile>\<langle>c,Normal t' \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> s'"
        by (auto intro: exec_to_exec_normalize)
      ultimately show ?case
        using t'_b
        by (auto intro: terminates.intros)
    qed (auto intro: terminates.intros)
  }
  from this [OF termi_norm_w]
  show ?case
    by auto
next
  case Call thus ?case by simp
next
  case DynCom thus ?case
    by (cases s) (auto intro: terminates.intros rangeI elim: terminates_Normal_elim_cases)
next
  case Guard thus ?case
    by (cases s) (auto intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case Throw thus ?case by (cases s) (auto intro: terminates.intros)
next
  case Catch
  thus ?case
    by (cases s)
       (auto dest: exec_to_exec_normalize elim!: terminates_Normal_elim_cases
         intro!: terminates.Catch)
qed

lemma terminates_iff_terminates_normalize:
"\<Gamma>\<turnstile>normalize c\<down>s = \<Gamma>\<turnstile>c\<down>s"
  by (auto intro: terminates_to_terminates_normalize
    terminates_normalize_to_terminates)

(* ************************************************************************* *)
subsection \<open>Lemmas about @{const "strip_guards"}\<close>
(* ************************************************************************* *)

lemma terminates_strip_guards_to_terminates: "\<And>s. \<Gamma>\<turnstile>strip_guards F c\<down>s  \<Longrightarrow> \<Gamma>\<turnstile>c\<down>s"
proof (induct c)
  case Skip thus ?case by simp
next
  case Basic thus ?case by simp
next
  case Spec thus ?case by simp
next
  case (Seq c1 c2)
  hence "\<Gamma>\<turnstile>Seq (strip_guards F c1) (strip_guards F c2) \<down> s" by simp
  thus "\<Gamma>\<turnstile>Seq c1 c2 \<down> s"
  proof (cases)
    fix f assume "s=Fault f" thus ?thesis by simp
  next
    assume "s=Stuck" thus ?thesis by simp
  next
    fix s' assume "s=Abrupt s'" thus ?thesis by simp
  next
    fix s'
    assume s: "s=Normal s'"
    assume "\<Gamma>\<turnstile>strip_guards F c1 \<down> Normal s'"
    hence "\<Gamma>\<turnstile>c1 \<down> Normal s'"
      by (rule Seq.hyps)
    moreover
    assume c2:
      "\<forall>s''. \<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s'\<rangle> \<Rightarrow> s'' \<longrightarrow> \<Gamma>\<turnstile>strip_guards F c2\<down>s''"
    {
      fix s'' assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s' \<rangle> \<Rightarrow> s''"
      have " \<Gamma>\<turnstile>c2 \<down> s''"
      proof (cases s'')
        case (Normal s''')
        with exec_c1
        have "\<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s' \<rangle> \<Rightarrow> s''"
          by (auto intro: exec_to_exec_strip_guards)
        with c2
        show ?thesis
          by (iprover intro: Seq.hyps)
      next
        case (Abrupt s''')
        with exec_c1
        have "\<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s' \<rangle> \<Rightarrow> s''"
          by (auto intro: exec_to_exec_strip_guards )
        with c2
        show ?thesis
          by (iprover intro: Seq.hyps)
      next
        case Fault thus ?thesis by simp
      next
        case Stuck thus ?thesis by simp
      qed
    }
    ultimately show ?thesis
      using s
      by (iprover intro: terminates.intros)
  qed
next
  case (Cond b c1 c2)
  hence "\<Gamma>\<turnstile>Cond b (strip_guards F c1) (strip_guards F c2) \<down> s" by simp
  thus "\<Gamma>\<turnstile>Cond b c1 c2 \<down> s"
  proof (cases)
    fix f assume "s=Fault f" thus ?thesis by simp
  next
    assume "s=Stuck" thus ?thesis by simp
  next
    fix s' assume "s=Abrupt s'" thus ?thesis by simp
  next
    fix s'
    assume "s'\<in>b" "\<Gamma>\<turnstile>strip_guards F c1 \<down> Normal s'" "s = Normal s'"
    thus ?thesis
      by (iprover intro: terminates.intros Cond.hyps)
  next
    fix s'
    assume "s'\<notin>b" "\<Gamma>\<turnstile>strip_guards F c2 \<down> Normal s'" "s = Normal s'"
    thus ?thesis
      by (iprover intro: terminates.intros Cond.hyps)
  qed
next
  case (While b c)
  have hyp_c: "\<And>s. \<Gamma>\<turnstile>strip_guards F c \<down> s \<Longrightarrow> \<Gamma>\<turnstile>c \<down> s" by fact
  have "\<Gamma>\<turnstile>While b (strip_guards F c) \<down> s" using While.prems by simp
  moreover
  {
    fix sw
    assume "\<Gamma>\<turnstile>sw\<down>s"
    then have "sw=While b (strip_guards F c) \<Longrightarrow>
      \<Gamma>\<turnstile>While b c \<down> s"
    proof (induct)
      case (WhileTrue s b' c')
      have eqs: "While b' c' = While b (strip_guards F c)" by fact
      with \<open>s\<in>b'\<close> have b: "s\<in>b" by simp
      from eqs \<open>\<Gamma>\<turnstile>c' \<down> Normal s\<close> have "\<Gamma>\<turnstile>strip_guards F c \<down> Normal s"
        by simp
      hence term_c: "\<Gamma>\<turnstile>c \<down> Normal s"
        by (rule hyp_c)
      moreover
      {
        fix t
        assume exec_c: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> t"
        have "\<Gamma>\<turnstile>While b c \<down> t"
        proof (cases t)
          case Fault
          thus ?thesis by simp
        next
          case Stuck
          thus ?thesis by simp
        next
          case (Abrupt t')
          thus ?thesis by simp
        next
          case (Normal t')
          with exec_c
          have "\<Gamma>\<turnstile>\<langle>strip_guards F c,Normal s \<rangle> \<Rightarrow> Normal t'"
            by (auto intro: exec_to_exec_strip_guards)
          with WhileTrue.hyps eqs Normal
          show ?thesis
            by fastforce
        qed
      }
      ultimately
      show ?case
        using b
        by (auto intro: terminates.intros)
    next
      case WhileFalse thus ?case by (auto intro: terminates.intros)
    qed simp_all
  }
  ultimately show "\<Gamma>\<turnstile>While b c \<down> s"
    by auto
next
  case Call thus ?case by simp
next
  case DynCom thus ?case
     by (cases s) (auto elim: terminates_Normal_elim_cases intro: terminates.intros rangeI)
next
  case Guard
  thus ?case
    by (cases s) (auto elim: terminates_Normal_elim_cases intro: terminates.intros
                  split: if_split_asm)
next
  case Throw thus ?case by simp
next
  case (Catch c1 c2)
  hence "\<Gamma>\<turnstile>Catch (strip_guards F c1) (strip_guards F c2) \<down> s" by simp
  thus "\<Gamma>\<turnstile>Catch c1 c2 \<down> s"
  proof (cases)
    fix f assume "s=Fault f" thus ?thesis by simp
  next
    assume "s=Stuck" thus ?thesis by simp
  next
    fix s' assume "s=Abrupt s'" thus ?thesis by simp
  next
    fix s'
    assume s: "s=Normal s'"
    assume "\<Gamma>\<turnstile>strip_guards F c1 \<down> Normal s'"
    hence "\<Gamma>\<turnstile>c1 \<down> Normal s'"
      by (rule Catch.hyps)
    moreover
    assume c2:
      "\<forall>s''. \<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s'\<rangle> \<Rightarrow> Abrupt s''
             \<longrightarrow> \<Gamma>\<turnstile>strip_guards F c2\<down>Normal s''"
    {
      fix s'' assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s' \<rangle> \<Rightarrow> Abrupt s''"
      have " \<Gamma>\<turnstile>c2 \<down> Normal s''"
      proof -
        from exec_c1
        have "\<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s' \<rangle> \<Rightarrow> Abrupt s''"
          by (auto intro: exec_to_exec_strip_guards)
        with c2
        show ?thesis
          by (auto intro: Catch.hyps)
      qed
    }
    ultimately show ?thesis
      using s
      by (iprover intro: terminates.intros)
  qed
qed

lemma terminates_strip_to_terminates:
  assumes termi_strip: "strip F \<Gamma>\<turnstile>c\<down>s"
  shows "\<Gamma>\<turnstile>c\<down>s"
using termi_strip
proof induct
  case (Seq c1 s c2)
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by fact
  moreover
  {
    fix s'
    assume exec: "\<Gamma>\<turnstile> \<langle>c1,Normal s\<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile>c2 \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis
        by (auto elim: isFaultE)
    next
      case False
      from exec_to_exec_strip [OF exec this] Seq.hyps
      show ?thesis
        by auto
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case (WhileTrue s b c)
  have "\<Gamma>\<turnstile>c \<down> Normal s" by fact
  moreover
  {
    fix s'
    assume exec: "\<Gamma>\<turnstile> \<langle>c,Normal s\<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile>While b c \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis
        by (auto elim: isFaultE)
    next
      case False
      from exec_to_exec_strip [OF exec this] WhileTrue.hyps
      show ?thesis
        by auto
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case (Catch c1 s c2)
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by fact
  moreover
  {
    fix s'
    assume exec: "\<Gamma>\<turnstile> \<langle>c1,Normal s\<rangle> \<Rightarrow> Abrupt s'"
    from exec_to_exec_strip [OF exec] Catch.hyps
    have "\<Gamma>\<turnstile>c2 \<down> Normal s'"
      by auto
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case Call thus ?case
    by (auto intro: terminates.intros terminates_strip_guards_to_terminates)
qed (auto intro: terminates.intros)

(* ************************************************************************* *)
subsection \<open>Lemmas about @{term "c\<^sub>1 \<inter>\<^sub>g c\<^sub>2"}\<close>
(* ************************************************************************* *)

lemma inter_guards_terminates:
  "\<And>c c2 s. \<lbrakk>(c1 \<inter>\<^sub>g c2) = Some c; \<Gamma>\<turnstile>c1\<down>s \<rbrakk>
        \<Longrightarrow> \<Gamma>\<turnstile>c\<down>s"
proof (induct c1)
  case Skip thus ?case by (fastforce simp add: inter_guards_Skip)
next
  case (Basic f) thus ?case by (fastforce simp add: inter_guards_Basic)
next
  case (Spec r) thus ?case by (fastforce simp add: inter_guards_Spec)
next
  case (Seq a1 a2)
  have "(Seq a1 a2 \<inter>\<^sub>g c2) = Some c" by fact
  then obtain b1 b2 d1 d2 where
    c2: "c2=Seq b1 b2" and
    d1: "(a1 \<inter>\<^sub>g b1) = Some d1" and d2: "(a2 \<inter>\<^sub>g b2) = Some d2" and
    c: "c=Seq d1 d2"
    by (auto simp add: inter_guards_Seq)
  have termi_c1: "\<Gamma>\<turnstile>Seq a1 a2 \<down> s" by fact
  have "\<Gamma>\<turnstile>Seq d1 d2 \<down> s"
  proof (cases s)
    case Fault thus ?thesis by simp
  next
    case Stuck thus ?thesis by simp
  next
    case Abrupt thus ?thesis by simp
  next
    case (Normal s')
    note Normal_s = this
    with d1 termi_c1
    have "\<Gamma>\<turnstile>d1 \<down> Normal s'"
      by (auto elim: terminates_Normal_elim_cases intro: Seq.hyps)
    moreover
    {
      fix t
      assume exec_d1: "\<Gamma>\<turnstile>\<langle>d1,Normal s' \<rangle> \<Rightarrow> t"
      have "\<Gamma>\<turnstile>d2 \<down> t"
      proof (cases t)
        case Fault thus ?thesis by simp
      next
        case Stuck thus ?thesis by simp
      next
        case Abrupt thus ?thesis by simp
      next
        case (Normal t')
        with inter_guards_exec_noFault [OF d1 exec_d1]
        have "\<Gamma>\<turnstile>\<langle>a1,Normal s' \<rangle> \<Rightarrow> Normal t'"
          by simp
        with termi_c1 Normal_s have "\<Gamma>\<turnstile>a2 \<down> Normal t'"
          by (auto elim: terminates_Normal_elim_cases)
        with d2 have "\<Gamma>\<turnstile>d2 \<down> Normal t'"
          by (auto intro: Seq.hyps)
        with Normal show ?thesis by simp
      qed
    }
    ultimately have "\<Gamma>\<turnstile>Seq d1 d2 \<down> Normal s'"
      by (fastforce intro: terminates.intros)
    with Normal show ?thesis by simp
  qed
  with c show ?case by simp
next
  case Cond thus ?case
    by - (cases s,
          auto intro: terminates.intros elim!: terminates_Normal_elim_cases
               simp add: inter_guards_Cond)
next
  case (While b bdy1)
  have "(While b bdy1 \<inter>\<^sub>g c2) = Some c" by fact
  then obtain bdy2 bdy where
    c2: "c2=While b bdy2" and
    bdy: "(bdy1 \<inter>\<^sub>g bdy2) = Some bdy" and
    c: "c=While b bdy"
    by (auto simp add: inter_guards_While)
  have "\<Gamma>\<turnstile>While b bdy1 \<down> s" by fact
  moreover
  {
    fix s w w1 w2
    assume termi_w:  "\<Gamma>\<turnstile>w \<down> s"
    assume w: "w=While b bdy1"
    from termi_w w
    have "\<Gamma>\<turnstile>While b bdy \<down> s"
    proof (induct)
      case (WhileTrue s b' bdy1')
      have eqs: "While b' bdy1' = While b bdy1" by fact
      from WhileTrue have s_in_b: "s \<in> b" by simp
      from WhileTrue have termi_bdy1: "\<Gamma>\<turnstile>bdy1 \<down> Normal s" by simp
      show ?case
      proof -
        from bdy termi_bdy1
        have "\<Gamma>\<turnstile>bdy\<down>(Normal s)"
          by (rule While.hyps)
        moreover
        {
          fix t
          assume exec_bdy: "\<Gamma>\<turnstile>\<langle>bdy,Normal s \<rangle> \<Rightarrow> t"
          have "\<Gamma>\<turnstile>While b bdy\<down>t"
          proof (cases t)
            case Fault thus ?thesis by simp
          next
            case Stuck thus ?thesis by simp
          next
            case Abrupt thus ?thesis by simp
          next
            case (Normal t')
            with inter_guards_exec_noFault [OF bdy exec_bdy]
            have "\<Gamma>\<turnstile>\<langle>bdy1,Normal s \<rangle> \<Rightarrow> Normal t'"
              by simp
            with WhileTrue have "\<Gamma>\<turnstile>While b bdy \<down> Normal t'"
              by simp
            with Normal show ?thesis by simp
          qed
        }
        ultimately show ?thesis
          using s_in_b
          by (blast intro: terminates.WhileTrue)
      qed
    next
      case WhileFalse thus ?case
        by (blast intro: terminates.WhileFalse)
    qed (simp_all)
  }
  ultimately
  show ?case using c by simp
next
  case Call thus ?case by (simp add: inter_guards_Call)
next
  case (DynCom f1)
  have "(DynCom f1 \<inter>\<^sub>g c2) = Some c" by fact
  then obtain f2 f where
    c2: "c2=DynCom f2" and
    f_defined: "\<forall>s. ((f1 s) \<inter>\<^sub>g (f2 s)) \<noteq> None" and
    c: "c=DynCom (\<lambda>s. the ((f1 s) \<inter>\<^sub>g (f2 s)))"
    by (auto simp add: inter_guards_DynCom)
  have termi: "\<Gamma>\<turnstile>DynCom f1 \<down> s" by fact
  show ?case
  proof (cases s)
    case Fault thus ?thesis by simp
  next
    case Stuck thus ?thesis by simp
  next
    case Abrupt thus ?thesis by simp
  next
    case (Normal s')
    from f_defined obtain f where f: "((f1 s') \<inter>\<^sub>g (f2 s')) = Some f"
      by auto
    from Normal termi
    have "\<Gamma>\<turnstile>f1 s'\<down> (Normal s')"
      by (auto elim: terminates_Normal_elim_cases)
    from DynCom.hyps f this
    have "\<Gamma>\<turnstile>f\<down> (Normal s')"
      by blast
    with c f Normal
    show ?thesis
      by (auto intro: terminates.intros)
  qed
next
  case (Guard f g1 bdy1)
  have "(Guard f g1 bdy1 \<inter>\<^sub>g c2) = Some c" by fact
  then obtain g2 bdy2 bdy where
    c2: "c2=Guard f g2 bdy2" and
    bdy: "(bdy1 \<inter>\<^sub>g bdy2) = Some bdy" and
    c: "c=Guard f (g1 \<inter> g2) bdy"
    by (auto simp add: inter_guards_Guard)
  have termi_c1: "\<Gamma>\<turnstile>Guard f g1 bdy1 \<down> s" by fact
  show ?case
  proof (cases s)
    case Fault thus ?thesis by simp
  next
    case Stuck thus ?thesis by simp
  next
    case Abrupt thus ?thesis by simp
  next
    case (Normal s')
    show ?thesis
    proof (cases "s' \<in> g1")
      case False
      with Normal c show ?thesis by (auto intro: terminates.GuardFault)
    next
      case True
      note s_in_g1 = this
      show ?thesis
      proof (cases "s' \<in> g2")
        case False
        with Normal c show ?thesis by (auto intro: terminates.GuardFault)
      next
        case True
        with termi_c1 s_in_g1 Normal have "\<Gamma>\<turnstile>bdy1 \<down> Normal s'"
          by (auto elim: terminates_Normal_elim_cases)
        with c bdy Guard.hyps Normal True s_in_g1
        show ?thesis by (auto intro: terminates.Guard)
      qed
    qed
  qed
next
  case Throw thus ?case
    by (auto simp add: inter_guards_Throw)
next
  case (Catch a1 a2)
  have "(Catch a1 a2 \<inter>\<^sub>g c2) = Some c" by fact
  then obtain b1 b2 d1 d2 where
    c2: "c2=Catch b1 b2" and
    d1: "(a1 \<inter>\<^sub>g b1) = Some d1" and d2: "(a2 \<inter>\<^sub>g b2) = Some d2" and
    c: "c=Catch d1 d2"
    by (auto simp add: inter_guards_Catch)
  have termi_c1: "\<Gamma>\<turnstile>Catch a1 a2 \<down> s" by fact
  have "\<Gamma>\<turnstile>Catch d1 d2 \<down> s"
  proof (cases s)
    case Fault thus ?thesis by simp
  next
    case Stuck thus ?thesis by simp
  next
    case Abrupt thus ?thesis by simp
  next
    case (Normal s')
    note Normal_s = this
    with d1 termi_c1
    have "\<Gamma>\<turnstile>d1 \<down> Normal s'"
      by (auto elim: terminates_Normal_elim_cases intro: Catch.hyps)
    moreover
    {
      fix t
      assume exec_d1: "\<Gamma>\<turnstile>\<langle>d1,Normal s' \<rangle> \<Rightarrow> Abrupt t"
      have "\<Gamma>\<turnstile>d2 \<down> Normal t"
      proof -
        from inter_guards_exec_noFault [OF d1 exec_d1]
        have "\<Gamma>\<turnstile>\<langle>a1,Normal s' \<rangle> \<Rightarrow> Abrupt t"
          by simp
        with termi_c1 Normal_s have "\<Gamma>\<turnstile>a2 \<down> Normal t"
          by (auto elim: terminates_Normal_elim_cases)
        with d2 have "\<Gamma>\<turnstile>d2 \<down> Normal t"
          by (auto intro: Catch.hyps)
        with Normal show ?thesis by simp
      qed
    }
    ultimately have "\<Gamma>\<turnstile>Catch d1 d2 \<down> Normal s'"
      by (fastforce intro: terminates.intros)
    with Normal show ?thesis by simp
  qed
  with c show ?case by simp
qed

lemma inter_guards_terminates':
  assumes c: "(c1 \<inter>\<^sub>g c2) = Some c"
  assumes termi_c2: "\<Gamma>\<turnstile>c2\<down>s"
  shows "\<Gamma>\<turnstile>c\<down>s"
proof -
  from c have "(c2 \<inter>\<^sub>g c1) = Some c"
    by (rule inter_guards_sym)
  from this termi_c2 show ?thesis
    by (rule inter_guards_terminates)
qed

(* ************************************************************************* *)
subsection \<open>Lemmas about @{const "mark_guards"}\<close>
(* ************************************************************************ *)

lemma terminates_to_terminates_mark_guards:
  assumes termi: "\<Gamma>\<turnstile>c\<down>s"
  shows "\<Gamma>\<turnstile>mark_guards f c\<down>s"
using termi
proof (induct)
  case Skip thus ?case by (fastforce intro: terminates.intros)
next
  case Basic thus ?case by (fastforce intro: terminates.intros)
next
  case Spec thus ?case by (fastforce intro: terminates.intros)
next
  case Guard thus ?case by (fastforce intro: terminates.intros)
next
  case GuardFault thus ?case by (fastforce intro: terminates.intros)
next
  case Fault thus ?case by (fastforce intro: terminates.intros)
next
  case (Seq c1 s c2)
  have "\<Gamma>\<turnstile>mark_guards f c1 \<down> Normal s" by fact
  moreover
  {
    fix t
    assume exec_mark: "\<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> t"
    have "\<Gamma>\<turnstile>mark_guards f c2 \<down> t"
    proof -
      from exec_mark_guards_to_exec [OF exec_mark] obtain t' where
        exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> t'" and
        t_Fault: "isFault t \<longrightarrow> isFault t'" and
        t'_Fault_f: "t' = Fault f \<longrightarrow> t' = t" and
        t'_Fault: "isFault t' \<longrightarrow> isFault t" and
        t'_noFault: "\<not> isFault t' \<longrightarrow> t' = t"
        by blast
      show ?thesis
      proof (cases "isFault t'")
        case True
        with t'_Fault have "isFault t" by simp
        thus ?thesis
          by (auto elim: isFaultE)
      next
        case False
        with t'_noFault have "t'=t" by simp
        with exec_c1 Seq.hyps
        show ?thesis
          by auto
      qed
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case CondTrue thus ?case by (fastforce intro: terminates.intros)
next
  case CondFalse thus ?case by (fastforce intro: terminates.intros)
next
  case (WhileTrue s b c)
  have s_in_b: "s \<in> b" by fact
  have "\<Gamma>\<turnstile>mark_guards f c \<down> Normal s" by fact
  moreover
  {
    fix t
    assume exec_mark: "\<Gamma>\<turnstile>\<langle>mark_guards f c,Normal s \<rangle> \<Rightarrow> t"
    have "\<Gamma>\<turnstile>mark_guards f (While b c) \<down> t"
    proof -
      from exec_mark_guards_to_exec [OF exec_mark] obtain t' where
        exec_c1: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> t'" and
        t_Fault: "isFault t \<longrightarrow> isFault t'" and
        t'_Fault_f: "t' = Fault f \<longrightarrow> t' = t" and
        t'_Fault: "isFault t' \<longrightarrow> isFault t" and
        t'_noFault: "\<not> isFault t' \<longrightarrow> t' = t"
        by blast
      show ?thesis
      proof (cases "isFault t'")
        case True
        with t'_Fault have "isFault t" by simp
        thus ?thesis
          by (auto elim: isFaultE)
      next
        case False
        with t'_noFault have "t'=t" by simp
        with exec_c1 WhileTrue.hyps
        show ?thesis
          by auto
      qed
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case WhileFalse thus ?case by (fastforce intro: terminates.intros)
next
  case Call thus ?case by (fastforce intro: terminates.intros)
next
  case CallUndefined thus ?case by (fastforce intro: terminates.intros)
next
  case Stuck thus ?case by (fastforce intro: terminates.intros)
next
  case DynCom thus ?case by (fastforce intro: terminates.intros)
next
  case Throw thus ?case by (fastforce intro: terminates.intros)
next
  case Abrupt thus ?case by (fastforce intro: terminates.intros)
next
  case (Catch c1 s c2)
  have "\<Gamma>\<turnstile>mark_guards f c1 \<down> Normal s" by fact
  moreover
  {
    fix t
    assume exec_mark: "\<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> Abrupt t"
    have "\<Gamma>\<turnstile>mark_guards f c2 \<down> Normal t"
    proof -
      from exec_mark_guards_to_exec [OF exec_mark] obtain t' where
        exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> t'" and
        t'_Fault_f: "t' = Fault f \<longrightarrow> t' = Abrupt t" and
        t'_Fault: "isFault t' \<longrightarrow> isFault (Abrupt t)" and
        t'_noFault: "\<not> isFault t' \<longrightarrow> t' = Abrupt t"
        by fastforce
      show ?thesis
      proof (cases "isFault t'")
        case True
        with t'_Fault have "isFault (Abrupt t)" by simp
        thus ?thesis by simp
      next
        case False
        with t'_noFault have "t'=Abrupt t" by simp
        with exec_c1 Catch.hyps
        show ?thesis
          by auto
      qed
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
qed

lemma terminates_mark_guards_to_terminates_Normal:
  "\<And>s. \<Gamma>\<turnstile>mark_guards f c\<down>Normal s \<Longrightarrow> \<Gamma>\<turnstile>c\<down>Normal s"
proof (induct c)
  case Skip thus ?case by (fastforce intro: terminates.intros)
next
  case Basic thus ?case by (fastforce intro: terminates.intros)
next
  case Spec thus ?case by (fastforce intro: terminates.intros)
next
  case (Seq c1 c2)
  have "\<Gamma>\<turnstile>mark_guards f (Seq c1 c2) \<down> Normal s" by fact
  then obtain
    termi_merge_c1: "\<Gamma>\<turnstile>mark_guards f c1 \<down> Normal s" and
    termi_merge_c2: "\<forall>s'. \<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>
                           \<Gamma>\<turnstile>mark_guards f c2 \<down> s'"
    by (auto elim: terminates_Normal_elim_cases)
  from termi_merge_c1 Seq.hyps
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by iprover
  moreover
  {
    fix s'
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile> c2 \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis by (auto elim: isFaultE)
    next
      case False
      from exec_to_exec_mark_guards [OF exec_c1 False]
      have "\<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> s'" .
      from termi_merge_c2 [rule_format, OF this] Seq.hyps
      show ?thesis
        by (cases s') (auto)
    qed
  }
  ultimately show ?case by (auto intro: terminates.intros)
next
  case Cond thus ?case
    by (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case (While b c)
  {
    fix u c'
    assume termi_c': "\<Gamma>\<turnstile>c' \<down> Normal u"
    assume c': "c' = mark_guards f (While b c)"
    have "\<Gamma>\<turnstile>While b c \<down> Normal u"
      using termi_c' c'
    proof (induct)
      case (WhileTrue s b' c')
      have s_in_b: "s \<in> b" using WhileTrue by simp
      have "\<Gamma>\<turnstile>mark_guards f c \<down> Normal s"
        using WhileTrue by (auto elim: terminates_Normal_elim_cases)
      with While.hyps have "\<Gamma>\<turnstile>c \<down> Normal s"
        by auto
      moreover
      have hyp_w: "\<forall>w. \<Gamma>\<turnstile>\<langle>mark_guards f c,Normal s \<rangle> \<Rightarrow> w \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> w"
        using WhileTrue by simp
      hence "\<forall>w. \<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> w \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> w"
        apply -
        apply (rule allI)
        apply (case_tac "w")
        apply (auto dest: exec_to_exec_mark_guards)
        done
      ultimately show ?case
        using s_in_b
        by (auto intro: terminates.intros)
    next
      case WhileFalse thus ?case by (auto intro: terminates.intros)
    qed auto
  }
  with While show ?case by simp
next
  case Call thus ?case
    by (fastforce intro: terminates.intros )
next
  case DynCom thus ?case
    by (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case (Guard f g c)
  thus ?case by (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case Throw thus ?case
    by (fastforce intro: terminates.intros )
next
  case (Catch c1 c2)
  have "\<Gamma>\<turnstile>mark_guards f (Catch c1 c2) \<down> Normal s" by fact
  then obtain
    termi_merge_c1: "\<Gamma>\<turnstile>mark_guards f c1 \<down> Normal s" and
    termi_merge_c2: "\<forall>s'. \<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> Abrupt s' \<longrightarrow>
                           \<Gamma>\<turnstile>mark_guards f c2 \<down> Normal s'"
    by (auto elim: terminates_Normal_elim_cases)
  from termi_merge_c1 Catch.hyps
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by iprover
  moreover
  {
    fix s'
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
    have "\<Gamma>\<turnstile> c2 \<down> Normal s'"
    proof -
      from exec_to_exec_mark_guards [OF exec_c1]
      have "\<Gamma>\<turnstile>\<langle>mark_guards f c1,Normal s \<rangle> \<Rightarrow> Abrupt s'" by simp
      from termi_merge_c2 [rule_format, OF this] Catch.hyps
      show ?thesis
        by iprover
    qed
  }
  ultimately show ?case by (auto intro: terminates.intros)
qed

lemma terminates_mark_guards_to_terminates:
  "\<Gamma>\<turnstile>mark_guards f c\<down>s \<Longrightarrow> \<Gamma>\<turnstile>c\<down> s"
  by (cases s) (auto intro: terminates_mark_guards_to_terminates_Normal)

(* ************************************************************************* *)
subsection \<open>Lemmas about @{const "merge_guards"}\<close>
(* ************************************************************************ *)

lemma terminates_to_terminates_merge_guards:
  assumes termi: "\<Gamma>\<turnstile>c\<down>s"
  shows "\<Gamma>\<turnstile>merge_guards c\<down>s"
using termi
proof (induct)
  case (Guard s g c f)
  have s_in_g: "s \<in> g" by fact
  have termi_merge_c: "\<Gamma>\<turnstile>merge_guards c \<down> Normal s" by fact
  show ?case
  proof (cases "\<exists>f' g' c'. merge_guards c = Guard f' g' c'")
    case False
    hence "merge_guards (Guard f g c) = Guard f g (merge_guards c)"
      by (cases "merge_guards c") (auto simp add: Let_def)
    with s_in_g termi_merge_c show ?thesis
      by (auto intro: terminates.intros)
  next
    case True
    then obtain f' g' c' where
      mc: "merge_guards c = Guard f' g' c'"
      by blast
    show ?thesis
    proof (cases "f=f'")
      case False
      with mc have "merge_guards (Guard f g c) = Guard f g (merge_guards c)"
        by (simp add: Let_def)
      with s_in_g termi_merge_c show ?thesis
        by (auto intro: terminates.intros)
    next
      case True
      with mc have "merge_guards (Guard f g c) = Guard f (g \<inter> g') c'"
        by simp
      with s_in_g mc True termi_merge_c
      show ?thesis
        by (cases "s \<in> g'")
           (auto intro: terminates.intros elim: terminates_Normal_elim_cases)
    qed
  qed
next
  case (GuardFault s g f c)
  have "s \<notin> g" by fact
  thus ?case
    by (cases "merge_guards c")
       (auto intro: terminates.intros split: if_split_asm simp add: Let_def)
qed (fastforce intro: terminates.intros dest: exec_merge_guards_to_exec)+

lemma terminates_merge_guards_to_terminates_Normal:
  shows "\<And>s. \<Gamma>\<turnstile>merge_guards c\<down>Normal s \<Longrightarrow> \<Gamma>\<turnstile>c\<down>Normal s"
proof (induct c)
  case Skip thus ?case by (fastforce intro: terminates.intros)
next
  case Basic thus ?case by (fastforce intro: terminates.intros)
next
  case Spec thus ?case by (fastforce intro: terminates.intros)
next
  case (Seq c1 c2)
  have "\<Gamma>\<turnstile>merge_guards (Seq c1 c2) \<down> Normal s" by fact
  then obtain
    termi_merge_c1: "\<Gamma>\<turnstile>merge_guards c1 \<down> Normal s" and
    termi_merge_c2: "\<forall>s'. \<Gamma>\<turnstile>\<langle>merge_guards c1,Normal s \<rangle> \<Rightarrow> s' \<longrightarrow>
                           \<Gamma>\<turnstile>merge_guards c2 \<down> s'"
    by (auto elim: terminates_Normal_elim_cases)
  from termi_merge_c1 Seq.hyps
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by iprover
  moreover
  {
    fix s'
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile> c2 \<down> s'"
    proof -
      from exec_to_exec_merge_guards [OF exec_c1]
      have "\<Gamma>\<turnstile>\<langle>merge_guards c1,Normal s \<rangle> \<Rightarrow> s'" .
      from termi_merge_c2 [rule_format, OF this] Seq.hyps
      show ?thesis
        by (cases s') (auto)
    qed
  }
  ultimately show ?case by (auto intro: terminates.intros)
next
  case Cond thus ?case
    by (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case (While b c)
  {
    fix u c'
    assume termi_c': "\<Gamma>\<turnstile>c' \<down> Normal u"
    assume c': "c' = merge_guards (While b c)"
    have "\<Gamma>\<turnstile>While b c \<down> Normal u"
      using termi_c' c'
    proof (induct)
      case (WhileTrue s b' c')
      have s_in_b: "s \<in> b" using WhileTrue by simp
      have "\<Gamma>\<turnstile>merge_guards c \<down> Normal s"
        using WhileTrue by (auto elim: terminates_Normal_elim_cases)
      with While.hyps have "\<Gamma>\<turnstile>c \<down> Normal s"
        by auto
      moreover
      have hyp_w: "\<forall>w. \<Gamma>\<turnstile>\<langle>merge_guards c,Normal s \<rangle> \<Rightarrow> w \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> w"
        using WhileTrue by simp
      hence "\<forall>w. \<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> w \<longrightarrow> \<Gamma>\<turnstile>While b c \<down> w"
        by (simp add: exec_iff_exec_merge_guards [symmetric])
      ultimately show ?case
        using s_in_b
        by (auto intro: terminates.intros)
    next
      case WhileFalse thus ?case by (auto intro: terminates.intros)
    qed auto
  }
  with While show ?case by simp
next
  case Call thus ?case
    by (fastforce intro: terminates.intros )
next
  case DynCom thus ?case
    by (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
next
  case (Guard f g c)
  have termi_merge: "\<Gamma>\<turnstile>merge_guards (Guard f g c) \<down> Normal s" by fact
  show ?case
  proof (cases "\<exists>f' g' c'. merge_guards c = Guard f' g' c'")
    case False
    hence m: "merge_guards (Guard f g c) = Guard f g (merge_guards c)"
      by (cases "merge_guards c") (auto simp add: Let_def)
    from termi_merge Guard.hyps show ?thesis
      by (simp only: m)
         (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
  next
    case True
    then obtain f' g' c' where
      mc: "merge_guards c = Guard f' g' c'"
      by blast
    show ?thesis
    proof (cases "f=f'")
      case False
      with mc have m: "merge_guards (Guard f g c) = Guard f g (merge_guards c)"
        by (simp add: Let_def)
      from termi_merge Guard.hyps show ?thesis
      by (simp only: m)
         (fastforce intro: terminates.intros elim: terminates_Normal_elim_cases)
    next
      case True
      with mc have m: "merge_guards (Guard f g c) = Guard f (g \<inter> g') c'"
        by simp
      from termi_merge Guard.hyps
      show ?thesis
        by (simp only: m mc)
           (auto intro: terminates.intros elim: terminates_Normal_elim_cases)
    qed
  qed
next
  case Throw thus ?case
    by (fastforce intro: terminates.intros )
next
  case (Catch c1 c2)
  have "\<Gamma>\<turnstile>merge_guards (Catch c1 c2) \<down> Normal s" by fact
  then obtain
    termi_merge_c1: "\<Gamma>\<turnstile>merge_guards c1 \<down> Normal s" and
    termi_merge_c2: "\<forall>s'. \<Gamma>\<turnstile>\<langle>merge_guards c1,Normal s \<rangle> \<Rightarrow> Abrupt s' \<longrightarrow>
                           \<Gamma>\<turnstile>merge_guards c2 \<down> Normal s'"
    by (auto elim: terminates_Normal_elim_cases)
  from termi_merge_c1 Catch.hyps
  have "\<Gamma>\<turnstile>c1 \<down> Normal s" by iprover
  moreover
  {
    fix s'
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
    have "\<Gamma>\<turnstile> c2 \<down> Normal s'"
    proof -
      from exec_to_exec_merge_guards [OF exec_c1]
      have "\<Gamma>\<turnstile>\<langle>merge_guards c1,Normal s \<rangle> \<Rightarrow> Abrupt s'" .
      from termi_merge_c2 [rule_format, OF this] Catch.hyps
      show ?thesis
        by iprover
    qed
  }
  ultimately show ?case by (auto intro: terminates.intros)
qed

lemma terminates_merge_guards_to_terminates:
   "\<Gamma>\<turnstile>merge_guards c\<down> s \<Longrightarrow> \<Gamma>\<turnstile>c\<down> s"
by (cases s) (auto intro: terminates_merge_guards_to_terminates_Normal)

theorem terminates_iff_terminates_merge_guards:
  "\<Gamma>\<turnstile>c\<down> s = \<Gamma>\<turnstile>merge_guards c\<down> s"
  by (iprover intro: terminates_to_terminates_merge_guards
    terminates_merge_guards_to_terminates)

(* ************************************************************************* *)
subsection \<open>Lemmas about @{term "c\<^sub>1 \<subseteq>\<^sub>g c\<^sub>2"}\<close>
(* ************************************************************************ *)

lemma terminates_fewer_guards_Normal:
  shows "\<And>c s. \<lbrakk>\<Gamma>\<turnstile>c'\<down>Normal s; c \<subseteq>\<^sub>g c'; \<Gamma>\<turnstile>\<langle>c',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV\<rbrakk>
              \<Longrightarrow> \<Gamma>\<turnstile>c\<down>Normal s"
proof (induct c')
  case Skip thus ?case by (auto intro: terminates.intros dest: subseteq_guardsD)
next
  case Basic thus ?case by (auto intro: terminates.intros dest: subseteq_guardsD)
next
  case Spec thus ?case by (auto intro: terminates.intros dest: subseteq_guardsD)
next
  case (Seq c1' c2')
  have termi: "\<Gamma>\<turnstile>Seq c1' c2' \<down> Normal s" by fact
  then obtain
    termi_c1': "\<Gamma>\<turnstile>c1'\<down> Normal s" and
    termi_c2': "\<forall>s'. \<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow> s' \<longrightarrow> \<Gamma>\<turnstile>c2'\<down> s'"
    by (auto elim: terminates_Normal_elim_cases)
  have noFault: "\<Gamma>\<turnstile>\<langle>Seq c1' c2',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  hence noFault_c1': "\<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
    by (auto intro: exec.intros simp add: final_notin_def)
  have "c \<subseteq>\<^sub>g Seq c1' c2'" by fact
  from subseteq_guards_Seq [OF this] obtain c1 c2 where
    c: "c = Seq c1 c2" and
    c1_c1': "c1 \<subseteq>\<^sub>g c1'" and
    c2_c2': "c2 \<subseteq>\<^sub>g c2'"
    by blast
  from termi_c1' c1_c1' noFault_c1'
  have "\<Gamma>\<turnstile>c1\<down> Normal s"
    by (rule Seq.hyps)
  moreover
  {
    fix t
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> t"
    have "\<Gamma>\<turnstile>c2\<down> t"
    proof -
      from exec_to_exec_subseteq_guards [OF c1_c1' exec_c1] obtain t' where
        exec_c1': "\<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow> t'" and
        t_Fault: "isFault t \<longrightarrow> isFault t'" and
        t'_noFault: "\<not> isFault t' \<longrightarrow> t' = t"
        by blast
      show ?thesis
      proof (cases "isFault t'")
        case True
        with exec_c1' noFault_c1'
        have False
          by (fastforce elim: isFaultE dest: Fault_end simp add: final_notin_def)
        thus ?thesis ..
      next
        case False
        with t'_noFault have t': "t'=t" by simp
        with termi_c2' exec_c1'
        have termi_c2': "\<Gamma>\<turnstile>c2'\<down> t"
          by auto
        show ?thesis
        proof (cases t)
          case Fault thus ?thesis by auto
        next
          case Abrupt thus ?thesis by auto
        next
          case Stuck thus ?thesis by auto
        next
          case (Normal u)
          with noFault exec_c1' t'
          have "\<Gamma>\<turnstile>\<langle>c2',Normal u \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
            by (auto intro: exec.intros simp add: final_notin_def)
          from termi_c2' [simplified Normal] c2_c2' this
          have "\<Gamma>\<turnstile>c2 \<down> Normal u"
            by (rule Seq.hyps)
          with Normal exec_c1
          show ?thesis by simp
        qed
      qed
    qed
  }
  ultimately show ?case using c by (auto intro: terminates.intros)
next
  case (Cond b c1' c2')
  have noFault: "\<Gamma>\<turnstile>\<langle>Cond b c1' c2',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  have termi: "\<Gamma>\<turnstile>Cond b c1' c2' \<down> Normal s" by fact
  have "c \<subseteq>\<^sub>g Cond b c1' c2'" by fact
  from subseteq_guards_Cond [OF this] obtain c1 c2 where
    c: "c = Cond b c1 c2" and
    c1_c1': "c1 \<subseteq>\<^sub>g c1'" and
    c2_c2': "c2 \<subseteq>\<^sub>g c2'"
    by blast
  thus ?case
  proof (cases "s \<in> b")
    case True
    with termi have termi_c1': "\<Gamma>\<turnstile>c1' \<down> Normal s"
      by (auto elim: terminates_Normal_elim_cases)
    from True noFault have "\<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
      by (auto intro: exec.intros simp add: final_notin_def)
    from termi_c1' c1_c1' this
    have "\<Gamma>\<turnstile>c1 \<down> Normal s"
      by (rule Cond.hyps)
    with True c show ?thesis
      by (auto intro: terminates.intros)
  next
    case False
    with termi have termi_c2': "\<Gamma>\<turnstile>c2' \<down> Normal s"
      by (auto elim: terminates_Normal_elim_cases)
    from False noFault have "\<Gamma>\<turnstile>\<langle>c2',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
      by (auto intro: exec.intros simp add: final_notin_def)
    from termi_c2' c2_c2' this
    have "\<Gamma>\<turnstile>c2 \<down> Normal s"
      by (rule Cond.hyps)
    with False c show ?thesis
      by (auto intro: terminates.intros)
  qed
next
  case (While b c')
  have noFault: "\<Gamma>\<turnstile>\<langle>While b c',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  have termi: "\<Gamma>\<turnstile>While b c' \<down> Normal s" by fact
  have "c \<subseteq>\<^sub>g While b c'" by fact
  from subseteq_guards_While [OF this]
  obtain c'' where
    c: "c = While b c''" and
    c''_c': "c'' \<subseteq>\<^sub>g c'"
    by blast
  {
    fix d u
    assume termi: "\<Gamma>\<turnstile>d \<down> u"
    assume d: "d = While b c'"
    assume noFault: "\<Gamma>\<turnstile>\<langle>While b c',u \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
    have "\<Gamma>\<turnstile>While b c'' \<down> u"
    using termi d noFault
    proof (induct)
      case (WhileTrue u b' c''')
      have u_in_b: "u \<in> b" using WhileTrue by simp
      have termi_c': "\<Gamma>\<turnstile>c' \<down> Normal u" using WhileTrue by simp
      have noFault: "\<Gamma>\<turnstile>\<langle>While b c',Normal u \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" using WhileTrue by simp
      hence noFault_c': "\<Gamma>\<turnstile>\<langle>c',Normal u \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" using u_in_b
        by (auto intro: exec.intros simp add: final_notin_def)
      from While.hyps [OF termi_c' c''_c' this]
      have "\<Gamma>\<turnstile>c'' \<down> Normal u".
      moreover
      from WhileTrue
      have hyp_w: "\<forall>s'. \<Gamma>\<turnstile>\<langle>c',Normal u \<rangle> \<Rightarrow> s'  \<longrightarrow> \<Gamma>\<turnstile>\<langle>While b c',s' \<rangle> \<Rightarrow>\<notin>Fault ` UNIV
                        \<longrightarrow> \<Gamma>\<turnstile>While b c'' \<down> s'"
        by simp
      {
        fix v
        assume exec_c'': "\<Gamma>\<turnstile>\<langle>c'',Normal u \<rangle> \<Rightarrow> v"
        have "\<Gamma>\<turnstile>While b c'' \<down> v"
        proof -
          from exec_to_exec_subseteq_guards [OF c''_c' exec_c''] obtain v' where
            exec_c': "\<Gamma>\<turnstile>\<langle>c',Normal u \<rangle> \<Rightarrow> v'" and
            v_Fault: "isFault v \<longrightarrow> isFault v'" and
            v'_noFault: "\<not> isFault v' \<longrightarrow> v' = v"
            by auto
          show ?thesis
          proof (cases "isFault v'")
            case True
            with exec_c' noFault u_in_b
            have False
              by (fastforce
                   simp add: final_notin_def intro: exec.intros elim: isFaultE)
            thus ?thesis ..
          next
            case False
            with v'_noFault have v': "v'=v"
              by simp
            with noFault exec_c' u_in_b
            have "\<Gamma>\<turnstile>\<langle>While b c',v \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
              by (fastforce simp add: final_notin_def intro: exec.intros)
            from hyp_w [rule_format, OF exec_c' [simplified v'] this]
            show "\<Gamma>\<turnstile>While b c'' \<down> v" .
          qed
        qed
      }
      ultimately
      show ?case using u_in_b
        by (auto intro: terminates.intros)
    next
      case WhileFalse thus ?case by (auto intro: terminates.intros)
    qed auto
  }
  with c noFault termi show ?case
    by auto
next
  case Call thus ?case by (auto intro: terminates.intros dest: subseteq_guardsD)
next
  case (DynCom C')
  have termi: "\<Gamma>\<turnstile>DynCom C' \<down> Normal s" by fact
  hence termi_C': "\<Gamma>\<turnstile>C' s \<down> Normal s"
    by cases
  have noFault: "\<Gamma>\<turnstile>\<langle>DynCom C',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  hence noFault_C': "\<Gamma>\<turnstile>\<langle>C' s,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
    by (auto intro: exec.intros simp add: final_notin_def)
  have "c \<subseteq>\<^sub>g DynCom C'" by fact
  from subseteq_guards_DynCom [OF this] obtain C where
    c: "c = DynCom C" and
    C_C': "\<forall>s. C s \<subseteq>\<^sub>g C' s"
    by blast
  from DynCom.hyps termi_C' C_C' [rule_format] noFault_C'
  have "\<Gamma>\<turnstile>C s \<down> Normal s"
    by fast
  with c show ?case
    by (auto intro: terminates.intros)
next
  case (Guard f' g' c')
  have noFault: "\<Gamma>\<turnstile>\<langle>Guard f' g' c',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  have termi: "\<Gamma>\<turnstile>Guard f' g' c' \<down> Normal s" by fact
  have "c \<subseteq>\<^sub>g Guard f' g' c'" by fact
  hence c_cases: "(c \<subseteq>\<^sub>g c') \<or> (\<exists>c''. c = Guard f' g' c'' \<and> (c'' \<subseteq>\<^sub>g c'))"
    by (rule subseteq_guards_Guard)
  thus ?case
  proof (cases "s \<in> g'")
    case True
    note s_in_g' = this
    with noFault have noFault_c': "\<Gamma>\<turnstile>\<langle>c',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
      by (auto simp add: final_notin_def intro: exec.intros)
    from termi s_in_g' have termi_c': "\<Gamma>\<turnstile>c' \<down> Normal s"
      by cases auto
    from c_cases show ?thesis
    proof
      assume "c \<subseteq>\<^sub>g c'"
      from termi_c' this noFault_c'
      show "\<Gamma>\<turnstile>c \<down> Normal s"
        by (rule Guard.hyps)
    next
      assume "\<exists>c''. c = Guard f' g' c'' \<and> (c'' \<subseteq>\<^sub>g c')"
      then obtain c'' where
        c: "c = Guard f' g' c''" and c''_c': "c'' \<subseteq>\<^sub>g c'"
        by blast
      from termi_c' c''_c' noFault_c'
      have "\<Gamma>\<turnstile>c'' \<down> Normal s"
        by (rule Guard.hyps)
      with s_in_g' c
      show ?thesis
        by (auto intro: terminates.intros)
    qed
  next
    case False
    with noFault have False
      by (auto intro: exec.intros simp add: final_notin_def)
    thus ?thesis ..
  qed
next
  case Throw thus ?case by (auto intro: terminates.intros dest: subseteq_guardsD)
next
  case (Catch c1' c2')
  have termi: "\<Gamma>\<turnstile>Catch c1' c2' \<down> Normal s" by fact
  then obtain
    termi_c1': "\<Gamma>\<turnstile>c1'\<down> Normal s" and
    termi_c2': "\<forall>s'. \<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow> Abrupt s' \<longrightarrow> \<Gamma>\<turnstile>c2'\<down> Normal s'"
    by (auto elim: terminates_Normal_elim_cases)
  have noFault: "\<Gamma>\<turnstile>\<langle>Catch c1' c2',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV" by fact
  hence noFault_c1': "\<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
    by (fastforce intro: exec.intros simp add: final_notin_def)
  have "c \<subseteq>\<^sub>g Catch c1' c2'"  by fact
  from subseteq_guards_Catch [OF this] obtain c1 c2 where
    c: "c = Catch c1 c2" and
    c1_c1': "c1 \<subseteq>\<^sub>g c1'" and
    c2_c2': "c2 \<subseteq>\<^sub>g c2'"
    by blast
  from termi_c1' c1_c1' noFault_c1'
  have "\<Gamma>\<turnstile>c1\<down> Normal s"
    by (rule Catch.hyps)
  moreover
  {
    fix t
    assume exec_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt t"
    have "\<Gamma>\<turnstile>c2\<down> Normal t"
    proof -
      from exec_to_exec_subseteq_guards [OF c1_c1' exec_c1] obtain t' where
        exec_c1': "\<Gamma>\<turnstile>\<langle>c1',Normal s \<rangle> \<Rightarrow> t'" and
        t'_noFault: "\<not> isFault t' \<longrightarrow> t' = Abrupt t"
        by blast
      show ?thesis
      proof (cases "isFault t'")
        case True
        with exec_c1' noFault_c1'
        have False
          by (fastforce elim: isFaultE dest: Fault_end simp add: final_notin_def)
        thus ?thesis ..
      next
        case False
        with t'_noFault have t': "t'=Abrupt t" by simp
        with termi_c2' exec_c1'
        have termi_c2': "\<Gamma>\<turnstile>c2'\<down> Normal t"
          by auto
        with noFault exec_c1' t'
        have "\<Gamma>\<turnstile>\<langle>c2',Normal t \<rangle> \<Rightarrow>\<notin>Fault ` UNIV"
          by (auto intro: exec.intros simp add: final_notin_def)
        from termi_c2' c2_c2' this
        show "\<Gamma>\<turnstile>c2 \<down> Normal t"
          by (rule Catch.hyps)
      qed
    qed
  }
  ultimately show ?case using c by (auto intro: terminates.intros)
qed

theorem terminates_fewer_guards:
  shows "\<lbrakk>\<Gamma>\<turnstile>c'\<down>s; c \<subseteq>\<^sub>g c'; \<Gamma>\<turnstile>\<langle>c',s \<rangle> \<Rightarrow>\<notin>Fault ` UNIV\<rbrakk>
         \<Longrightarrow> \<Gamma>\<turnstile>c\<down>s"
  by (cases s) (auto intro: terminates_fewer_guards_Normal)

lemma terminates_noFault_strip_guards:
  assumes termi: "\<Gamma>\<turnstile>c\<down>Normal s"
  shows "\<lbrakk>\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F\<rbrakk> \<Longrightarrow> \<Gamma>\<turnstile>strip_guards F c\<down>Normal s"
using termi
proof (induct)
  case Skip thus ?case by (auto intro: terminates.intros)
next
  case Basic thus ?case by (auto intro: terminates.intros)
next
  case Spec thus ?case by (auto intro: terminates.intros)
next
  case (Guard s g c f)
  have s_in_g: "s \<in> g" by fact
  have "\<Gamma>\<turnstile>c \<down> Normal s" by fact
  have "\<Gamma>\<turnstile>\<langle>Guard f g c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  with s_in_g have "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (fastforce simp add: final_notin_def intro: exec.intros)
  with Guard.hyps have "\<Gamma>\<turnstile>strip_guards F c \<down> Normal s" by simp
  with s_in_g show ?case
    by (auto intro: terminates.intros)
next
  case GuardFault thus ?case
    by (auto intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case Fault thus ?case by (auto intro: terminates.intros)
next
  case (Seq c1 s c2)
  have noFault_Seq: "\<Gamma>\<turnstile>\<langle>Seq c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  hence noFault_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto simp add: final_notin_def intro: exec.intros)
  with Seq.hyps have "\<Gamma>\<turnstile>strip_guards F c1 \<down> Normal s" by simp
  moreover
  {
    fix s'
    assume exec_strip_guards_c1: "\<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s \<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile>strip_guards F c2 \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis by (auto elim: isFaultE intro: terminates.intros)
    next
      case False
      with exec_strip_guards_to_exec [OF exec_strip_guards_c1] noFault_c1
      have *: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with noFault_Seq have "\<Gamma>\<turnstile>\<langle>c2,s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using Seq.hyps by simp
    qed
  }
  ultimately show ?case
    by (auto intro: terminates.intros)
next
  case CondTrue thus ?case
    by (fastforce intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case CondFalse thus ?case
    by (fastforce intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case (WhileTrue s b c)
  have s_in_b: "s \<in> b" by fact
  have noFault_while: "\<Gamma>\<turnstile>\<langle>While b c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  with s_in_b have noFault_c: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto simp add: final_notin_def intro: exec.intros)
  with WhileTrue.hyps have "\<Gamma>\<turnstile>strip_guards F c \<down> Normal s" by simp
  moreover
  {
    fix s'
    assume exec_strip_guards_c: "\<Gamma>\<turnstile>\<langle>strip_guards F c,Normal s \<rangle> \<Rightarrow> s'"
    have "\<Gamma>\<turnstile>strip_guards F (While b c) \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis by (auto elim: isFaultE intro: terminates.intros)
    next
      case False
      with exec_strip_guards_to_exec [OF exec_strip_guards_c] noFault_c
      have *: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with s_in_b noFault_while have "\<Gamma>\<turnstile>\<langle>While b c,s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using WhileTrue.hyps by simp
    qed
  }
  ultimately show ?case
    using WhileTrue.hyps by (auto intro: terminates.intros)
next
  case WhileFalse thus ?case by (auto intro: terminates.intros)
next
  case Call thus ?case by (auto intro: terminates.intros)
next
  case CallUndefined thus ?case by (auto intro: terminates.intros)
next
  case Stuck thus ?case by (auto intro: terminates.intros)
next
  case DynCom thus ?case
    by (auto intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case Throw thus ?case by (auto intro: terminates.intros)
next
  case Abrupt thus ?case by (auto intro: terminates.intros)
next
  case (Catch c1 s c2)
  have noFault_Catch: "\<Gamma>\<turnstile>\<langle>Catch c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  hence noFault_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (fastforce simp add: final_notin_def intro: exec.intros)
  with Catch.hyps have "\<Gamma>\<turnstile>strip_guards F c1 \<down> Normal s" by simp
  moreover
  {
    fix s'
    assume exec_strip_guards_c1: "\<Gamma>\<turnstile>\<langle>strip_guards F c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
    have "\<Gamma>\<turnstile>strip_guards F c2 \<down> Normal s'"
    proof -
      from exec_strip_guards_to_exec [OF exec_strip_guards_c1] noFault_c1
      have *: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with noFault_Catch have "\<Gamma>\<turnstile>\<langle>c2,Normal s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using Catch.hyps by simp
    qed
  }
  ultimately show ?case
    using Catch.hyps by (auto intro: terminates.intros)
qed

(* ************************************************************************* *)
subsection \<open>Lemmas about @{const "strip_guards"}\<close>
(* ************************************************************************* *)

lemma terminates_noFault_strip:
  assumes termi: "\<Gamma>\<turnstile>c\<down>Normal s"
  shows "\<lbrakk>\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F\<rbrakk> \<Longrightarrow> strip F \<Gamma>\<turnstile>c\<down>Normal s"
using termi
proof (induct)
  case Skip thus ?case by (auto intro: terminates.intros)
next
  case Basic thus ?case by (auto intro: terminates.intros)
next
  case Spec thus ?case by (auto intro: terminates.intros)
next
  case (Guard s g c f)
  have s_in_g: "s \<in> g" by fact
  have "\<Gamma>\<turnstile>\<langle>Guard f g c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  with s_in_g have "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (fastforce simp add: final_notin_def intro: exec.intros)
  then have "strip F \<Gamma>\<turnstile>c \<down> Normal s" by (simp add: Guard.hyps)
  with s_in_g show ?case
    by (auto intro: terminates.intros simp del: strip_simp)
next
  case GuardFault thus ?case
    by (auto intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case Fault thus ?case by (auto intro: terminates.intros)
next
  case (Seq c1 s c2)
  have noFault_Seq: "\<Gamma>\<turnstile>\<langle>Seq c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  hence noFault_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto simp add: final_notin_def intro: exec.intros)
  then have "strip F \<Gamma>\<turnstile>c1 \<down> Normal s" by (simp add: Seq.hyps)
  moreover
  {
    fix s'
    assume exec_strip_c1: "strip F \<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
    have "strip F \<Gamma>\<turnstile>c2 \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis by (auto elim: isFaultE intro: terminates.intros)
    next
      case False
      with exec_strip_to_exec [OF exec_strip_c1] noFault_c1
      have *: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with noFault_Seq have "\<Gamma>\<turnstile>\<langle>c2,s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using Seq.hyps by (simp del: strip_simp)
    qed
  }
  ultimately show ?case
    by (fastforce intro: terminates.intros)
next
  case CondTrue thus ?case
    by (fastforce intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case CondFalse thus ?case
    by (fastforce intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case (WhileTrue s b c)
  have s_in_b: "s \<in> b" by fact
  have noFault_while: "\<Gamma>\<turnstile>\<langle>While b c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  with s_in_b have noFault_c: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto simp add: final_notin_def intro: exec.intros)
  then have "strip F \<Gamma>\<turnstile>c \<down> Normal s" by (simp add: WhileTrue.hyps)
  moreover
  {
    fix s'
    assume exec_strip_c: "strip F \<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> s'"
    have "strip F \<Gamma>\<turnstile>While b c \<down> s'"
    proof (cases "isFault s'")
      case True
      thus ?thesis by (auto elim: isFaultE intro: terminates.intros)
    next
      case False
      with exec_strip_to_exec [OF exec_strip_c] noFault_c
      have *: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with s_in_b noFault_while have "\<Gamma>\<turnstile>\<langle>While b c,s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using WhileTrue.hyps by (simp del: strip_simp)
    qed
  }
  ultimately show ?case
    using WhileTrue.hyps by (auto intro: terminates.intros simp del: strip_simp)
next
  case WhileFalse thus ?case by (auto intro: terminates.intros)
next
  case (Call p bdy s)
  have bdy: "\<Gamma> p = Some bdy" by fact
  have "\<Gamma>\<turnstile>\<langle>Call p,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  with bdy have bdy_noFault: "\<Gamma>\<turnstile>\<langle>bdy,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto intro: exec.intros simp add: final_notin_def)
  then have strip_bdy_noFault: "strip F \<Gamma>\<turnstile>\<langle>bdy,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (auto simp add: final_notin_def dest!: exec_strip_to_exec elim!: isFaultE)

  from bdy_noFault have "strip F \<Gamma>\<turnstile>bdy \<down> Normal s" by (simp add: Call.hyps)
  from terminates_noFault_strip_guards [OF this strip_bdy_noFault]
  have "strip F \<Gamma>\<turnstile>strip_guards F bdy \<down> Normal s".
  with bdy show ?case
    by (fastforce intro: terminates.Call)
next
  case CallUndefined thus ?case by (auto intro: terminates.intros)
next
  case Stuck thus ?case by (auto intro: terminates.intros)
next
  case DynCom thus ?case
    by (auto intro: terminates.intros exec.intros simp add: final_notin_def )
next
  case Throw thus ?case by (auto intro: terminates.intros)
next
  case Abrupt thus ?case by (auto intro: terminates.intros)
next
  case (Catch c1 s c2)
  have noFault_Catch: "\<Gamma>\<turnstile>\<langle>Catch c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F" by fact
  hence noFault_c1: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>Fault ` F"
    by (fastforce simp add: final_notin_def intro: exec.intros)
  then have "strip F \<Gamma>\<turnstile>c1 \<down> Normal s" by (simp add: Catch.hyps)
  moreover
  {
    fix s'
    assume exec_strip_c1: "strip F \<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
    have "strip F \<Gamma>\<turnstile>c2 \<down> Normal s'"
    proof -
      from exec_strip_to_exec [OF exec_strip_c1] noFault_c1
      have *: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
        by (auto simp add: final_notin_def elim!: isFaultE)
      with * noFault_Catch have "\<Gamma>\<turnstile>\<langle>c2,Normal s' \<rangle> \<Rightarrow>\<notin>Fault ` F"
        by (auto simp add: final_notin_def intro: exec.intros)
      with * show ?thesis
        using Catch.hyps by (simp del: strip_simp)
    qed
  }
  ultimately show ?case
    using Catch.hyps by (auto intro: terminates.intros simp del: strip_simp)
qed

(* ************************************************************************* *)
subsection \<open>Miscellaneous\<close>
(* ************************************************************************* *)

lemma terminates_while_lemma:
  assumes termi: "\<Gamma>\<turnstile>w\<down>fk"
  shows "\<And>k b c. \<lbrakk>fk = Normal (f k); w=While b c;
                       \<forall>i. \<Gamma>\<turnstile>\<langle>c,Normal (f i) \<rangle> \<Rightarrow> Normal (f (Suc i))\<rbrakk>
         \<Longrightarrow> \<exists>i. f i \<notin> b"
using termi
proof (induct)
  case WhileTrue thus ?case by blast
next
  case WhileFalse thus ?case by blast
qed simp_all

lemma terminates_while:
  "\<lbrakk>\<Gamma>\<turnstile>(While b c)\<down>Normal (f k);
    \<forall>i. \<Gamma>\<turnstile>\<langle>c,Normal (f i) \<rangle> \<Rightarrow> Normal (f (Suc i))\<rbrakk>
         \<Longrightarrow> \<exists>i. f i \<notin> b"
  by (blast intro: terminates_while_lemma)

lemma wf_terminates_while:
 "wf {(t,s). \<Gamma>\<turnstile>(While b c)\<down>Normal s \<and> s\<in>b \<and>
             \<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> Normal t}"
apply(subst wf_iff_no_infinite_down_chain)
apply(rule notI)
apply clarsimp
apply(insert terminates_while)
apply blast
done

lemma terminates_restrict_to_terminates:
  assumes terminates_res: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile> c \<down> s"
  assumes not_Stuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c,s \<rangle> \<Rightarrow>\<notin>{Stuck}"
  shows "\<Gamma>\<turnstile> c \<down> s"
using terminates_res not_Stuck
proof (induct)
  case Skip show ?case by (rule terminates.Skip)
next
  case Basic show ?case by (rule terminates.Basic)
next
  case Spec show ?case by (rule terminates.Spec)
next
  case Guard thus ?case
    by (auto intro: terminates.Guard dest: notStuck_GuardD)
next
  case GuardFault thus ?case by (auto intro: terminates.GuardFault)
next
  case Fault show ?case by (rule terminates.Fault)
next
  case (Seq c1 s c2)
  have not_Stuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>Seq c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}" by fact
  hence c1_notStuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}"
    by (rule notStuck_SeqD1)
  show "\<Gamma>\<turnstile>Seq c1 c2 \<down> Normal s"
  proof (rule terminates.Seq,safe)
    from c1_notStuck
    show "\<Gamma>\<turnstile>c1 \<down> Normal s"
      by (rule Seq.hyps)
  next
    fix s'
    assume exec: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> s'"
    show "\<Gamma>\<turnstile>c2 \<down> s'"
    proof -
      from exec_to_exec_restrict [OF exec] obtain t' where
        exec_res: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> t'" and
        t'_notStuck: "t' \<noteq> Stuck \<longrightarrow> t' = s'"
        by blast
      show ?thesis
      proof (cases "t'=Stuck")
        case True
        with c1_notStuck exec_res have "False"
          by (auto simp add: final_notin_def)
        thus ?thesis ..
      next
        case False
        with t'_notStuck have t': "t'=s'" by simp
        with not_Stuck exec_res
        have "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c2,s' \<rangle> \<Rightarrow>\<notin>{Stuck}"
          by (auto dest: notStuck_SeqD2)
        with exec_res t' Seq.hyps
        show ?thesis
          by auto
      qed
    qed
  qed
next
  case CondTrue thus ?case
    by (auto intro: terminates.CondTrue dest: notStuck_CondTrueD)
next
  case CondFalse thus ?case
    by (auto intro: terminates.CondFalse dest: notStuck_CondFalseD)
next
  case (WhileTrue s b c)
  have s: "s \<in> b" by fact
  have not_Stuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>While b c,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}" by fact
  with WhileTrue have c_notStuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}"
    by (iprover intro:  notStuck_WhileTrueD1)
  show ?case
  proof (rule terminates.WhileTrue [OF s],safe)
    from c_notStuck
    show "\<Gamma>\<turnstile>c \<down> Normal s"
      by (rule WhileTrue.hyps)
  next
    fix s'
    assume exec: "\<Gamma>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> s'"
    show "\<Gamma>\<turnstile>While b c \<down> s'"
    proof -
      from exec_to_exec_restrict [OF exec] obtain t' where
        exec_res: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c,Normal s \<rangle> \<Rightarrow> t'" and
        t'_notStuck: "t' \<noteq> Stuck \<longrightarrow> t' = s'"
        by blast
      show ?thesis
      proof (cases "t'=Stuck")
        case True
        with c_notStuck exec_res have "False"
          by (auto simp add: final_notin_def)
        thus ?thesis ..
      next
        case False
        with t'_notStuck have t': "t'=s'" by simp
        with not_Stuck exec_res s
        have "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>While b c,s' \<rangle> \<Rightarrow>\<notin>{Stuck}"
          by (auto dest: notStuck_WhileTrueD2)
        with exec_res t' WhileTrue.hyps
        show ?thesis
          by auto
      qed
    qed
  qed
next
  case WhileFalse then show ?case by (iprover intro: terminates.WhileFalse)
next
  case Call thus ?case
    by (auto intro: terminates.Call dest: notStuck_CallD restrict_SomeD)
next
  case CallUndefined
  thus ?case
    by (auto dest: notStuck_CallDefinedD)
next
  case Stuck show ?case by (rule terminates.Stuck)
next
  case DynCom
  thus ?case
    by (auto intro: terminates.DynCom dest: notStuck_DynComD)
next
  case Throw show ?case by (rule terminates.Throw)
next
  case Abrupt show ?case by (rule terminates.Abrupt)
next
  case (Catch c1 s c2)
  have not_Stuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>Catch c1 c2,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}" by fact
  hence c1_notStuck: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow>\<notin>{Stuck}"
    by (rule notStuck_CatchD1)
  show "\<Gamma>\<turnstile>Catch c1 c2 \<down> Normal s"
  proof (rule terminates.Catch,safe)
    from c1_notStuck
    show "\<Gamma>\<turnstile>c1 \<down> Normal s"
      by (rule Catch.hyps)
  next
    fix s'
    assume exec: "\<Gamma>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> Abrupt s'"
    show "\<Gamma>\<turnstile>c2 \<down> Normal s'"
    proof -
      from exec_to_exec_restrict [OF exec] obtain t' where
        exec_res: "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c1,Normal s \<rangle> \<Rightarrow> t'" and
        t'_notStuck: "t' \<noteq> Stuck \<longrightarrow> t' = Abrupt s'"
        by blast
      show ?thesis
      proof (cases "t'=Stuck")
        case True
        with c1_notStuck exec_res have "False"
          by (auto simp add: final_notin_def)
        thus ?thesis ..
      next
        case False
        with t'_notStuck have t': "t'=Abrupt s'" by simp
        with not_Stuck exec_res
        have "\<Gamma>|\<^bsub>M\<^esub>\<turnstile>\<langle>c2,Normal s' \<rangle> \<Rightarrow>\<notin>{Stuck}"
          by (auto dest: notStuck_CatchD2)
        with exec_res t' Catch.hyps
        show ?thesis
          by auto
      qed
    qed
  qed
qed

end


(*  Title:      HOL/Auth/n_german_lemma_inv__29_on_rules.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

(*header{*The n_german Protocol Case Study*}*)

theory n_german_lemma_inv__29_on_rules imports n_german_lemma_on_inv__29
begin
section{*All lemmas on causal relation between inv__29*}
lemma lemma_inv__29_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__29  p__Inv0 p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqSVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqE__part__0Vsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqE__part__1Vsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqSVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqEVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__0Vsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__1Vsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvAckVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvInvAckVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntSVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntEVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntSVsinv__29) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntEVsinv__29) done
    }

  ultimately show "invHoldForRule s f r (invariants N)"
  by satx
qed

end