theory flash14Bra  imports flash14Rev

  begin
lemma onInv14:

   assumes  a1:"iInv1 \<le> N" and

     b1:"r \<in> rules N" and b2:"invf=inv14  iInv1 "
   shows  "invHoldForRule' s invf r (invariants   N)"
   proof -
have c1:"ex1P N (% iRule1 .  r=NI_Local_GetX_PutX1 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_GetX  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Replace  iRule1 )\<or>ex0P N (  r=NI_ShWb N )\<or>ex0P N (  r=PI_Local_GetX_GetX2 )\<or>ex0P N (  r=NI_Local_PutXAcksDone )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX7 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak2  iRule1 )\<or>ex0P N (  r=NI_ReplaceHomeShrVld )\<or>ex1P N (% iRule1 .  r=NI_Remote_Put  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX5 N  iRule1 )\<or>ex0P N (  r=NI_Wb )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Get  iRule1 )\<or>ex0P N (  r=PI_Local_Replace )\<or>ex1P N (% iRule1 .  r=NI_ReplaceShrVld  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX8 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_InvAck_2 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Nak2  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Replace  iRule1 )\<or>ex0P N (  r=NI_Nak_Home )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put2  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_InvAck_1  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX11 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX6 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Put2  iRule1  iRule2 )\<or>ex0P N (  r=PI_Local_Get_Put )\<or>ex0P N (  r=PI_Local_GetX_PutX1 N )\<or>ex1P N (% iRule1 .  r=NI_InvAck_1_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak2  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX10_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Get  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak3  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX10 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX2 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Put1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_PutX  iRule1 )\<or>ex1P N (% iRule1 .  r=Store  iRule1 )\<or>ex0P N (  r=NI_FAck )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX3 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX3 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_PutX  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX8_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put1 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_GetX1 )\<or>ex0P N (  r=StoreHome )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_Nak  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Inv  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_PutX  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX4 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX4 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Nak  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX2 N )\<or>ex0P N (  r=NI_Local_Put )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak1  iRule1 )\<or>ex0P N (  r=NI_Nak_Clear )\<or>ex0P N (  r=PI_Local_PutX )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak3  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_Nak_Home  iRule1 )\<or>ex0P N (  r=PI_Local_Get_Get )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX9 N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_GetX  iRule1 )\<or>ex0P N (  r=NI_ReplaceHome )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_PutX_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put3  iRule1 )"

        apply(cut_tac  b1)
        apply auto
        done      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_GetXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ShWb N )
"

         from c1 have c2:" r= NI_ShWb N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ShWbVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX2 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX2 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_PutXAcksDone )
"

         from c1 have c2:" r= NI_Local_PutXAcksDone "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX7 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX7 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX7VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHomeShrVld )
"

         from c1 have c2:" r= NI_ReplaceHomeShrVld "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Put  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Put  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX5 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX5 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX5VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Wb )
"

         from c1 have c2:" r= NI_Wb "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Wb ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_WbVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_GetVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Replace )
"

         from c1 have c2:" r= PI_Local_Replace "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_ReplaceVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_ReplaceShrVld  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_ReplaceShrVld  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceShrVldVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Nak2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Nak2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_ReplaceVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Home )
"

         from c1 have c2:" r= NI_Nak_Home "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_HomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_InvAck_1  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_InvAck_1  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX11 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX11 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX11VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX6 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX6 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX6VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Put2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Put2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Put )
"

         from c1 have c2:" r= PI_Local_Get_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_PutVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX1 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX1 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_1_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_1_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1_HomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX10_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX10_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10_homeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak3VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Put1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Put1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= Store  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= Store  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis StoreVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_FAck )
"

         from c1 have c2:" r= NI_FAck "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_FAck ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_FAckVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX3 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX3 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX3VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX3 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX3 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_PutX  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_PutX  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX8_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX8_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8_homeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX1 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX1 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= StoreHome )
"

         from c1 have c2:" r= StoreHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (StoreHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis StoreHomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_Nak  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_Nak  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_NakVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Inv  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Inv  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_PutXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX4 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX4 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX4 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX4 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX4VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Nak  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Nak  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_NakVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX2 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX2 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_Put )
"

         from c1 have c2:" r= NI_Local_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak1VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Clear )
"

         from c1 have c2:" r= NI_Nak_Clear "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_ClearVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_PutX )
"

         from c1 have c2:" r= PI_Local_PutX "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_PutXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak3VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_Nak_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_Nak_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_Nak_HomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Get )
"

         from c1 have c2:" r= PI_Local_Get_Get "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_GetVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX9 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX9 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX9VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetXVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHome )
"

         from c1 have c2:" r= NI_ReplaceHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_PutX_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_PutX_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutX_HomeVsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put3VsInv14 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }ultimately show "invHoldForRule' s invf r (invariants N) "
          by blast
     qed
end


theory javacap_runtime_representation
imports
  Main
  javacap_syntax
  javacap_auxiliary
  javacap_typing
begin

(* Dynamic semantics types *)
typedecl heaploc

datatype v = href "heaploc" | null | num "nat"

primrec the_href :: "v \<Rightarrow> heaploc"
  where "the_href (href l) = l" |
        "the_href null = undefined" |
        "the_href (num n) = undefined"

primrec the_num :: "v \<Rightarrow> nat"
  where "the_num (num v) = v" |
        "the_num null = undefined" |
        "the_num (href l) = undefined"

record heapobj =
  HClass :: "cname"
  HFields :: "(fname \<rightharpoonup> v)"
  HLabel :: "label"        (*  The global label of this object.
                               This field exists merely to aid verification; the operational
                               semantics should not use it to make any decision, so it need
                               not exist in an actual runtime. *)

type_synonym staticfields = "(fname \<rightharpoonup> v)"

type_synonym Stack = "(var \<rightharpoonup> v)"
type_synonym Heap = "(heaploc \<rightharpoonup> heapobj)"
type_synonym Globals = "(cname \<rightharpoonup> staticfields)"

record State =
  stack :: "Stack"
  heap :: "Heap"
  globals :: "Globals"
  except :: "v option"
  retval :: "v option"
  privs :: "label" (* Exists purely to aid verification, this is the maximal label
                      the currently executing code should be able to access. *)

(* Creates a mapping which sets all the fields in the specified class to null, and leaves
   everything else unset (None). *)
definition new_object :: "prog \<Rightarrow> cname \<Rightarrow> label \<Rightarrow> heapobj"
  where "new_object P cname label =
         \<lparr> HClass = cname, HFields = (\<lambda>f. case (field P cname f) of Some t \<Rightarrow> Some null | None \<Rightarrow> None), HLabel = label\<rparr>"

definition is_obj_label_ok :: "prog \<Rightarrow> heapobj \<Rightarrow> \<T> \<Rightarrow> bool"
  where "is_obj_label_ok P obj T \<equiv>
            (if (is_cap_type P (ttype T))
            (* it's only safe to let (tlabel T) be less than (HLabel obj) this allowance because one cannot unwrap (downcast)
               a capability. One can only call the methods of the capability, and these have stricter restrictions than
               the label. *)
            then (let cbname = (the_iname (ttype T)) in (tlabel T) = (cap_label P cbname) \<inter> (HLabel obj) \<and>
                                                        (* This gives some 'meaning' to the labels. *)
                                                        (superinterface_set P cbname) \<subseteq> (tlabel T))
            else (HLabel obj) = (tlabel T))
         \<and> creq (the (class P (HClass obj))) \<subseteq> (HLabel obj) (* object must have a label that is a superset of the class ambient clause *)
         \<and> (HLabel obj) \<subseteq> (the (grant P (HClass obj)))" (* object must have a label less than what has been granted *)

