theory flash112Rev imports flashPub
begin
section{*Main defintions*}
lemma NI_FAckVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_FAck ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_InvVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Inv  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1VsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1_HomeVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_InvAck_1_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_2VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_InvAck_2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_GetXVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak1VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak2VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak3VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX1VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX2VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX3VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX4VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX5VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX6VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX7VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX8VsInv112:
  (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX8_homeVsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX9VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX10VsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX10_homeVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX11VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_Get_GetVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak1VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak2VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak3VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put1VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put2VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Put2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put3VsInv112:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Local_Get_Put3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_PutVsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (NI_Local_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"formEval  ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s  \<or>formEval  ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s  \<or>formEval  ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s  \<or>formEval  ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s  "
	                      by auto

    moreover
                       {assume b1:"formEval ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_PutXAcksDoneVsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (NI_Local_PutXAcksDone ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_NakVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Nak  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Nak_ClearVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_Nak_Clear ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_Nak_HomeVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_Nak_Home ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_Remote_GetX_NakVsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_Nak_HomeVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_PutXVsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_PutX_HomeVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Nak1VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Nak2VsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Put1VsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_Get_Put1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Put2VsInv112:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_PutVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_Put  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_PutXVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceHomeVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_ReplaceHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_ReplaceHomeShrVldVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_ReplaceHomeShrVld ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_ReplaceShrVldVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (NI_ReplaceShrVld  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ShWbVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_ShWb N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_WbVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (NI_Wb ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma PI_Local_GetX_GetX1VsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_GetX1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma PI_Local_GetX_GetX2VsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_GetX2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma PI_Local_GetX_PutX1VsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_PutX1 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX2VsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_PutX2 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX3VsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_PutX3 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX4VsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_GetX_PutX4 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_Get_GetVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (PI_Local_Get_Get ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma PI_Local_Get_PutVsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_Get_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"formEval  ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s  \<or>formEval  ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s  \<or>formEval  ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s  \<or>formEval  ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s  "
	                      by auto

    moreover
                       {assume b1:"formEval ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )    ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval ( andForm  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )     (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Local_PutXVsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_PutX ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_ReplaceVsInv112:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv112 ) (PI_Local_Replace ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Remote_GetVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (PI_Remote_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_GetXVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (PI_Remote_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_PutXVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (PI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_ReplaceVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (PI_Remote_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma StoreVsInv112:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv112 ) (Store  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma StoreHomeVsInv112:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv112 ) (StoreHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  end


theory ProcHoleVars
  imports RedSafeHoleLemma
begin

fun hole_free_vars :: "p_hole \<Rightarrow> string set" where
  "hole_free_vars ExpHole = {}"
| "hole_free_vars (AppHole1 h e) = (hole_free_vars h \<union> free_vars e)"
| "hole_free_vars (AppHole2 v h) = (free_vars v \<union> hole_free_vars h)"
| "hole_free_vars (IfHole h e1 e2) = (hole_free_vars h \<union> free_vars e1 \<union> free_vars e2)"
| "hole_free_vars (PairHole1 h e) = (hole_free_vars h \<union> free_vars e)"
| "hole_free_vars (PairHole2 e h) = (free_vars e \<union> hole_free_vars h)"
(*| "hole_free_vars (UnpackHole e h) = (free_vars e \<union> hole_free_vars h)"    *)

fun hole_res_vars :: "owner_env \<Rightarrow> p_hole \<Rightarrow> res_id set" where
  "hole_res_vars delta ExpHole = {}"
| "hole_res_vars delta (AppHole1 h e) = (hole_res_vars delta h \<union> res_vars delta e)"
| "hole_res_vars delta (AppHole2 v h) = (res_vars delta v \<union> hole_res_vars delta h)"
| "hole_res_vars delta (IfHole h e1 e2) = (hole_res_vars delta h \<union> res_vars delta e1 \<union> res_vars delta e2)"
| "hole_res_vars delta (PairHole1 h e) = (hole_res_vars delta h \<union> res_vars delta e)"
| "hole_res_vars delta (PairHole2 e h) = (res_vars delta e \<union> hole_res_vars delta h)"

lemma app_hole_free_vars: "\<lbrakk> x \<in> free_vars e \<rbrakk> \<Longrightarrow> x \<in> free_vars (app_hole h e)"
  apply (induct h)
    apply (auto)
  done

lemma app_hole_free_vars2: "\<lbrakk> x \<in> hole_free_vars h \<rbrakk> \<Longrightarrow> x \<in> free_vars (app_hole h e)"
  apply (induct h)
    apply (auto)
  done

lemma app_hole_free_vars_rev: "\<lbrakk> x \<in> free_vars (app_hole h e) \<rbrakk> \<Longrightarrow> x \<in> hole_free_vars h \<or> x \<in> free_vars e"
  apply (induct h)
    apply (auto)
  done

lemma app_hole_res_vars: "\<lbrakk> x \<in> res_vars delta e \<rbrakk> \<Longrightarrow> x \<in> res_vars delta (app_hole h e)"
  apply (induct h)
    apply (auto)
  done

lemma app_hole_res_vars2: "\<lbrakk> x \<in> hole_res_vars delta h \<rbrakk> \<Longrightarrow> x \<in> res_vars delta (app_hole h e)"
  apply (induct h)
    apply (auto)
  done

lemma app_hole_res_vars_rev: "\<lbrakk> x \<in> res_vars delta (app_hole h e) \<rbrakk> \<Longrightarrow> x \<in> hole_res_vars delta h \<or> x \<in> res_vars delta e"
  apply (induct h)
    apply (auto)
  done

    (* ##### states that if x is a non-prim var in 'e', it will not be a free var in 'h' if 'h (fork e)' is well-typed.  ##### *)

fun strong_fun_ty where
  "strong_fun_ty (FunTy t1 t2 r a) = (r = OwnPerm)"
| "strong_fun_ty tau = False"

fun strong_fun_ty2 where
  "strong_fun_ty2 (FunTy t1 (FunTy t2 t3 r a) rx ax) = (r = OwnPerm)"
| "strong_fun_ty2 tau = False"

fun strong_fun where
  "strong_fun (ConstExp c) = (\<forall> tau. tau \<in> const_type c \<longrightarrow> strong_fun_ty tau)"
| "strong_fun (AppExp (ConstExp c) v) = (\<forall> tau. tau \<in> const_type c \<longrightarrow> strong_fun_ty2 tau)"
| "strong_fun e = False"

lemma strong_fun_own: "\<lbrakk>  well_typed env delta r_s1 f (FunTy t1 t2 r a) r_s2 rx; strong_fun f \<rbrakk> \<Longrightarrow> is_own r"
  apply (case_tac f)
        apply (auto)
   apply (simp add: is_own_def)
   apply (auto)
  apply (simp add: is_own_def)
  apply (case_tac x71)
        apply (auto)
  done

lemma safe_hole_npv_use_ih: "\<lbrakk> well_typed env delta r_s1 (app_hole h (AppExp f e)) tau r_s2 rx; well_formed_delta env delta;
  is_value f; strong_fun f; is_value e; x \<in> non_prim_vars env delta e \<rbrakk> \<Longrightarrow> r_s2 x = NoPerm"
  apply (induct h arbitrary: env r_s1 r_s2 tau rx)
       apply (auto)
    (* base case. x is subtracted out in the lifting of the inflected rx2 *)
       apply (cut_tac env="env" and ?r_s1.0="r_s2a" and e="e" and tau="t1" and ?r_s2.0="r_s3" and rx="rx2" in infl_sexp_wp)
         apply (auto)
        apply (rule_tac value_is_sexp)
        apply (simp)
    (* - r_s3 x has a value since otherwise it would be trivial *)
       apply (case_tac "r_s3 x = NoPerm")
        apply (rule_tac r_s="r_s3" in leq_use_none)
         apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
          apply (rule_tac self_diff_leq_use_env)
         apply (auto)
    (* - we know that rx2 has a value, because otherwise rx2 + [r_s2a - r_s3] would not have a value, altho it is the start perms of e *)
       apply (case_tac "rx2 x = NoPerm")
        apply (cut_tac r_sa="rx2" and r_sb="infl_use_env r_s2a r_s3" and x="x" in comp_use_none)
          apply (simp)
         apply (simp add: infl_use_env_def)
        apply (cut_tac env="env" and ?r_s1.0="comp_use_env rx2 (infl_use_env r_s2a r_s3)" and x="x" in well_typed_no_npv_use)
          apply (auto)
    (* - by construction of strong functions, we also know that r = OwnPerm *)
       apply (cut_tac f="f" and r="r" in strong_fun_own)
         apply (auto)
    (* - from here we can deduce EX x = Own *)
        apply (rule_tac r_s="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in leq_use_none)
         apply (auto)
        apply (rule_tac diff_use_none_ex)
        apply (rule_tac r_x="lift_use_env rx2 r" in leq_use_own)
         apply (simp add: is_own_def)
        apply (rule_tac comp_leq_use_env1)
        apply (rule_tac self_comp_leq_use_env2)
    (* lhs induct. *)
      apply (rule_tac r_s="r_s2a" in leq_use_none)
       apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
        apply (rule_tac diff_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
    (* rhs induct. *)
     apply (rule_tac r_s="r_s3" in leq_use_none)
      apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (auto)
    (* if case. *)
    apply (rule_tac r_s="r_s2a" in leq_use_none)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* pair case 1. *)
   apply (rule_tac r_s="r_s2a" in leq_use_none)
    apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* pair case 2. *)
  apply (rule_tac r_s="r_s3" in leq_use_none)
   apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (auto)
  done

lemma safe_hole_npv_use_st: "\<lbrakk> well_typed env delta r_s1 (app_hole h (AppExp f e)) tau r_s2 rx; well_formed_delta env delta; is_value f; strong_fun f;
 wf_hole h; is_value e \<rbrakk> \<Longrightarrow> x \<notin> non_prim_vars env delta e \<or> x \<notin> hole_res_vars delta h"
  apply (induct h arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* lhs induct. since r_s2a x = None, it cannot be in e2 *)
       apply (cut_tac h="h" and e="e" and ?r_s2.0="r_s2a" and x="x" in safe_hole_npv_use_ih)
            apply (auto)
       apply (cut_tac ?r_s1.0="r_s2a" and e="x2" and x="x" in well_typed_no_npv_use)
         apply (auto)
       apply (simp add: non_prim_vars_def)
    (* rhs induct. r_s2a x has a value. since x is in e2. *)
      apply (case_tac "r_s2a x = NoPerm")
       apply (cut_tac ?r_s1.0="r_s2a" and x="x" and e="app_hole h (AppExp f e)" in well_typed_no_npv_use)
         apply (auto)
       apply (cut_tac h="h" and e="AppExp f e" and x="x" and delta="delta" in app_hole_res_vars)
        apply (simp add: non_prim_vars_def)
       apply (simp add: non_prim_vars_def)
    (* - by lemma, rx1 x has a value as well. *)
      apply (cut_tac env="env" and e="x1" and tau="FunTy t1 tau r a" and ?r_s2.0="r_s2a" and rx="rx1" in wt_sexp_req_use)
          apply (auto)
        apply (rule_tac value_is_sexp)
        apply (auto)
       apply (simp add: non_prim_vars_def)
    (* - this is a contradiction, since r_s3 x = None, and rx1 is contained by it *)
      apply (cut_tac r_x="rx1" and r_s="r_s3" and x="x" in leq_use_none)
        apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac self_comp_leq_use_env1)
       apply (rule_tac safe_hole_npv_use_ih)
           apply (auto)
    (* lhs if case. since r_s2a x = None, it cannot be in e2 *)
     apply (cut_tac h="h" and e="e" and ?r_s2.0="r_s2a" and x="x" in safe_hole_npv_use_ih)
          apply (auto)
     apply (cut_tac ?r_s1.0="r_s2a" and e="x2" and x="x" in well_typed_no_npv_use)
       apply (auto)
     apply (simp add: non_prim_vars_def)
    (* rhs if case. since r_s2a x = None, it cannot be in e2 *)
    apply (cut_tac h="h" and e="e" and ?r_s2.0="r_s2a" and x="x" in safe_hole_npv_use_ih)
         apply (auto)
    apply (cut_tac ?r_s1.0="r_s2a" and e="x3" and x="x" in well_typed_no_npv_use)
      apply (auto)
    apply (simp add: non_prim_vars_def)
    (* lhs pair case. same for lhs induct *)
   apply (cut_tac h="h" and e="e" and ?r_s2.0="r_s2a" and x="x" in safe_hole_npv_use_ih)
        apply (auto)
   apply (cut_tac ?r_s1.0="r_s2a" and e="x2" and x="x" in well_typed_no_npv_use)
     apply (auto)
   apply (simp add: non_prim_vars_def)
    (* rhs pair case. same for rhs induct *)
    (* - r_s2a x has a value. since x is in e2 *)
  apply (case_tac "r_s2a x = NoPerm")
   apply (cut_tac ?r_s1.0="r_s2a" and x="x" and e="app_hole h (AppExp f e)" in well_typed_no_npv_use)
     apply (auto)
   apply (cut_tac h="h" and e="AppExp f e" and x="x" and delta="delta" in app_hole_res_vars)
    apply (auto)
    apply (simp add: non_prim_vars_def)
   apply (simp add: non_prim_vars_def)
    (* - then rx1 x has a value *)
  apply (cut_tac env="env" and ?r_s1.0="r_s1" and e="x1" and tau="t1" and ?r_s2.0="r_s2a" and rx="rx1" in wt_sexp_req_use)
      apply (auto)
    apply (rule_tac value_is_sexp)
    apply (auto)
   apply (simp add: non_prim_vars_def)
    (* - this is a contradiction, since r_s3 x = None, and rx1 is contained by it *)
  apply (cut_tac r_x="rx1" and r_s="r_s3" and x="x" in leq_use_none)
    apply (rule_tac r_sb="lift_use_env rx1 r" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac self_lift_leq_use_env)
   apply (rule_tac safe_hole_npv_use_ih)
       apply (auto)
  done

lemma safe_fork_hole_npv_use: "\<lbrakk> well_typed env delta r_s1 (app_hole h (AppExp (ConstExp ForkConst) e)) tau r_s2 rx; well_formed_delta env delta;
 wf_hole h; is_value e; x \<in> non_prim_vars env delta e \<rbrakk> \<Longrightarrow> x \<notin> hole_res_vars delta h"
  apply (cut_tac env="env" and ?r_s1.0="r_s1" and h="h" and e="e" and f="ConstExp ForkConst" and x="x" in safe_hole_npv_use_st)
       apply (auto)
  apply (simp add: is_own_def)
  done

lemma safe_send_hole_npv_use: "\<lbrakk> well_typed env delta r_s1 (app_hole h (AppExp (AppExp (ConstExp SendConst) v) e)) tau r_s2 rx;
  well_formed_delta env delta; wf_hole h; is_value v; is_value e; x \<in> non_prim_vars env delta e \<rbrakk> \<Longrightarrow> x \<notin> hole_res_vars delta h"
  apply (cut_tac env="env" and ?r_s1.0="r_s1" and h="h" and e="e" and f="AppExp (ConstExp SendConst) v" and x="x" and delta="delta" in safe_hole_npv_use_st)
       apply (auto)
  apply (simp add: pure_fun_def)
  apply (simp add: is_own_def)
  done

end


(*******************************************************************************

  Project: Development of Security Protocols by Refinement

  Module:  Auth_simple/m2_auth_chan.thy (Isabelle/HOL 2016-1)
  ID:      $Id: m2_auth_chan.thy 133854 2017-03-20 17:53:50Z csprenge $
  Author:  Christoph Sprenger, ETH Zurich <sprenger@inf.ethz.ch>

  One-Way authentication protocols
  Refinement 2: protocol using authentic channels

  Copyright (c) 2009-2016 Christoph Sprenger
  Licence: LGPL

*******************************************************************************)

section \<open>Refinement 2a: Authentic Channel Protocol\<close>

theory m2_auth_chan imports m1_auth "../Refinement/Channels"
begin

text \<open>We refine the abstract authentication protocol to a version of the
ISO/IEC 9798-3 protocol using abstract channels. In standard protocol notation,
the original protocol is specified as follows.
\[
\begin{array}{llll}
  \mathrm{M1.} & A \rightarrow B & : & A, B, N_A \\
  \mathrm{M2.} & B \rightarrow A & : & \{N_B, N_A, A\}_{K^{-1}(B)}
\end{array}
\]
We introduce insecure channels between pairs of agents for the first message and
authentic channels for the second.\<close>

declare domIff [simp, iff del]

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

text \<open>State: we extend the state with insecure and authentic channels
defined above.\<close>

record m2_state = m1_state +
  chan :: "chmsg set"

text \<open>Observations.\<close>

type_synonym
  m2_obs = m1_state

definition
  m2_obs :: "m2_state \<Rightarrow> m2_obs" where
  "m2_obs s \<equiv> \<lparr>
     runs = runs s
  \<rparr>"

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

definition
  m2_step1 :: "[rid_t, agent, agent, nonce] \<Rightarrow> (m2_state \<times> m2_state) set"
where
  "m2_step1 Ra A B Na \<equiv> {(s, s1).
     \<comment> \<open>guards\<close>
     Ra \<notin> dom (runs s) \<and>
     Na = Ra$0 \<and>

     \<comment> \<open>actions\<close>
     s1 = s\<lparr>
       runs := (runs s)(Ra \<mapsto> (Init, [A, B], [])),
       chan := insert (Insec A B (Msg [aNon Na])) (chan s)
     \<rparr>
  }"

definition
  m2_step2 :: "[rid_t, agent, agent, nonce, nonce] \<Rightarrow> (m2_state \<times> m2_state) set"
where
  "m2_step2 Rb A B Na Nb \<equiv> {(s, s1).
     \<comment> \<open>guards\<close>
     Rb \<notin> dom (runs s) \<and>
     Nb = Rb$0 \<and>

     Insec A B (Msg [aNon Na]) \<in> chan s \<and>                          \<comment> \<open>\<open>rcv M1\<close>\<close>

     \<comment> \<open>actions\<close>
     s1 = s\<lparr>
       runs := (runs s)(Rb \<mapsto> (Resp, [A, B], [aNon Na])),
       chan := insert (Auth B A (Msg [aNon Nb, aNon Na])) (chan s)  \<comment> \<open>\<open>snd M2\<close>\<close>
     \<rparr>
  }"

definition
  m2_step3 :: "[rid_t, agent, agent, nonce, nonce] \<Rightarrow> (m2_state \<times> m2_state) set"
where
  "m2_step3 Ra A B Na Nb \<equiv> {(s, s1).
     \<comment> \<open>guards\<close>
     runs s Ra = Some (Init, [A, B], []) \<and>
     Na = Ra$0 \<and>

     Auth B A (Msg [aNon Nb, aNon Na]) \<in> chan s \<and>            \<comment> \<open>\<open>recv M2\<close>\<close>

     \<comment> \<open>actions\<close>
     s1 = s\<lparr>
       runs := (runs s)(Ra \<mapsto> (Init, [A, B], [aNon Nb]))
     \<rparr>
  }"

text \<open>Intruder fake event.\<close>

definition     \<comment> \<open>refines @{term Id}\<close>
  m2_fake :: "(m2_state \<times> m2_state) set"
where
  "m2_fake \<equiv> {(s, s1).

    \<comment> \<open>actions:\<close>
    s1 = s\<lparr> chan := fake ik0 (dom (runs s)) (chan s) \<rparr>
  }"

