Theory Correctness

(*  Title:       Information Flow Control via Stateful Intransitive Noninterference in Language IMP
    Author:      Pasquale Noce
                 Senior Staff Firmware Engineer at HID Global, Italy
                 pasquale dot noce dot lavoro at gmail dot com
                 pasquale dot noce at hidglobal dot com
*)

section "Sufficiency of well-typedness for information flow correctness"

theory Correctness
  imports Overapproximation
begin

text ‹
\null

The purpose of this section is to prove that type system @{const [names_short] noninterf.ctyping2}
is correct in that it guarantees that well-typed programs satisfy the information flow correctness
criterion expressed by predicate @{const [names_short] noninterf.correct}, namely that if the type
system outputs a value other than @{const None} (that is, a \emph{pass} verdict) when it is input
program @{term c}, @{typ "state set"} @{term A}, and @{typ "vname set"} @{term X}, then
@{prop "correct c A X"} (theorem @{text ctyping2_correct}).

This proof makes use of the lemmas @{text ctyping1_idem} and @{text ctyping2_approx} proven in the
previous sections.
›


subsection "Global context proofs"

lemma flow_append_1:
  assumes A: "cfs' :: (com × state) list.
    c # map fst (cfs :: (com × state) list) = map fst cfs' 
      flow_aux (map fst cfs' @ map fst cfs'') =
      flow_aux (map fst cfs') @ flow_aux (map fst cfs'')"
  shows "flow_aux (c # map fst cfs @ map fst cfs'') =
    flow_aux (c # map fst cfs) @ flow_aux (map fst cfs'')"
using A [of "(c, λx. 0) # cfs"] by simp

lemma flow_append:
 "flow (cfs @ cfs') = flow cfs @ flow cfs'"
by (simp add: flow_def, induction "map fst cfs" arbitrary: cfs
 rule: flow_aux.induct, auto, rule flow_append_1)

lemma flow_cons:
 "flow (cf # cfs) = flow_aux (fst cf # []) @ flow cfs"
by (subgoal_tac "cf # cfs = [cf] @ cfs", simp only: flow_append,
 simp_all add: flow_def)

lemma small_stepsl_append:
 "(c, s) →*{cfs} (c', s'); (c', s') →*{cfs'} (c'', s'') 
    (c, s) →*{cfs @ cfs'} (c'', s'')"
by (induction c' s' cfs' c'' s'' rule: small_stepsl_induct,
 simp, simp only: append_assoc [symmetric] small_stepsl.simps)


lemma small_stepsl_cons_1:
 "(c, s) →*{[cf]} (c'', s'') 
    cf = (c, s) 
    (c' s'. (c, s)  (c', s')  (c', s') →*{[]} (c'', s''))"
by (subst (asm) append_Nil [symmetric],
 simp only: small_stepsl.simps, simp)

lemma small_stepsl_cons_2:
 "(c, s) →*{cf # cfs} (c'', s'') 
    cf = (c, s) 
    (c' s'. (c, s)  (c', s')  (c', s') →*{cfs} (c'', s''));
  (c, s) →*{cf # cfs @ [(c'', s'')]} (c''', s''') 
    cf = (c, s) 
    (c' s'. (c, s)  (c', s') 
      (c', s') →*{cfs @ [(c'', s'')]} (c''', s'''))"
by (simp only: append_Cons [symmetric],
 simp only: small_stepsl.simps, simp)

lemma small_stepsl_cons:
 "(c, s) →*{cf # cfs} (c'', s'') 
    cf = (c, s) 
    (c' s'. (c, s)  (c', s')  (c', s') →*{cfs} (c'', s''))"
by (induction c s cfs c'' s'' rule: small_stepsl_induct,
 erule small_stepsl_cons_1, rule small_stepsl_cons_2)


lemma small_steps_stepsl_1:
 "cfs. (c, s) →*{cfs} (c, s)"
by (rule exI [of _ "[]"], simp)

lemma small_steps_stepsl_2:
 "(c, s)  (c', s'); (c', s') →*{cfs} (c'', s'') 
    cfs'. (c, s) →*{cfs'} (c'', s'')"
by (rule exI [of _ "[(c, s)] @ cfs"], rule small_stepsl_append
 [where c' = c' and s' = s'], subst append_Nil [symmetric],
 simp only: small_stepsl.simps)

lemma small_steps_stepsl:
 "(c, s) →* (c', s')  cfs. (c, s) →*{cfs} (c', s')"
by (induction c s c' s' rule: star_induct,
 rule small_steps_stepsl_1, blast intro: small_steps_stepsl_2)

lemma small_stepsl_steps:
 "(c, s) →*{cfs} (c', s')  (c, s) →* (c', s')"
by (induction c s cfs c' s' rule: small_stepsl_induct,
 auto intro: star_trans)

lemma small_stepsl_skip:
 "(SKIP, s) →*{cfs} (c, t) 
    (c, t) = (SKIP, s)  flow cfs = []"
by (induction SKIP s cfs c t rule: small_stepsl_induct,
 auto simp: flow_def)


lemma small_stepsl_assign_1:
 "(x ::= a, s) →*{[]} (c', s') 
    (c', s') = (x ::= a, s)  flow [] = [] 
    (c', s') = (SKIP, s(x := aval a s))  flow [] = [x ::= a]"
by (simp add: flow_def)

lemma small_stepsl_assign_2:
 "(x ::= a, s) →*{cfs} (c', s') 
    (c', s') = (x ::= a, s)  flow cfs = [] 
      (c', s') = (SKIP, s(x := aval a s))  flow cfs = [x ::= a];
    (x ::= a, s) →*{cfs @ [(c', s')]} (c'', s'') 
  (c'', s'') = (x ::= a, s) 
    flow (cfs @ [(c', s')]) = [] 
  (c'', s'') = (SKIP, s(x := aval a s)) 
    flow (cfs @ [(c', s')]) = [x ::= a]"
by (auto, (simp add: flow_append, simp add: flow_def)+)

lemma small_stepsl_assign:
 "(x ::= a, s) →*{cfs} (c, t) 
    (c, t) = (x ::= a, s)  flow cfs = [] 
    (c, t) = (SKIP, s(x := aval a s))  flow cfs = [x ::= a]"
by (induction "x ::= a :: com" s cfs c t rule: small_stepsl_induct,
 erule small_stepsl_assign_1, rule small_stepsl_assign_2)


lemma small_stepsl_seq_1:
 "(c1;; c2, s) →*{[]} (c', s') 
    (c'' cfs'. c' = c'';; c2 
      (c1, s) →*{cfs'} (c'', s') 
      flow [] = flow cfs') 
    (s'' cfs' cfs''. length cfs'' < length [] 
      (c1, s) →*{cfs'} (SKIP, s'') 
      (c2, s'') →*{cfs''} (c', s') 
      flow [] = flow cfs' @ flow cfs'')"
by force

lemma small_stepsl_seq_2:
  assumes
    A: "(c1;; c2, s) →*{cfs} (c', s') 
      (c'' cfs'. c' = c'';; c2 
        (c1, s) →*{cfs'} (c'', s') 
        flow cfs = flow cfs') 
      (s'' cfs' cfs''. length cfs'' < length cfs 
        (c1, s) →*{cfs'} (SKIP, s'') 
        (c2, s'') →*{cfs''} (c', s') 
        flow cfs = flow cfs' @ flow cfs'')" and
    B: "(c1;; c2, s) →*{cfs @ [(c', s')]} (c'', s'')"
  shows
   "(d cfs'. c'' = d;; c2 
      (c1, s) →*{cfs'} (d, s'') 
      flow (cfs @ [(c', s')]) = flow cfs') 
    (t cfs' cfs''. length cfs'' < length (cfs @ [(c', s')]) 
      (c1, s) →*{cfs'} (SKIP, t) 
      (c2, t) →*{cfs''} (c'', s'') 
      flow (cfs @ [(c', s')]) = flow cfs' @ flow cfs'')"
    (is "?P  ?Q")
proof -
  {
    assume C: "(c', s')  (c'', s'')"
    assume
     "(d. c' = d;; c2  (cfs'.
        (c1, s) →*{cfs'} (d, s') 
        flow cfs = flow cfs')) 
      (t cfs' cfs''. length cfs'' < length cfs 
        (c1, s) →*{cfs'} (SKIP, t) 
        (c2, t) →*{cfs''} (c', s') 
        flow cfs = flow cfs' @ flow cfs'')"
      (is "(d. ?R d  (cfs'. ?S d cfs')) 
        (t cfs' cfs''. ?T t cfs' cfs'')")
    hence ?thesis
    proof
      assume "c''. ?R c''  (cfs'. ?S c'' cfs')"
      then obtain d and cfs' where
        D: "c' = d;; c2" and
        E: "(c1, s) →*{cfs'} (d, s')" and
        F: "flow cfs = flow cfs'"
        by blast
      hence "(d;; c2, s')  (c'', s'')"
        using C by simp
      moreover {
        assume
          G: "d = SKIP" and
          H: "(c'', s'') = (c2, s')"
        have ?Q
        proof (rule exI [of _ s'], rule exI [of _ cfs'],
         rule exI [of _ "[]"])
          from D and E and F and G and H show
           "length [] < length (cfs @ [(c', s')]) 
            (c1, s) →*{cfs'} (SKIP, s') 
            (c2, s') →*{[]} (c'', s'') 
            flow (cfs @ [(c', s')]) = flow cfs' @ flow []"
            by (simp add: flow_append, simp add: flow_def)
        qed
      }
      moreover {
        fix d' t'
        assume
          G: "(d, s')  (d', t')" and
          H: "(c'', s'') = (d';; c2, t')"
        have ?P
        proof (rule exI [of _ d'], rule exI [of _ "cfs' @ [(d, s')]"])
          from D and E and F and G and H show
           "c'' = d';; c2 
            (c1, s) →*{cfs' @ [(d, s')]} (d', s'') 
            flow (cfs @ [(c', s')]) = flow (cfs' @ [(d, s')])"
            by (simp add: flow_append, simp add: flow_def)
        qed
      }
      ultimately show ?thesis
        by blast
    next
      assume "t cfs' cfs''. ?T t cfs' cfs''"
      then obtain t and cfs' and cfs'' where
        D: "length cfs'' < length cfs" and
        E: "(c1, s) →*{cfs'} (SKIP, t)" and
        F: "(c2, t) →*{cfs''} (c', s')" and
        G: "flow cfs = flow cfs' @ flow cfs''"
        by blast
      show ?thesis
      proof (rule disjI2, rule exI [of _ t], rule exI [of _ cfs'],
       rule exI [of _ "cfs'' @ [(c', s')]"])
        from C and D and E and F and G show
         "length (cfs'' @ [(c', s')]) < length (cfs @ [(c', s')]) 
          (c1, s) →*{cfs'} (SKIP, t) 
          (c2, t) →*{cfs'' @ [(c', s')]} (c'', s'') 
          flow (cfs @ [(c', s')]) =
            flow cfs' @ flow (cfs'' @ [(c', s')])"
          by (simp add: flow_append)
      qed
    qed
  }
  with A and B show ?thesis
    by simp
qed

lemma small_stepsl_seq:
 "(c1;; c2, s) →*{cfs} (c, t) 
    (c' cfs'. c = c';; c2 
      (c1, s) →*{cfs'} (c', t) 
      flow cfs = flow cfs') 
    (s' cfs' cfs''. length cfs'' < length cfs 
      (c1, s) →*{cfs'} (SKIP, s')  (c2, s') →*{cfs''} (c, t) 
      flow cfs = flow cfs' @ flow cfs'')"
by (induction "c1;; c2" s cfs c t arbitrary: c1 c2
 rule: small_stepsl_induct, erule small_stepsl_seq_1,
 rule small_stepsl_seq_2)


lemma small_stepsl_if_1:
 "(IF b THEN c1 ELSE c2, s) →*{[]} (c', s') 
    (c', s') = (IF b THEN c1 ELSE c2, s) 
      flow [] = [] 
    bval b s  (c1, s) →*{tl []} (c', s') 
      flow [] = bvars b # flow (tl []) 
    ¬ bval b s  (c2, s) →*{tl []} (c', s') 
      flow [] = bvars b # flow (tl [])"
by (simp add: flow_def)

lemma small_stepsl_if_2:
  assumes
    A: "(IF b THEN c1 ELSE c2, s) →*{cfs} (c', s') 
      (c', s') = (IF b THEN c1 ELSE c2, s) 
        flow cfs = [] 
      bval b s  (c1, s) →*{tl cfs} (c', s') 
        flow cfs = bvars b # flow (tl cfs) 
      ¬ bval b s  (c2, s) →*{tl cfs} (c', s') 
        flow cfs = bvars b # flow (tl cfs)" and
    B: "(IF b THEN c1 ELSE c2, s) →*{cfs @ [(c', s')]} (c'', s'')"
  shows
   "(c'', s'') = (IF b THEN c1 ELSE c2, s) 
      flow (cfs @ [(c', s')]) = [] 
    bval b s  (c1, s) →*{tl (cfs @ [(c', s')])} (c'', s'') 
      flow (cfs @ [(c', s')]) = bvars b # flow (tl (cfs @ [(c', s')])) 
    ¬ bval b s  (c2, s) →*{tl (cfs @ [(c', s')])} (c'', s'') 
      flow (cfs @ [(c', s')]) = bvars b # flow (tl (cfs @ [(c', s')]))"
    (is "_  ?P")
proof -
  {
    assume
      C: "(IF b THEN c1 ELSE c2, s) →*{cfs} (c', s')" and
      D: "(c', s')  (c'', s'')"
    assume
     "c' = IF b THEN c1 ELSE c2  s' = s 
        flow cfs = [] 
      bval b s  (c1, s) →*{tl cfs} (c', s') 
        flow cfs = bvars b # flow (tl cfs) 
      ¬ bval b s  (c2, s) →*{tl cfs} (c', s') 
        flow cfs = bvars b # flow (tl cfs)"
      (is "?Q  ?R  ?S")
    hence ?P
    proof (rule disjE, erule_tac [2] disjE)
      assume ?Q
      moreover from this have "(IF b THEN c1 ELSE c2, s)  (c'', s'')"
        using D by simp
      ultimately show ?thesis
        using C by (erule_tac IfE, auto dest: small_stepsl_cons
         simp: tl_append flow_cons split: list.split)
    next
      assume ?R
      with C and D show ?thesis
        by (auto simp: tl_append flow_cons split: list.split)
    next
      assume ?S
      with C and D show ?thesis
        by (auto simp: tl_append flow_cons split: list.split)
    qed
  }
  with A and B show ?thesis
    by simp
qed

lemma small_stepsl_if:
 "(IF b THEN c1 ELSE c2, s) →*{cfs} (c, t) 
    (c, t) = (IF b THEN c1 ELSE c2, s) 
      flow cfs = [] 
    bval b s  (c1, s) →*{tl cfs} (c, t) 
      flow cfs = bvars b # flow (tl cfs) 
    ¬ bval b s  (c2, s) →*{tl cfs} (c, t) 
      flow cfs = bvars b # flow (tl cfs)"
by (induction "IF b THEN c1 ELSE c2" s cfs c t arbitrary: b c1 c2
 rule: small_stepsl_induct, erule small_stepsl_if_1,
 rule small_stepsl_if_2)


lemma small_stepsl_while_1:
 "(WHILE b DO c, s) →*{[]} (c', s') 
    (c', s') = (WHILE b DO c, s)  flow [] = [] 
    (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl []} (c', s') 
      flow [] = flow (tl [])"
by (simp add: flow_def)

lemma small_stepsl_while_2:
  assumes
    A: "(WHILE b DO c, s) →*{cfs} (c', s') 
      (c', s') = (WHILE b DO c, s) 
        flow cfs = [] 
      (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs} (c', s') 
        flow cfs = flow (tl cfs)" and
    B: "(WHILE b DO c, s) →*{cfs @ [(c', s')]} (c'', s'')"
  shows
   "(c'', s'') = (WHILE b DO c, s) 
      flow (cfs @ [(c', s')]) = [] 
    (IF b THEN c;; WHILE b DO c ELSE SKIP, s)
      →*{tl (cfs @ [(c', s')])} (c'', s'') 
      flow (cfs @ [(c', s')]) = flow (tl (cfs @ [(c', s')]))"
    (is "_  ?P")
proof -
  {
    assume
      C: "(WHILE b DO c, s) →*{cfs} (c', s')" and
      D: "(c', s')  (c'', s'')"
    assume
     "c' = WHILE b DO c  s' = s 
        flow cfs = [] 
      (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs} (c', s') 
        flow cfs = flow (tl cfs)"
      (is "?Q  ?R")
    hence ?P
    proof
      assume ?Q
      moreover from this have "(WHILE b DO c, s)  (c'', s'')"
        using D by simp
      ultimately show ?thesis
        using C by (erule_tac WhileE, auto dest: small_stepsl_cons
         simp: tl_append flow_cons split: list.split)
    next
      assume ?R
      with C and D show ?thesis
        by (auto simp: tl_append flow_cons split: list.split)
    qed
  }
  with A and B show ?thesis
    by simp
qed

lemma small_stepsl_while:
 "(WHILE b DO c, s) →*{cfs} (c', s') 
    (c', s') = (WHILE b DO c, s) 
      flow cfs = [] 
    (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs} (c', s') 
      flow cfs = flow (tl cfs)"
by (induction "WHILE b DO c" s cfs c' s' arbitrary: b c
 rule: small_stepsl_induct, erule small_stepsl_while_1,
 rule small_stepsl_while_2)


lemma bvars_bval:
 "s = t (⊆ bvars b)  bval b s = bval b t"
by (induction b, simp_all, rule arg_cong2, auto intro: avars_aval)

lemma run_flow_append:
 "run_flow (cs @ cs') s = run_flow cs' (run_flow cs s)"
by (induction cs s rule: run_flow.induct, simp_all (no_asm))

lemma no_upd_append:
 "no_upd (cs @ cs') x = (no_upd cs x  no_upd cs' x)"
by (induction cs, simp_all)

lemma no_upd_run_flow:
 "no_upd cs x  run_flow cs s x = s x"
by (induction cs s rule: run_flow.induct, auto)

lemma small_stepsl_run_flow_1:
 "(c, s) →*{[]} (c', s')  s' = run_flow (flow []) s"
by (simp add: flow_def)

lemma small_stepsl_run_flow_2:
 "(c, s)  (c', s')  s' = run_flow (flow_aux [c]) s"
by (induction "[c]" arbitrary: c c' rule: flow_aux.induct, auto)

lemma small_stepsl_run_flow_3:
 "(c, s) →*{cfs} (c', s')  s' = run_flow (flow cfs) s;
    (c, s) →*{cfs @ [(c', s')]} (c'', s'') 
  s'' = run_flow (flow (cfs @ [(c', s')])) s"
by (simp add: flow_append run_flow_append,
 auto intro: small_stepsl_run_flow_2 simp: flow_def)

lemma small_stepsl_run_flow:
 "(c, s) →*{cfs} (c', s')  s' = run_flow (flow cfs) s"
by (induction c s cfs c' s' rule: small_stepsl_induct,
 erule small_stepsl_run_flow_1, rule small_stepsl_run_flow_3)


subsection "Local context proofs"

context noninterf
begin


lemma no_upd_sources:
 "no_upd cs x  x  sources cs s x"
by (induction cs rule: rev_induct, auto simp: no_upd_append
 split: com_flow.split)

lemma sources_aux_sources:
 "sources_aux cs s x  sources cs s x"
by (induction cs rule: rev_induct, auto split: com_flow.split)

lemma sources_aux_append:
 "sources_aux cs s x  sources_aux (cs @ cs') s x"
by (induction cs' rule: rev_induct, simp, subst append_assoc [symmetric],
 auto simp del: append_assoc split: com_flow.split)

lemma sources_aux_observe_hd_1:
 "y  X. s: dom y  dom x  X  sources_aux [X] s x"
by (subst append_Nil [symmetric], subst sources_aux.simps, auto)

lemma sources_aux_observe_hd_2:
 "(y  X. s: dom y  dom x  X  sources_aux (X # xs) s x) 
    y  X. s: dom y  dom x  X  sources_aux (X # xs @ [x']) s x"
by (subst append_Cons [symmetric], subst sources_aux.simps,
 auto split: com_flow.split)

lemma sources_aux_observe_hd:
 "y  X. s: dom y  dom x  X  sources_aux (X # cs) s x"
by (induction cs rule: rev_induct,
 erule sources_aux_observe_hd_1, rule sources_aux_observe_hd_2)


lemma sources_observe_tl_1:
  assumes
    A: "z a. c = (x ::= a :: com_flow)  z = x 
      sources_aux cs s x  sources_aux (X # cs) s x" and
    B: "z a y. c = (x ::= a :: com_flow)  z = x 
      sources cs s y  sources (X # cs) s y" and
    C: "z a. c = (z ::= a :: com_flow)  z  x 
      sources cs s x  sources (X # cs) s x" and
    D: "Y y. c = Y 
      sources cs s y  sources (X # cs) s y" and
    E: "z  (case c of
      z ::= a  if z = x
        then sources_aux cs s x   {sources cs s y | y.
          run_flow cs s: dom y  dom x  y  avars a}
        else sources cs s x |
      X 
        sources cs s x   {sources cs s y | y.
          run_flow cs s: dom y  dom x  y  X})"
  shows "z  sources (X # cs @ [c]) s x"
proof -
  {
    fix a
    assume
      F: "A. (y. run_flow cs s: dom y  dom x 
        A = sources (X # cs) s y  y  avars a)  z  A" and
      G: "c = x ::= a"
    have "z  sources_aux cs s x   {sources cs s y | y.
      run_flow cs s: dom y  dom x  y  avars a}"
      using E and G by simp
    hence "z  sources_aux (X # cs) s x"
    using A and G proof (erule_tac UnE, blast)
      assume "z   {sources cs s y | y.
        run_flow cs s: dom y  dom x  y  avars a}"
      then obtain y where
        H: "z  sources cs s y" and
        I: "run_flow cs s: dom y  dom x" and
        J: "y  avars a"
        by blast
      have "z  sources (X # cs) s y"
        using B and G and H by blast
      hence "y  avars a"
        using F and I by blast
      thus ?thesis
        using J by contradiction
    qed
  }
  moreover {
    fix y a
    assume "c = y ::= a" and "y  x"
    moreover from this have "z  sources cs s x"
      using E by simp
    ultimately have "z  sources (X # cs) s x"
      using C by blast
  }
  moreover {
    fix Y
    assume
      F: "A. (y. run_flow cs s: dom y  dom x 
        A = sources (X # cs) s y  y  Y)  z  A" and
      G: "c = Y"
    have "z  sources cs s x   {sources cs s y | y.
      run_flow cs s: dom y  dom x  y  Y}"
      using E and G by simp
    hence "z  sources (X # cs) s x"
    using D and G proof (erule_tac UnE, blast)
      assume "z   {sources cs s y | y.
        run_flow cs s: dom y  dom x  y  Y}"
      then obtain y where
        H: "z  sources cs s y" and
        I: "run_flow cs s: dom y  dom x" and
        J: "y  Y"
        by blast
      have "z  sources (X # cs) s y"
        using D and G and H by blast
      hence "y  Y"
        using F and I by blast
      thus ?thesis
        using J by contradiction
    qed
  }
  ultimately show ?thesis
    by (simp only: append_Cons [symmetric] sources.simps,
     auto split: com_flow.split)
qed

lemma sources_observe_tl_2:
  assumes
    A: "z a. c = (z ::= a :: com_flow) 
      sources_aux cs s x  sources_aux (X # cs) s x" and
    B: "Y. c = Y 
      sources_aux cs s x  sources_aux (X # cs) s x" and
    C: "Y y. c = Y 
      sources cs s y  sources (X # cs) s y" and
    D: "z  (case c of
      z ::= a 
        sources_aux cs s x |
      X 
        sources_aux cs s x   {sources cs s y | y.
          run_flow cs s: dom y  dom x  y  X})"
  shows "z  sources_aux (X # cs @ [c]) s x"
proof -
  {
    fix y a
    assume "c = y ::= a"
    moreover from this have "z  sources_aux cs s x"
      using D by simp
    ultimately have "z  sources_aux (X # cs) s x"
      using A by blast
  }
  moreover {
    fix Y
    assume
      E: "A. (y. run_flow cs s: dom y  dom x 
        A = sources (X # cs) s y  y  Y)  z  A" and
      F: "c = Y"
    have "z  sources_aux cs s x   {sources cs s y | y.
      run_flow cs s: dom y  dom x  y  Y}"
      using D and F by simp
    hence "z  sources_aux (X # cs) s x"
    using B and F proof (erule_tac UnE, blast)
      assume "z   {sources cs s y | y.
        run_flow cs s: dom y  dom x  y  Y}"
      then obtain y where
        H: "z  sources cs s y" and
        I: "run_flow cs s: dom y  dom x" and
        J: "y  Y"
        by blast
      have "z  sources (X # cs) s y"
        using C and F and H by blast
      hence "y  Y"
        using E and I by blast
      thus ?thesis
        using J by contradiction
    qed
  }
  ultimately show ?thesis
    by (simp only: append_Cons [symmetric] sources_aux.simps,
     auto split: com_flow.split)
qed

lemma sources_observe_tl:
 "sources cs s x  sources (X # cs) s x"
and sources_aux_observe_tl:
 "sources_aux cs s x  sources_aux (X # cs) s x"
proof (induction cs s x and cs s x rule: sources_induct)
  fix cs c s x
  show
   "z a. c = z ::= a  z = x 
      sources_aux cs s x  sources_aux (X # cs) s x;
    z a b y. c = z ::= a  z = x 
      sources cs s y  sources (X # cs) s y;
    z a. c = z ::= a  z  x 
      sources cs s x  sources (X # cs) s x;
    Y. c = Y 
      sources cs s x  sources (X # cs) s x;
    Y a y. c = Y 
      sources cs s y  sources (X # cs) s y 
      sources (cs @ [c]) s x  sources (X # cs @ [c]) s x"
    by (auto, rule sources_observe_tl_1)
next
  fix s x
  show "sources [] s x  sources [X] s x"
    by (subst (3) append_Nil [symmetric],
     simp only: sources.simps, simp)
next
  fix cs c s x
  show
   "z a. c = z ::= a 
      sources_aux cs s x  sources_aux (X # cs) s x;
    Y. c = Y 
      sources_aux cs s x  sources_aux (X # cs) s x;
    Y a y. c = Y 
      sources cs s y  sources (X # cs) s y 
      sources_aux (cs @ [c]) s x  sources_aux (X # cs @ [c]) s x"
    by (auto, rule sources_observe_tl_2)
qed simp


lemma sources_member_1:
  assumes
    A: "z a. c = (x ::= a :: com_flow)  z = x 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x" and
    B: "z a w. c = (x ::= a :: com_flow)  z = x 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w" and
    C: "z a. c = (z ::= a :: com_flow)  z  x 
      y  sources cs' (run_flow cs s) x 
        sources cs s y  sources (cs @ cs') s x" and
    D: "Y w. c = Y 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w" and
    E: "y  (case c of
      z ::= a  if z = x
        then sources_aux cs' (run_flow cs s) x 
           {sources cs' (run_flow cs s) y | y.
            run_flow cs' (run_flow cs s): dom y  dom x  y  avars a}
        else sources cs' (run_flow cs s) x |
      X 
        sources cs' (run_flow cs s) x 
           {sources cs' (run_flow cs s) y | y.
            run_flow cs' (run_flow cs s): dom y  dom x  y  X})" and
    F: "z  sources cs s y"
  shows "z  sources (cs @ cs' @ [c]) s x"
proof -
  {
    fix a
    assume
      G: "A. (y. run_flow cs' (run_flow cs s): dom y  dom x 
        A = sources (cs @ cs') s y  y  avars a)  z  A" and
      H: "c = x ::= a"
    have "y  sources_aux cs' (run_flow cs s) x 
       {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  avars a}"
      using E and H by simp
    hence "z  sources_aux (cs @ cs') s x"
    using A and F and H proof (erule_tac UnE, blast)
      assume "y   {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  avars a}"
      then obtain w where
        I: "y  sources cs' (run_flow cs s) w" and
        J: "run_flow cs' (run_flow cs s): dom w  dom x" and
        K: "w  avars a"
        by blast
      have "z  sources (cs @ cs') s w"
        using B and F and H and I by blast
      hence "w  avars a"
        using G and J by blast
      thus ?thesis
        using K by contradiction
    qed
  }
  moreover {
    fix w a
    assume "c = w ::= a" and "w  x"
    moreover from this have "y  sources cs' (run_flow cs s) x"
      using E by simp
    ultimately have "z  sources (cs @ cs') s x"
      using C and F by blast
  }
  moreover {
    fix Y
    assume
      G: "A. (y. run_flow cs' (run_flow cs s): dom y  dom x 
        A = sources (cs @ cs') s y  y  Y)  z  A" and
      H: "c = Y"
    have "y  sources cs' (run_flow cs s) x 
       {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  Y}"
      using E and H by simp
    hence "z  sources (cs @ cs') s x"
    using D and F and H proof (erule_tac UnE, blast)
      assume "y   {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  Y}"
      then obtain w where
        I: "y  sources cs' (run_flow cs s) w" and
        J: "run_flow cs' (run_flow cs s): dom w  dom x" and
        K: "w  Y"
        by blast
      have "z  sources (cs @ cs') s w"
        using D and F and H and I by blast
      hence "w  Y"
        using G and J by blast
      thus ?thesis
        using K by contradiction
    qed
  }
  ultimately show ?thesis
    by (simp only: append_assoc [symmetric] sources.simps,
     auto simp: run_flow_append split: com_flow.split)
qed

lemma sources_member_2:
  assumes
    A: "z a. c = (z ::= a :: com_flow) 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x" and
    B: "Y. c = Y 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x" and
    C: "Y w. c = Y 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w" and
    D: "y  (case c of
      z ::= a 
        sources_aux cs' (run_flow cs s) x |
      X 
        sources_aux cs' (run_flow cs s) x 
           {sources cs' (run_flow cs s) y | y.
            run_flow cs' (run_flow cs s): dom y  dom x  y  X})" and
    E: "z  sources cs s y"
  shows "z  sources_aux (cs @ cs' @ [c]) s x"
proof -
  {
    fix w a
    assume "c = w ::= a"
    moreover from this have "y  sources_aux cs' (run_flow cs s) x"
      using D by simp
    ultimately have "z  sources_aux (cs @ cs') s x"
      using A and E by blast
  }
  moreover {
    fix Y
    assume
      G: "A. (y. run_flow cs' (run_flow cs s): dom y  dom x 
        A = sources (cs @ cs') s y  y  Y)  z  A" and
      H: "c = Y"
    have "y  sources_aux cs' (run_flow cs s) x 
       {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  Y}"
      using D and H by simp
    hence "z  sources_aux (cs @ cs') s x"
    using B and E and H proof (erule_tac UnE, blast)
      assume "y   {sources cs' (run_flow cs s) y | y.
        run_flow cs' (run_flow cs s): dom y  dom x  y  Y}"
      then obtain w where
        I: "y  sources cs' (run_flow cs s) w" and
        J: "run_flow cs' (run_flow cs s): dom w  dom x" and
        K: "w  Y"
        by blast
      have "z  sources (cs @ cs') s w"
        using C and E and H and I by blast
      hence "w  Y"
        using G and J by blast
      thus ?thesis
        using K by contradiction
    qed
  }
  ultimately show ?thesis
    by (simp only: append_assoc [symmetric] sources_aux.simps,
     auto simp: run_flow_append split: com_flow.split)
qed

lemma sources_member:
 "y  sources cs' (run_flow cs s) x 
    sources cs s y  sources (cs @ cs') s x"
and sources_aux_member:
 "y  sources_aux cs' (run_flow cs s) x 
    sources cs s y  sources_aux (cs @ cs') s x"
proof (induction cs' s x and cs' s x rule: sources_induct)
  fix cs' c s x
  show
   "z a. c = z ::= a  z = x 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x;
    z a b w. c = z ::= a  z = x 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w;
    z a. c = z ::= a  z  x 
      y  sources cs' (run_flow cs s) x 
        sources cs s y  sources (cs @ cs') s x;
    Y. c = Y 
      y  sources cs' (run_flow cs s) x 
        sources cs s y  sources (cs @ cs') s x;
    Y a w. c = Y 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w;
    y  sources (cs' @ [c]) (run_flow cs s) x 
      sources cs s y  sources (cs @ cs' @ [c]) s x"
    by (auto, rule sources_member_1)
next
  fix cs' c s x
  show
   "z a. c = z ::= a 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x;
    Y. c = Y 
      y  sources_aux cs' (run_flow cs s) x 
        sources cs s y  sources_aux (cs @ cs') s x;
    Y a w. c = Y 
      y  sources cs' (run_flow cs s) w 
        sources cs s y  sources (cs @ cs') s w;
    y  sources_aux (cs' @ [c]) (run_flow cs s) x 
      sources cs s y  sources_aux (cs @ cs' @ [c]) s x"
    by (auto, rule sources_member_2)
qed simp_all


lemma ctyping2_confine:
 "(c, s)  s'; (U, v)  c (⊆ A, X) = Some (B, Y);
    (C, Z)  U. ¬ C: dom ` Z  {dom x}  s' x = s x"
by (induction arbitrary: A B X Y U v rule: big_step_induct,
 auto split: if_split_asm option.split_asm prod.split_asm, fastforce+)

lemma ctyping2_term_if:
 "x' y' z'' s. x' = x  y' = y  z = z''  s'. (c1, s)  s';
    x' y' z'' s. x' = x  y' = y  z' = z''  s'. (c2, s)  s' 
  s'. (IF b THEN c1 ELSE c2, s)  s'"
by (cases "bval b s", fastforce+)

lemma ctyping2_term:
 "(U, v)  c (⊆ A, X) = Some (B, Y);
    (C, Z)  U. ¬ C: dom ` Z  UNIV  s'. (c, s)  s'"
by (induction "(U, v)" c A X arbitrary: B Y U v s rule: ctyping2.induct,
 auto split: if_split_asm option.split_asm prod.split_asm, fastforce,
 erule ctyping2_term_if)


lemma ctyping2_correct_aux_skip [elim]:
 "(SKIP, s) →*{cfs1} (c1, s1); (c1, s1) →*{cfs2} (c2, s2) 
    (t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. (p  U. case p of (B, W) 
      s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs2) x)"
by (fastforce dest: small_stepsl_skip)

lemma ctyping2_correct_aux_assign [elim]:
  assumes
    A: "(if (s  Univ? A X. y  avars a. s: dom y  dom x) 
          (p  U. B Y. p = (B, Y) 
            (s  B. y  Y. s: dom y  dom x))
        then Some (if x  state  A  {}
          then if v  a (⊆ X)
            then ({s(x := aval a s) |s. s  A}, insert x X)
            else (A, X - {x})
          else (A, Univ?? A X))
        else None) = Some (B, Y)"
      (is "(if ?P then _ else _) = _") and
    B: "(x ::= a, s) →*{cfs1} (c1, s1)" and
    C: "(c1, s1) →*{cfs2} (c2, s2)" and
    D: "r  A" and
    E: "s = r (⊆ state  X)"
  shows
   "(t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. (p  U. case p of (B, Y) 
      s  B. y  Y. ¬ s: dom y  dom x)  no_upd (flow cfs2) x)"
proof -
  have ?P
    using A by (simp split: if_split_asm)
  have F: "avars a  {y. s: dom y  dom x}"
  proof (cases "state  X")
    case True
    with E have "interf s = interf r"
      by (blast intro: interf_state)
    with D and `?P` show ?thesis
      by (erule_tac conjE, drule_tac bspec, auto simp: univ_states_if_def)
  next
    case False
    with D and `?P` show ?thesis
      by (erule_tac conjE, drule_tac bspec, auto simp: univ_states_if_def)
  qed
  have "(c1, s1) = (x ::= a, s)  (c1, s1) = (SKIP, s(x := aval a s))"
    using B by (blast dest: small_stepsl_assign)
  thus ?thesis
  proof
    assume "(c1, s1) = (x ::= a, s)"
    moreover from this have "(x ::= a, s) →*{cfs2} (c2, s2)"
      using C by simp
    hence "(c2, s2) = (x ::= a, s)  flow cfs2 = [] 
      (c2, s2) = (SKIP, s(x := aval a s))  flow cfs2 = [x ::= a]"
      by (rule small_stepsl_assign)
    moreover {
      fix t
      have "c' t'. y.
        (y = x 
          (s = t (⊆ sources_aux [x ::= a] s x) 
            (x ::= a, t) →* (c', t')  c' = SKIP) 
          (s = t (⊆ sources [x ::= a] s x)  aval a s = t' x)) 
        (y  x 
          (s = t (⊆ sources_aux [x ::= a] s y) 
            (x ::= a, t) →* (c', t')  c' = SKIP) 
          (s = t (⊆ sources [x ::= a] s y)  s y = t' y))"
      proof (rule exI [of _ SKIP], rule exI [of _ "t(x := aval a t)"])
        {
          assume "s = t (⊆ sources [x ::= a] s x)"
          hence "s = t (⊆ {y. s: dom y  dom x  y  avars a})"
            by (subst (asm) append_Nil [symmetric],
             simp only: sources.simps, auto)
          hence "aval a s = aval a t"
            using F by (blast intro: avars_aval)
        }
        moreover {
          fix y
          assume "s = t (⊆ sources [x ::= a] s y)" and "y  x"
          hence "s y = t y"
            by (subst (asm) append_Nil [symmetric],
             simp only: sources.simps, auto)
        }
        ultimately show "y.
          (y = x 
            (s = t (⊆ sources_aux [x ::= a] s x) 
              (x ::= a, t) →* (SKIP, t(x := aval a t))  SKIP = SKIP) 
            (s = t (⊆ sources [x ::= a] s x) 
              aval a s = (t(x := aval a t)) x)) 
          (y  x 
            (s = t (⊆ sources_aux [x ::= a] s y) 
              (x ::= a, t) →* (SKIP, t(x := aval a t))  SKIP = SKIP) 
            (s = t (⊆ sources [x ::= a] s y) 
              s y = (t(x := aval a t)) y))"
          by simp
      qed
    }
    ultimately show ?thesis
      using `?P` by fastforce
  next
    assume "(c1, s1) = (SKIP, s(x := aval a s))"
    moreover from this have "(SKIP, s(x := aval a s)) →*{cfs2} (c2, s2)"
      using C by simp
    hence "(c2, s2) = (SKIP, s(x := aval a s))  flow cfs2 = []"
      by (rule small_stepsl_skip)
    ultimately show ?thesis
      by auto
  qed
qed

lemma ctyping2_correct_aux_seq:
  assumes
    A: "B' s c' c'' s1 s2 cfs1 cfs2. B = B' 
      r  A. s = r (⊆ state  X) 
        (c1, s) →*{cfs1} (c', s1)  (c', s1) →*{cfs2} (c'', s2) 
          (t1. c2' t2. x.
            (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
              (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
            (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
          (x. (p  U. case p of (B, W) 
            s  B. y  W. ¬ s: dom y  dom x) 
              no_upd (flow cfs2) x)" and
    B: "B' B'' C Z s c' c'' s1 s2 cfs1 cfs2. B = B'  B'' = B' 
      (U, v)  c2 (⊆ B', Y) = Some (C, Z) 
        r  B'. s = r (⊆ state  Y) 
          (c2, s) →*{cfs1} (c', s1)  (c', s1) →*{cfs2} (c'', s2) 
            (t1. c2' t2. x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
            (x. (p  U. case p of (B, W) 
              s  B. y  W. ¬ s: dom y  dom x) 
                no_upd (flow cfs2) x)" and
    C: "(U, v)  c1 (⊆ A, X) = Some (B, Y)" and
    D: "(U, v)  c2 (⊆ B, Y) = Some (C, Z)" and
    E: "(c1;; c2, s) →*{cfs1} (c', s1)" and
    F: "(c', s1) →*{cfs2} (c'', s2)" and
    G: "r  A" and
    H: "s = r (⊆ state  X)"
  shows
   "(t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. (p  U. case p of (B, W) 
      s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs2) x)"
proof -
  have
   "(d' cfs. c' = d';; c2 
      (c1, s) →*{cfs} (d', s1)) 
    (s' cfs cfs'.
      (c1, s) →*{cfs} (SKIP, s') 
      (c2, s') →*{cfs'} (c', s1))"
    using E by (blast dest: small_stepsl_seq)
  thus ?thesis
  proof (rule disjE, (erule_tac exE)+, (erule_tac [2] exE)+,
   erule_tac [!] conjE)
    fix d' cfs
    assume
      I: "c' = d';; c2" and
      J: "(c1, s) →*{cfs} (d', s1)"
    hence "(d';; c2, s1) →*{cfs2} (c'', s2)"
      using F by simp
    hence
     "(d'' cfs'. c'' = d'';; c2 
        (d', s1) →*{cfs'} (d'', s2) 
        flow cfs2 = flow cfs') 
      (s' cfs' cfs''.
        (d', s1) →*{cfs'} (SKIP, s') 
        (c2, s') →*{cfs''} (c'', s2) 
        flow cfs2 = flow cfs' @ flow cfs'')"
      by (blast dest: small_stepsl_seq)
    thus ?thesis
    proof (rule disjE, (erule_tac exE)+, (erule_tac [2] exE)+,
     (erule_tac [!] conjE)+)
      fix d'' cfs'
      assume "(d', s1) →*{cfs'} (d'', s2)"
      hence K:
       "(t1. c2' t2. x.
          (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
            (d', t1) →* (c2', t2)  (d'' = SKIP) = (c2' = SKIP)) 
          (s1 = t1 (⊆ sources (flow cfs') s1 x)  s2 x = t2 x)) 
        (x. (p  U. case p of (B, W) 
          s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs') x)"
        using A [of B s cfs d' s1 cfs' d'' s2] and J and G and H by blast
      moreover assume "c'' = d'';; c2" and "flow cfs2 = flow cfs'"
      moreover {
        fix t1
        obtain c2' and t2 where L: "x.
          (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
            (d', t1) →* (c2', t2)  (d'' = SKIP) = (c2' = SKIP)) 
          (s1 = t1 (⊆ sources (flow cfs') s1 x)  s2 x = t2 x)"
          using K by blast
        have "c2' t2. x.
          (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
            (d';; c2, t1) →* (c2', t2)  c2'  SKIP) 
          (s1 = t1 (⊆ sources (flow cfs') s1 x)  s2 x = t2 x)"
        proof (rule exI [of _ "c2';; c2"], rule exI [of _ t2])
          show "x.
            (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
              (d';; c2, t1) →* (c2';; c2, t2)  c2';; c2  SKIP) 
            (s1 = t1 (⊆ sources (flow cfs') s1 x)  s2 x = t2 x)"
            using L by (auto intro: star_seq2)
        qed
      }
      ultimately show ?thesis
        using I by auto
    next
      fix s' cfs' cfs''
      assume
        K: "(d', s1) →*{cfs'} (SKIP, s')" and
        L: "(c2, s') →*{cfs''} (c'', s2)"
      moreover have M: "s' = run_flow (flow cfs') s1"
        using K by (rule small_stepsl_run_flow)
      ultimately have N:
       "(t1. c2' t2. x.
          (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
            (d', t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
          (s1 = t1 (⊆ sources (flow cfs') s1 x) 
            run_flow (flow cfs') s1 x = t2 x)) 
        (x. (p  U. case p of (B, W) 
          s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs') x)"
        using A [of B s cfs d' s1 cfs' SKIP s'] and J and G and H by blast
      have O: "s2 = run_flow (flow cfs'') s'"
        using L by (rule small_stepsl_run_flow)
      moreover have "(c1, s) →*{cfs @ cfs'} (SKIP, s')"
        using J and K by (simp add: small_stepsl_append)
      hence "(c1, s)  s'"
        by (auto dest: small_stepsl_steps simp: big_iff_small)
      hence "s'  Univ B (⊆ state  Y)"
        using C and G and H by (erule_tac ctyping2_approx, auto)
      ultimately have P:
       "(t1. c2' t2. x.
          (run_flow (flow cfs') s1 = t1
            (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x) 
              (c2, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
          (run_flow (flow cfs') s1 = t1
            (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x) 
              run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t2 x)) 
        (x. (p  U. case p of (B, W) 
          s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs'') x)"
        using B [of B B C Z s' "[]" c2 s' cfs'' c'' s2]
         and D and L and M by simp
      moreover assume "flow cfs2 = flow cfs' @ flow cfs''"
      moreover {
        fix t1
        obtain c2' and t2 where Q: "x.
          (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
            (d', t1) →* (SKIP, t2)  (SKIP = SKIP) = (c2' = SKIP)) 
          (s1 = t1 (⊆ sources (flow cfs') s1 x) 
            run_flow (flow cfs') s1 x = t2 x)"
          using N by blast
        obtain c3' and t3 where R: "x.
          (run_flow (flow cfs') s1 = t2
            (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x) 
              (c2, t2) →* (c3', t3)  (c'' = SKIP) = (c3' = SKIP)) 
          (run_flow (flow cfs') s1 = t2
            (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x) 
              run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t3 x)"
          using P by blast
        {
          fix x
          assume S: "s1 = t1
            (⊆ sources_aux (flow cfs' @ flow cfs'') s1 x)"
          moreover have "sources_aux (flow cfs') s1 x 
            sources_aux (flow cfs' @ flow cfs'') s1 x"
            by (rule sources_aux_append)
          ultimately have "(d', t1) →* (SKIP, t2)"
            using Q by blast
          hence "(d';; c2, t1) →* (SKIP;; c2, t2)"
            by (rule star_seq2)
          hence "(d';; c2, t1) →* (c2, t2)"
            by (blast intro: star_trans)
          moreover have "run_flow (flow cfs') s1 = t2
            (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x)"
          proof
            fix y
            assume "y  sources_aux (flow cfs'')
              (run_flow (flow cfs') s1) x"
            hence "sources (flow cfs') s1 y 
              sources_aux (flow cfs' @ flow cfs'') s1 x"
              by (rule sources_aux_member)
            thus "run_flow (flow cfs') s1 y = t2 y"
              using Q and S by blast
          qed
          hence "(c2, t2) →* (c3', t3)  (c'' = SKIP) = (c3' = SKIP)"
            using R by simp
          ultimately have "(d';; c2, t1) →* (c3', t3) 
            (c'' = SKIP) = (c3' = SKIP)"
            by (blast intro: star_trans)
        }
        moreover {
          fix x
          assume S: "s1 = t1
            (⊆ sources (flow cfs' @ flow cfs'') s1 x)"
          have "run_flow (flow cfs') s1 = t2
            (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x)"
          proof
            fix y
            assume "y  sources (flow cfs'')
              (run_flow (flow cfs') s1) x"
            hence "sources (flow cfs') s1 y 
              sources (flow cfs' @ flow cfs'') s1 x"
              by (rule sources_member)
            thus "run_flow (flow cfs') s1 y = t2 y"
              using Q and S by blast
          qed
          hence "run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t3 x"
            using R by simp
        }
        ultimately have "c2' t2. x.
          (s1 = t1 (⊆ sources_aux (flow cfs' @ flow cfs'') s1 x) 
            (d';; c2, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
          (s1 = t1 (⊆ sources (flow cfs' @ flow cfs'') s1 x) 
            run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t2 x)"
          by auto
      }
      ultimately show ?thesis
        using I and N and M and O by (auto simp: no_upd_append)
    qed
  next
    fix s' cfs cfs'
    assume "(c1, s) →*{cfs} (SKIP, s')"
    hence "(c1, s)  s'"
      by (auto dest: small_stepsl_steps simp: big_iff_small)
    hence "s'  Univ B (⊆ state  Y)"
      using C and G and H by (erule_tac ctyping2_approx, auto)
    moreover assume "(c2, s') →*{cfs'} (c', s1)"
    ultimately show ?thesis
      using B [of B B C Z s' cfs' c' s1 cfs2 c'' s2] and D and F by simp
  qed
qed

lemma ctyping2_correct_aux_if:
  assumes
    A: "U' B C s c' c'' s1 s2 cfs1 cfs2.
      U' = insert (Univ? A X, bvars b) U  B = B1  C1 = C 
        r  B1. s = r (⊆ state  X) 
          (c1, s) →*{cfs1} (c', s1)  (c', s1) →*{cfs2} (c'', s2) 
            (t1. c2' t2. x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
            (x.
              ((s  Univ? A X. y  bvars b. ¬ s: dom y  dom x) 
                no_upd (flow cfs2) x) 
              ((p  U. case p of (B, W) 
                s  B. y  W. ¬ s: dom y  dom x) 
                  no_upd (flow cfs2) x))" and
    B: "U' B C s c' c'' s1 s2 cfs1 cfs2.
      U' = insert (Univ? A X, bvars b) U  B = B1  C2 = C 
        r  B2. s = r (⊆ state  X) 
          (c2, s) →*{cfs1} (c', s1)  (c', s1) →*{cfs2} (c'', s2) 
            (t1. c2' t2. x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
            (x.
              ((s  Univ? A X. y  bvars b. ¬ s: dom y  dom x) 
                no_upd (flow cfs2) x) 
              ((p  U. case p of (B, W) 
                s  B. y  W. ¬ s: dom y  dom x) 
                  no_upd (flow cfs2) x))" and
    C: " b (⊆ A, X) = (B1, B2)" and
    D: "(insert (Univ? A X, bvars b) U, v)  c1 (⊆ B1, X) =
      Some (C1, Y1)" and
    E: "(insert (Univ? A X, bvars b) U, v)  c2 (⊆ B2, X) =
      Some (C2, Y2)" and
    F: "(IF b THEN c1 ELSE c2, s) →*{cfs1} (c', s1)" and
    G: "(c', s1) →*{cfs2} (c'', s2)" and
    H: "r  A" and
    I: "s = r (⊆ state  X)"
  shows
   "(t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
    (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. (p  U. case p of (B, W) 
      s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs2) x)"
proof -
  let ?U' = "insert (Univ? A X, bvars b) U"
  have J: "cs t x. s = t (⊆ sources_aux (bvars b # cs) s x) 
    bval b s  bval b t  ¬ Univ? A X: dom ` bvars b  {dom x}"
  proof (clarify del: notI)
    fix cs t x
    assume "s = t (⊆ sources_aux (bvars b # cs) s x)"
    moreover assume "bval b s  bval b t"
    hence "¬ s = t (⊆ bvars b)"
      by (erule_tac contrapos_nn, auto dest: bvars_bval)
    ultimately have "¬ (y  bvars b. s: dom y  dom x)"
      by (blast dest: sources_aux_observe_hd)
    moreover {
      fix r y
      assume "r  A" and "y  bvars b" and "¬ s: dom y  dom x"
      moreover assume "state  X" and "s = r (⊆ state  X)"
      hence "interf s = interf r"
        by (blast intro: interf_state)
      ultimately have "s  A. y  bvars b. ¬ s: dom y  dom x"
        by auto
    }
    ultimately show "¬ Univ? A X: dom ` bvars b  {dom x}"
      using H and I by (auto simp: univ_states_if_def)
  qed
  have
   "(c', s1) = (IF b THEN c1 ELSE c2, s) 
    bval b s  (c1, s) →*{tl cfs1} (c', s1) 
    ¬ bval b s  (c2, s) →*{tl cfs1} (c', s1)"
    using F by (blast dest: small_stepsl_if)
  thus ?thesis
  proof (rule disjE, erule_tac [2] disjE, erule_tac [2-3] conjE)
    assume K: "(c', s1) = (IF b THEN c1 ELSE c2, s)"
    hence "(IF b THEN c1 ELSE c2, s) →*{cfs2} (c'', s2)"
      using G by simp
    hence
     "(c'', s2) = (IF b THEN c1 ELSE c2, s) 
        flow cfs2 = [] 
      bval b s  (c1, s) →*{tl cfs2} (c'', s2) 
        flow cfs2 = bvars b # flow (tl cfs2) 
      ¬ bval b s  (c2, s) →*{tl cfs2} (c'', s2) 
        flow cfs2 = bvars b # flow (tl cfs2)"
      by (rule small_stepsl_if)
    thus ?thesis
    proof (rule disjE, erule_tac [2] disjE, (erule_tac [2-3] conjE)+)
      assume "(c'', s2) = (IF b THEN c1 ELSE c2, s)  flow cfs2 = []"
      thus ?thesis
        using K by auto
    next
      assume L: "bval b s"
      with C and H and I have "s  Univ B1 (⊆ state  X)"
        by (drule_tac btyping2_approx [where s = s], auto)
      moreover assume M: "(c1, s) →*{tl cfs2} (c'', s2)"
      moreover from this have N: "s2 = run_flow (flow (tl cfs2)) s"
        by (rule small_stepsl_run_flow)
      ultimately have O:
       "(t1. c2' t2. x.
          (s = t1 (⊆ sources_aux (flow (tl cfs2)) s x) 
            (c1, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
          (s = t1 (⊆ sources (flow (tl cfs2)) s x) 
            run_flow (flow (tl cfs2)) s x = t2 x)) 
        (x.
          ((s  Univ? A X. y  bvars b. ¬ s: dom y  dom x) 
            no_upd (flow (tl cfs2)) x) 
          ((p  U. case p of (B, W) 
            s  B. y  W. ¬ s: dom y  dom x) 
              no_upd (flow (tl cfs2)) x))"
        using A [of ?U' B1 C1 s "[]" c1 s "tl cfs2" c'' s2] by simp
      moreover assume "flow cfs2 = bvars b # flow (tl cfs2)"
      moreover {
        fix t1
        have "c2' t2. x.
          (s = t1 (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
            (IF b THEN c1 ELSE c2, t1) →* (c2', t2) 
            (c'' = SKIP) = (c2' = SKIP)) 
          (s = t1 (⊆ sources (bvars b # flow (tl cfs2)) s x) 
            run_flow (flow (tl cfs2)) s x = t2 x)"
        proof (cases "bval b t1")
          case True
          hence P: "(IF b THEN c1 ELSE c2, t1)  (c1, t1)" ..
          obtain c2' and t2 where Q: "x.
            (s = t1 (⊆ sources_aux (flow (tl cfs2)) s x) 
              (c1, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
            (s = t1 (⊆ sources (flow (tl cfs2)) s x) 
              run_flow (flow (tl cfs2)) s x = t2 x)"
            using O by blast
          {
            fix x
            assume "s = t1
              (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
            moreover have "sources_aux (flow (tl cfs2)) s x 
              sources_aux (bvars b # flow (tl cfs2)) s x"
              by (rule sources_aux_observe_tl)
            ultimately have "(IF b THEN c1 ELSE c2, t1) →* (c2', t2) 
              (c'' = SKIP) = (c2' = SKIP)"
              using P and Q by (blast intro: star_trans)
          }
          moreover {
            fix x
            assume "s = t1
              (⊆ sources (bvars b # flow (tl cfs2)) s x)"
            moreover have "sources (flow (tl cfs2)) s x 
              sources (bvars b # flow (tl cfs2)) s x"
              by (rule sources_observe_tl)
            ultimately have "run_flow (flow (tl cfs2)) s x = t2 x"
              using Q by blast
          }
          ultimately show ?thesis
            by auto
        next
          assume P: "¬ bval b t1"
          show ?thesis
          proof (cases "x. s = t1
           (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)")
            from P have "(IF b THEN c1 ELSE c2, t1)  (c2, t1)" ..
            moreover assume "x. s = t1
              (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
            hence "x. ¬ Univ? A X: dom ` bvars b  {dom x}"
              using J and L and P by blast
            then obtain t2 where Q: "(c2, t1)  t2"
              using E by (blast dest: ctyping2_term)
            hence "(c2, t1) →* (SKIP, t2)"
              by (simp add: big_iff_small)
            ultimately have
              R: "(IF b THEN c1 ELSE c2, t1) →* (SKIP, t2)"
              by (blast intro: star_trans)
            show ?thesis
            proof (cases "c'' = SKIP")
              case True
              show ?thesis
              proof (rule exI [of _ SKIP], rule exI [of _ t2])
                {
                  have "(IF b THEN c1 ELSE c2, t1) →* (SKIP, t2) 
                    (c'' = SKIP) = (SKIP = SKIP)"
                    using R and True by simp
                }
                moreover {
                  fix x
                  assume S: "s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x)"
                  moreover have
                   "sources_aux (bvars b # flow (tl cfs2)) s x 
                    sources (bvars b # flow (tl cfs2)) s x"
                    by (rule sources_aux_sources)
                  ultimately have "s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
                    by blast
                  hence T: "¬ Univ? A X: dom ` bvars b  {dom x}"
                    using J and L and P by blast
                  hence U: "no_upd (bvars b # flow (tl cfs2)) x"
                    using O by simp
                  hence "run_flow (flow (tl cfs2)) s x = s x"
                    by (simp add: no_upd_run_flow)
                  also from S and U have " = t1 x"
                    by (blast dest: no_upd_sources)
                  also from E and Q and T have " = t2 x"
                    by (drule_tac ctyping2_confine, auto)
                  finally have "run_flow (flow (tl cfs2)) s x = t2 x" .
                }
                ultimately show "x.
                  (s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
                      (IF b THEN c1 ELSE c2, t1) →* (SKIP, t2) 
                        (c'' = SKIP) = (SKIP = SKIP)) 
                  (s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x) 
                      run_flow (flow (tl cfs2)) s x = t2 x)"
                  by blast
              qed
            next
              case False
              show ?thesis
              proof (rule exI [of _ "IF b THEN c1 ELSE c2"],
               rule exI [of _ t1])
                {
                  have "(IF b THEN c1 ELSE c2, t1) →*
                    (IF b THEN c1 ELSE c2, t1) 
                      (c'' = SKIP) = (IF b THEN c1 ELSE c2 = SKIP)"
                    using False by simp
                }
                moreover {
                  fix x
                  assume S: "s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x)"
                  moreover have
                   "sources_aux (bvars b # flow (tl cfs2)) s x 
                    sources (bvars b # flow (tl cfs2)) s x"
                    by (rule sources_aux_sources)
                  ultimately have "s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
                    by blast
                  hence "¬ Univ? A X: dom ` bvars b  {dom x}"
                    using J and L and P by blast
                  hence T: "no_upd (bvars b # flow (tl cfs2)) x"
                    using O by simp
                  hence "run_flow (flow (tl cfs2)) s x = s x"
                    by (simp add: no_upd_run_flow)
                  also have " = t1 x"
                    using S and T by (blast dest: no_upd_sources)
                  finally have "run_flow (flow (tl cfs2)) s x = t1 x" .
                }
                ultimately show "x.
                  (s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
                      (IF b THEN c1 ELSE c2, t1) →*
                        (IF b THEN c1 ELSE c2, t1) 
                          (c'' = SKIP) = (IF b THEN c1 ELSE c2 = SKIP)) 
                  (s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x) 
                      run_flow (flow (tl cfs2)) s x = t1 x)"
                  by blast
              qed
            qed
          qed blast
        qed
      }
      ultimately show ?thesis
        using K and N by auto
    next
      assume L: "¬ bval b s"
      with C and H and I have "s  Univ B2 (⊆ state  X)"
        by (drule_tac btyping2_approx [where s = s], auto)
      moreover assume M: "(c2, s) →*{tl cfs2} (c'', s2)"
      moreover from this have N: "s2 = run_flow (flow (tl cfs2)) s"
        by (rule small_stepsl_run_flow)
      ultimately have O:
       "(t1. c2' t2. x.
          (s = t1 (⊆ sources_aux (flow (tl cfs2)) s x) 
            (c2, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
          (s = t1 (⊆ sources (flow (tl cfs2)) s x) 
            run_flow (flow (tl cfs2)) s x = t2 x)) 
        (x.
          ((s  Univ? A X. y  bvars b. ¬ s: dom y  dom x) 
            no_upd (flow (tl cfs2)) x) 
          ((p  U. case p of (B, W) 
            s  B. y  W. ¬ s: dom y  dom x) 
              no_upd (flow (tl cfs2)) x))"
        using B [of ?U' B1 C2 s "[]" c2 s "tl cfs2" c'' s2] by simp
      moreover assume "flow cfs2 = bvars b # flow (tl cfs2)"
      moreover {
        fix t1
        have "c2' t2. x.
          (s = t1 (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
            (IF b THEN c1 ELSE c2, t1) →* (c2', t2) 
            (c'' = SKIP) = (c2' = SKIP)) 
          (s = t1 (⊆ sources (bvars b # flow (tl cfs2)) s x) 
            run_flow (flow (tl cfs2)) s x = t2 x)"
        proof (cases "¬ bval b t1")
          case True
          hence P: "(IF b THEN c1 ELSE c2, t1)  (c2, t1)" ..
          obtain c2' and t2 where Q: "x.
            (s = t1 (⊆ sources_aux (flow (tl cfs2)) s x) 
              (c2, t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
            (s = t1 (⊆ sources (flow (tl cfs2)) s x) 
              run_flow (flow (tl cfs2)) s x = t2 x)"
            using O by blast
          {
            fix x
            assume "s = t1
              (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
            moreover have "sources_aux (flow (tl cfs2)) s x 
              sources_aux (bvars b # flow (tl cfs2)) s x"
              by (rule sources_aux_observe_tl)
            ultimately have "(IF b THEN c1 ELSE c2, t1) →* (c2', t2) 
              (c'' = SKIP) = (c2' = SKIP)"
              using P and Q by (blast intro: star_trans)
          }
          moreover {
            fix x
            assume "s = t1
              (⊆ sources (bvars b # flow (tl cfs2)) s x)"
            moreover have "sources (flow (tl cfs2)) s x 
              sources (bvars b # flow (tl cfs2)) s x"
              by (rule sources_observe_tl)
            ultimately have "run_flow (flow (tl cfs2)) s x = t2 x"
              using Q by blast
          }
          ultimately show ?thesis
            by auto
        next
          case False
          hence P: "bval b t1"
            by simp
          show ?thesis
          proof (cases "x. s = t1
           (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)")
            from P have "(IF b THEN c1 ELSE c2, t1)  (c1, t1)" ..
            moreover assume "x. s = t1
              (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
            hence "x. ¬ Univ? A X: dom ` bvars b  {dom x}"
              using J and L and P by blast
            then obtain t2 where Q: "(c1, t1)  t2"
              using D by (blast dest: ctyping2_term)
            hence "(c1, t1) →* (SKIP, t2)"
              by (simp add: big_iff_small)
            ultimately have
              R: "(IF b THEN c1 ELSE c2, t1) →* (SKIP, t2)"
              by (blast intro: star_trans)
            show ?thesis
            proof (cases "c'' = SKIP")
              case True
              show ?thesis
              proof (rule exI [of _ SKIP], rule exI [of _ t2])
                {
                  have "(IF b THEN c1 ELSE c2, t1) →* (SKIP, t2) 
                    (c'' = SKIP) = (SKIP = SKIP)"
                    using R and True by simp
                }
                moreover {
                  fix x
                  assume S: "s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x)"
                  moreover have
                   "sources_aux (bvars b # flow (tl cfs2)) s x 
                    sources (bvars b # flow (tl cfs2)) s x"
                    by (rule sources_aux_sources)
                  ultimately have "s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
                    by blast
                  hence T: "¬ Univ? A X: dom ` bvars b  {dom x}"
                    using J and L and P by blast
                  hence U: "no_upd (bvars b # flow (tl cfs2)) x"
                    using O by simp
                  hence "run_flow (flow (tl cfs2)) s x = s x"
                    by (simp add: no_upd_run_flow)
                  also from S and U have " = t1 x"
                    by (blast dest: no_upd_sources)
                  also from D and Q and T have " = t2 x"
                    by (drule_tac ctyping2_confine, auto)
                  finally have "run_flow (flow (tl cfs2)) s x = t2 x" .
                }
                ultimately show "x.
                  (s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
                      (IF b THEN c1 ELSE c2, t1) →* (SKIP, t2) 
                        (c'' = SKIP) = (SKIP = SKIP)) 
                  (s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x) 
                      run_flow (flow (tl cfs2)) s x = t2 x)"
                  by blast
              qed
            next
              case False
              show ?thesis
              proof (rule exI [of _ "IF b THEN c1 ELSE c2"],
               rule exI [of _ t1])
                {
                  have "(IF b THEN c1 ELSE c2, t1) →*
                    (IF b THEN c1 ELSE c2, t1) 
                      (c'' = SKIP) = (IF b THEN c1 ELSE c2 = SKIP)"
                    using False by simp
                }
                moreover {
                  fix x
                  assume S: "s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x)"
                  moreover have
                   "sources_aux (bvars b # flow (tl cfs2)) s x 
                    sources (bvars b # flow (tl cfs2)) s x"
                    by (rule sources_aux_sources)
                  ultimately have "s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x)"
                    by blast
                  hence "¬ Univ? A X: dom ` bvars b  {dom x}"
                    using J and L and P by blast
                  hence T: "no_upd (bvars b # flow (tl cfs2)) x"
                    using O by simp
                  hence "run_flow (flow (tl cfs2)) s x = s x"
                    by (simp add: no_upd_run_flow)
                  also have " = t1 x"
                    using S and T by (blast dest: no_upd_sources)
                  finally have "run_flow (flow (tl cfs2)) s x = t1 x" .
                }
                ultimately show "x.
                  (s = t1
                    (⊆ sources_aux (bvars b # flow (tl cfs2)) s x) 
                      (IF b THEN c1 ELSE c2, t1) →*
                        (IF b THEN c1 ELSE c2, t1) 
                        (c'' = SKIP) = (IF b THEN c1 ELSE c2 = SKIP)) 
                  (s = t1
                    (⊆ sources (bvars b # flow (tl cfs2)) s x) 
                      run_flow (flow (tl cfs2)) s x = t1 x)"
                  by blast
              qed
            qed
          qed blast
        qed
      }
      ultimately show ?thesis
        using K and N by auto
    qed
  next
    assume "bval b s" and "(c1, s) →*{tl cfs1} (c', s1)"
    moreover from this and C and H and I have "s  Univ B1 (⊆ state  X)"
      by (drule_tac btyping2_approx [where s = s], auto)
    ultimately show ?thesis
      using A [of ?U' B1 C1 s "tl cfs1" c' s1 cfs2 c'' s2] and G by simp
  next
    assume "¬ bval b s" and "(c2, s) →*{tl cfs1} (c', s1)"
    moreover from this and C and H and I have "s  Univ B2 (⊆ state  X)"
      by (drule_tac btyping2_approx [where s = s], auto)
    ultimately show ?thesis
      using B [of ?U' B1 C2 s "tl cfs1" c' s1 cfs2 c'' s2] and G by simp
  qed
qed

lemma ctyping2_correct_aux_while:
  assumes
    A: "B C' B' D' s c1 c2 s1 s2 cfs1 cfs2.
      B = B1  C' = C  B' = B1' 
      (s  Univ? A X  Univ? C Y. x  bvars b. All (interf s (dom x))) 
      (p  U. case p of (B, W)  s  B. x  W. All (interf s (dom x))) 
        D = D'  r  B1. s = r (⊆ state  X) 
          (c, s) →*{cfs1} (c1, s1)  (c1, s1) →*{cfs2} (c2, s2) 
            t1. c2' t2. x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)" and
    B: "B C' B' D'' s c1 c2 s1 s2 cfs1 cfs2.
      B = B1  C' = C  B' = B1' 
      (s  Univ? A X  Univ? C Y. x  bvars b. All (interf s (dom x))) 
      (p  U. case p of (B, W)  s  B. x  W. All (interf s (dom x))) 
        D' = D''  r  B1'. s = r (⊆ state  Y) 
          (c, s) →*{cfs1} (c1, s1)  (c1, s1) →*{cfs2} (c2, s2) 
            t1. c2' t2. x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)" and
    C: "(if (s  Univ? A X  Univ? C Y. x  bvars b. All (interf s (dom x))) 
      (p  U. B W. p = (B, W)  (s  B. x  W. All (interf s (dom x))))
        then Some (B2  B2', Univ?? B2 X  Y) else None) = Some (B, W)" and
    D: " b (⊆ A, X) = (B1, B2)" and
    E: " c (⊆ B1, X) = (C, Y)" and
    F: " b (⊆ C, Y) = (B1', B2')" and
    G: "({}, False)  c (⊆ B1, X) = Some (D, Z)" and
    H: "({}, False)  c (⊆ B1', Y) = Some (D', Z')"
  shows
   "(WHILE b DO c, s) →*{cfs1} (c1, s1);
      (c1, s1) →*{cfs2} (c2, s2);
      s  Univ A (⊆ state  X)  Univ C (⊆ state  Y) 
    (t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. (p  U. case p of (B, W) 
      s  B. y  W. ¬ s: dom y  dom x)  no_upd (flow cfs2) x)"
proof (induction "cfs1 @ cfs2" arbitrary: cfs1 cfs2 s c1 s1 rule: length_induct)
  fix cfs1 cfs2 s c1 s1
  assume
    I: "(WHILE b DO c, s) →*{cfs1} (c1, s1)" and
    J: "(c1, s1) →*{cfs2} (c2, s2)"
  assume "cfs. length cfs < length (cfs1 @ cfs2) 
      (cfs1 cfs2. cfs = cfs1 @ cfs2 
        (s c1 s1. (WHILE b DO c, s) →*{cfs1} (c1, s1) 
          (c1, s1) →*{cfs2} (c2, s2) 
            s  Univ A (⊆ state  X)  Univ C (⊆ state  Y) 
              (t1. c2' t2. x.
                (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                  (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
                (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
              (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
                no_upd (flow cfs2) x)))"
  note K = this [rule_format]
  assume L: "s  Univ A (⊆ state  X)  Univ C (⊆ state  Y)"
  moreover {
    fix s'
    assume "s  Univ A (⊆ state  X)" and "bval b s"
    hence N: "s  Univ B1 (⊆ state  X)"
      using D by (drule_tac btyping2_approx, auto)
    assume "(c, s)  s'"
    hence "s'  Univ D (⊆ state  Z)"
      using G and N by (rule ctyping2_approx)
    moreover have "D  C  Y  Z"
      using E and G by (rule ctyping1_ctyping2)
    ultimately have "s'  Univ C (⊆ state  Y)"
      by blast
  }
  moreover {
    fix s'
    assume "s  Univ C (⊆ state  Y)" and "bval b s"
    hence N: "s  Univ B1' (⊆ state  Y)"
      using F by (drule_tac btyping2_approx, auto)
    assume "(c, s)  s'"
    hence "s'  Univ D' (⊆ state  Z')"
      using H and N by (rule ctyping2_approx)
    moreover obtain C' and Y' where O: " c (⊆ B1', Y) = (C', Y')"
      by (cases " c (⊆ B1', Y)", simp)
    hence "D'  C'  Y'  Z'"
      using H by (rule ctyping1_ctyping2)
    ultimately have P: "s'  Univ C' (⊆ state  Y')"
      by blast
    have " c (⊆ C, Y) = (C, Y)"
      using E by (rule ctyping1_idem)
    moreover have "B1'  C"
      using F by (blast dest: btyping2_un_eq)
    ultimately have "C'  C  Y  Y'"
      by (metis order_refl ctyping1_mono O)
    hence "s'  Univ C (⊆ state  Y)"
      using P by blast
  }
  ultimately have M:
   "s'. (c, s)  s'  bval b s  s'  Univ C (⊆ state  Y)"
    by blast
  have N:
   "(s  Univ? A X  Univ? C Y. x  bvars b. All (interf s (dom x))) 
    (p  U. B W. p = (B, W)  (s  B. x  W. All (interf s (dom x))))"
    using C by (simp split: if_split_asm)
  hence "cs x. ((B, Y)  U.
    s  B. y  Y. ¬ s: dom y  dom x)  no_upd cs x"
    by auto
  moreover {
    fix r t1
    assume O: "r  A" and P: "s = r (⊆ state  X)"
    have Q: "x. y  bvars b. s: dom y  dom x"
    proof (cases "state  X")
      case True
      with P have "interf s = interf r"
        by (blast intro: interf_state)
      with N and O show ?thesis
        by (erule_tac conjE, drule_tac bspec,
         auto simp: univ_states_if_def)
    next
      case False
      with N and O show ?thesis
        by (erule_tac conjE, drule_tac bspec,
         auto simp: univ_states_if_def)
    qed
    have "(c1, s1) = (WHILE b DO c, s) 
      (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs1} (c1, s1)"
      using I by (blast dest: small_stepsl_while)
    hence "c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)"
    proof
      assume R: "(c1, s1) = (WHILE b DO c, s)"
      hence "(WHILE b DO c, s) →*{cfs2} (c2, s2)"
        using J by simp
      hence
       "(c2, s2) = (WHILE b DO c, s) 
          flow cfs2 = [] 
        (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs2} (c2, s2) 
          flow cfs2 = flow (tl cfs2)"
        (is "?P  ?Q  ?R")
        by (rule small_stepsl_while)
      thus ?thesis
      proof (rule disjE, erule_tac [2] conjE)
        assume ?P
        with R show ?thesis
          by auto
      next
        assume ?Q and ?R
        have
         "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow (tl cfs2) = [] 
          bval b s  (c;; WHILE b DO c, s) →*{tl2 cfs2} (c2, s2) 
            flow (tl cfs2) = bvars b # flow (tl2 cfs2) 
          ¬ bval b s  (SKIP, s) →*{tl2 cfs2} (c2, s2) 
            flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          using `?Q` by (rule small_stepsl_if)
        thus ?thesis
        proof (erule_tac disjE, erule_tac [2] disjE, (erule_tac [2-3] conjE)+)
          assume "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow (tl cfs2) = []"
          with R and `?R` show ?thesis
            by auto
        next
          assume S: "bval b s"
          with D and O and P have T: "s  Univ B1 (⊆ state  X)"
            by (drule_tac btyping2_approx [where s = s], auto)
          assume U: "(c;; WHILE b DO c, s) →*{tl2 cfs2} (c2, s2)"
          hence
           "(c' cfs. c2 = c';; WHILE b DO c 
              (c, s) →*{cfs} (c', s2) 
              flow (tl2 cfs2) = flow cfs) 
            (s' cfs cfs'. length cfs' < length (tl2 cfs2) 
              (c, s) →*{cfs} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs'} (c2, s2) 
              flow (tl2 cfs2) = flow cfs @ flow cfs')"
            by (rule small_stepsl_seq)
          moreover assume "flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          moreover have "s2 = run_flow (flow (tl2 cfs2)) s"
            using U by (rule small_stepsl_run_flow)
          moreover {
            fix c' cfs
            assume "(c, s) →*{cfs} (c', run_flow (flow cfs) s)"
            then obtain c2' and t2 where V: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (c' = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              using A [of B1 C B1' D s "[]" c s cfs c'
               "run_flow (flow cfs) s"] and N and T by force
            {
              fix x
              assume W: "s = t1 (⊆ sources_aux (bvars b # flow cfs) s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (bvars b # (flow cfs)) s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (c2', t2)"
                using V by blast
              hence "(c;; WHILE b DO c, t1) →* (c2';; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and W by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(WHILE b DO c, t1) →* (c;; WHILE b DO c, t1)"
                by (blast intro: star_trans)
              ultimately have "(WHILE b DO c, t1) →*
               (c2';; WHILE b DO c, t2)  c2';; WHILE b DO c  SKIP"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources (bvars b # flow cfs) s x)"
              moreover have "sources (flow cfs) s x 
                sources (bvars b # (flow cfs)) s x"
                by (rule sources_observe_tl)
              ultimately have "run_flow (flow cfs) s x = t2 x"
                using V by blast
            }
            ultimately have "c2' t2. x.
              (s = t1 (⊆ sources_aux (bvars b # flow cfs) s x) 
                (WHILE b DO c, t1) →* (c2', t2)  c2'  SKIP) 
              (s = t1 (⊆ sources (bvars b # flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
          }
          moreover {
            fix s' cfs cfs'
            assume
              V: "length cfs' < length cfs2 - Suc (Suc 0)" and
              W: "(c, s) →*{cfs} (SKIP, s')" and
              X: "(WHILE b DO c, s') →*{cfs'}
                (c2, run_flow (flow cfs') (run_flow (flow cfs) s))"
            then obtain c2' and t2 where "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x)  s' x = t2 x)"
              using A [of B1 C B1' D s "[]" c s cfs SKIP s']
               and N and T by force
            moreover have Y: "s' = run_flow (flow cfs) s"
              using W by (rule small_stepsl_run_flow)
            ultimately have Z: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (SKIP, t2)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
            assume "s2 = run_flow (flow cfs') (run_flow (flow cfs) s)"
            moreover have "(c, s)  s'"
              using W by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and S by blast
            ultimately obtain c3' and t3 where AA: "x.
              (run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x) 
                  (WHILE b DO c, t2) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              using K [of cfs' "[]" cfs' s' "WHILE b DO c" s']
               and V and X and Y by force
            {
              fix x
              assume AB: "s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (flow cfs @ flow cfs') s x"
                by (rule sources_aux_append)
              moreover have AC: "sources_aux (flow cfs @ flow cfs') s x 
                sources_aux (bvars b # flow cfs @ flow cfs') s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (SKIP, t2)"
                using Z by blast
              hence "(c;; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and AB by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(WHILE b DO c, t1) →* (c;; WHILE b DO c, t1)"
                by (blast intro: star_trans)
              ultimately have "(WHILE b DO c, t1) →* (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources_aux (flow cfs @ flow cfs') s x"
                  by (rule sources_aux_member)
                hence "sources (flow cfs) s y 
                  sources_aux (bvars b # flow cfs @ flow cfs') s x"
                  using AC by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "(WHILE b DO c, t2) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                using AA by simp
              ultimately have "(WHILE b DO c, t1) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AB: "s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x)"
              have "run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources (flow cfs @ flow cfs') s x"
                  by (rule sources_member)
                moreover have "sources (flow cfs @ flow cfs') s x 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by (rule sources_observe_tl)
                ultimately have "sources (flow cfs) s y 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x"
                using AA by simp
            }
            ultimately have "c3' t3. x.
              (s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x) 
                  (WHILE b DO c, t1) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              by auto
          }
          ultimately show ?thesis
            using R and `?R` by (auto simp: run_flow_append)
        next
          assume
            S: "¬ bval b s" and
            T: "flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          moreover assume "(SKIP, s) →*{tl2 cfs2} (c2, s2)"
          hence U: "(c2, s2) = (SKIP, s)  flow (tl2 cfs2) = []"
            by (rule small_stepsl_skip)
          show ?thesis
          proof (rule exI [of _ SKIP], rule exI [of _ t1])
            {
              fix x
              have "(WHILE b DO c, t1) 
                (IF b THEN c;; WHILE b DO c ELSE SKIP, t1)" ..
              moreover assume "s = t1 (⊆ sources_aux [bvars b] s x)"
              hence "s = t1 (⊆ bvars b)"
                using Q by (blast dest: sources_aux_observe_hd)
              hence "¬ bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (SKIP, t1)" ..
              ultimately have "(WHILE b DO c, t1) →* (SKIP, t1)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources [bvars b] s x)"
              hence "s x = t1 x"
                by (subst (asm) append_Nil [symmetric],
                 simp only: sources.simps, auto)
            }
            ultimately show "x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (SKIP, t1)  (c2 = SKIP) = (SKIP = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t1 x)"
              using R and T and U and `?R` by auto
          qed
        qed
      qed
    next
      assume "(IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs1} (c1, s1)"
      hence
       "(c1, s1) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
          flow (tl cfs1) = [] 
        bval b s  (c;; WHILE b DO c, s) →*{tl2 cfs1} (c1, s1) 
          flow (tl cfs1) = bvars b # flow (tl2 cfs1) 
        ¬ bval b s  (SKIP, s) →*{tl2 cfs1} (c1, s1) 
          flow (tl cfs1) = bvars b # flow (tl2 cfs1)"
        by (rule small_stepsl_if)
      thus ?thesis
      proof (rule disjE, erule_tac [2] disjE, erule_tac conjE,
       (erule_tac [2-3] conjE)+)
        assume R: "(c1, s1) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s)"
        hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{cfs2} (c2, s2)"
          using J by simp
        hence
         "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow cfs2 = [] 
          bval b s  (c;; WHILE b DO c, s) →*{tl cfs2} (c2, s2) 
            flow cfs2 = bvars b # flow (tl cfs2) 
          ¬ bval b s  (SKIP, s) →*{tl cfs2} (c2, s2) 
            flow cfs2 = bvars b # flow (tl cfs2)"
          by (rule small_stepsl_if)
        thus ?thesis
        proof (erule_tac disjE, erule_tac [2] disjE, (erule_tac [2-3] conjE)+)
          assume "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow cfs2 = []"
          with R show ?thesis
            by auto
        next
          assume S: "bval b s"
          with D and O and P have T: "s  Univ B1 (⊆ state  X)"
            by (drule_tac btyping2_approx [where s = s], auto)
          assume U: "(c;; WHILE b DO c, s) →*{tl cfs2} (c2, s2)"
          hence
           "(c' cfs. c2 = c';; WHILE b DO c 
              (c, s) →*{cfs} (c', s2) 
              flow (tl cfs2) = flow cfs) 
            (s' cfs cfs'. length cfs' < length (tl cfs2) 
              (c, s) →*{cfs} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs'} (c2, s2) 
              flow (tl cfs2) = flow cfs @ flow cfs')"
            by (rule small_stepsl_seq)
          moreover assume "flow cfs2 = bvars b # flow (tl cfs2)"
          moreover have "s2 = run_flow (flow (tl cfs2)) s"
            using U by (rule small_stepsl_run_flow)
          moreover {
            fix c' cfs
            assume "(c, s) →*{cfs} (c', run_flow (flow cfs) s)"
            then obtain c2' and t2 where V: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (c' = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              using A [of B1 C B1' D s "[]" c s cfs c'
               "run_flow (flow cfs) s"] and N and T by force
            {
              fix x
              assume W: "s = t1 (⊆ sources_aux (bvars b # flow cfs) s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (bvars b # (flow cfs)) s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (c2', t2)"
                using V by blast
              hence "(c;; WHILE b DO c, t1) →* (c2';; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and W by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (c;; WHILE b DO c, t1)" ..
              ultimately have
               "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                  (c2';; WHILE b DO c, t2)  c2';; WHILE b DO c  SKIP"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources (bvars b # flow cfs) s x)"
              moreover have "sources (flow cfs) s x 
                sources (bvars b # (flow cfs)) s x"
                by (rule sources_observe_tl)
              ultimately have "run_flow (flow cfs) s x = t2 x"
                using V by blast
            }
            ultimately have "c2' t2. x.
              (s = t1 (⊆ sources_aux (bvars b # flow cfs) s x) 
                (IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →* (c2', t2) 
                  c2'  SKIP) 
              (s = t1 (⊆ sources (bvars b # flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
          }
          moreover {
            fix s' cfs cfs'
            assume
              V: "length cfs' < length cfs2 - Suc 0" and
              W: "(c, s) →*{cfs} (SKIP, s')" and
              X: "(WHILE b DO c, s') →*{cfs'}
                (c2, run_flow (flow cfs') (run_flow (flow cfs) s))"
            then obtain c2' and t2 where "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x)  s' x = t2 x)"
              using A [of B1 C B1' D s "[]" c s cfs SKIP s']
               and N and T by force
            moreover have Y: "s' = run_flow (flow cfs) s"
              using W by (rule small_stepsl_run_flow)
            ultimately have Z: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (SKIP, t2)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
            assume "s2 = run_flow (flow cfs') (run_flow (flow cfs) s)"
            moreover have "(c, s)  s'"
              using W by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and S by blast
            ultimately obtain c3' and t3 where AA: "x.
              (run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x) 
                  (WHILE b DO c, t2) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              using K [of cfs' "[]" cfs' s' "WHILE b DO c" s']
               and V and X and Y by force
            {
              fix x
              assume AB: "s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (flow cfs @ flow cfs') s x"
                by (rule sources_aux_append)
              moreover have AC: "sources_aux (flow cfs @ flow cfs') s x 
                sources_aux (bvars b # flow cfs @ flow cfs') s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (SKIP, t2)"
                using Z by blast
              hence "(c;; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and AB by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (c;; WHILE b DO c, t1)" ..
              ultimately have "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources_aux (flow cfs @ flow cfs') s x"
                  by (rule sources_aux_member)
                hence "sources (flow cfs) s y 
                  sources_aux (bvars b # flow cfs @ flow cfs') s x"
                  using AC by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "(WHILE b DO c, t2) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                using AA by simp
              ultimately have
               "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                  (c3', t3)  (c2 = SKIP) = (c3' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AB: "s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x)"
              have "run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources (flow cfs @ flow cfs') s x"
                  by (rule sources_member)
                moreover have "sources (flow cfs @ flow cfs') s x 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by (rule sources_observe_tl)
                ultimately have "sources (flow cfs) s y 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x"
                using AA by simp
            }
            ultimately have "c3' t3. x.
              (s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x) 
                  (IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              by auto
          }
          ultimately show ?thesis
            using R by (auto simp: run_flow_append)
        next
          assume
            S: "¬ bval b s" and
            T: "flow cfs2 = bvars b # flow (tl cfs2)"
          assume "(SKIP, s) →*{tl cfs2} (c2, s2)"
          hence U: "(c2, s2) = (SKIP, s)  flow (tl cfs2) = []"
            by (rule small_stepsl_skip)
          show ?thesis
          proof (rule exI [of _ SKIP], rule exI [of _ t1])
            {
              fix x
              assume "s = t1 (⊆ sources_aux [bvars b] s x)"
              hence "s = t1 (⊆ bvars b)"
                using Q by (blast dest: sources_aux_observe_hd)
              hence "¬ bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (SKIP, t1)" ..
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources [bvars b] s x)"
              hence "s x = t1 x"
                by (subst (asm) append_Nil [symmetric],
                 simp only: sources.simps, auto)
            }
            ultimately show "x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (SKIP, t1)  (c2 = SKIP) = (SKIP = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t1 x)"
              using R and T and U by auto
          qed
        qed
      next
        assume R: "bval b s"
        with D and O and P have S: "s  Univ B1 (⊆ state  X)"
          by (drule_tac btyping2_approx [where s = s], auto)
        assume "(c;; WHILE b DO c, s) →*{tl2 cfs1} (c1, s1)"
        hence
         "(c' cfs'. c1 = c';; WHILE b DO c 
            (c, s) →*{cfs'} (c', s1) 
            flow (tl2 cfs1) = flow cfs') 
          (s' cfs' cfs''. length cfs'' < length (tl2 cfs1) 
            (c, s) →*{cfs'} (SKIP, s') 
            (WHILE b DO c, s') →*{cfs''} (c1, s1) 
            flow (tl2 cfs1) = flow cfs' @ flow cfs'')"
          by (rule small_stepsl_seq)
        moreover {
          fix c' cfs
          assume
            T: "(c, s) →*{cfs} (c', s1)" and
            U: "c1 = c';; WHILE b DO c"
          hence V: "(c';; WHILE b DO c, s1) →*{cfs2} (c2, s2)"
            using J by simp
          hence W: "s2 = run_flow (flow cfs2) s1"
            by (rule small_stepsl_run_flow)
          have
           "(c'' cfs'. c2 = c'';; WHILE b DO c 
              (c', s1) →*{cfs'} (c'', s2) 
              flow cfs2 = flow cfs') 
            (s' cfs' cfs''. length cfs'' < length cfs2 
              (c', s1) →*{cfs'} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs''} (c2, s2) 
              flow cfs2 = flow cfs' @ flow cfs'')"
            using V by (rule small_stepsl_seq)
          moreover {
            fix c'' cfs'
            assume "(c', s1) →*{cfs'} (c'', s2)"
            then obtain c2' and t2 where X: "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x) 
                run_flow (flow cfs2) s1 x = t2 x)"
              using A [of B1 C B1' D s cfs c' s1 cfs' c''
               "run_flow (flow cfs2) s1"] and N and S and T and W by force
            assume
              Y: "c2 = c'';; WHILE b DO c" and
              Z: "flow cfs2 = flow cfs'"
            have ?thesis
            proof (rule exI [of _ "c2';; WHILE b DO c"], rule exI [of _ t2])
              from U and W and X and Y and Z show "x.
                (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                  (c1, t1) →* (c2';; WHILE b DO c, t2) 
                    (c2 = SKIP) = (c2';; WHILE b DO c = SKIP)) 
                (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)"
                by (auto intro: star_seq2)
            qed
          }
          moreover {
            fix s' cfs' cfs''
            assume
              X: "length cfs'' < length cfs2" and
              Y: "(c', s1) →*{cfs'} (SKIP, s')" and
              Z: "(WHILE b DO c, s') →*{cfs''} (c2, s2)"
            then obtain c2' and t2 where "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x)  s' x = t2 x)"
              using A [of B1 C B1' D s cfs c' s1 cfs' SKIP s']
               and N and S and T by force
            moreover have AA: "s' = run_flow (flow cfs') s1"
              using Y by (rule small_stepsl_run_flow)
            ultimately have AB: "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (SKIP, t2)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x) 
                run_flow (flow cfs') s1 x = t2 x)"
              by blast
            have AC: "s2 = run_flow (flow cfs'') s'"
              using Z by (rule small_stepsl_run_flow)
            moreover have "(c, s) →*{cfs @ cfs'} (SKIP, s')"
              using T and Y by (simp add: small_stepsl_append)
            hence "(c, s)  s'"
              by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and R by blast
            ultimately obtain c2' and t3 where AD: "x.
              (run_flow (flow cfs') s1 = t2
                (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x) 
                  (WHILE b DO c, t2) →* (c2', t3) 
                  (c2 = SKIP) = (c2' = SKIP)) 
              (run_flow (flow cfs') s1 = t2
                (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x) 
                  run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t3 x)"
              using K [of cfs'' "[]" cfs'' s' "WHILE b DO c" s']
               and X and Z and AA by force
            moreover assume "flow cfs2 = flow cfs' @ flow cfs''"
            moreover {
              fix x
              assume AE: "s1 = t1
                (⊆ sources_aux (flow cfs' @ flow cfs'') s1 x)"
              moreover have "sources_aux (flow cfs') s1 x 
                sources_aux (flow cfs' @ flow cfs'') s1 x"
                by (rule sources_aux_append)
              ultimately have "(c', t1) →* (SKIP, t2)"
                using AB by blast
              hence "(c';; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              hence "(c';; WHILE b DO c, t1) →* (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs') s1 = t2
                (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs'')
                  (run_flow (flow cfs') s1) x"
                hence "sources (flow cfs') s1 y 
                  sources_aux (flow cfs' @ flow cfs'') s1 x"
                  by (rule sources_aux_member)
                thus "run_flow (flow cfs') s1 y = t2 y"
                  using AB and AE by blast
              qed
              hence "(WHILE b DO c, t2) →* (c2', t3) 
                (c2 = SKIP) = (c2' = SKIP)"
                using AD by simp
              ultimately have "(c';; WHILE b DO c, t1) →* (c2', t3) 
                (c2 = SKIP) = (c2' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AE: "s1 = t1
                (⊆ sources (flow cfs' @ flow cfs'') s1 x)"
              have "run_flow (flow cfs') s1 = t2
                (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x)"
              proof
                fix y
                assume "y  sources (flow cfs'')
                  (run_flow (flow cfs') s1) x"
                hence "sources (flow cfs') s1 y 
                  sources (flow cfs' @ flow cfs'') s1 x"
                  by (rule sources_member)
                thus "run_flow (flow cfs') s1 y = t2 y"
                  using AB and AE by blast
              qed
              hence "run_flow (flow cfs'')
                (run_flow (flow cfs') s1) x = t3 x"
                using AD by simp
            }
            ultimately have ?thesis
              by (metis U AA AC)
          }
          ultimately have ?thesis
            by blast
        }
        moreover {
          fix s' cfs cfs'
          assume
           "length cfs' < length (tl2 cfs1)" and
           "(c, s) →*{cfs} (SKIP, s')" and
           "(WHILE b DO c, s') →*{cfs'} (c1, s1)"
          moreover from this have "(c, s)  s'"
            by (auto dest: small_stepsl_steps simp: big_iff_small)
          hence "s'  Univ C (⊆ state  Y)"
            using M and R by blast
          ultimately have ?thesis
            using K [of "cfs' @ cfs2" cfs' cfs2 s' c1 s1] and J by force
        }
        ultimately show ?thesis
          by blast
      next
        assume "(SKIP, s) →*{tl2 cfs1} (c1, s1)"
        hence "(c1, s1) = (SKIP, s)"
          by (blast dest: small_stepsl_skip)
        moreover from this have "(c2, s2) = (SKIP, s)  flow cfs2 = []"
          using J by (blast dest: small_stepsl_skip)
        ultimately show ?thesis
          by auto
      qed
    qed
  }
  moreover {
    fix r t1
    assume O: "r  C" and P: "s = r (⊆ state  Y)"
    have Q: "x. y  bvars b. s: dom y  dom x"
    proof (cases "state  Y")
      case True
      with P have "interf s = interf r"
        by (blast intro: interf_state)
      with N and O show ?thesis
        by (erule_tac conjE, drule_tac bspec,
         auto simp: univ_states_if_def)
    next
      case False
      with N and O show ?thesis
        by (erule_tac conjE, drule_tac bspec,
         auto simp: univ_states_if_def)
    qed
    have "(c1, s1) = (WHILE b DO c, s) 
      (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs1} (c1, s1)"
      using I by (blast dest: small_stepsl_while)
    hence "c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)"
    proof
      assume R: "(c1, s1) = (WHILE b DO c, s)"
      hence "(WHILE b DO c, s) →*{cfs2} (c2, s2)"
        using J by simp
      hence
       "(c2, s2) = (WHILE b DO c, s) 
          flow cfs2 = [] 
        (IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs2} (c2, s2) 
          flow cfs2 = flow (tl cfs2)"
        (is "?P  ?Q  ?R")
        by (rule small_stepsl_while)
      thus ?thesis
      proof (rule disjE, erule_tac [2] conjE)
        assume ?P
        with R show ?thesis
          by auto
      next
        assume ?Q and ?R
        have
         "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow (tl cfs2) = [] 
          bval b s  (c;; WHILE b DO c, s) →*{tl2 cfs2} (c2, s2) 
            flow (tl cfs2) = bvars b # flow (tl2 cfs2) 
          ¬ bval b s  (SKIP, s) →*{tl2 cfs2} (c2, s2) 
            flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          using `?Q` by (rule small_stepsl_if)
        thus ?thesis
        proof (erule_tac disjE, erule_tac [2] disjE, (erule_tac [2-3] conjE)+)
          assume "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow (tl cfs2) = []"
          with R and `?R` show ?thesis
            by auto
        next
          assume S: "bval b s"
          with F and O and P have T: "s  Univ B1' (⊆ state  Y)"
            by (drule_tac btyping2_approx [where s = s], auto)
          assume U: "(c;; WHILE b DO c, s) →*{tl2 cfs2} (c2, s2)"
          hence
           "(c' cfs. c2 = c';; WHILE b DO c 
              (c, s) →*{cfs} (c', s2) 
              flow (tl2 cfs2) = flow cfs) 
            (s' cfs cfs'. length cfs' < length (tl2 cfs2) 
              (c, s) →*{cfs} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs'} (c2, s2) 
              flow (tl2 cfs2) = flow cfs @ flow cfs')"
            by (rule small_stepsl_seq)
          moreover assume "flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          moreover have "s2 = run_flow (flow (tl2 cfs2)) s"
            using U by (rule small_stepsl_run_flow)
          moreover {
            fix c' cfs
            assume "(c, s) →*{cfs} (c', run_flow (flow cfs) s)"
            then obtain c2' and t2 where V: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (c' = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              using B [of B1 C B1' D' s "[]" c s cfs c'
               "run_flow (flow cfs) s"] and N and T by force
            {
              fix x
              assume W: "s = t1 (⊆ sources_aux (bvars b # flow cfs) s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (bvars b # (flow cfs)) s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (c2', t2)"
                using V by blast
              hence "(c;; WHILE b DO c, t1) →* (c2';; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and W by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(WHILE b DO c, t1) →* (c;; WHILE b DO c, t1)"
                by (blast intro: star_trans)
              ultimately have "(WHILE b DO c, t1) →*
               (c2';; WHILE b DO c, t2)  c2';; WHILE b DO c  SKIP"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources (bvars b # flow cfs) s x)"
              moreover have "sources (flow cfs) s x 
                sources (bvars b # (flow cfs)) s x"
                by (rule sources_observe_tl)
              ultimately have "run_flow (flow cfs) s x = t2 x"
                using V by blast
            }
            ultimately have "c2' t2. x.
              (s = t1 (⊆ sources_aux (bvars b # flow cfs) s x) 
                (WHILE b DO c, t1) →* (c2', t2)  c2'  SKIP) 
              (s = t1 (⊆ sources (bvars b # flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
          }
          moreover {
            fix s' cfs cfs'
            assume
              V: "length cfs' < length cfs2 - Suc (Suc 0)" and
              W: "(c, s) →*{cfs} (SKIP, s')" and
              X: "(WHILE b DO c, s') →*{cfs'}
                (c2, run_flow (flow cfs') (run_flow (flow cfs) s))"
            then obtain c2' and t2 where "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x)  s' x = t2 x)"
              using B [of B1 C B1' D' s "[]" c s cfs SKIP s']
               and N and T by force
            moreover have Y: "s' = run_flow (flow cfs) s"
              using W by (rule small_stepsl_run_flow)
            ultimately have Z: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (SKIP, t2)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
            assume "s2 = run_flow (flow cfs') (run_flow (flow cfs) s)"
            moreover have "(c, s)  s'"
              using W by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and S by blast
            ultimately obtain c3' and t3 where AA: "x.
              (run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x) 
                  (WHILE b DO c, t2) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              using K [of cfs' "[]" cfs' s' "WHILE b DO c" s']
               and V and X and Y by force
            {
              fix x
              assume AB: "s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (flow cfs @ flow cfs') s x"
                by (rule sources_aux_append)
              moreover have AC: "sources_aux (flow cfs @ flow cfs') s x 
                sources_aux (bvars b # flow cfs @ flow cfs') s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (SKIP, t2)"
                using Z by blast
              hence "(c;; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and AB by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(WHILE b DO c, t1) →* (c;; WHILE b DO c, t1)"
                by (blast intro: star_trans)
              ultimately have "(WHILE b DO c, t1) →* (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources_aux (flow cfs @ flow cfs') s x"
                  by (rule sources_aux_member)
                hence "sources (flow cfs) s y 
                  sources_aux (bvars b # flow cfs @ flow cfs') s x"
                  using AC by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "(WHILE b DO c, t2) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                using AA by simp
              ultimately have "(WHILE b DO c, t1) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AB: "s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x)"
              have "run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources (flow cfs @ flow cfs') s x"
                  by (rule sources_member)
                moreover have "sources (flow cfs @ flow cfs') s x 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by (rule sources_observe_tl)
                ultimately have "sources (flow cfs) s y 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x"
                using AA by simp
            }
            ultimately have "c3' t3. x.
              (s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x) 
                  (WHILE b DO c, t1) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              by auto
          }
          ultimately show ?thesis
            using R and `?R` by (auto simp: run_flow_append)
        next
          assume
            S: "¬ bval b s" and
            T: "flow (tl cfs2) = bvars b # flow (tl2 cfs2)"
          assume "(SKIP, s) →*{tl2 cfs2} (c2, s2)"
          hence U: "(c2, s2) = (SKIP, s)  flow (tl2 cfs2) = []"
            by (rule small_stepsl_skip)
          show ?thesis
          proof (rule exI [of _ SKIP], rule exI [of _ t1])
            {
              fix x
              have "(WHILE b DO c, t1) 
                (IF b THEN c;; WHILE b DO c ELSE SKIP, t1)" ..
              moreover assume "s = t1 (⊆ sources_aux [bvars b] s x)"
              hence "s = t1 (⊆ bvars b)"
                using Q by (blast dest: sources_aux_observe_hd)
              hence "¬ bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (SKIP, t1)" ..
              ultimately have "(WHILE b DO c, t1) →* (SKIP, t1)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources [bvars b] s x)"
              hence "s x = t1 x"
                by (subst (asm) append_Nil [symmetric],
                 simp only: sources.simps, auto)
            }
            ultimately show "x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (SKIP, t1)  (c2 = SKIP) = (SKIP = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t1 x)"
              using R and T and U and `?R` by auto
          qed
        qed
      qed
    next
      assume "(IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{tl cfs1} (c1, s1)"
      hence
       "(c1, s1) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
          flow (tl cfs1) = [] 
        bval b s  (c;; WHILE b DO c, s) →*{tl2 cfs1} (c1, s1) 
          flow (tl cfs1) = bvars b # flow (tl2 cfs1) 
        ¬ bval b s  (SKIP, s) →*{tl2 cfs1} (c1, s1) 
          flow (tl cfs1) = bvars b # flow (tl2 cfs1)"
        by (rule small_stepsl_if)
      thus ?thesis
      proof (rule disjE, erule_tac [2] disjE, erule_tac conjE,
       (erule_tac [2-3] conjE)+)
        assume R: "(c1, s1) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s)"
        hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, s) →*{cfs2} (c2, s2)"
          using J by simp
        hence
         "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow cfs2 = [] 
          bval b s  (c;; WHILE b DO c, s) →*{tl cfs2} (c2, s2) 
            flow cfs2 = bvars b # flow (tl cfs2) 
          ¬ bval b s  (SKIP, s) →*{tl cfs2} (c2, s2) 
            flow cfs2 = bvars b # flow (tl cfs2)"
          by (rule small_stepsl_if)
        thus ?thesis
        proof (erule_tac disjE, erule_tac [2] disjE, (erule_tac [2-3] conjE)+)
          assume "(c2, s2) = (IF b THEN c;; WHILE b DO c ELSE SKIP, s) 
            flow cfs2 = []"
          with R show ?thesis
            by auto
        next
          assume S: "bval b s"
          with F and O and P have T: "s  Univ B1' (⊆ state  Y)"
            by (drule_tac btyping2_approx [where s = s], auto)
          assume U: "(c;; WHILE b DO c, s) →*{tl cfs2} (c2, s2)"
          hence
           "(c' cfs. c2 = c';; WHILE b DO c 
              (c, s) →*{cfs} (c', s2) 
              flow (tl cfs2) = flow cfs) 
            (s' cfs cfs'. length cfs' < length (tl cfs2) 
              (c, s) →*{cfs} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs'} (c2, s2) 
              flow (tl cfs2) = flow cfs @ flow cfs')"
            by (rule small_stepsl_seq)
          moreover assume "flow cfs2 = bvars b # flow (tl cfs2)"
          moreover have "s2 = run_flow (flow (tl cfs2)) s"
            using U by (rule small_stepsl_run_flow)
          moreover {
            fix c' cfs
            assume "(c, s) →*{cfs} (c', run_flow (flow cfs) s)"
            then obtain c2' and t2 where V: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (c' = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              using B [of B1 C B1' D' s "[]" c s cfs c'
               "run_flow (flow cfs) s"] and N and T by force
            {
              fix x
              assume W: "s = t1 (⊆ sources_aux (bvars b # flow cfs) s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (bvars b # (flow cfs)) s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (c2', t2)"
                using V by blast
              hence "(c;; WHILE b DO c, t1) →* (c2';; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and W by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (c;; WHILE b DO c, t1)" ..
              ultimately have
               "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                  (c2';; WHILE b DO c, t2)  c2';; WHILE b DO c  SKIP"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources (bvars b # flow cfs) s x)"
              moreover have "sources (flow cfs) s x 
                sources (bvars b # (flow cfs)) s x"
                by (rule sources_observe_tl)
              ultimately have "run_flow (flow cfs) s x = t2 x"
                using V by blast
            }
            ultimately have "c2' t2. x.
              (s = t1 (⊆ sources_aux (bvars b # flow cfs) s x) 
                (IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →* (c2', t2) 
                  c2'  SKIP) 
              (s = t1 (⊆ sources (bvars b # flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
          }
          moreover {
            fix s' cfs cfs'
            assume
              V: "length cfs' < length cfs2 - Suc 0" and
              W: "(c, s) →*{cfs} (SKIP, s')" and
              X: "(WHILE b DO c, s') →*{cfs'}
                (c2, run_flow (flow cfs') (run_flow (flow cfs) s))"
            then obtain c2' and t2 where "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s = t1 (⊆ sources (flow cfs) s x)  s' x = t2 x)"
              using B [of B1 C B1' D' s "[]" c s cfs SKIP s']
               and N and T by force
            moreover have Y: "s' = run_flow (flow cfs) s"
              using W by (rule small_stepsl_run_flow)
            ultimately have Z: "x.
              (s = t1 (⊆ sources_aux (flow cfs) s x) 
                (c, t1) →* (SKIP, t2)) 
              (s = t1 (⊆ sources (flow cfs) s x) 
                run_flow (flow cfs) s x = t2 x)"
              by blast
            assume "s2 = run_flow (flow cfs') (run_flow (flow cfs) s)"
            moreover have "(c, s)  s'"
              using W by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and S by blast
            ultimately obtain c3' and t3 where AA: "x.
              (run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x) 
                  (WHILE b DO c, t2) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              using K [of cfs' "[]" cfs' s' "WHILE b DO c" s']
               and V and X and Y by force
            {
              fix x
              assume AB: "s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x)"
              moreover have "sources_aux (flow cfs) s x 
                sources_aux (flow cfs @ flow cfs') s x"
                by (rule sources_aux_append)
              moreover have AC: "sources_aux (flow cfs @ flow cfs') s x 
                sources_aux (bvars b # flow cfs @ flow cfs') s x"
                by (rule sources_aux_observe_tl)
              ultimately have "(c, t1) →* (SKIP, t2)"
                using Z by blast
              hence "(c;; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              moreover have "s = t1 (⊆ bvars b)"
                using Q and AB by (blast dest: sources_aux_observe_hd)
              hence "bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (c;; WHILE b DO c, t1)" ..
              ultimately have "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs) s = t2
                (⊆ sources_aux (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources_aux (flow cfs @ flow cfs') s x"
                  by (rule sources_aux_member)
                hence "sources (flow cfs) s y 
                  sources_aux (bvars b # flow cfs @ flow cfs') s x"
                  using AC by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "(WHILE b DO c, t2) →* (c3', t3) 
                (c2 = SKIP) = (c3' = SKIP)"
                using AA by simp
              ultimately have
               "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →*
                  (c3', t3)  (c2 = SKIP) = (c3' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AB: "s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x)"
              have "run_flow (flow cfs) s = t2
                (⊆ sources (flow cfs') (run_flow (flow cfs) s) x)"
              proof
                fix y
                assume "y  sources (flow cfs')
                  (run_flow (flow cfs) s) x"
                hence "sources (flow cfs) s y 
                  sources (flow cfs @ flow cfs') s x"
                  by (rule sources_member)
                moreover have "sources (flow cfs @ flow cfs') s x 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by (rule sources_observe_tl)
                ultimately have "sources (flow cfs) s y 
                  sources (bvars b # flow cfs @ flow cfs') s x"
                  by simp
                thus "run_flow (flow cfs) s y = t2 y"
                  using Z and AB by blast
              qed
              hence "run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x"
                using AA by simp
            }
            ultimately have "c3' t3. x.
              (s = t1
                (⊆ sources_aux (bvars b # flow cfs @ flow cfs') s x) 
                  (IF b THEN c;; WHILE b DO c ELSE SKIP, t1) →* (c3', t3) 
                  (c2 = SKIP) = (c3' = SKIP)) 
              (s = t1
                (⊆ sources (bvars b # flow cfs @ flow cfs') s x) 
                  run_flow (flow cfs') (run_flow (flow cfs) s) x = t3 x)"
              by auto
          }
          ultimately show ?thesis
            using R by (auto simp: run_flow_append)
        next
          assume
            S: "¬ bval b s" and
            T: "flow cfs2 = bvars b # flow (tl cfs2)"
          assume "(SKIP, s) →*{tl cfs2} (c2, s2)"
          hence U: "(c2, s2) = (SKIP, s)  flow (tl cfs2) = []"
            by (rule small_stepsl_skip)
          show ?thesis
          proof (rule exI [of _ SKIP], rule exI [of _ t1])
            {
              fix x
              assume "s = t1 (⊆ sources_aux [bvars b] s x)"
              hence "s = t1 (⊆ bvars b)"
                using Q by (blast dest: sources_aux_observe_hd)
              hence "¬ bval b t1"
                using S by (blast dest: bvars_bval)
              hence "(IF b THEN c;; WHILE b DO c ELSE SKIP, t1) 
                (SKIP, t1)" ..
            }
            moreover {
              fix x
              assume "s = t1 (⊆ sources [bvars b] s x)"
              hence "s x = t1 x"
                by (subst (asm) append_Nil [symmetric],
                 simp only: sources.simps, auto)
            }
            ultimately show "x.
              (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                (c1, t1) →* (SKIP, t1)  (c2 = SKIP) = (SKIP = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t1 x)"
              using R and T and U by auto
          qed
        qed
      next
        assume R: "bval b s"
        with F and O and P have S: "s  Univ B1' (⊆ state  Y)"
          by (drule_tac btyping2_approx [where s = s], auto)
        assume "(c;; WHILE b DO c, s) →*{tl2 cfs1} (c1, s1)"
        hence
         "(c' cfs'. c1 = c';; WHILE b DO c 
            (c, s) →*{cfs'} (c', s1) 
            flow (tl2 cfs1) = flow cfs') 
          (s' cfs' cfs''. length cfs'' < length (tl2 cfs1) 
            (c, s) →*{cfs'} (SKIP, s') 
            (WHILE b DO c, s') →*{cfs''} (c1, s1) 
            flow (tl2 cfs1) = flow cfs' @ flow cfs'')"
          by (rule small_stepsl_seq)
        moreover {
          fix c' cfs
          assume
            T: "(c, s) →*{cfs} (c', s1)" and
            U: "c1 = c';; WHILE b DO c"
          hence V: "(c';; WHILE b DO c, s1) →*{cfs2} (c2, s2)"
            using J by simp
          hence W: "s2 = run_flow (flow cfs2) s1"
            by (rule small_stepsl_run_flow)
          have
           "(c'' cfs'. c2 = c'';; WHILE b DO c 
              (c', s1) →*{cfs'} (c'', s2) 
              flow cfs2 = flow cfs') 
            (s' cfs' cfs''. length cfs'' < length cfs2 
              (c', s1) →*{cfs'} (SKIP, s') 
              (WHILE b DO c, s') →*{cfs''} (c2, s2) 
              flow cfs2 = flow cfs' @ flow cfs'')"
            using V by (rule small_stepsl_seq)
          moreover {
            fix c'' cfs'
            assume "(c', s1) →*{cfs'} (c'', s2)"
            then obtain c2' and t2 where X: "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x) 
                run_flow (flow cfs2) s1 x = t2 x)"
              using B [of B1 C B1' D' s cfs c' s1 cfs' c''
               "run_flow (flow cfs2) s1"] and N and S and T and W by force
            assume
              Y: "c2 = c'';; WHILE b DO c" and
              Z: "flow cfs2 = flow cfs'"
            have ?thesis
            proof (rule exI [of _ "c2';; WHILE b DO c"], rule exI [of _ t2])
              from U and W and X and Y and Z show "x.
                (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
                  (c1, t1) →* (c2';; WHILE b DO c, t2) 
                    (c2 = SKIP) = (c2';; WHILE b DO c = SKIP)) 
                (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)"
                by (auto intro: star_seq2)
            qed
          }
          moreover {
            fix s' cfs' cfs''
            assume
              X: "length cfs'' < length cfs2" and
              Y: "(c', s1) →*{cfs'} (SKIP, s')" and
              Z: "(WHILE b DO c, s') →*{cfs''} (c2, s2)"
            then obtain c2' and t2 where "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (c2', t2)  (SKIP = SKIP) = (c2' = SKIP)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x)  s' x = t2 x)"
              using B [of B1 C B1' D' s cfs c' s1 cfs' SKIP s']
               and N and S and T by force
            moreover have AA: "s' = run_flow (flow cfs') s1"
              using Y by (rule small_stepsl_run_flow)
            ultimately have AB: "x.
              (s1 = t1 (⊆ sources_aux (flow cfs') s1 x) 
                (c', t1) →* (SKIP, t2)) 
              (s1 = t1 (⊆ sources (flow cfs') s1 x) 
                run_flow (flow cfs') s1 x = t2 x)"
              by blast
            have AC: "s2 = run_flow (flow cfs'') s'"
              using Z by (rule small_stepsl_run_flow)
            moreover have "(c, s) →*{cfs @ cfs'} (SKIP, s')"
              using T and Y by (simp add: small_stepsl_append)
            hence "(c, s)  s'"
              by (auto dest: small_stepsl_steps simp: big_iff_small)
            hence "s'  Univ C (⊆ state  Y)"
              using M and R by blast
            ultimately obtain c2' and t3 where AD: "x.
              (run_flow (flow cfs') s1 = t2
                (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x) 
                  (WHILE b DO c, t2) →* (c2', t3) 
                  (c2 = SKIP) = (c2' = SKIP)) 
              (run_flow (flow cfs') s1 = t2
                (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x) 
                  run_flow (flow cfs'') (run_flow (flow cfs') s1) x = t3 x)"
              using K [of cfs'' "[]" cfs'' s' "WHILE b DO c" s']
               and X and Z and AA by force
            moreover assume "flow cfs2 = flow cfs' @ flow cfs''"
            moreover {
              fix x
              assume AE: "s1 = t1
                (⊆ sources_aux (flow cfs' @ flow cfs'') s1 x)"
              moreover have "sources_aux (flow cfs') s1 x 
                sources_aux (flow cfs' @ flow cfs'') s1 x"
                by (rule sources_aux_append)
              ultimately have "(c', t1) →* (SKIP, t2)"
                using AB by blast
              hence "(c';; WHILE b DO c, t1) →* (SKIP;; WHILE b DO c, t2)"
                by (rule star_seq2)
              hence "(c';; WHILE b DO c, t1) →* (WHILE b DO c, t2)"
                by (blast intro: star_trans)
              moreover have "run_flow (flow cfs') s1 = t2
                (⊆ sources_aux (flow cfs'') (run_flow (flow cfs') s1) x)"
              proof
                fix y
                assume "y  sources_aux (flow cfs'')
                  (run_flow (flow cfs') s1) x"
                hence "sources (flow cfs') s1 y 
                  sources_aux (flow cfs' @ flow cfs'') s1 x"
                  by (rule sources_aux_member)
                thus "run_flow (flow cfs') s1 y = t2 y"
                  using AB and AE by blast
              qed
              hence "(WHILE b DO c, t2) →* (c2', t3) 
                (c2 = SKIP) = (c2' = SKIP)"
                using AD by simp
              ultimately have "(c';; WHILE b DO c, t1) →* (c2', t3) 
                (c2 = SKIP) = (c2' = SKIP)"
                by (blast intro: star_trans)
            }
            moreover {
              fix x
              assume AE: "s1 = t1
                (⊆ sources (flow cfs' @ flow cfs'') s1 x)"
              have "run_flow (flow cfs') s1 = t2
                (⊆ sources (flow cfs'') (run_flow (flow cfs') s1) x)"
              proof
                fix y
                assume "y  sources (flow cfs'')
                  (run_flow (flow cfs') s1) x"
                hence "sources (flow cfs') s1 y 
                  sources (flow cfs' @ flow cfs'') s1 x"
                  by (rule sources_member)
                thus "run_flow (flow cfs') s1 y = t2 y"
                  using AB and AE by blast
              qed
              hence "run_flow (flow cfs'')
                (run_flow (flow cfs') s1) x = t3 x"
                using AD by simp
            }
            ultimately have ?thesis
              by (metis U AA AC)
          }
          ultimately have ?thesis
            by blast
        }
        moreover {
          fix s' cfs cfs'
          assume
           "length cfs' < length (tl2 cfs1)" and
           "(c, s) →*{cfs} (SKIP, s')" and
           "(WHILE b DO c, s') →*{cfs'} (c1, s1)"
          moreover from this have "(c, s)  s'"
            by (auto dest: small_stepsl_steps simp: big_iff_small)
          hence "s'  Univ C (⊆ state  Y)"
            using M and R by blast
          ultimately have ?thesis
            using K [of "cfs' @ cfs2" cfs' cfs2 s' c1 s1] and J by force
        }
        ultimately show ?thesis
          by blast
      next
        assume "(SKIP, s) →*{tl2 cfs1} (c1, s1)"
        hence "(c1, s1) = (SKIP, s)"
          by (blast dest: small_stepsl_skip)
        moreover from this have "(c2, s2) = (SKIP, s)  flow cfs2 = []"
          using J by (blast dest: small_stepsl_skip)
        ultimately show ?thesis
          by auto
      qed
    qed
  }
  ultimately show
   "(t1. c2' t2. x.
      (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
    (x. ((B, Y)  U. s  B. y  Y. ¬ s: dom y  dom x) 
      no_upd (flow cfs2) x)"
    using L by auto
qed

lemma ctyping2_correct_aux:
 "(U, v)  c (⊆ A, X) = Some (B, Y); s  Univ A (⊆ state  X);
    (c, s) →*{cfs1} (c1, s1); (c1, s1) →*{cfs2} (c2, s2) 
  ok_flow_aux U c1 c2 s1 s2 (flow cfs2)"
proof (induction "(U, v)" c A X arbitrary: B Y U v s c1 c2 s1 s2 cfs1 cfs2
 rule: ctyping2.induct)
  fix A X C Z U v c1 c2 c' c'' s s1 s2 cfs1 cfs2
  show
   "B Y s c' c'' s1 s2 cfs1 cfs2.
      (U, v)  c1 (⊆ A, X) = Some (B, Y) 
      s  Univ A (⊆ state  X) 
      (c1, s) →*{cfs1} (c', s1) 
      (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    p B Y C Z s c' c'' s1 s2 cfs1 cfs2.
      (U, v)  c1 (⊆ A, X) = Some p 
      (B, Y) = p 
      (U, v)  c2 (⊆ B, Y) = Some (C, Z) 
      s  Univ B (⊆ state  Y) 
      (c2, s) →*{cfs1} (c', s1) 
      (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2'' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2'', t2)  (c'' = SKIP) = (c2'' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    (U, v)  c1;; c2 (⊆ A, X) = Some (C, Z);
    s  Univ A (⊆ state  X);
    (c1;; c2, s) →*{cfs1} (c', s1);
    (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x)"
    by (auto del: conjI split: option.split_asm,
     rule ctyping2_correct_aux_seq)
next
  fix A X C Y U v b c1 c2 c' c'' s s1 s2 cfs1 cfs2
  show
   "U' p B1 B2 C Y s c' c'' s1 s2 cfs1 cfs2.
      (U', p) = (insert (Univ? A X, bvars b) U,  b (⊆ A, X)) 
      (B1, B2) = p 
      (U', v)  c1 (⊆ B1, X) = Some (C, Y) 
      s  Univ B1 (⊆ state  X) 
      (c1, s) →*{cfs1} (c', s1) 
      (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U'. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    U' p B1 B2 C Y s c' c'' s1 s2 cfs1 cfs2.
      (U', p) = (insert (Univ? A X, bvars b) U,  b (⊆ A, X)) 
      (B1, B2) = p 
      (U', v)  c2 (⊆ B2, X) = Some (C, Y) 
      s  Univ B2 (⊆ state  X) 
      (c2, s) →*{cfs1} (c', s1) 
      (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2'' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2'', t2)  (c'' = SKIP) = (c2'' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U'. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    (U, v)  IF b THEN c1 ELSE c2 (⊆ A, X) = Some (C, Y);
    s  Univ A (⊆ state  X);
    (IF b THEN c1 ELSE c2, s) →*{cfs1} (c', s1);
    (c', s1) →*{cfs2} (c'', s2) 
      (t1. c2' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c', t1) →* (c2', t2)  (c'' = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x)"
    by (auto del: conjI split: option.split_asm prod.split_asm,
     rule ctyping2_correct_aux_if)
next
  fix A X B Y U v b c c1 c2 s s1 s2 cfs1 cfs2
  show
   "B1 B2 C Y B1' B2' D Z s c1 c2 s1 s2 cfs1 cfs2.
      (B1, B2) =  b (⊆ A, X) 
      (C, Y) =  c (⊆ B1, X) 
      (B1', B2') =  b (⊆ C, Y) 
      (B, W)  insert (Univ? A X  Univ? C Y, bvars b) U.
        B: dom ` W  UNIV 
      ({}, False)  c (⊆ B1, X) = Some (D, Z) 
      s  Univ B1 (⊆ state  X) 
      (c, s) →*{cfs1} (c1, s1) 
      (c1, s1) →*{cfs2} (c2, s2) 
      (t1. c2' t2. B1.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 B1) 
          (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 B1)  s2 B1 = t2 B1)) 
      (x. ((B, W)  {}. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    B1 B2 C Y B1' B2' D' Z' s c1 c2 s1 s2 cfs1 cfs2.
      (B1, B2) =  b (⊆ A, X) 
      (C, Y) =  c (⊆ B1, X) 
      (B1', B2') =  b (⊆ C, Y) 
      (B, W)  insert (Univ? A X  Univ? C Y, bvars b) U.
        B: dom ` W  UNIV 
      ({}, False)  c (⊆ B1', Y) = Some (D', Z') 
      s  Univ B1' (⊆ state  Y) 
      (c, s) →*{cfs1} (c1, s1) 
      (c1, s1) →*{cfs2} (c2, s2) 
      (t1. c2' t2. B1.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 B1) 
          (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 B1)  s2 B1 = t2 B1)) 
      (x. ((B, W)  {}. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x);
    (U, v)  WHILE b DO c (⊆ A, X) = Some (B, Y);
    s  Univ A (⊆ state  X);
    (WHILE b DO c, s) →*{cfs1} (c1, s1);
    (c1, s1) →*{cfs2} (c2, s2) 
      (t1. c2' t2. x.
        (s1 = t1 (⊆ sources_aux (flow cfs2) s1 x) 
          (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
        (s1 = t1 (⊆ sources (flow cfs2) s1 x)  s2 x = t2 x)) 
      (x. ((B, W)  U. s  B. y  W. ¬ s: dom y  dom x) 
        no_upd (flow cfs2) x)"
    by (auto del: conjI split: option.split_asm prod.split_asm,
     rule ctyping2_correct_aux_while, assumption+, blast)
qed (auto del: conjI split: prod.split_asm)


theorem ctyping2_correct:
  assumes A: "(U, v)  c (⊆ A, X) = Some (B, Y)"
  shows "correct c A X"
proof -
  {
    fix c1 c2 s1 s2 cfs t1
    assume "ok_flow_aux U c1 c2 s1 s2 (flow cfs)"
    then obtain c2' and t2 where A: "x.
      (s1 = t1 (⊆ sources_aux (flow cfs) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)) 
      (s1 = t1 (⊆ sources (flow cfs) s1 x)  s2 x = t2 x)"
      by blast
    have "c2' t2. x. s1 = t1 (⊆ sources (flow cfs) s1 x) 
      (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)  s2 x = t2 x"
    proof (rule exI [of _ c2'], rule exI [of _ t2])
      have "x. s1 = t1 (⊆ sources (flow cfs) s1 x) 
        s1 = t1 (⊆ sources_aux (flow cfs) s1 x)"
      proof (rule allI, rule impI)
        fix x
        assume "s1 = t1 (⊆ sources (flow cfs) s1 x)"
        moreover have "sources_aux (flow cfs) s1 x 
          sources (flow cfs) s1 x"
          by (rule sources_aux_sources)
        ultimately show "s1 = t1 (⊆ sources_aux (flow cfs) s1 x)"
          by blast
      qed
      with A show "x. s1 = t1 (⊆ sources (flow cfs) s1 x) 
        (c1, t1) →* (c2', t2)  (c2 = SKIP) = (c2' = SKIP)  s2 x = t2 x"
        by auto
    qed
  }
  with A show ?thesis
    by (clarsimp dest!: small_steps_stepsl simp: correct_def,
     drule_tac ctyping2_correct_aux, auto)
qed

end

end