(* Performs basic (non-recursive) checks of the type-correctness of a value.
   For pointers, this means the pointer points to a object that exists on the heap, and the
   object is of a type compatible with the static type of the value. *)
fun is_value_ok :: "prog \<Rightarrow> Heap \<Rightarrow> \<T> \<Rightarrow> v \<Rightarrow> bool"
  where is_value_ok_num: "is_value_ok P H T (num v) = ((ttype T) = (ValT IntT))"
      | is_value_ok_href: "is_value_ok P H T (href loc) = (\<exists>obj. H loc = Some obj \<and> (P \<turnstile> (ClassT (HClass obj)) <: (ttype T)) \<and> is_obj_label_ok P obj T)"
      | is_value_ok_null: "is_value_ok P H T (null) = True"

(* Performs shallow checks that an object at runtime is type-correct to its own type. *)
definition is_heapobj_ok :: "prog \<Rightarrow> Heap \<Rightarrow> heapobj \<Rightarrow> bool"
  where "is_heapobj_ok P H obj \<equiv> (\<forall>f fd. field P (HClass obj) f = Some fd \<and> \<not>fstatic fd \<longrightarrow> (\<exists>v. (HFields obj) f = Some v \<and> is_value_ok P H (intersect_label (ftype fd) (HLabel obj)) v))"

definition is_heap_ok :: "prog \<Rightarrow> Heap \<Rightarrow> bool"
  where "is_heap_ok P H \<equiv> (\<forall>loc\<in>dom(H). (is_heapobj_ok P H (the (H loc))))"

definition is_staticfields_ok :: "prog \<Rightarrow> Heap \<Rightarrow> cname \<Rightarrow> staticfields \<Rightarrow> bool"
  where "is_staticfields_ok P H c sf \<equiv> (\<forall>f fd. field P c f = Some fd \<and> fstatic fd \<longrightarrow> (\<exists>v. sf f = Some v \<and> is_value_ok P H (ftype fd) v))"

definition is_globals_ok :: "prog \<Rightarrow> Heap \<Rightarrow> Globals \<Rightarrow> bool"
  where "is_globals_ok P H G \<equiv> (\<forall>c. is_class P c \<longrightarrow> (\<exists>sf. G c = Some sf \<and> is_staticfields_ok P H c sf)) "

(* For all method (even if they return void), the return value stored against the state should be
   a type-correct value when the method returns. Otherwise, an exception may be return upon return. *)
definition is_retval_ok :: "prog \<Rightarrow> Heap \<Rightarrow> \<T> \<Rightarrow> v option \<Rightarrow> bool"
  where "is_retval_ok P H T rv \<equiv> (rv \<noteq> None \<longrightarrow> is_value_ok P H T (the rv))"