text \<open>Transition system.\<close>

definition
  m2_init :: "m2_state set"
where
  "m2_init \<equiv> { \<lparr>
     runs = Map.empty,
     chan = {}
  \<rparr> }"

definition
  m2_trans :: "(m2_state \<times> m2_state) set" where
  "m2_trans \<equiv> (\<Union>A B Ra Rb Na Nb.
     (m2_step1 Ra A B Na)    \<union>
     (m2_step2 Rb A B Na Nb) \<union>
     (m2_step3 Ra A B Na Nb) \<union>
     m2_fake \<union>
     Id
  )"

definition
  m2 :: "(m2_state, m2_obs) spec" where
  "m2 \<equiv> \<lparr>
    init = m2_init,
    trans = m2_trans,
    obs = m2_obs
  \<rparr>"

lemmas m2_defs =
  m2_def m2_init_def m2_trans_def m2_obs_def
  m2_step1_def m2_step2_def m2_step3_def m2_fake_def

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

subsubsection \<open>Authentic channel and responder\<close>
(******************************************************************************)

text \<open>This property relates the messages in the authentic channel to the
responder run frame.\<close>

definition
  m2_inv1_auth :: "m2_state set" where
  "m2_inv1_auth \<equiv> {s. \<forall>A B Na Nb.
     Auth B A (Msg [aNon Nb, aNon Na]) \<in> chan s \<longrightarrow> B \<notin> bad \<longrightarrow> A \<notin> bad \<longrightarrow>
       (\<exists>Rb. runs s Rb = Some (Resp, [A, B], [aNon Na]) \<and> Nb = Rb$0)
  }"