(* For now, we don't use a special base class for exceptions. Any object can be thrown. *)
definition is_except_ok :: "prog \<Rightarrow> Heap \<Rightarrow> v option \<Rightarrow> bool"
  where "is_except_ok P H e \<equiv> (e \<noteq> None \<longrightarrow> (is_value_ok P H ((ClassT Object),{}) (the e) \<and> (the e) \<noteq> null))"

definition var_corr :: "prog \<Rightarrow> lenv \<Rightarrow> State \<Rightarrow> var \<Rightarrow> bool"
  where "var_corr P \<Gamma> S x \<equiv>  (\<forall>T. (\<Gamma>\<lbrakk>x\<rbrakk>\<^sub>v = Some T) \<longrightarrow> (\<exists>v. (stack S x = Some v) \<and> (is_value_ok P (heap S) (intersect_label T (privs S)) v)))"

(* Defines the correlation between the static typing and the runtime state of the system. *)
definition corr :: "prog \<Rightarrow> msenv \<Rightarrow> lenv \<Rightarrow> State \<Rightarrow> bool" ("_ _ _ \<^bold>\<turnstile> _") (* P \<Gamma> \<turnstile> S H *)
  where "P M \<Gamma> \<^bold>\<turnstile> S \<equiv> (\<forall>x. var_corr P \<Gamma> S x) \<and>
                       (is_heap_ok P (heap S)) \<and>
                       (is_globals_ok P (heap S) (globals S)) \<and>
                       (is_retval_ok P (heap S) (intersect_label (msreturn M) (privs S)) (retval S)) \<and>
                       (is_except_ok P (heap S) (except S)) \<and>
                       (msreq M) \<subseteq> (privs S) \<and>
                       (privs S) \<subseteq> the (grant P (mscname M))
  "

(* A requirement that the heap is only extended (only grows) from H to H' and that the
   type of those objects remains the same. This is a simplifying assumption. If we want to
   allow garbage collection in our operational semantics, we could instead do the following:
    - Redefine our configuration correlation (type-correctness) property to only require
      type-correctness of all objects which are reachable from the stack
    - Extend the representation of the stack to include the frames of calling methods. In other
      words, \<Gamma> \<^bold>\<turnstile> S H will require all objects reachable from any variable on any stack frame
      to remain type-correct. All other objects on the heap then become irrelevant.
 *)
definition obj_consistent :: "heapobj \<Rightarrow> heapobj \<Rightarrow> bool"
  where "obj_consistent o1 o2 \<equiv> (HClass o1) = (HClass o2) \<and> (HLabel o1) = (HLabel o2)"

definition heap_extends :: "Heap \<Rightarrow> Heap \<Rightarrow> bool"
  where "heap_extends H H' \<equiv> (\<forall>l\<in>dom(H). l\<in>dom(H') \<and> (obj_consistent (the (H l)) (the (H' l))))"

(* Represents the invariants that must hold over all statement executions.
   Note that this invariant is end-to-end and does not need to be met in intermediate states. *)
definition transition_ok :: "State \<Rightarrow> State \<Rightarrow> bool"
  where "transition_ok S S' \<equiv> heap_extends (heap S) (heap S') \<and> (privs S = privs S')"

lemma heap_extends_transitive:
  assumes extends: "heap_extends S S1"
  assumes extends2: "heap_extends S1 S2"
  shows "heap_extends S S2"
  using assms unfolding heap_extends_def obj_consistent_def by auto

lemma transition_ok_self:
  shows "transition_ok S S"
  unfolding transition_ok_def heap_extends_def obj_consistent_def by simp

lemma transition_ok_simple:
  assumes "heap S = heap S' \<and> privs S = privs S'"
  shows "transition_ok S S'"
  using assms unfolding transition_ok_def heap_extends_def obj_consistent_def by simp

lemma transition_ok_trans:
  assumes ok1: "transition_ok S S1"
  assumes ok2: "transition_ok S1 S2"
  shows "transition_ok S S2"
  using assms heap_extends_transitive unfolding transition_ok_def by auto

lemma is_value_ok_valid_object_cast:
  assumes ok: "is_value_ok P H T' (href l)"
  assumes heap_access: "(obj::heapobj) = the (H l)"
  assumes cast_valid: "P \<turnstile> (ClassT (HClass obj)) <: (ttype T)"
  assumes label_same: "tlabel T = tlabel T'"
  assumes source_non_cap: "\<not>is_cap_type P (ttype T')"
  assumes target_non_cap: "\<not>is_cap_type P (ttype T)"
  shows "is_value_ok P H T (href l)"
proof -
  have a1: "H l = Some obj \<and> (P \<turnstile> (ClassT (HClass obj)) <: (ttype T')) \<and> is_obj_label_ok P obj T'"
    using ok heap_access by auto
  then have "is_obj_label_ok P obj T"
    using source_non_cap target_non_cap label_same unfolding is_obj_label_ok_def by auto
  then show ?thesis
    using a1 cast_valid by auto
qed

lemma stack_access_ok:
  assumes static: "\<Gamma>\<lbrakk>x\<rbrakk>\<^sub>v = Some T"
  assumes dynamic: "v = the (stack S x)"
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  shows "stack S x = Some v \<and> is_value_ok P (heap S) (intersect_label T (privs S)) v"
proof -
  have "\<exists>v. (stack S x = Some v) \<and> (is_value_ok P (heap S) (intersect_label T (privs S)) v)"
    using corr static unfolding corr_def var_corr_def by metis
  then show ?thesis
    using dynamic by auto
qed

lemma allocate_is_value_shallow_ok:
  assumes ok: "is_value_ok P H T v"
  assumes new: "l \<notin> dom(H)"
  assumes op: "H' = H(l\<mapsto>obj)"
  shows "is_value_ok P H' T v"
proof (cases v)
  case (href x1)
  then show ?thesis using ok new op by auto
next
  case null
  then show ?thesis by simp
next
  case (num x3)
  then show ?thesis using ok by simp
qed

lemma allocate_is_heapobj_ok:
  assumes ok: "is_heapobj_ok P H obj"
  assumes new: "l \<notin> dom(H)"
  assumes op: "H' = H(l\<mapsto>obj')"
  shows "is_heapobj_ok P H' obj"
  using assms allocate_is_value_shallow_ok unfolding is_heapobj_ok_def by blast

lemma is_retval_ok_value_ok:
  assumes "\<And>T v. is_value_ok P H T v \<Longrightarrow> is_value_ok P H' T v"
  assumes "is_retval_ok P H T r"
  shows "is_retval_ok P H' T r"
  using assms unfolding is_retval_ok_def by simp

lemma is_except_ok_value_ok:
  assumes "\<And>T v. is_value_ok P H T v \<Longrightarrow> is_value_ok P H' T v"
  assumes "is_except_ok P H e"
  shows "is_except_ok P H' e"
  using assms unfolding is_except_ok_def by simp

lemma is_globals_ok_value_ok:
  assumes "\<And>T v. is_value_ok P H T v \<Longrightarrow> is_value_ok P H' T v"
  assumes "is_globals_ok P H G"
  shows "is_globals_ok P H' G"
  using assms unfolding is_globals_ok_def is_staticfields_ok_def by meson

lemma allocate_ok:
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes new: "l \<notin> dom(heap S)"
  assumes op: "S' = S\<lparr>heap := (heap S)(l\<mapsto>obj)\<rparr>"
  assumes new_obj_ok: "is_heapobj_ok P (heap S) obj"
  shows "P M \<Gamma> \<^bold>\<turnstile> S'"
proof -
  have a1: "\<And>t v. is_value_ok P (heap S) t v \<Longrightarrow> is_value_ok P (heap S') t v"
    using assms allocate_is_value_shallow_ok by simp
  moreover have "privs S = privs S' \<and> stack S = stack S'" using op by simp
  ultimately have "(\<forall>x. var_corr P \<Gamma> S' x)"
    using corr op unfolding corr_def var_corr_def by metis
  moreover have "is_heap_ok P (heap S')"
  proof -
    have "(\<forall>loc\<in>dom(heap S). (is_heapobj_ok P (heap S) (the (heap S loc))))"
      using corr unfolding corr_def is_heap_ok_def by auto
    then have "(\<forall>loc\<in>dom(heap S). (is_heapobj_ok P (heap S') (the ((heap S') loc))))"
      using allocate_is_heapobj_ok new op by auto
    moreover have "is_heapobj_ok P (heap S') obj"
      using new_obj_ok allocate_is_heapobj_ok new op by auto
    moreover have "dom(heap S') = dom((heap S)) \<union> {l}"
      using op by auto
    ultimately show ?thesis
      unfolding is_heap_ok_def using op by auto
  qed
  moreover have "is_globals_ok P (heap S') (globals S')"
    using a1 corr is_globals_ok_value_ok op unfolding corr_def by fastforce
  moreover have "is_retval_ok P (heap S') (intersect_label (msreturn M) (privs S')) (retval S')"
  proof -
    have "(retval S') = (retval S) \<and> (privs S' = privs S) " using op by simp
    then show ?thesis using a1 is_retval_ok_value_ok corr unfolding corr_def by metis
  qed
  moreover have "is_except_ok P (heap S') (except S')"
    using a1 is_except_ok_value_ok corr op unfolding corr_def by fastforce
  moreover have "(msreq M) \<subseteq> (privs S')"
    using corr op unfolding corr_def by simp
  moreover have "(privs S') \<subseteq> (the (grant P (mscname M)))"
    using corr op unfolding corr_def by simp
  ultimately show ?thesis using corr_def by simp
qed

lemma allocate_extends_heap:
  assumes new: "l \<notin> dom(H)"
  assumes op: "H' = H(l\<mapsto>obj)"
  shows "heap_extends H H'"
  unfolding heap_extends_def obj_consistent_def using new op by auto

lemma stack_update_ok:
  assumes corr_initial: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes static: "\<Gamma>' = \<Gamma>(x\<mapsto>T)"
  assumes ok: "is_value_ok P (heap S) (intersect_label T (privs S)) v"
  assumes op: "S' = S\<lparr>stack := (stack S)(x\<mapsto>v)\<rparr>"
  shows "P M \<Gamma>' \<^bold>\<turnstile> S'"
proof -
  have "\<And>x'. var_corr P \<Gamma>' S' x'"
  proof -
    fix x'
    show "var_corr P \<Gamma>' S' x'"
    proof (cases "x = x'")
      case True
      then show ?thesis unfolding var_corr_def op using ok static by auto
    next
      case False
      then show ?thesis using corr_initial unfolding corr_def var_corr_def static op by simp
    qed
  qed
  then show ?thesis using corr_initial unfolding corr_def op by simp
qed

lemma retval_update_ok:
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes val_ok: "is_value_ok P (heap S) (intersect_label (msreturn M) (privs S)) v"
  assumes op: "S' = S\<lparr>retval := Some v\<rparr>"
  shows "P M \<Gamma> \<^bold>\<turnstile> S'"
  using corr op val_ok unfolding corr_def is_retval_ok_def var_corr_def by simp

lemma except_update_ok:
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes val_ok: "is_value_ok P (heap S) ((ClassT Object),{}) e"
  assumes notnull: "e \<noteq> null"
  assumes op: "S' = S\<lparr>except := Some e\<rparr>"
  shows "P M \<Gamma> \<^bold>\<turnstile> S'"
  using corr op val_ok notnull unfolding corr_def is_except_ok_def var_corr_def by simp

lemma is_obj_label_ok_consistent:
  assumes "obj_consistent obj obj'"
  shows "is_obj_label_ok P obj T = is_obj_label_ok P obj' T"
  using assms unfolding is_obj_label_ok_def obj_consistent_def by simp

lemma obj_consistent_field_update: (*field_update_consistent:*)
  assumes "upd_obj = (obj\<lparr>HFields := ((HFields obj)(f\<mapsto>v))\<rparr>)"
  shows "obj_consistent obj upd_obj"
  unfolding obj_consistent_def using assms by simp

lemma heap_extends_consistent_heap_update: (* heap_update_extends_heap *)
  assumes exist: "H l' = Some obj"
  assumes "obj_consistent obj upd_obj"
  assumes op: "H' = H(l'\<mapsto>upd_obj)"
  shows "heap_extends H H'"
  unfolding heap_extends_def using assms obj_consistent_def by auto

lemma is_value_ok_heap_extends: (*is_value_ok_heap_extends*)
  assumes extends: "heap_extends H H'"
  assumes ok: "is_value_ok P H T v"
  shows "is_value_ok P H' T v"
proof (cases v)
  case (href l)
  then obtain obj where a1: "H l = Some obj \<and> (P \<turnstile> (ClassT (HClass obj)) <: (ttype T)) \<and> is_obj_label_ok P obj T"
    using ok by auto
  then obtain obj' where "H' l = Some obj' \<and> obj_consistent obj obj'"
    using extends unfolding heap_extends_def by (metis domI domIff option.collapse option.sel)
  then have "H' l = Some obj' \<and> (P \<turnstile> (ClassT (HClass obj')) <: (ttype T)) \<and> is_obj_label_ok P obj' T"
    using a1 is_obj_label_ok_consistent unfolding obj_consistent_def by metis
  then show ?thesis using href by simp
next
  case null
  then show ?thesis by simp
next
  case (num x3)
  then show ?thesis using assms by simp
qed

(* is_value_ok is a shallow check, so it doesn't depend on the fields of an object *)
lemma is_value_ok_heap_update: (* heap_update_is_value_ok*)
  assumes ok: "is_value_ok P H T v"
  assumes exist: "H l = Some obj"
  assumes op: "H' = H(l\<mapsto>obj')" (* assumes op: "H' = H(l\<mapsto>(obj\<lparr>HFields := (HFields obj)(f\<mapsto>v')\<rparr>))"*)
  assumes consistent: "obj_consistent obj obj'"
  shows "is_value_ok P H' T v"
  using assms is_value_ok_heap_extends heap_extends_consistent_heap_update by metis

(* When we update the heap in a type-correct way, any set of objects that exists and is type-correct
   will continue to exist and remain type-correct. *)
lemma heap_update_heap_ok:
  assumes ok: "is_heap_ok P H"
  assumes ok': "is_value_ok P H (intersect_label (ftype fd) (HLabel obj)) v"
  assumes field: "field P (HClass obj) f = Some fd"
  assumes exist: "H l = Some obj"
  assumes upd_obj: "upd_obj = (obj\<lparr>HFields := ((HFields obj)(f\<mapsto>v))\<rparr>)"
  assumes op: "H' = H(l\<mapsto>upd_obj)"
  shows "is_heap_ok P H'"
proof -
  have a1: "\<And>T v. is_value_ok P H T v \<Longrightarrow> is_value_ok P H' T v"
    using is_value_ok_heap_update obj_consistent_field_update exist op upd_obj by blast
  have a2: "\<forall>obj. is_heapobj_ok P H obj \<longrightarrow> is_heapobj_ok P H' obj"
    using a1 unfolding is_heapobj_ok_def by blast
  (* Ascertain that the new value is shallowly OK inside the updated heap H' *)
  have "is_value_ok P H' (intersect_label (ftype fd) (HLabel obj)) v"
    using ok' a1 by blast
  (* Then that the updated object with that value is OK. *)
  moreover have "is_heapobj_ok P H' obj"
    using a2 ok exist unfolding is_heap_ok_def by force
  ultimately have "is_heapobj_ok P H' upd_obj"
    unfolding is_heapobj_ok_def upd_obj using field by simp
  (* Show that for each object in the original object graph, including l, it is (shallowly) OK inside H' *)
  then have "\<forall>loc\<in>dom(H'). is_heapobj_ok P H' (the (H' loc))"
    using ok a2 op unfolding is_heap_ok_def by auto
  then show "is_heap_ok P H'" unfolding is_heap_ok_def by simp
qed

lemma heap_update_ok:
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes ok: "is_value_ok P (heap S) (intersect_label (ftype fd) (HLabel obj)) v"
  assumes exist: "heap S l' = Some obj"
  assumes field: "field P (HClass obj) f = Some fd"
  assumes upd_obj: "upd_obj = (obj\<lparr>HFields := ((HFields obj)(f\<mapsto>v))\<rparr>)"
  assumes op: "S' = S\<lparr>heap:= (heap S)(l'\<mapsto>upd_obj)\<rparr>"
  shows "P M \<Gamma> \<^bold>\<turnstile> S'"
proof -
  have a1: "\<forall>t v. is_value_ok P (heap S) t v \<longrightarrow> is_value_ok P (heap S') t v"
    using is_value_ok_heap_update obj_consistent_field_update ok exist field upd_obj op by simp
  moreover have "\<forall>x. var_corr P \<Gamma> S x" using corr unfolding corr_def by simp
  moreover have "privs S = privs S' \<and> stack S = stack S'" using op by simp
  ultimately have "\<forall>x. var_corr P \<Gamma> S' x" using op unfolding var_corr_def by metis
  moreover have "is_heap_ok P (heap S')"
   using corr_def assms heap_update_heap_ok by simp
  moreover have "is_globals_ok P (heap S') (globals S')"
    using a1 corr is_globals_ok_value_ok op unfolding corr_def by fastforce
  moreover have "is_retval_ok P (heap S') (intersect_label (msreturn M) (privs S')) (retval S')"
  proof -
    have "retval S' = retval S \<and> privs S' = privs S" using op by simp
    then show ?thesis using a1 is_retval_ok_value_ok corr unfolding corr_def by metis
  qed
  moreover have "is_except_ok P (heap S') (except S')"
    using a1 is_except_ok_value_ok corr op unfolding corr_def by fastforce
  moreover have "(msreq M) \<subseteq> (privs S')"
    using corr op unfolding corr_def by simp
  moreover have "(privs S') \<subseteq> (the (grant P (mscname M)))"
    using corr op unfolding corr_def by simp
  ultimately show ?thesis using corr_def by simp
qed

(*lemma heap_extends_corr:
  assumes stack_corr: "P \<Gamma> \<^bold>\<turnstile> S"
  assumes extends: "heap_extends S S'"
  assumes heap_corr: "P \<Gamma>' \<^bold>\<turnstile> S'"
  shows "P \<Gamma> \<^bold>\<turnstile> (S\<lparr>heap := (heap S')\<rparr>)"
proof -
  have "\<forall>t v. is_value_ok P (heap S) t v \<longrightarrow> is_value_ok P (heap S') t v"
    using is_value_ok_heap_extends extends by simp
  then have "(\<forall>x. var_corr P \<Gamma> (S\<lparr>heap := (heap S')\<rparr>) x)"
    using stack_corr unfolding corr_def var_corr_def by force
  then show ?thesis using heap_corr unfolding corr_def by simp
qed*)

lemma heap_extends_corr:
  assumes s0: "S0 = S\<lparr>stack := s, retval:= r, privs := p\<rparr>"
  assumes s': "S' = S1\<lparr>stack := stack S, retval := retval S, privs := privs S\<rparr>" (* i.e. S' takes the heap, globals and exception from S1 but the rest from S *)
  assumes stack_corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  assumes extends: "heap_extends (heap S0) (heap S1)"
  assumes call_corr: "(P M0 \<Gamma>0 \<^bold>\<turnstile> S1)"
  shows "(P M \<Gamma> \<^bold>\<turnstile> S')"
proof -
  have a1: "\<forall>t v. is_value_ok P (heap S) t v \<longrightarrow> is_value_ok P (heap S') t v"
    using is_value_ok_heap_extends extends s0 s' by simp
  moreover have "stack S = stack S' \<and> privs S = privs S'" using s' by simp
  ultimately have "(\<forall>x. var_corr P \<Gamma> S' x)"
    using stack_corr s' unfolding corr_def var_corr_def by metis
  moreover have "is_heap_ok P (heap S')"
    using call_corr s' unfolding corr_def by simp
  moreover have "is_globals_ok P (heap S') (globals S')"
    using call_corr s' unfolding corr_def by fastforce
  moreover have "is_retval_ok P (heap S') (intersect_label (msreturn M) (privs S')) (retval S')"
  proof -
    have "(privs S = privs S') \<and> (retval S' = retval S)" using s' by simp
    then show ?thesis using a1 is_retval_ok_value_ok stack_corr unfolding corr_def by metis
  qed
  moreover have "is_except_ok P (heap S') (except S')"
    using call_corr s' unfolding corr_def by simp
  moreover have "(msreq M) \<subseteq> (privs S')"
    using stack_corr s' unfolding corr_def by simp
  moreover have "(privs S') \<subseteq> (the (grant P (mscname M)))"
    using stack_corr s' unfolding corr_def by simp
  ultimately show ?thesis unfolding corr_def by simp
qed

lemma allocate_new_object_ok:
  shows "is_heapobj_ok P H (new_object P cname label)"
  unfolding is_heapobj_ok_def new_object_def by simp

lemma allocate_new_value_ok:
  assumes op: "H' = H(l\<mapsto>(new_object P cname label))"
  assumes lbl_min: "creq (the (class P cname)) \<subseteq> label"
  assumes lbl_max: "label \<subseteq> (the (grant P cname))"
  shows "is_value_ok P H' ((ClassT cname),label) (href l)"
  using assms by (simp add: new_object_def op subtype_self is_obj_label_ok_def)

lemma globals_access_ok:
  assumes cls: "is_class P c"
  assumes field: "field P c f = Some fd"
  assumes static: "fstatic fd"
  assumes op1: "classStatics = the (globals S c)"
  assumes op2: "v = the (classStatics f)"
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  shows "is_value_ok P (heap S) (ftype fd) v"
proof -
  have "globals S c = Some classStatics \<and> is_staticfields_ok P (heap S) c classStatics"
    using corr cls op1 unfolding corr_def is_globals_ok_def by auto
  then have "(classStatics f) = Some v \<and>  is_value_ok P (heap S) (ftype fd) v"
    using field static op2 unfolding is_staticfields_ok_def by fastforce
  then show ?thesis by simp
qed

lemma globals_update_globals_ok:
  assumes globals_ok: "is_globals_ok P (heap S) (globals S)"
  assumes cls: "is_class P c"
  assumes field: "field P c f = Some fd"
  assumes static: "fstatic fd"
  assumes value_ok: "is_value_ok P (heap S) (ftype fd) v"
  assumes update: "S' = S\<lparr>globals := globals S(c \<mapsto> (the (globals S c))(f \<mapsto> v))\<rparr>"
  shows "is_globals_ok P (heap S') (globals S')"
proof -
  have a1: "is_globals_ok P (heap S') (globals S)"
    using update globals_ok is_globals_ok_value_ok by fastforce
  then have "globals S c \<noteq> None \<and> is_staticfields_ok P (heap S') c (the (globals S c))"
    using cls unfolding is_globals_ok_def by auto
  moreover have "is_value_ok P (heap S') (ftype fd) v"
    using update value_ok by simp
  ultimately have "globals S' c \<noteq> None \<and> is_staticfields_ok P (heap S') c (the (globals S' c))"
    unfolding is_staticfields_ok_def using field static update by simp
  then show ?thesis
    using a1 update unfolding is_globals_ok_def by simp
qed

lemma globals_update_ok:
  assumes cls: "is_class P c"
  assumes field: "field P c f = Some fd"
  assumes static: "fstatic fd"
  assumes ok: "is_value_ok P (heap S) (ftype fd) v"
  assumes update: "S' = S\<lparr>globals := globals S(c \<mapsto> (the (globals S c))(f \<mapsto> v))\<rparr>"
  assumes corr: "P M \<Gamma> \<^bold>\<turnstile> S"
  shows "P M \<Gamma> \<^bold>\<turnstile> S'"
proof -
  have a1: "(heap S) = (heap S')"
    using update by simp
  have "\<forall>x. var_corr P \<Gamma> S' x"
    using corr corr_def update unfolding var_corr_def by simp
  moreover have "is_heap_ok P (heap S')"
   using corr_def corr update by simp
  moreover have "is_retval_ok P (heap S') (intersect_label (msreturn M) (privs S')) (retval S')"
    using a1 corr update unfolding corr_def is_retval_ok_def by simp
  moreover have "is_globals_ok P (heap S') (globals S')"
    using globals_update_globals_ok corr cls field static ok update unfolding corr_def by metis
  moreover have "is_except_ok P (heap S') (except S')"
    using a1 corr update unfolding corr_def by simp
  moreover have "(msreq M) \<subseteq> (privs S')"
    using corr update unfolding corr_def by simp
  moreover have "(privs S') \<subseteq> (the (grant P (mscname M)))"
    using corr update unfolding corr_def by simp
  ultimately show ?thesis using corr_def by simp
qed

end


subsection \<open>Reassociation Phase\<close>
theory ReassociationPhase
  imports Canonicalizations.Common
begin

text \<open>The reassociation phase focuses re-ordering associative binary operations.
The purpose of this phase is to disassociate constants and invariant variables within a loop from variant variables.
This enables later phases to hoist more expressions outside of a loop.\<close>

phase ReassociationPhase
  terminating size
begin

subsubsection \<open>Rewrite Shifts to Multiplication\<close>

text \<open>Multiplication to powers of 2 are optimized to left shift operations in earlier phases.
As left shifts aren't associative this reduces the scope of this phase so the following undoes the optimization.\<close>

fun intval_power :: "nat \<Rightarrow> Value \<Rightarrow> Value" where
  "intval_power b (IntVal32 v) = IntVal32 (word_of_nat (b^(unat v)))" |
  "intval_power b (IntVal64 v) = IntVal64 (word_of_nat (b^(unat v)))" |
  "intval_power _ _ = UndefVal"

lemma LeftShift32:
  fixes x y :: "32 word"
  shows "x << unat (and y 31) = x << unat y"
  sorry

lemma LeftShiftToMulVal:
  assumes "intval_mul x (intval_power 2 y) \<noteq> UndefVal"
  shows "intval_left_shift x y = intval_mul x (intval_power 2 y)"
  using assms apply (cases x; cases y; auto) sorry

optimization LeftShiftToMul:
  "x << (const c) \<longmapsto> x * (const (intval_power 2 c))"
   defer apply simp sorry

end

end


theory Proof_3_7
  imports HandDryer VCTheoryLemmas Extra
begin

theorem proof_3_7:
"VC7 inv3 s0 hands_value"
  apply(simp only: VC7_def inv3_def  R3_def
  dryer_def)
  apply(rule impI)
  apply(rule conjI)
   apply(rule conjI)
    apply(simp)
proof -
  define s:: state where
"s = (toEnv (setVarAny s0 hands_value))"
  assume VC: "  ((toEnvP s0 \<and>
      (\<forall>s1 s2.
          substate s1 s2 \<and>
          substate s2 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvNum s1 s2 = hands \<and>
          10 \<le> toEnvNum s2 s0 \<and>
          getVarBool s1 hands = ON \<and>
          getVarBool s1 (Suc (Suc 0)) = ON \<and>
          getVarBool s2 hands = OFF \<longrightarrow>
          (\<exists>s4. toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF)))) \<and>
     extraInv s0) \<and>
    env (setVarAny s0 hands_value) hands_value \<and>
    getPstate (setVarAny s0 hands_value) Ctrl =
    drying \<and>
    getVarBool (setVarAny s0 hands_value) hands \<noteq>
    ON \<and>
    \<not> 10 \<le> ltimeEnv (setVarAny s0 hands_value)
             Ctrl "
  show "\<forall>s1 s2.
       substate s1 s2 \<and>
       substate s2
        (toEnv (setVarAny s0 hands_value)) \<and>
       toEnvP s1 \<and>
       toEnvP s2 \<and>
       toEnvNum s1 s2 = hands \<and>
       10 \<le> toEnvNum s2
              (toEnv (setVarAny s0 hands_value)) \<and>
       getVarBool s1 hands = ON \<and>
       getVarBool s1 (Suc (Suc 0)) = ON \<and>
       getVarBool s2 hands = OFF \<longrightarrow>
       (\<exists>s4. toEnvP s4 \<and>
             substate s2 s4 \<and>
             substate s4
              (toEnv (setVarAny s0 hands_value)) \<and>
             toEnvNum s2 s4 \<le> 10 \<and>
             (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
              getVarBool s4 hands = ON) \<and>
             (\<forall>s3. toEnvP s3 \<and>
                   substate s2 s3 \<and>
                   substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                   getVarBool s3 (Suc (Suc 0)) =
                   ON \<and>
                   getVarBool s3 hands = OFF))"
    apply(simp only: s_def[symmetric])
  proof(rule allI; rule allI; rule impI)
    fix s1 s2
    assume req_prems: "substate s1 s2 \<and>
       substate s2 s \<and>
       toEnvP s1 \<and>
       toEnvP s2 \<and>
       toEnvNum s1 s2 = hands \<and>
       10 \<le> toEnvNum s2 s \<and>
       getVarBool s1 hands = ON \<and>
       getVarBool s1 (Suc (Suc 0)) = ON \<and>
       getVarBool s2 hands = OFF"
    then obtain "10 \<le> toEnvNum s2 s" by auto
    from le_imp_less_or_eq[OF this]
    show " \<exists>s4. toEnvP s4 \<and>
            substate s2 s4 \<and>
            substate s4 s \<and>
            toEnvNum s2 s4 \<le> 10 \<and>
            (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
             getVarBool s4 hands = ON) \<and>
            (\<forall>s3. toEnvP s3 \<and>
                  substate s2 s3 \<and>
                  substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                  getVarBool s3 (Suc (Suc 0)) = ON \<and>
                  getVarBool s3 hands = OFF)"
    proof
      assume 1: "10 < toEnvNum s2 s"
      with req_prems substate_eq_or_predEnv
 toEnvNum_id s_def  have 2: "substate s2 s0"
        by (simp add: s_def split: if_splits)
      from VC obtain "\<forall>s1 s2.
          substate s1 s2 \<and>
          substate s2 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvNum s1 s2 = hands \<and>
          10 \<le> toEnvNum s2 s0 \<and>
          getVarBool s1 hands = ON \<and>
          getVarBool s1 (Suc (Suc 0)) = ON \<and>
          getVarBool s2 hands = OFF \<longrightarrow>
          (\<exists>s4. toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF))"
        by auto
      with req_prems 1 2 have "\<exists>s4. toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF)"
        by (auto simp add: s_def split: if_splits)
      then obtain s4 where 3: " toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF)" ..
      have  "(toEnvP s4 \<and>
      substate s2 s4 \<and>
      substate s4 s \<and>
      toEnvNum s2 s4 \<le> 10 \<and>
      (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
       getVarBool s4 hands = ON)) \<and>
      (\<forall>s3. toEnvP s3 \<and>
            substate s2 s3 \<and>
            substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
            getVarBool s3 (Suc (Suc 0)) = ON \<and>
            getVarBool s3 hands = OFF)"
      proof
        from 3 show "toEnvP s4 \<and>
      substate s2 s4 \<and>
      substate s4 s \<and>
      toEnvNum s2 s4 \<le> 10 \<and>
      (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
       getVarBool s4 hands = ON)"
          by (simp add: s_def)
      next
        from 3 show "\<forall>s3. toEnvP s3 \<and>
         substate s2 s3 \<and>
         substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
         getVarBool s3 (Suc (Suc 0)) = ON \<and>
         getVarBool s3 hands = OFF"
          by simp
      qed
      thus ?thesis by auto
    next
      assume 4: "10 = toEnvNum s2 s"
      from substate_asym have 5:
"\<forall>s3. toEnvP s3 \<and>
               substate s2 s3 \<and>
               substate s3 s2 \<and> s3 \<noteq> s2 \<longrightarrow>
               getVarBool s3 (Suc (Suc 0)) = ON \<and>
               getVarBool s3 hands = OFF"
        by auto
      show ?thesis
      proof -
        define s5:: state where "s5=s2"
        have "toEnvP s5 \<and> substate s2 s5 \<and>
substate s5 s \<longrightarrow>pred3 s2 s s5"
        proof(induction rule: state_down_ind)
          case 1
          then show ?case
            using req_prems s_def by auto
        next
          case 2
          then show ?case
            apply(simp only: pred3_def)
          proof
            assume 6: " \<forall>s3. toEnvP s3 \<and>
         substate s2 s3 \<and>
         substate s3 s \<and> s3 \<noteq> s \<longrightarrow>
         getVarBool s3 (Suc (Suc 0)) = ON \<and>
         getVarBool s3 hands = OFF"
            from VC have "\<exists> s3. ~ (toEnvP s3 \<and>
         substate s2 s3 \<and>
         substate s3 s \<and> s3 \<noteq> s \<longrightarrow>
         getVarBool s3 (Suc (Suc 0)) = ON \<and>
         getVarBool s3 hands = OFF)"
              apply(simp only: extraInv_def)
            proof -
              print_state
              assume "((toEnvP s0 \<and>
      (\<forall>s1 s2.
          substate s1 s2 \<and>
          substate s2 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvNum s1 s2 = hands \<and>
          10 \<le> toEnvNum s2 s0 \<and>
          getVarBool s1 hands = ON \<and>
          getVarBool s1 (Suc (Suc 0)) = ON \<and>
          getVarBool s2 hands = OFF \<longrightarrow>
          (\<exists>s4. toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF)))) \<and>
     toEnvP s0 \<and>
     (getPstate s0 Ctrl = drying \<longrightarrow>
      0 < ltimeEnv s0 Ctrl \<and>
      ltimeEnv s0 Ctrl \<le> 10 \<and>
      (\<forall>s1. toEnvP s1 \<and>
            substate s1 s0 \<and>
            toEnvNum s1 s0 + hands =
            ltimeEnv s0 Ctrl \<longrightarrow>
            getVarBool s1 hands = ON \<and>
            getVarBool s1 dryer = ON) \<and>
      (\<forall>s1. toEnvP s1 \<and>
            substate s1 s0 \<and>
            toEnvNum s1 s0 + hands
            < ltimeEnv s0 Ctrl \<longrightarrow>
            getVarBool s1 hands = OFF \<and>
            getVarBool s1 dryer = ON)) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<longrightarrow>
           getPstate s1 Ctrl = waiting \<or>
           getPstate s1 Ctrl = drying)) \<and>
    env (setVarAny s0 hands_value) hands_value \<and>
    getPstate (setVarAny s0 hands_value) Ctrl =
    drying \<and>
    getVarBool (setVarAny s0 hands_value) hands \<noteq>
    ON \<and>
    \<not> 10 \<le> ltimeEnv (setVarAny s0 hands_value)
             Ctrl"
              then obtain 7:
 " 0 < ltimeEnv s0 Ctrl \<and> ltimeEnv s0 Ctrl \<le> 10 \<and>