lemmas m2_inv1_authI =
  m2_inv1_auth_def [THEN setc_def_to_intro, rule_format]
lemmas m2_inv1_authE [elim] =
  m2_inv1_auth_def [THEN setc_def_to_elim, rule_format]
lemmas m2_inv1_authD [dest] =
  m2_inv1_auth_def [THEN setc_def_to_dest, rule_format, rotated 1]

text \<open>Invariance proof.\<close>

lemma PO_m2_inv2_init [iff]:
  "init m2 \<subseteq> m2_inv1_auth"
by (auto simp add: PO_hoare_def m2_defs intro!: m2_inv1_authI)

lemma PO_m2_inv2_trans [iff]:
  "{m2_inv1_auth} trans m2 {> m2_inv1_auth}"
apply (auto simp add: PO_hoare_def m2_defs intro!: m2_inv1_authI)
apply (auto dest: dom_lemmas)
\<comment> \<open>1 subgoal\<close>
apply (force)                            (* SLOW *)
done

lemma PO_m2_inv2 [iff]: "reach m2 \<subseteq> m2_inv1_auth"
by (rule_tac inv_rule_incr) (auto)

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

text \<open>Simulation relation and mediator function. This is a pure superposition
refinement.\<close>

definition
  R12 :: "(m1_state \<times> m2_state) set" where
  "R12 \<equiv> {(s, t). runs s = runs t}"           \<comment> \<open>That's it!\<close>