(\<forall>s1. toEnvP s1 \<and>
            substate s1 s0 \<and>
            toEnvNum s1 s0 + hands =
            ltimeEnv s0 Ctrl \<longrightarrow>
            getVarBool s1 hands = ON \<and>
            getVarBool s1 dryer = ON)" by auto
              from shiftEnv_substate have 8:
"substate (shiftEnv s0 (ltimeEnv s0 Ctrl - 1)) s0"
                by auto
from VC obtain  9: "toEnvP s0" by auto
            from 7 obtain 10:
 "0 < ltimeEnv s0 Ctrl" by auto
            from 9 10 ltime_le_toEnvNum[of s0 Ctrl]
shift_spec have 11: "toEnvP (shiftEnv s0 (ltimeEnv s0 Ctrl - 1))"
              by auto
              have
"toEnvNum (shiftEnv s0 (ltimeEnv s0 Ctrl - 1)) s0
+ 1 = ltimeEnv s0 Ctrl"
              proof -
                from VC obtain  9: "toEnvP s0" by auto
            from 7 obtain 10:
 "0 < ltimeEnv s0 Ctrl" by auto
                with 9 10 ltime_le_toEnvNum[of s0 Ctrl]
toEnvNum_shift show ?thesis
                  by auto
              qed
              with 7 8 11 have 12:
"getVarBool (shiftEnv s0 (ltimeEnv s0 Ctrl - 1))
hands = ON \<and>
 getVarBool (shiftEnv s0 (ltimeEnv s0 Ctrl - 1))
dryer = ON" by auto
              have 13:"substate s2 (shiftEnv s0 (ltimeEnv s0 Ctrl - 1))"
              proof -
                from 4 req_prems substate_eq_or_predEnv
 toEnvNum_id s_def  have 2: "substate s2 s0"
                  by (simp add: s_def split: if_splits)
                from 7 obtain 14: "ltimeEnv s0 Ctrl \<le> 10" by auto
      from req_prems obtain "toEnvP s2"
        by auto
                with 2 9 10 4 14  substate_shift[of s2 s0 "ltimeEnv s0 Ctrl - 1"]
                show ?thesis
                  by (auto simp add: s_def split: if_splits)
              qed
              have 14: "substate (shiftEnv s0 (ltimeEnv s0 Ctrl - hands)) s0"
                using shiftEnv_substate by auto
              have 15: "substate s0 s" using substate_refl
                by (auto simp add: s_def)
              with 14 have 16:  "substate (shiftEnv s0 (ltimeEnv s0 Ctrl - hands)) s"
                using substate_trans by blast
              have  " (shiftEnv s0 (ltimeEnv s0 Ctrl - hands)) \<noteq> s"
              proof
                assume "shiftEnv s0 (ltimeEnv s0 Ctrl - hands) = s"
                with shiftEnv_substate
                have "substate s s0" by auto
                with 15 substate_asym
                have "s0 = s" by auto
                with s_def show False by auto
              qed
              with 11 12 13 16 show ?thesis
                by auto
            qed
            with 6 show " \<exists>s4. toEnvP s4 \<and>
         substate s s4 \<and>
         substate s4 s \<and>
         toEnvNum s2 s4 \<le> 10 \<and>
         (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
          getVarBool s4 hands = ON) \<and>
         (\<forall>s3. toEnvP s3 \<and>
               substate s s3 \<and>
               substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
               getVarBool s3 (Suc (Suc 0)) = ON \<and>
               getVarBool s3 hands = OFF)" by auto
          qed
        next
          case (3 s5)
          then show ?case
            apply(simp only: pred3_def)
          proof
            from 3(3) have  6: " (\<forall>s3. toEnvP s3 \<and>
          substate s2 s3 \<and>
          substate s3 s5 \<and> s3 \<noteq> s5 \<longrightarrow>
          getVarBool s3 (Suc (Suc 0)) = ON \<and>
          getVarBool s3 hands = OFF) \<Longrightarrow>
    (\<exists>s4. toEnvP s4 \<and>
          substate s5 s4 \<and>
          substate s4 s \<and>
          toEnvNum s2 s4 \<le> 10 \<and>
          (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
           getVarBool s4 hands = ON) \<and>
          (\<forall>s3. toEnvP s3 \<and>
                substate s5 s3 \<and>
                substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                getVarBool s3 (Suc (Suc 0)) = ON \<and>
                getVarBool s3 hands = OFF)) "
              by (auto simp add: pred3_def)
            assume 7: " \<forall>s3. toEnvP s3 \<and>
         substate s2 s3 \<and>
         substate s3 (predEnv s5) \<and>
         s3 \<noteq> predEnv s5 \<longrightarrow>
         getVarBool s3 (Suc (Suc 0)) = ON \<and>
         getVarBool s3 hands = OFF"
            show "\<exists>s4. toEnvP s4 \<and>
         substate (predEnv s5) s4 \<and>
         substate s4 s \<and>
         toEnvNum s2 s4 \<le> 10 \<and>
         (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
          getVarBool s4 hands = ON) \<and>
         (\<forall>s3. toEnvP s3 \<and>
               substate (predEnv s5) s3 \<and>
               substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
               getVarBool s3 (Suc (Suc 0)) = ON \<and>
               getVarBool s3 hands = OFF)"
            proof cases
              assume 10: "(getVarBool (predEnv s5) (Suc (Suc 0)) = OFF \<or>
          getVarBool (predEnv s5) hands = ON)"
              from predEnv_substate 3