definition
  med21 :: "m2_obs \<Rightarrow> m1_obs" where
  "med21 \<equiv> id"

text \<open>Refinement proof\<close>

lemma PO_m2_step1_refines_m1_step1:
  "{R12}
     (m1_step1 Ra A B Na), (m2_step1 Ra A B Na)
   {> R12}"
by (auto simp add: PO_rhoare_defs R12_def m1_defs m2_defs)

lemma PO_m2_step2_refines_m1_step2:
  "{R12}
     (m1_step2 Ra A B Na Nb), (m2_step2 Ra A B Na Nb)
   {> R12}"
by (auto simp add: PO_rhoare_defs R12_def m1_defs m2_defs)

lemma PO_m2_step3_refines_m1_step3:
  "{R12 \<inter> UNIV \<times> m2_inv1_auth}
     (m1_step3 Ra A B Na Nb), (m2_step3 Ra A B Na Nb)
   {> R12}"
by (auto simp add: PO_rhoare_defs R12_def m1_defs m2_defs)

text \<open>New fake event refines skip.\<close>

lemma PO_m2_fake_refines_m1_skip:
  "{R12} Id, m2_fake {> R12}"
by (auto simp add: PO_rhoare_defs R12_def m1_defs m2_defs)

lemmas PO_m2_trans_refines_m1_trans =
  PO_m2_step1_refines_m1_step1 PO_m2_step2_refines_m1_step2
  PO_m2_step3_refines_m1_step3 PO_m2_fake_refines_m1_skip

text \<open>All together now...\<close>

lemma PO_m2_refines_init_m1 [iff]:
  "init m2 \<subseteq> R12``(init m1)"
by (auto simp add: R12_def m1_defs m2_defs)

lemma PO_m2_refines_trans_m1 [iff]:
  "{R12 \<inter> UNIV \<times> m2_inv1_auth}
     (trans m1), (trans m2)
   {> R12}"
apply (auto simp add: m2_def m2_trans_def m1_def m1_trans_def)
apply (blast intro!: PO_m2_trans_refines_m1_trans)+
done

lemma PO_obs_consistent [iff]:
  "obs_consistent R12 med21 m1 m2"
by (auto simp add: obs_consistent_def R12_def med21_def m1_defs m2_defs)

lemma m2_refines_m1:
  "refines
     (R12 \<inter> UNIV \<times> m2_inv1_auth)
     med21 m1 m2"
by (rule Refinement_using_invariants) (auto)

end


theory Proof_3_7_no_setVarAny
  imports HandDryer_no_setVarAny VCTheoryLemmas_no_setVarAny Extra_no_setVarAny
begin

(*abbreviation s where "s s0 hands_value\<equiv> (toEnv (setVarBool s0 hands hands_value))"*)

(*
theorem proof_3_7: "VC7 inv3 s0 hands_value"
  apply(simp only: VC7_def inv3_def R3_def extraInv_def)
  apply(rule impI)
  apply(rule conjI)
   apply(rule conjI)
    apply simp
   apply(drule conjE)
    prefer 2
    apply assumption
   apply(drule conjE)
    prefer 2
  apply assumption
  subgoal premises vc_prems
    using vc_prems(2) apply -
    apply(drule conjE)
     prefer 2
     apply assumption
    subgoal premises invs0
    apply((rule allI)+)
      apply(rule impI)
      subgoal premises req_prems for s1 s2
        apply(rule disjE[of "10 < toEnvNum s2 (s s0 hands_value)" "10 = toEnvNum s2 (s s0 hands_value)"])
        using req_prems le_imp_less_or_eq apply fast
        apply(rule cut_rl[of "\<exists>s4. toEnvP s4 \<and>
         substate s2 s4 \<and>
         substate s4 s0 \<and>
         toEnvNum s2 s4 \<le> 10 \<and>
         (getVarBool s4 dryer = 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 dryer = ON \<and> getVarBool s3 hands = OFF)"])
          apply(drule exE)
           prefer 2
           apply assumption
        subgoal for s4
          apply(rule exI[of _ s4])
          by simp
        using invs0(1) req_prems apply -[1]
         apply(drule conjE)
          prefer 2
          apply assumption
         apply(drule allE[of _ s1])
          prefer 2
          apply assumption
         apply(drule allE[of _ s2])
          prefer 2
          apply assumption
         apply(simp split: if_splits)
        apply(rule cut_rl[of "\<forall> s5. toEnvP s5 \<and> substate s2 s5 \<and> substate s5 (s s0 hands_value) \<longrightarrow>
pred3 s2 (s s0 hands_value) s5"])
         apply(drule allE[of _ s2])
          prefer 2
          apply assumption
         apply(drule impE)
           prefer 3
           apply assumption
        using req_prems substate_refl apply fast
         apply(simp only: pred3_def)
         apply(drule impE)
           prefer 3
           apply assumption
        using req_prems substate_refl substate_trans substate_asym apply blast
         apply (simp add: dryer_def)
        apply(rule allI)
        subgoal premises toEnvNums2s for s5
          apply(induction rule: state_down_ind)
          using req_prems apply simp
           apply(simp only: pred3_def)
           apply(rule impI)

          apply(rule cut_rl[of "\<exists> s3. toEnvP s3 \<and> substate s2 s3 \<and> substate s3 s0 \<and>
(getVarBool s3 (Suc hands) = OFF \<or> getVarBool s3 hands = ON)"])
            apply(drule exE)
             prefer 2
             apply assumption
          subgoal for s3
            apply(drule allE[of _ s3])
             prefer 2
             apply assumption
            by (metis state.distinct(11) substate.simps(2) substate.simps(3) substate_asym)
          apply(rule cut_rl[of " 0 < ltimeEnv s0 Ctrl \<and>
     ltimeEnv s0 Ctrl \<le> 10 \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> toEnvNum s1 s0 + 1 = 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 + 1 < 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)"])
            apply((drule conjE)+)
                prefer 5
                apply assumption
                prefer 4
                apply assumption
               prefer 3
               apply assumption
             prefer 2
             apply assumption
          subgoal premises prems
            using prems(4) apply -
            apply(drule allE[of _ "shiftEnv s0 (ltimeEnv s0 Ctrl)"])
             prefer 2
          apply assumption
             apply(rule exI[of _ "shiftEnv s0 (ltimeEnv s0 Ctrl)"])

*)

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 (setVarBool s0 hands 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 = 1 \<and>
           10 \<le> toEnvNum s2 s0 \<and> getVarBool s1 hands = ON \<and> getVarBool s1 (Suc hands) = 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 hands) = 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 hands) = ON \<and> getVarBool s3 hands = OFF)))) \<and>
      extraInv s0) \<and>
     env (setVarBool s0 hands hands_value) hands_value) \<and>
    getPstate (setVarBool s0 hands hands_value) Ctrl = drying \<and>
    getVarBool (setVarBool s0 hands hands_value) hands \<noteq> ON \<and> \<not> 10 \<le> ltimeEnv (setVarBool s0 hands hands_value) Ctrl "
  show " \<forall>s1 s2.
       substate s1 s2 \<and>
       substate s2 s \<and>
       toEnvP s1 \<and>
       toEnvP s2 \<and>
       toEnvNum s1 s2 = 1 \<and>
       10 \<le> toEnvNum s2 s \<and>
       getVarBool s1 hands = ON \<and> getVarBool s1 (Suc hands) = ON \<and> getVarBool s2 hands = OFF \<longrightarrow>
       (\<exists>s4. toEnvP s4 \<and>
             substate s2 s4 \<and>
             substate s4 s \<and>
             toEnvNum s2 s4 \<le> 10 \<and>
             (getVarBool s4 (Suc hands) = 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 hands) = ON \<and> getVarBool s3 hands = OFF))"
  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 = 1 \<and>
       10 \<le> toEnvNum s2 s \<and> getVarBool s1 hands = ON \<and> getVarBool s1 (Suc hands) = 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 = 1 \<and>
           10 \<le> toEnvNum s2 s0 \<and> getVarBool s1 hands = ON \<and> getVarBool s1 (Suc hands) = 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 hands) = 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 hands) = 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 + 1 = 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 + 1 < 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 (setVarBool s0 hands hands_value) hands_value) \<and>
    getPstate (setVarBool s0 hands hands_value) Ctrl = drying \<and>
    getVarBool (setVarBool s0 hands hands_value) hands \<noteq> ON \<and> \<not> 10 \<le> ltimeEnv (setVarBool s0 hands 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 = 1 \<and>
           10 \<le> toEnvNum s2 s0 \<and> getVarBool s1 hands = ON \<and> getVarBool s1 (Suc hands) = 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 hands) = 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 hands) = ON \<and> getVarBool s3 hands = OFF)))) \<and>
      extraInv s0) \<and>
     env (setVarBool s0 hands hands_value) hands_value) \<and>
    getPstate (setVarBool s0 hands hands_value) Ctrl = drying \<and>
    getVarBool (setVarBool s0 hands hands_value) hands \<noteq> ON \<and> \<not> 10 \<le> ltimeEnv (setVarBool s0 hands hands_value) Ctrl "
  with extra7 show " extraInv (toEnv (setVarBool s0 hands hands_value))"
    by (auto simp add: VC7_def)