substate_trans have 8:  "substate (predEnv s5) s"
                by blast
              from 3(2) substate_eq_or_predEnv req_prems
              have 9: "substate s2 (predEnv s5)"
                by auto
              have "toEnvP (predEnv s5) \<and>
         substate (predEnv s5) (predEnv s5) \<and>
         substate (predEnv s5) s \<and>
         toEnvNum s2 (predEnv s5) \<le> 10 \<and>
         (getVarBool (predEnv s5) (Suc (Suc 0)) = OFF \<or>
          getVarBool (predEnv s5) hands = ON) \<and>
         (\<forall>s3. toEnvP s3 \<and>
               substate (predEnv s5) s3 \<and>
               substate s3 (predEnv s5) \<and>
 s3 \<noteq> (predEnv s5) \<longrightarrow>
               getVarBool s3 (Suc (Suc 0)) = ON \<and>
               getVarBool s3 hands = OFF)"
              proof -
                from predEnvP_or_emptyState[of s5]
                have "toEnvP (predEnv s5)"
                proof
                  assume "toEnvP (predEnv s5)"
                  thus ?thesis by assumption
                next
                  assume   "predEnv s5 = emptyState"
                  with 9 req_prems show ?thesis
                    by (cases s2; auto)
                qed
                moreover from substate_refl have
" substate (predEnv s5) (predEnv s5)" by auto
                moreover from 8
                have "substate (predEnv s5) s"
                  by assumption
                moreover from 4 8 9 toEnvNum3
                have "toEnvNum s2 (predEnv s5) \<le> 10"
                  by auto
                moreover from 10
                have "(getVarBool (predEnv s5) (Suc (Suc 0)) = OFF \<or>
     getVarBool (predEnv s5) hands = ON)"
                  by assumption
                moreover from substate_asym
                have "\<forall>s3. toEnvP s3 \<and>
          substate (predEnv s5) s3 \<and>
          substate s3 (predEnv s5) \<and>
          s3 \<noteq> predEnv s5 \<longrightarrow>
          getVarBool s3 (Suc (Suc 0)) = ON \<and>
          getVarBool s3 hands = OFF" by auto
                ultimately show ?thesis by auto
              qed
              thus ?thesis by auto
            next
              assume 10: "\<not> (getVarBool (predEnv s5) (Suc (Suc 0)) = OFF \<or>
        getVarBool (predEnv s5) hands = ON)"
              with substate_eq_or_predEnv 7
              have " \<forall>s3. toEnvP s3 \<and>
         substate s2 s3 \<and>
         substate s3  s5 \<and>
         s3 \<noteq> s5 \<longrightarrow>
         getVarBool s3 (Suc (Suc 0)) = ON \<and>
         getVarBool s3 hands = OFF"
                by auto
              from 6[OF this] obtain s4 where 11:
"toEnvP s4 \<and>
       substate s5 s4 \<and>
       substate s4 s \<and>
       toEnvNum s2 s4 \<le> 10 \<and>
       (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
        getVarBool s4 hands = ON) \<and>
       (\<forall>s3. toEnvP s3 \<and>
             substate s5 s3 \<and>
             substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
             getVarBool s3 (Suc (Suc 0)) = ON \<and>
             getVarBool s3 hands = OFF)" ..
              have "(toEnvP s4 \<and>
      substate (predEnv s5) s4 \<and>
      substate s4 s \<and>
      toEnvNum s2 s4 \<le> 10 \<and>
      (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
       getVarBool s4 hands = ON)) \<and>
      (\<forall>s3. toEnvP s3 \<and>
            substate (predEnv s5) s3 \<and>
            substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
            getVarBool s3 (Suc (Suc 0)) = ON \<and>
            getVarBool s3 hands = OFF)"
              proof
                from 11 predEnv_substate substate_trans
                show "toEnvP s4 \<and>
      substate (predEnv s5) s4 \<and>
      substate s4 s \<and>
      toEnvNum s2 s4 \<le> 10 \<and>
      (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
       getVarBool s4 hands = ON)" by blast
              next
                show "\<forall>s3. toEnvP s3 \<and>
            substate (predEnv s5) s3 \<and>
            substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
            getVarBool s3 (Suc (Suc 0)) = ON \<and>
            getVarBool s3 hands = OFF"
                proof(rule allI; rule impI)
                  fix s3
                  assume 12: "toEnvP s3 \<and>
            substate (predEnv s5) s3 \<and>
            substate s3 s4 \<and> s3 \<noteq> s4"
                  with  11 3(1) predEnv_substate_imp_eq_or_substate
                  have "s3 = predEnv s5 \<or> substate s5 s3"
                    by auto
                  with 10 11 12 show "getVarBool s3 (Suc (Suc 0)) = ON \<and>
            getVarBool s3 hands = OFF"
                    by auto

                qed
              qed
              thus ?thesis by auto
            qed
          qed
        qed
        with s5_def req_prems substate_refl
 pred3_def 5 show ?thesis by auto
      qed
    qed
  qed
next
  assume "((toEnvP s0 \<and>
      (\<forall>s1 s2.
          substate s1 s2 \<and>
          substate s2 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvNum s1 s2 = hands \<and>
          10 \<le> toEnvNum s2 s0 \<and>
          getVarBool s1 hands = ON \<and>
          getVarBool s1 (Suc (Suc 0)) = ON \<and>
          getVarBool s2 hands = OFF \<longrightarrow>
          (\<exists>s4. toEnvP s4 \<and>
                substate s2 s4 \<and>
                substate s4 s0 \<and>
                toEnvNum s2 s4 \<le> 10 \<and>
                (getVarBool s4 (Suc (Suc 0)) = OFF \<or>
                 getVarBool s4 hands = ON) \<and>
                (\<forall>s3. toEnvP s3 \<and>
                      substate s2 s3 \<and>
                      substate s3 s4 \<and> s3 \<noteq> s4 \<longrightarrow>
                      getVarBool s3 (Suc (Suc 0)) =
                      ON \<and>
                      getVarBool s3 hands =
                      OFF)))) \<and>
     extraInv s0) \<and>
    env (setVarAny s0 hands_value) hands_value \<and>
    getPstate (setVarAny s0 hands_value) Ctrl =
    drying \<and>
    getVarBool (setVarAny s0 hands_value) hands \<noteq>
    ON \<and>
    \<not> 10 \<le> ltimeEnv (setVarAny s0 hands_value)
             Ctrl"
  with extra7 show " extraInv (toEnv (setVarAny s0 hands_value))"
    by (auto simp add: VC7_def)
qed

end