qed

end


(*
 * Copyright 2014, NICTA
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(NICTA_BSD)
 *)

theory word_abs_options imports "../../AutoCorres" begin

install_C_file "word_abs_options.c"

autocorres [
  ts_rules = nondet,
  unsigned_word_abs = usum2, no_signed_word_abs = isum1
  ] "word_abs_options.c"

context word_abs_options begin

lemma "\<lbrace> \<top> \<rbrace> isum1' (a :: sword32) (b :: sword32) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding isum1'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> isum2' (a :: int) (b :: int) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding isum2'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> usum1' (a :: word32) (b :: word32) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding usum1'_def
  apply (wp refl)
  done

lemma "\<lbrace> \<top> \<rbrace> usum2' (a :: nat) (b :: nat) \<lbrace> \<lambda>r _. r = a + b \<rbrace>"
  unfolding usum2'_def
  apply (wp refl)
  done

end

end


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

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

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

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

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

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

theory Generalise imports "HOL-Statespace.DistinctTreeProver"
begin

lemma protectRefl: "PROP Pure.prop (PROP C) \<Longrightarrow> PROP Pure.prop (PROP C)"
  by (simp add: prop_def)

lemma protectImp:
 assumes i: "PROP Pure.prop (PROP P \<Longrightarrow> PROP Q)"
 shows "PROP Pure.prop (PROP Pure.prop P \<Longrightarrow> PROP Pure.prop Q)"
proof -
  {
    assume P: "PROP Pure.prop P"
    from i [unfolded prop_def, OF P [unfolded prop_def]]
    have "PROP Pure.prop Q"
      by (simp add: prop_def)
  }
  note i' = this
  show "PROP ?thesis"
    apply (rule protectI)
    apply (rule i')
    apply assumption
    done
qed

lemma generaliseConj:
  assumes i1: "PROP Pure.prop (PROP Pure.prop (Trueprop P) \<Longrightarrow> PROP Pure.prop (Trueprop Q))"
  assumes i2: "PROP Pure.prop (PROP Pure.prop (Trueprop P') \<Longrightarrow> PROP Pure.prop (Trueprop Q'))"
  shows "PROP Pure.prop (PROP Pure.prop (Trueprop (P \<and> P')) \<Longrightarrow> (PROP Pure.prop (Trueprop (Q \<and> Q'))))"
  using i1 i2
  by (auto simp add: prop_def)

lemma generaliseAll:
 assumes i: "PROP Pure.prop (\<And>s. PROP Pure.prop (Trueprop (P s)) \<Longrightarrow> PROP Pure.prop (Trueprop (Q s)))"
 shows "PROP Pure.prop (PROP Pure.prop (Trueprop (\<forall>s. P s)) \<Longrightarrow> PROP Pure.prop (Trueprop (\<forall>s. Q s)))"
  using i
  by (auto simp add: prop_def)

lemma generalise_all:
 assumes i: "PROP Pure.prop (\<And>s. PROP Pure.prop (PROP P s) \<Longrightarrow> PROP Pure.prop (PROP Q s))"
 shows "PROP Pure.prop ((PROP Pure.prop (\<And>s. PROP P s)) \<Longrightarrow> (PROP Pure.prop (\<And>s. PROP Q s)))"
  using i
  proof (unfold prop_def)
    assume i1: "\<And>s. (PROP P s) \<Longrightarrow> (PROP Q s)"
    assume i2: "\<And>s. PROP P s"
    show "\<And>s. PROP Q s"
      by (rule i1) (rule i2)
  qed

lemma generaliseTrans:
  assumes i1: "PROP Pure.prop (PROP P \<Longrightarrow> PROP Q)"
  assumes i2: "PROP Pure.prop (PROP Q \<Longrightarrow> PROP R)"
  shows "PROP Pure.prop (PROP P \<Longrightarrow> PROP R)"
  using i1 i2
  proof (unfold prop_def)
    assume P_Q: "PROP P \<Longrightarrow> PROP Q"
    assume Q_R: "PROP Q \<Longrightarrow> PROP R"
    assume P: "PROP P"
    show "PROP R"
      by (rule Q_R [OF P_Q [OF P]])
  qed

lemma meta_spec:
  assumes "\<And>x. PROP P x"
  shows "PROP P x" by fact

lemma meta_spec_protect:
  assumes g: "\<And>x. PROP P x"
  shows "PROP Pure.prop (PROP P x)"
using g
by (auto simp add: prop_def)

lemma generaliseImp:
  assumes i: "PROP Pure.prop (PROP Pure.prop (Trueprop P) \<Longrightarrow> PROP Pure.prop (Trueprop Q))"
  shows "PROP Pure.prop (PROP Pure.prop (Trueprop (X \<longrightarrow> P)) \<Longrightarrow> PROP Pure.prop (Trueprop (X \<longrightarrow> Q)))"
  using i
  by (auto simp add: prop_def)

lemma generaliseEx:
 assumes i: "PROP Pure.prop (\<And>s. PROP Pure.prop (Trueprop (P s)) \<Longrightarrow> PROP Pure.prop (Trueprop (Q s)))"
 shows "PROP Pure.prop (PROP Pure.prop (Trueprop (\<exists>s. P s)) \<Longrightarrow> PROP Pure.prop (Trueprop (\<exists>s. Q s)))"
  using i
  by (auto simp add: prop_def)

lemma generaliseRefl: "PROP Pure.prop (PROP Pure.prop (Trueprop P) \<Longrightarrow> PROP Pure.prop (Trueprop P))"
  by (auto simp add: prop_def)

lemma generaliseRefl': "PROP Pure.prop (PROP P \<Longrightarrow> PROP P)"
  by (auto simp add: prop_def)

lemma generaliseAllShift:
  assumes i: "PROP Pure.prop (\<And>s. P \<Longrightarrow> Q s)"
  shows "PROP Pure.prop (PROP Pure.prop (Trueprop P) \<Longrightarrow> PROP Pure.prop (Trueprop (\<forall>s. Q s)))"
  using i
  by (auto simp add: prop_def)

lemma generalise_allShift:
  assumes i: "PROP Pure.prop (\<And>s. PROP P \<Longrightarrow> PROP Q s)"
  shows "PROP Pure.prop (PROP Pure.prop (PROP P) \<Longrightarrow> PROP Pure.prop (\<And>s. PROP Q s))"
  using i
  proof (unfold prop_def)
    assume P_Q: "\<And>s. PROP P \<Longrightarrow> PROP Q s"
    assume P: "PROP P"
    show "\<And>s. PROP Q s"
      by (rule P_Q [OF P])
  qed

lemma generaliseImpl:
  assumes i: "PROP Pure.prop (PROP Pure.prop P \<Longrightarrow> PROP Pure.prop Q)"
  shows "PROP Pure.prop ((PROP Pure.prop (PROP X \<Longrightarrow> PROP P)) \<Longrightarrow> (PROP Pure.prop (PROP X \<Longrightarrow> PROP Q)))"
  using i
  proof (unfold prop_def)
    assume i1: "PROP P \<Longrightarrow> PROP Q"
    assume i2: "PROP X \<Longrightarrow> PROP P"
    assume X: "PROP X"
    show "PROP Q"
      by (rule i1 [OF i2 [OF X]])
  qed

ML_file \<open>generalise_state.ML\<close>

end


section "An even simpler version without mutual induction"

theory Big_Step_Unclocked_Single
  imports Big_Step_Unclocked Big_Step_Clocked Evaluate_Single Big_Step_Fun_Equiv
begin

inductive evaluate_list ::
  "('ffi state \<Rightarrow> exp \<Rightarrow> 'ffi state*(v,v) result \<Rightarrow> bool) \<Rightarrow>
    'ffi state \<Rightarrow> exp list \<Rightarrow> 'ffi state*(v list, v)result \<Rightarrow> bool" for P where
empty:
  "evaluate_list P s [] (s,Rval [])" |

cons1:
  "P s1 e (s2, Rval v) \<Longrightarrow>
   evaluate_list P s2 es (s3, Rval vs) \<Longrightarrow>
   evaluate_list P s1 (e#es) (s3, Rval (v#vs))" |

cons2:
  "P s1 e (s2, Rerr err) \<Longrightarrow>
   evaluate_list P s1 (e#es) (s2, Rerr err)" |

cons3:
  "P s1 e (s2, Rval v) \<Longrightarrow>
   evaluate_list P s2 es (s3, Rerr err) \<Longrightarrow>
   evaluate_list P s1 (e#es) (s3, Rerr err)"

lemma evaluate_list_mono_strong[intro?]:
  assumes "evaluate_list R s es r"
  assumes "\<And>s e r. e \<in> set es \<Longrightarrow> R s e r \<Longrightarrow> Q s e r"
  shows "evaluate_list Q s es r"
using assms by (induction; fastforce intro: evaluate_list.intros)

lemma evaluate_list_mono[mono]:
  assumes "R \<le> Q"
  shows "evaluate_list R \<le> evaluate_list Q"
using assms unfolding le_fun_def le_bool_def
by (metis evaluate_list_mono_strong)

inductive evaluate :: "v sem_env \<Rightarrow> 'ffi state \<Rightarrow> exp \<Rightarrow> 'ffi state*(v,v) result \<Rightarrow> bool" where

lit:
  "evaluate env s (Lit l) (s, Rval (Litv l))" |

raise1:
  "evaluate env s1 e (s2, Rval v) \<Longrightarrow>
   evaluate env s1 (Raise e) (s2, Rerr (Rraise v))" |

raise2:
  "evaluate env s1 e (s2, Rerr err) \<Longrightarrow>
   evaluate env s1 (Raise e) (s2, Rerr err)" |

handle1:
  "evaluate env s1 e (s2, Rval v) \<Longrightarrow>
   evaluate env s1 (Handle e pes) (s2, Rval v)" |

handle2:
  "evaluate env s1 e (s2, Rerr (Rraise v)) \<Longrightarrow>
   match_result env s2 v pes v = Rval (e', env') \<Longrightarrow>
   evaluate (env \<lparr> sem_env.v := nsAppend (alist_to_ns env') (sem_env.v env) \<rparr>) s2 e' bv \<Longrightarrow>
   evaluate env s1 (Handle e pes) bv" |

handle2b:
  "evaluate env s1 e (s2, Rerr (Rraise v)) \<Longrightarrow>
   match_result env s2 v pes v = Rerr err \<Longrightarrow>
   evaluate env s1 (Handle e pes) (s2, Rerr err)" |

handle3:
  "evaluate env s1 e (s2, Rerr (Rabort a)) \<Longrightarrow>
   evaluate env s1 (Handle e pes) (s2, Rerr (Rabort a))" |

con1:
  "do_con_check (c env) cn (length es) \<Longrightarrow>
   build_conv (c env) cn (rev vs) = Some v \<Longrightarrow>
   evaluate_list (evaluate env) s1 (rev es) (s2, Rval vs) \<Longrightarrow>
   evaluate env s1 (Con cn es) (s2, Rval v)" |

con2:
  "\<not>(do_con_check (c env) cn (length es)) \<Longrightarrow>
   evaluate env s (Con cn es) (s, Rerr (Rabort Rtype_error))" |

con3:
  "do_con_check (c env) cn (length es) \<Longrightarrow>
   evaluate_list (evaluate env) s1 (rev es) (s2, Rerr err) \<Longrightarrow>
   evaluate env s1 (Con cn es) (s2, Rerr err)" |

var1:
  "nsLookup (sem_env.v env) n = Some v \<Longrightarrow>
   evaluate env s (Var n) (s, Rval v)" |

var2:
  "nsLookup (sem_env.v env) n = None \<Longrightarrow>
   evaluate env s (Var n) (s, Rerr (Rabort Rtype_error))" |

fn:
  "evaluate env s (Fun n e) (s, Rval (Closure env n e))" |

app1:
  "evaluate_list (evaluate env) s1 (rev es) (s2, Rval vs) \<Longrightarrow>
   do_opapp (rev vs) = Some (env', e) \<Longrightarrow>
   evaluate env' s2 e bv \<Longrightarrow>
   evaluate env s1 (App Opapp es) bv" |

app3:
  "evaluate_list (evaluate env) s1 (rev es) (s2, Rval vs) \<Longrightarrow>
   (do_opapp (rev vs) = None) \<Longrightarrow>
   evaluate env s1 (App Opapp es) (s2, Rerr (Rabort Rtype_error))" |

app4:
  "evaluate_list (evaluate env) s1 (rev es) (s2, Rval vs) \<Longrightarrow>
   do_app (refs s2, ffi s2) op0 (rev vs) = Some ((refs',ffi'), res) \<Longrightarrow>
   op0 \<noteq> Opapp \<Longrightarrow>
   evaluate env s1 (App op0 es) (s2 \<lparr>refs:=refs',ffi:=ffi'\<rparr>, res)" |

app5:
  "evaluate_list (evaluate env) s1 (rev es) (s2, Rval vs) \<Longrightarrow>
   do_app (refs s2, ffi s2) op0 (rev vs) = None \<Longrightarrow>
   op0 \<noteq> Opapp \<Longrightarrow>
   evaluate env s1 (App op0 es) (s2, Rerr (Rabort Rtype_error))" |

app6:
  "evaluate_list (evaluate env) s1 (rev es) (s2, Rerr err) \<Longrightarrow>
   evaluate env s1 (App op0 es) (s2, Rerr err)" |

log1:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   do_log op0 v1 e2 = Some (Exp e') \<Longrightarrow>
   evaluate env s2 e' bv \<Longrightarrow>
   evaluate env s1 (Log op0 e1 e2) bv " |

log2:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   (do_log op0 v1 e2 = Some (Val bv)) \<Longrightarrow>
   evaluate env s1 (Log op0 e1 e2) (s2, Rval bv)" |

log3:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   (do_log op0 v1 e2 = None) \<Longrightarrow>
   evaluate env s1 (Log op0 e1 e2) (s2, Rerr (Rabort Rtype_error))" |

log4:
  "evaluate env s e1 (s', Rerr err) \<Longrightarrow>
   evaluate env s (Log op0 e1 e2) (s', Rerr err)" |

if1:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   do_if v1 e2 e3 = Some e' \<Longrightarrow>
   evaluate env s2 e' bv \<Longrightarrow>
   evaluate env s1 (If e1 e2 e3) bv " |

if2:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   (do_if v1 e2 e3 = None) \<Longrightarrow>
   evaluate env s1 (If e1 e2 e3) (s2, Rerr (Rabort Rtype_error))" |

if3:
  "evaluate env s e1 (s', Rerr err) \<Longrightarrow>
   evaluate env s (If e1 e2 e3) (s', Rerr err)" |

mat1:
  "evaluate env s1 e (s2, Rval v1) \<Longrightarrow>
   match_result env s2 v1 pes Bindv = Rval (e', env') \<Longrightarrow>
   evaluate (env \<lparr> sem_env.v := nsAppend (alist_to_ns env') (sem_env.v env) \<rparr>) s2 e' bv \<Longrightarrow>
   evaluate env s1 (Mat e pes) bv " |

mat1b:
  "evaluate env s1 e (s2, Rval v1) \<Longrightarrow>
   match_result env s2 v1 pes Bindv = Rerr err \<Longrightarrow>
   evaluate env s1 (Mat e pes) (s2, Rerr err)" |

mat2:
  "evaluate env s e (s', Rerr err) \<Longrightarrow>
   evaluate env s (Mat e pes) (s', Rerr err)" |

let1:
  "evaluate env s1 e1 (s2, Rval v1) \<Longrightarrow>
   evaluate ( env \<lparr> sem_env.v := (nsOptBind n v1(sem_env.v env)) \<rparr>) s2 e2 bv \<Longrightarrow>
   evaluate env s1 (Let n e1 e2) bv " |

let2:
  "evaluate env s e1 (s', Rerr err) \<Longrightarrow>
   evaluate env s (Let n e1 e2) (s', Rerr err)" |

letrec1:
  "distinct (List.map ( \<lambda>x .
     (case  x of (x,y,z) => x )) funs) \<Longrightarrow>
   evaluate ( env \<lparr> sem_env.v := (build_rec_env funs env(sem_env.v env)) \<rparr>) s e bv \<Longrightarrow>
   evaluate env s (Letrec funs e) bv " |

letrec2:
  "\<not> (distinct (List.map ( \<lambda>x .
     (case  x of (x,y,z) => x )) funs)) \<Longrightarrow>
   evaluate env s (Letrec funs e) (s, Rerr (Rabort Rtype_error))" |

tannot:
  "evaluate env s e bv \<Longrightarrow>
   evaluate env s (Tannot e t0) bv " |

locannot:
  "evaluate env s e bv \<Longrightarrow>
   evaluate env s (Lannot e l) bv "

lemma unclocked_single_list_sound:
  "evaluate_list (Big_Step_Unclocked.evaluate v) s es bv \<Longrightarrow> Big_Step_Unclocked.evaluate_list v s es bv"
by (induction rule: evaluate_list.induct) (auto intro: evaluate_list_evaluate.intros)

lemma unclocked_single_sound:
  "evaluate v s e bv \<Longrightarrow> Big_Step_Unclocked.evaluate v s e bv"
by (induction rule:evaluate.induct)
   (auto simp del: do_app.simps intro: Big_Step_Unclocked.evaluate_list_evaluate.intros unclocked_single_list_sound
         evaluate_list_mono_strong)

lemma unclocked_single_complete:
  "Big_Step_Unclocked.evaluate_list v s es bv1 \<Longrightarrow> evaluate_list (evaluate v) s es bv1"
  "Big_Step_Unclocked.evaluate v s e bv2 \<Longrightarrow> evaluate v s e bv2"
by (induction rule: evaluate_list_evaluate.inducts)
   (auto intro: evaluate.intros evaluate_list.intros)

corollary unclocked_single_eq:
  "evaluate = Big_Step_Unclocked.evaluate"
by (rule ext)+ (metis unclocked_single_sound unclocked_single_complete)

corollary unclocked_single_eq':
  "evaluate = BigStep.evaluate False"
by (simp add: unclocked_single_eq unclocked_eq)

corollary unclocked_single_determ:
  "evaluate env s e r3a \<Longrightarrow> evaluate env s e r3b \<Longrightarrow> r3a = r3b"
by (metis unclocked_single_eq unclocked_determ)

lemma unclocked_single_fun_eq:
  "((\<exists>k. Evaluate_Single.evaluate env (s \<lparr> clock:= k \<rparr>) e = (s', r)) \<and> r \<noteq>  Rerr (Rabort Rtimeout_error) \<and> (clock s) = (clock s')) =
    evaluate env s e (s',r)"
  apply (subst fun_evaluate_equiv')
  apply (subst unclocked_single_eq)
  apply (subst unclocked_eq)
  apply (subst fun.evaluate_iff_sym(1)[symmetric])
  apply (subst big_clocked_unclocked_equiv)
  using clocked_evaluate by metis

end


theory DenotationalUpd
  imports "Denotational-Common" "Value-Meet" "HSemUpd"
begin

subsubsection {* The denotational semantics *}

nominal_function
  ESem :: "exp \<Rightarrow> Env \<Rightarrow> Value" ("\<lbrakk>_\<rbrakk>\<^bsub>_\<^esub>"  [60,60] 60)
where
  "atom x \<sharp> \<rho> \<Longrightarrow> \<lbrakk> Lam [x]. e \<rbrakk>\<^bsub>\<rho>\<^esub> = Fn \<cdot> (\<Lambda> v. (\<lbrakk> e \<rbrakk>\<^bsub>\<rho>(x f\<mapsto> v)\<^esub>))"
| "\<lbrakk> App e x \<rbrakk>\<^bsub>\<rho>\<^esub> = \<lbrakk> e \<rbrakk>\<^bsub>\<rho>\<^esub> \<down>Fn \<lbrakk> Var x \<rbrakk>\<^bsub>\<rho>\<^esub> "
| "\<lbrakk> Var x \<rbrakk>\<^bsub>\<rho>\<^esub> = \<rho> f! x"
| "set (bn as) \<sharp>* \<rho> \<Longrightarrow> \<lbrakk> Let as body \<rbrakk>\<^bsub>\<rho>\<^esub> = \<lbrakk>body\<rbrakk>\<^bsub>has_ESem.HSem ESem (asToHeap as) \<rho>\<^esub>"
proof-
txt {* The following proofs discharge technical obligations generated by the Nominal package. *}

case goal1 thus ?case
  unfolding eqvt_def ESem_graph_aux_def by simp
next
case (goal3 P x)
  show ?case
  proof(cases x)
  case (Pair e \<rho>)
    show ?thesis
      using Pair goal3
      by (metis (full_types) "Nominal-Utils.fresh_star_singleton" exp_assn.strong_exhaust(1) supp_atom)
  qed
next

case (goal4 x \<rho> e x' \<rho>' e')
  have all_fresh: "(x' \<leftrightarrow> x) \<bullet> \<rho>' = \<rho>'"  and [simp]:"\<rho> = \<rho>'"
    using goal4
    by (auto simp add: flip_fresh_fresh)

  from goal4(7)
  have "(x' \<leftrightarrow> x) \<bullet> e = e'"
    apply (simp only: Pair_eq exp_assn.eq_iff(4) Abs1_eq_iff)
    by auto

  { fix xa
    have "ESem_sumC (e, (\<rho>(x f\<mapsto> xa))) = (x' \<leftrightarrow> x) \<bullet> (ESem_sumC (e, (\<rho>(x f\<mapsto> xa))))" by (simp add: permute_Value_def)
    also have "\<dots> = ESem_sumC ((x' \<leftrightarrow> x) \<bullet> ((e, (\<rho>(x f\<mapsto> xa)))))"
      using goal4(1) by (metis eqvt_at_def)
    also have "\<dots> = ESem_sumC ((x' \<leftrightarrow> x) \<bullet> e, \<rho>(x' f\<mapsto> xa))"
      by (simp add: all_fresh)
    also have "\<dots> = ESem_sumC (e', \<rho>'(x' f\<mapsto> xa))"
      by (simp only: `(x' \<leftrightarrow> x) \<bullet> e = e'` `\<rho> = \<rho>'`)
    finally
    have "ESem_sumC (e, (\<rho>(x f\<mapsto> xa))) = ESem_sumC (e', (\<rho>'(x' f\<mapsto> xa)))".
  }
  thus ?case by simp
next

case (goal13 as \<rho> body as' \<rho>' body')
  assume eqvt1: "\<And> e x. e \<in> snd ` set (asToHeap as) \<Longrightarrow> eqvt_at ESem_sumC (e, x)"
    and eqvt2:"eqvt_at ESem_sumC (body, has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as) \<rho>)"
    and eqvt3:"\<And>e x. e \<in> snd ` set (asToHeap as') \<Longrightarrow> eqvt_at ESem_sumC (e, x)"
    and eqvt4:"eqvt_at ESem_sumC (body', has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as') \<rho>')"

  assume fresh1: "set (bn as) \<sharp>* \<rho>" and fresh2: "set (bn as') \<sharp>* \<rho>'"
  assume "(Terms.Let as body, \<rho>) =  (Terms.Let as' body', \<rho>')"
  hence tmp: "[bn as]lst. (body, as) = [bn as']lst. (body', as')" and rho:"\<rho>' = \<rho>" by auto

  have "ESem_sumC (body, has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as) \<rho>) =
        ESem_sumC (body', has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as') \<rho>)"
  proof (rule Abs_lst_fcb[where ba = bn and f = "(\<lambda> as (body, as'). ESem_sumC (body, has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as) \<rho>))", OF tmp pure_fresh pure_fresh, simplified])
    fix p
    assume "p \<bullet> body = body' \<and> p \<bullet> as = as'" hence "p \<bullet> body = body'" and "p \<bullet> as = as'" by auto
    assume "supp p \<subseteq> set (bn as) \<union> set (bn as')"
    have "p \<bullet> \<rho> = \<rho>"
      apply (rule perm_supp_eq)
      using fresh1 fresh2
      apply (simp add: fresh_star_def)
      by (metis (full_types) Un_iff `supp p \<subseteq> set (bn as) \<union> set (bn as')` rho set_mp)

    have "(p \<bullet> ESem_sumC) (body', has_ESem.HSem (\<lambda>x xa. (p \<bullet> ESem_sumC) (x, xa)) (asToHeap as') (p \<bullet> \<rho>)) =
          (p \<bullet> ESem_sumC) (body', has_ESem.HSem (\<lambda>x xa. ESem_sumC (x, xa)) (asToHeap as') (p \<bullet> \<rho>))"
      apply (rule arg_cong[OF HSem_cong[OF _ refl refl]])
      apply (subst eqvt_at_apply[OF eqvt3], assumption)
      by rule
    also have "\<dots> = (p \<bullet> ESem_sumC) (body', has_ESem.HSem (\<lambda>x xa. ESem_sumC (x, xa)) (asToHeap as') \<rho>')"
      by (simp add: `p \<bullet> \<rho> = \<rho>` `\<rho>' = \<rho>`)
    also have "\<dots> = ESem_sumC (body', has_ESem.HSem (\<lambda>x xa. ESem_sumC (x, xa)) (asToHeap as') \<rho>')"
      by (rule eqvt_at_apply[OF eqvt4])
    also have "\<dots> = ESem_sumC (body', has_ESem.HSem (\<lambda>x xa. ESem_sumC (x, xa)) (asToHeap as') \<rho>)"
      by (simp add: `\<rho>' = \<rho>`)
    finally
    show "(p \<bullet> ESem_sumC) (body', has_ESem.HSem (\<lambda>x xa. (p \<bullet> ESem_sumC) (x, xa)) (asToHeap as') (p \<bullet> \<rho>)) =
               ESem_sumC (body', has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as') \<rho>)".
  qed
  thus "ESem_sumC (body, has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as) \<rho>) =
      ESem_sumC (body', has_ESem.HSem (\<lambda>x0 x1. ESem_sumC (x0, x1)) (asToHeap as') \<rho>')" using `\<rho>' = \<rho>`  by simp
qed auto

lemma  True and [simp]:"(a, b) \<in> set (asToHeap as) \<Longrightarrow> size b < Suc (size as + size body)"
  by(induct and as rule:exp_assn.inducts, auto simp add: exp_assn.bn_defs fresh_star_insert)

nominal_termination (eqvt) by lexicographic_order

interpretation has_ESem ESem.

subsubsection {* Equivariance of the semantics *}

lemma permute_ESem: "\<pi> \<bullet> ESem = ESem"
  by (perm_simp, rule)

lemmas HSem_eqvt' = HSem_eqvt[of _ ESem, unfolded permute_ESem]

lemmas HSem_fresh[simp] = eqvt_fresh_cong2[of HSem, OF HSem_eqvt']
 and   HSem_fresh_star[simp] = eqvt_fresh_star_cong2[of HSem, OF HSem_eqvt']
 and   asToHeap_fresh[simp] = eqvt_fresh_cong1[of asToHeap, OF asToHeap.eqvt]
 and   fresh_fmap_upd[simp] = eqvt_fresh_cong3[of fmap_upd, OF fmap_upd_eqvt]
 and   fresh_star_fmap_upd[simp] = eqvt_fresh_star_cong3[of fmap_upd, OF fmap_upd_eqvt]

end