thys2/Hoare_tm_basis.thy
changeset 25 a5f5b9336007
equal deleted inserted replaced
24:77daf1b85cf0 25:a5f5b9336007
       
     1 header {* 
       
     2   Separation logic for TM
       
     3 *}
       
     4 
       
     5 theory Hoare_tm_basis
       
     6 imports Hoare_gen My_block Data_slot MLs Term_pat (* BaseSS *) Subgoal Sort_ops
       
     7         Thm_inst
       
     8 begin
       
     9 
       
    10 section {* Aux lemmas on seperation algebra *}
       
    11 
       
    12 lemma cond_eq: "((<b> \<and>* p) s) = (b \<and> (p s))"
       
    13 proof
       
    14   assume "(<b> \<and>* p) s"
       
    15   from condD[OF this] show " b \<and> p s" .
       
    16 next
       
    17   assume "b \<and> p s"
       
    18   hence b and "p s" by auto
       
    19   from `b` have "(<b>) 0" by (auto simp:pasrt_def)
       
    20   moreover have "s = 0 + s" by auto
       
    21   moreover have "0 ## s" by auto
       
    22   moreover note `p s`
       
    23   ultimately show "(<b> \<and>* p) s" by (auto intro!:sep_conjI)
       
    24 qed
       
    25 
       
    26 lemma cond_eqI:
       
    27   assumes h: "b \<Longrightarrow> r = s"
       
    28   shows "(<b> ** r) = (<b> ** s)"
       
    29 proof(cases b)
       
    30   case True
       
    31   from h[OF this] show ?thesis by simp
       
    32 next
       
    33   case False
       
    34   thus ?thesis
       
    35     by (unfold sep_conj_def set_ins_def pasrt_def, auto)
       
    36 qed
       
    37 
       
    38 lemma EXS_intro: 
       
    39   assumes h: "(P x) s"
       
    40   shows "((EXS x. P(x))) s"
       
    41   by (smt h pred_ex_def sep_conj_impl)
       
    42 
       
    43 lemma EXS_elim: 
       
    44   assumes "(EXS x. P x) s"
       
    45   obtains x where "P x s"
       
    46   by (metis assms pred_ex_def)
       
    47 
       
    48 lemma EXS_eq:
       
    49   fixes x
       
    50   assumes h: "Q (p x)" 
       
    51   and h1: "\<And> y s. \<lbrakk>p y s\<rbrakk> \<Longrightarrow> y = x"
       
    52   shows "p x = (EXS x. p x)"
       
    53 proof
       
    54   fix s
       
    55   show "p x s = (EXS x. p x) s"
       
    56   proof
       
    57     assume "p x s"
       
    58     thus "(EXS x. p x) s" by (auto simp:pred_ex_def)
       
    59   next
       
    60     assume "(EXS x. p x) s"
       
    61     thus "p x s"
       
    62     proof(rule EXS_elim)
       
    63       fix y
       
    64       assume "p y s"
       
    65       from this[unfolded h1[OF this]] show "p x s" .
       
    66     qed
       
    67   qed
       
    68 qed
       
    69 
       
    70 section {* The TM assembly language *}
       
    71 
       
    72 subsection {* The TM assembly language *}
       
    73 
       
    74 datatype taction = W0 | W1 | L | R
       
    75 
       
    76 datatype tstate = St nat
       
    77 
       
    78 fun nat_of :: "tstate \<Rightarrow> nat"
       
    79 where "nat_of (St n) = n"
       
    80 
       
    81 declare [[coercion_enabled]]
       
    82 
       
    83 declare [[coercion "St :: nat \<Rightarrow> tstate"]]
       
    84 
       
    85 type_synonym tm_inst = "(taction \<times> tstate) \<times> (taction \<times> tstate)"
       
    86 
       
    87 datatype Block = Oc | Bk
       
    88 
       
    89 datatype tpg = 
       
    90    TInstr tm_inst
       
    91  | TLabel tstate
       
    92  | TSeq tpg tpg
       
    93  | TLocal "(tstate \<Rightarrow> tpg)"
       
    94 
       
    95 notation TLocal (binder "TL " 10)
       
    96 
       
    97 abbreviation tprog_instr :: "tm_inst \<Rightarrow> tpg" ("\<guillemotright> _" [61] 61)
       
    98 where "\<guillemotright> i \<equiv> TInstr i"
       
    99 
       
   100 abbreviation tprog_seq :: "tpg \<Rightarrow> tpg \<Rightarrow> tpg" (infixr ";" 52)
       
   101 where "c1 ; c2 \<equiv> TSeq c1 c2"
       
   102 
       
   103 subsection {* The notion of assembling *}
       
   104 
       
   105 datatype tresource = 
       
   106     TM int Block
       
   107   | TC nat tm_inst
       
   108   | TAt nat
       
   109   | TPos int
       
   110   | TFaults nat
       
   111 
       
   112 type_synonym tassert = "tresource set \<Rightarrow> bool"
       
   113 
       
   114 definition "sg e = (\<lambda> s. s = e)"
       
   115 
       
   116 primrec tassemble_to :: "tpg \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> tassert" 
       
   117   where 
       
   118   "tassemble_to (TInstr ai) i j = (sg ({TC i ai}) ** <(j = i + 1)>)" |
       
   119   "tassemble_to (TSeq p1 p2) i j = (EXS j'. (tassemble_to p1 i j') ** (tassemble_to p2 j' j))" |
       
   120   "tassemble_to (TLocal fp) i j  = (EXS l. (tassemble_to (fp l) i j))" | 
       
   121   "tassemble_to (TLabel l) i j = <(i = j \<and> j = nat_of l)>"
       
   122 
       
   123 declare tassemble_to.simps [simp del]
       
   124 
       
   125 lemmas tasmp = tassemble_to.simps (2, 3, 4)
       
   126 
       
   127 abbreviation tasmb_to :: "nat \<Rightarrow> tpg \<Rightarrow> nat \<Rightarrow> tassert" ("_ :[ _ ]: _" [60, 60, 60] 60)
       
   128   where "i :[ tpg ]: j \<equiv> tassemble_to tpg i j"
       
   129 
       
   130 section {* Automatic checking of assemblility *}
       
   131 
       
   132 subsection {* Basic theories *}
       
   133 
       
   134 text {* @{text cpg} is the type for skeleton assembly language. Every constructor
       
   135         corresponds to one in the definition of @{text tpg} *}
       
   136 
       
   137 datatype cpg = 
       
   138    CInstr tm_inst
       
   139  | CLabel nat
       
   140  | CSeq cpg cpg
       
   141  | CLocal cpg
       
   142 
       
   143 text {* Conversion from @{text cpg} to @{text tpg}*}
       
   144 
       
   145 fun c2t :: "tstate list \<Rightarrow> cpg \<Rightarrow> tpg" where 
       
   146   "c2t env (CInstr ((act0, St st0), (act1, St st1))) = 
       
   147                          TInstr ((act0, env!st0), (act1, env!st1))" |
       
   148   "c2t env (CLabel l) = TLabel (env!l)" |
       
   149   "c2t env (CSeq cpg1 cpg2) = TSeq (c2t env cpg1) (c2t env cpg2)" |
       
   150   "c2t env (CLocal cpg) = TLocal (\<lambda> x. c2t (x#env) cpg)"
       
   151 
       
   152 text {* Well formedness checking of @{text cpg} *}
       
   153 
       
   154 datatype status = Free | Bound
       
   155 
       
   156 text {* @{text wf_cpg_test} is the checking function *}
       
   157 
       
   158 fun  wf_cpg_test :: "status list \<Rightarrow> cpg \<Rightarrow> (bool \<times> status list)" where
       
   159   "wf_cpg_test sts (CInstr ((a0, l0), (a1, l1))) = ((l0 < length sts \<and> l1 < length sts), sts)" |
       
   160   "wf_cpg_test sts (CLabel l) = ((l < length sts) \<and> sts!l = Free, sts[l:=Bound])" |
       
   161   "wf_cpg_test sts (CSeq c1 c2) = (let (b1, sts1) = wf_cpg_test sts c1;
       
   162                                   (b2, sts2) = wf_cpg_test sts1 c2 in
       
   163                                      (b1 \<and> b2, sts2))" |
       
   164   "wf_cpg_test sts (CLocal body) = (let (b, sts') = (wf_cpg_test (Free#sts) body) in 
       
   165                                    (b, tl sts'))"
       
   166 
       
   167 text {*
       
   168   The meaning the following @{text "c2p"} has to be understood together with 
       
   169   the following lemma @{text "wf_cpg_test_correct"}. The intended use of @{text "c2p"}
       
   170   is when the elements of @{text "sts"} are all @{text "Free"}, in which case, 
       
   171   the precondition on @{text "f"}, i.e. 
       
   172        @{text "\<forall> x. ((length x = length sts \<and> 
       
   173                                     (\<forall> k < length sts. sts!k = Bound \<longrightarrow> (x!k = f i k))"}
       
   174   is trivially true. 
       
   175 *}
       
   176 definition 
       
   177    "c2p sts i cpg j = 
       
   178            (\<exists> f. \<forall> x. ((length x = length sts \<and> 
       
   179                         (\<forall> k < length sts. sts!k = Bound \<longrightarrow> (x!k = f i k)))
       
   180                    \<longrightarrow> (\<exists> s. (i:[(c2t x cpg)]:j) s)))"
       
   181 
       
   182 instantiation status :: order
       
   183 begin
       
   184   definition less_eq_status_def: "((st1::status) \<le> st2) = (st1 = Free \<or> st2 = Bound)"
       
   185   definition less_status_def: "((st1::status) < st2) = (st1 \<le> st2 \<and> st1 \<noteq> st2)"
       
   186 instance
       
   187 proof
       
   188   fix x y 
       
   189   show "(x < (y::status)) = (x \<le> y \<and> \<not> y \<le> x)"
       
   190     by (metis less_eq_status_def less_status_def status.distinct(1))
       
   191 next
       
   192   fix x show "x \<le> (x::status)"
       
   193     by (metis (full_types) less_eq_status_def status.exhaust)
       
   194 next
       
   195   fix x y z
       
   196   assume "x \<le> y" "y \<le> (z::status)" show "x \<le> (z::status)"
       
   197     by (metis `x \<le> y` `y \<le> z` less_eq_status_def status.distinct(1))
       
   198 next
       
   199   fix x y
       
   200   assume "x \<le> y" "y \<le> (x::status)" show "x = y"
       
   201     by (metis `x \<le> y` `y \<le> x` less_eq_status_def status.distinct(1))
       
   202 qed
       
   203 end
       
   204 
       
   205 instantiation list :: (order)order
       
   206 begin
       
   207   definition "((sts::('a::order) list)  \<le> sts') = 
       
   208                    ((length sts = length sts') \<and> (\<forall> i < length sts. sts!i \<le> sts'!i))"
       
   209   definition "((sts::('a::order) list)  < sts') = ((sts \<le> sts') \<and> sts \<noteq> sts')"
       
   210 
       
   211   lemma anti_sym: assumes h: "x \<le> (y::'a list)" "y \<le> x"
       
   212       shows "x = y"
       
   213   proof -
       
   214     from h have "length x = length y"
       
   215       by (metis less_eq_list_def)
       
   216     moreover from h have " (\<forall> i < length x. x!i = y!i)"
       
   217       by (metis (full_types) antisym_conv less_eq_list_def)
       
   218     ultimately show ?thesis
       
   219       by (metis nth_equalityI)
       
   220   qed
       
   221 
       
   222   lemma refl: "x \<le> (x::('a::order) list)"
       
   223     apply (unfold less_eq_list_def)
       
   224     by (metis order_refl)
       
   225 
       
   226   instance
       
   227   proof
       
   228     fix x y
       
   229     show "((x::('a::order) list) < y) = (x \<le> y \<and> \<not> y \<le> x)"
       
   230     proof
       
   231       assume h: "x \<le> y \<and> \<not> y \<le> x"
       
   232       have "x \<noteq> y"
       
   233       proof
       
   234         assume "x = y" with h have "\<not> (x \<le> x)" by simp
       
   235         with refl show False by auto
       
   236       qed
       
   237       moreover from h have "x \<le> y" by blast
       
   238       ultimately show "x < y" by (auto simp:less_list_def)
       
   239     next
       
   240       assume h: "x < y"
       
   241       hence hh: "x \<le> y"
       
   242         by (metis less_list_def)
       
   243       moreover have "\<not> y \<le> x"
       
   244       proof
       
   245         assume "y \<le> x"
       
   246         from anti_sym[OF hh this] have "x = y" .
       
   247         with h show False
       
   248           by (metis less_list_def) 
       
   249       qed
       
   250       ultimately show "x \<le> y \<and> \<not> y \<le> x" by auto
       
   251     qed
       
   252   next
       
   253     fix x from refl show "(x::'a list) \<le> x" .
       
   254   next
       
   255     fix x y assume "(x::'a list) \<le> y" "y \<le> x" 
       
   256     from anti_sym[OF this] show "x = y" .
       
   257   next
       
   258     fix x y z
       
   259     assume h: "(x::'a list) \<le> y" "y \<le> z"
       
   260     show "x \<le> z"
       
   261     proof -
       
   262       from h have "length x = length z" by (metis less_eq_list_def)
       
   263       moreover from h have "\<forall> i < length x. x!i \<le> z!i"
       
   264         by (metis less_eq_list_def order_trans)
       
   265       ultimately show "x \<le> z"
       
   266         by (metis less_eq_list_def)
       
   267     qed
       
   268   qed
       
   269 end
       
   270 
       
   271 lemma sts_bound_le: "sts \<le> sts[l := Bound]"
       
   272 proof -
       
   273   have "length sts = length (sts[l := Bound])"
       
   274     by (metis length_list_update)
       
   275   moreover have "\<forall> i < length sts. sts!i \<le> (sts[l:=Bound])!i"
       
   276   proof -
       
   277     { fix i
       
   278       assume "i < length sts"
       
   279       have "sts ! i \<le> sts[l := Bound] ! i"
       
   280       proof(cases "l < length sts")
       
   281         case True
       
   282         note le_l = this
       
   283         show ?thesis
       
   284         proof(cases "l = i")
       
   285           case True with le_l
       
   286           have "sts[l := Bound] ! i = Bound" by auto
       
   287           thus ?thesis by (metis less_eq_status_def) 
       
   288         next
       
   289           case False
       
   290           with le_l have "sts[l := Bound] ! i = sts!i" by auto
       
   291           thus ?thesis by auto
       
   292         qed
       
   293       next
       
   294         case False
       
   295         hence "sts[l := Bound] = sts" by auto
       
   296         thus ?thesis by auto
       
   297       qed
       
   298     } thus ?thesis by auto
       
   299   qed
       
   300   ultimately show ?thesis by (metis less_eq_list_def) 
       
   301 qed
       
   302 
       
   303 lemma sts_tl_le:
       
   304   assumes "sts \<le> sts'"
       
   305   shows "tl sts \<le> tl sts'"
       
   306 proof -
       
   307   from assms have "length (tl sts) = length (tl sts')"
       
   308     by (metis (hide_lams, no_types) length_tl less_eq_list_def)
       
   309   moreover from assms have "\<forall> i < length (tl sts). (tl sts)!i \<le> (tl sts')!i"
       
   310     by (smt calculation length_tl less_eq_list_def nth_tl)
       
   311   ultimately show ?thesis
       
   312     by (metis less_eq_list_def)
       
   313 qed
       
   314 
       
   315 lemma wf_cpg_test_le:
       
   316   assumes "wf_cpg_test sts cpg = (True, sts')"
       
   317   shows "sts \<le> sts'" using assms
       
   318 proof(induct cpg arbitrary:sts sts')
       
   319   case (CInstr instr sts sts')
       
   320   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
   321     by (metis surj_pair tstate.exhaust)
       
   322   from CInstr[unfolded this]
       
   323   show ?case by simp
       
   324 next
       
   325   case (CLabel l sts sts')
       
   326   thus ?case by (auto simp:sts_bound_le)
       
   327 next
       
   328   case (CLocal body sts sts')
       
   329   from this(2)
       
   330   obtain sts1 where h: "wf_cpg_test (Free # sts) body = (True, sts1)" "sts' = tl sts1"
       
   331     by (auto split:prod.splits)
       
   332   from CLocal(1)[OF this(1)] have "Free # sts \<le> sts1" .
       
   333   from sts_tl_le[OF this]
       
   334   have "sts \<le> tl sts1" by simp
       
   335   from this[folded h(2)]
       
   336   show ?case .
       
   337 next
       
   338   case (CSeq cpg1 cpg2 sts sts')
       
   339   from this(3)
       
   340   show ?case
       
   341     by (auto split:prod.splits dest!:CSeq(1, 2))
       
   342 qed
       
   343 
       
   344 lemma c2p_assert:
       
   345   assumes "(c2p [] i cpg j)"
       
   346   shows "\<exists> s. (i :[(c2t [] cpg)]: j) s"
       
   347 proof -
       
   348   from assms obtain f where
       
   349     h [rule_format]: 
       
   350     "\<forall> x. length x = length [] \<and> (\<forall>k<length []. [] ! k = Bound \<longrightarrow> (x ! k = f i k)) \<longrightarrow>
       
   351                         (\<exists> s. (i :[ c2t [] cpg ]: j) s)"
       
   352     by (unfold c2p_def, auto)
       
   353   have "length [] = length [] \<and> (\<forall>k<length []. [] ! k = Bound \<longrightarrow> ([] ! k = f i k))"
       
   354     by auto
       
   355   from h[OF this] obtain s where "(i :[ c2t [] cpg ]: j) s" by blast
       
   356   thus ?thesis by auto
       
   357 qed
       
   358 
       
   359 definition "sts_disj sts sts' = ((length sts = length sts') \<and> 
       
   360                                  (\<forall> i < length sts. \<not>(sts!i = Bound \<and> sts'!i = Bound)))"
       
   361 
       
   362 instantiation list :: (plus)plus
       
   363 begin
       
   364    fun plus_list :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
       
   365      "plus_list [] ys = []" |
       
   366      "plus_list (x#xs) [] = []" |
       
   367      "plus_list (x#xs) (y#ys) = ((x + y)#plus_list xs ys)"
       
   368    instance ..
       
   369 end
       
   370 
       
   371 instantiation list :: (minus)minus
       
   372 begin
       
   373    fun minus_list :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
       
   374      "minus_list [] ys = []" |
       
   375      "minus_list (x#xs) [] = []" |
       
   376      "minus_list (x#xs) (y#ys) = ((x - y)#minus_list xs ys)"
       
   377    instance ..
       
   378 end
       
   379 
       
   380 instantiation status :: minus
       
   381 begin
       
   382    fun minus_status :: "status \<Rightarrow> status \<Rightarrow> status" where
       
   383      "minus_status Bound Bound = Free" |
       
   384      "minus_status Bound Free = Bound" |
       
   385      "minus_status Free x = Free "
       
   386    instance ..
       
   387 end
       
   388 
       
   389 instantiation status :: plus
       
   390 begin
       
   391    fun plus_status :: "status \<Rightarrow> status \<Rightarrow> status" where
       
   392      "plus_status Free x = x" |
       
   393      "plus_status Bound x = Bound"
       
   394    instance ..
       
   395 end
       
   396 
       
   397 lemma length_sts_plus:
       
   398   assumes "length (sts1 :: status list) = length sts2"
       
   399   shows "length (sts1 + sts2) = length sts1"
       
   400   using assms
       
   401 proof(induct sts1 arbitrary: sts2)
       
   402   case Nil
       
   403   thus ?case
       
   404     by (metis plus_list.simps(1))
       
   405 next
       
   406   case (Cons s' sts' sts2)
       
   407   thus ?case
       
   408   proof(cases "sts2 = []")
       
   409     case True
       
   410     with Cons show ?thesis by auto
       
   411   next
       
   412     case False
       
   413     then obtain s'' sts'' where eq_sts2: "sts2 = s''#sts''"
       
   414       by (metis neq_Nil_conv)
       
   415     with Cons
       
   416     show ?thesis
       
   417       by (metis length_Suc_conv list.inject plus_list.simps(3))
       
   418   qed
       
   419 qed
       
   420 
       
   421 lemma nth_sts_plus:
       
   422   assumes "i < length ((sts1::status list) + sts2)"
       
   423   shows "(sts1 + sts2)!i = sts1!i + sts2!i"
       
   424   using assms
       
   425 proof(induct sts1 arbitrary:i sts2)
       
   426   case (Nil i sts2)
       
   427   thus ?case by auto
       
   428 next
       
   429   case (Cons s' sts' i sts2)
       
   430   show ?case
       
   431   proof(cases "sts2 = []")
       
   432     case True
       
   433     with Cons show ?thesis by auto
       
   434   next
       
   435     case False
       
   436     then obtain s'' sts'' where eq_sts2: "sts2 = s''#sts''"
       
   437       by (metis neq_Nil_conv)
       
   438     with Cons
       
   439     show ?thesis
       
   440       by (smt list.size(4) nth_Cons' plus_list.simps(3))
       
   441   qed
       
   442 qed
       
   443 
       
   444 lemma nth_sts_minus:
       
   445   assumes "i < length ((sts1::status list) - sts2)"
       
   446   shows "(sts1 - sts2)!i = sts1!i - sts2!i"
       
   447   using assms
       
   448 proof(induct  arbitrary:i rule:minus_list.induct)
       
   449   case (3 x xs y ys i)
       
   450   show ?case
       
   451   proof(cases i)
       
   452     case 0
       
   453     thus ?thesis by simp
       
   454   next
       
   455     case (Suc k)
       
   456     with 3(2) have "k < length (xs - ys)" by auto
       
   457     from 3(1)[OF this] and Suc
       
   458     show ?thesis
       
   459       by auto
       
   460   qed
       
   461 qed auto
       
   462 
       
   463 fun taddr :: "tresource \<Rightarrow> nat" where
       
   464    "taddr (TC i instr) = i"
       
   465 
       
   466 lemma tassemble_to_range:
       
   467   assumes "(i :[tpg]: j) s"
       
   468   shows "(i \<le> j) \<and> (\<forall> r \<in> s. i \<le> taddr r \<and> taddr r < j)"
       
   469   using assms
       
   470 proof(induct tpg arbitrary: i j s)
       
   471   case (TInstr instr i j s)
       
   472   obtain a0 l0 a1 l1 where "instr = ((a0, l0), (a1, l1))"
       
   473     by (metis pair_collapse)
       
   474   with TInstr
       
   475   show ?case
       
   476     apply (simp add:tassemble_to.simps sg_def)
       
   477     by (smt `instr = ((a0, l0), a1, l1)` cond_eq cond_true_eq1 
       
   478         empty_iff insert_iff le_refl lessI sep.mult_commute taddr.simps)
       
   479 next
       
   480   case (TLabel l i j s)
       
   481   thus ?case
       
   482     apply (simp add:tassemble_to.simps)
       
   483     by (smt equals0D pasrt_def set_zero_def)
       
   484 next
       
   485   case (TSeq c1 c2 i j s)
       
   486   from TSeq(3) obtain s1 s2 j' where 
       
   487     h: "(i :[ c1 ]: j') s1" "(j' :[ c2 ]: j) s2" "s1 ## s2" "s = s1 + s2"
       
   488     by (auto simp:tassemble_to.simps elim!:EXS_elim sep_conjE)
       
   489   show ?case
       
   490   proof -
       
   491     { fix r 
       
   492       assume "r \<in> s"
       
   493       with h (3, 4) have "r \<in> s1 \<or> r \<in> s2"
       
   494         by (auto simp:set_ins_def)
       
   495       hence "i \<le> j \<and> i \<le> taddr r \<and> taddr r < j" 
       
   496       proof
       
   497         assume " r \<in> s1"
       
   498         from TSeq(1)[OF h(1)]
       
   499         have "i \<le> j'" "(\<forall>r\<in>s1. i \<le> taddr r \<and> taddr r < j')" by auto
       
   500         from this(2)[rule_format, OF `r \<in> s1`]
       
   501         have "i \<le> taddr r" "taddr r < j'" by auto
       
   502         with TSeq(2)[OF h(2)]
       
   503         show ?thesis by auto
       
   504       next
       
   505         assume "r \<in> s2"
       
   506         from TSeq(2)[OF h(2)]
       
   507         have "j' \<le> j" "(\<forall>r\<in>s2. j' \<le> taddr r \<and> taddr r < j)" by auto
       
   508         from this(2)[rule_format, OF `r \<in> s2`]
       
   509         have "j' \<le> taddr r" "taddr r < j" by auto
       
   510         with TSeq(1)[OF h(1)]
       
   511         show ?thesis by auto
       
   512       qed
       
   513     } thus ?thesis
       
   514       by (smt TSeq.hyps(1) TSeq.hyps(2) h(1) h(2))
       
   515   qed
       
   516 next
       
   517   case (TLocal body i j s)
       
   518   from this(2) obtain l s' where "(i :[ body l ]: j) s"
       
   519     by (simp add:tassemble_to.simps, auto elim!:EXS_elim)
       
   520   from TLocal(1)[OF this]
       
   521   show ?case by auto
       
   522 qed
       
   523 
       
   524 lemma c2p_seq:
       
   525   assumes "c2p sts1 i cpg1 j'"
       
   526           "c2p sts2 j' cpg2 j"
       
   527           "sts_disj sts1 sts2"
       
   528   shows "(c2p (sts1 + sts2) i (CSeq cpg1 cpg2) j)" 
       
   529 proof -
       
   530   from assms(1)[unfolded c2p_def]
       
   531   obtain f1 where
       
   532     h1[rule_format]: 
       
   533         "\<forall>x. length x = length sts1 \<and> (\<forall>k<length sts1. sts1 ! k = Bound \<longrightarrow> (x ! k = f1 i k)) \<longrightarrow>
       
   534               Ex (i :[ c2t x cpg1 ]: j')" by blast
       
   535   from assms(2)[unfolded c2p_def]
       
   536   obtain f2 where h2[rule_format]: 
       
   537         "\<forall>x. length x = length sts2 \<and> (\<forall>k<length sts2. sts2 ! k = Bound \<longrightarrow> (x ! k = f2 j' k)) \<longrightarrow>
       
   538               Ex (j' :[ c2t x cpg2 ]: j)" by blast
       
   539   from assms(3)[unfolded sts_disj_def]
       
   540   have h3: "length sts1 = length sts2" 
       
   541     and h4[rule_format]: 
       
   542         "(\<forall>i<length sts1. \<not> (sts1 ! i = Bound \<and> sts2 ! i = Bound))" by auto
       
   543   let ?f = "\<lambda> i k. if (sts1!k = Bound) then f1 i k else f2 j' k"
       
   544   { fix x 
       
   545     assume h5: "length x = length (sts1 + sts2)" and
       
   546            h6[rule_format]: "(\<forall>k<length (sts1 + sts2). (sts1 + sts2) ! k = Bound \<longrightarrow> x ! k = ?f i k)"
       
   547     obtain s1 where h_s1: "(i :[ c2t x cpg1 ]: j') s1"
       
   548     proof(atomize_elim, rule h1)
       
   549       from h3 h5 have "length x = length sts1"
       
   550         by (metis length_sts_plus)
       
   551       moreover {
       
   552         fix k assume hh: "k<length sts1" "sts1 ! k = Bound"
       
   553         from hh(1) h3 h5 have p1: "k < length (sts1 + sts2)"
       
   554           by (metis calculation)
       
   555         from h3 hh(2) have p2: "(sts1 + sts2)!k = Bound"
       
   556           by (metis nth_sts_plus p1 plus_status.simps(2))
       
   557         from h6[OF p1 p2] have "x ! k = (if sts1 ! k = Bound then f1 i k else f2 j' k)" .
       
   558         with hh(2)
       
   559         have "x ! k = f1 i k" by simp
       
   560       } ultimately show "length x = length sts1 \<and> 
       
   561           (\<forall>k<length sts1. sts1 ! k = Bound \<longrightarrow> (x ! k = f1 i k))"
       
   562         by blast
       
   563     qed
       
   564     obtain s2 where h_s2: "(j' :[ c2t x cpg2 ]: j) s2"
       
   565     proof(atomize_elim, rule h2)
       
   566       from h3 h5 have "length x = length sts2"
       
   567         by (metis length_sts_plus) 
       
   568       moreover {
       
   569         fix k
       
   570         assume hh: "k<length sts2" "sts2 ! k = Bound"
       
   571         from hh(1) h3 h5 have p1: "k < length (sts1 + sts2)"
       
   572           by (metis calculation)
       
   573         from  hh(1) h3 h5 hh(2) have p2: "(sts1 + sts2)!k = Bound"
       
   574           by (metis `length sts1 = length sts2 \<and> 
       
   575                (\<forall>i<length sts1. \<not> (sts1 ! i = Bound \<and> sts2 ! i = Bound))` 
       
   576              calculation nth_sts_plus plus_status.simps(1) status.distinct(1) status.exhaust)
       
   577         from h6[OF p1 p2] have "x ! k = (if sts1 ! k = Bound then f1 i k else f2 j' k)" .
       
   578         moreover from h4[OF hh(1)[folded h3]] hh(2) have "sts1!k \<noteq> Bound" by auto
       
   579         ultimately have "x!k = f2 j' k" by simp
       
   580       } ultimately show "length x = length sts2 \<and> 
       
   581                                (\<forall>k<length sts2. sts2 ! k = Bound \<longrightarrow> (x ! k = f2 j' k))"
       
   582         by blast
       
   583     qed
       
   584     have h_s12: "s1 ## s2"
       
   585     proof -
       
   586       { fix r assume h: "r \<in> s1" "r \<in> s2"
       
   587         with h_s1 h_s2
       
   588         have "False"by (smt tassemble_to_range) 
       
   589       } thus ?thesis by (auto simp:set_ins_def)
       
   590     qed  
       
   591     have "(EXS j'. i :[ c2t x cpg1 ]: j' \<and>* j' :[ c2t x cpg2 ]: j) (s1 + s2)"
       
   592     proof(rule_tac x = j' in EXS_intro)
       
   593       from h_s1 h_s2 h_s12
       
   594       show "(i :[ c2t x cpg1 ]: j' \<and>* j' :[ c2t x cpg2 ]: j) (s1 + s2)"
       
   595         by (metis sep_conjI)
       
   596     qed
       
   597     hence "\<exists> s. (i :[ c2t x (CSeq cpg1 cpg2) ]: j) s" 
       
   598       by (auto simp:tassemble_to.simps)
       
   599   }
       
   600   hence "\<exists>f. \<forall>x. length x = length (sts1 + sts2) \<and>
       
   601                (\<forall>k<length (sts1 + sts2). (sts1 + sts2) ! k = Bound \<longrightarrow> x ! k = f i k) \<longrightarrow>
       
   602                Ex (i :[ c2t x (CSeq cpg1 cpg2) ]: j)"
       
   603     by (rule_tac x = ?f in exI, auto)
       
   604   thus ?thesis 
       
   605     by(unfold c2p_def, auto)
       
   606 qed
       
   607 
       
   608 lemma plus_list_len:
       
   609   "length ((sts1::status list) + sts2) = min (length sts1) (length sts2)"
       
   610   by(induct rule:plus_list.induct, auto)
       
   611 
       
   612 lemma minus_list_len:
       
   613   "length ((sts1::status list) - sts2) = min (length sts1) (length sts2)"
       
   614   by(induct rule:minus_list.induct, auto)
       
   615 
       
   616 lemma sts_le_comb:
       
   617   assumes "sts1 \<le> sts2"
       
   618   and "sts2 \<le> sts3"
       
   619   shows "sts_disj (sts2 - sts1) (sts3 - sts2)" and
       
   620         "(sts3 - sts1) = (sts2 - sts1) + (sts3 - sts2)"
       
   621 proof -
       
   622   from assms 
       
   623   have h1: "length sts1 = length sts2" "\<forall>i<length sts1. sts1 ! i \<le> sts2 ! i"
       
   624     and h2: "length sts2 = length sts3" "\<forall>i<length sts1. sts2 ! i \<le> sts3 ! i"
       
   625     by (unfold less_eq_list_def, auto)
       
   626   have "sts_disj (sts2 - sts1) (sts3 - sts2)"
       
   627   proof -
       
   628     from h1(1) h2(1)
       
   629     have "length (sts2 - sts1) = length (sts3 - sts2)"
       
   630       by (metis minus_list_len)
       
   631     moreover {
       
   632       fix i
       
   633       assume lt_i: "i<length (sts2 - sts1)"
       
   634       from lt_i h1(1) h2(1) have "i < length sts1"
       
   635         by (smt minus_list_len)
       
   636       from h1(2)[rule_format, of i, OF this] h2(2)[rule_format, of i, OF this]
       
   637       have "sts1 ! i \<le> sts2 ! i" "sts2 ! i \<le> sts3 ! i" .
       
   638       moreover have "(sts2 - sts1) ! i = sts2!i - sts1!i"
       
   639         by (metis lt_i nth_sts_minus)
       
   640       moreover have "(sts3 - sts2)!i = sts3!i - sts2!i"
       
   641         by (metis `length (sts2 - sts1) = length (sts3 - sts2)` lt_i nth_sts_minus)
       
   642       ultimately have " \<not> ((sts2 - sts1) ! i = Bound \<and> (sts3 - sts2) ! i = Bound)"
       
   643         apply (cases "sts2!i", cases "sts1!i", cases "sts3!i", simp, simp)
       
   644         apply (cases "sts3!i", simp, simp)
       
   645         apply (cases "sts1!i", cases "sts3!i", simp, simp)
       
   646         by (cases "sts3!i", simp, simp)
       
   647     } ultimately show ?thesis by (unfold sts_disj_def, auto)
       
   648   qed
       
   649   moreover have "(sts3 - sts1) = (sts2 - sts1) + (sts3 - sts2)"
       
   650   proof(induct rule:nth_equalityI)
       
   651     case 1
       
   652     show ?case by (metis h1(1) h2(1) length_sts_plus minus_list_len)
       
   653   next 
       
   654     case 2
       
   655     { fix i
       
   656       assume lt_i: "i<length (sts3 - sts1)"
       
   657       have "(sts3 - sts1) ! i = (sts2 - sts1 + (sts3 - sts2)) ! i" (is "?L = ?R")
       
   658       proof -
       
   659         have "?R = sts2!i - sts1!i + (sts3!i - sts2!i)"
       
   660           by (smt `i < length (sts3 - sts1)` h2(1) minus_list_len nth_sts_minus 
       
   661                    nth_sts_plus plus_list_len)
       
   662         moreover have "?L = sts3!i - sts1!i"
       
   663           by (metis `i < length (sts3 - sts1)` nth_sts_minus)
       
   664         moreover 
       
   665         have "sts2!i - sts1!i + (sts3!i - sts2!i) = sts3!i - sts1!i"
       
   666         proof -
       
   667           from lt_i h1(1) h2(1) have "i < length sts1"
       
   668             by (smt minus_list_len)
       
   669           from h1(2)[rule_format, of i, OF this] h2(2)[rule_format, of i, OF this]
       
   670           show ?thesis
       
   671             apply (cases "sts2!i", cases "sts1!i", cases "sts3!i", simp, simp)
       
   672             apply (cases "sts3!i", simp, simp)
       
   673             apply (cases "sts1!i", cases "sts3!i", simp, simp)
       
   674             by (cases "sts3!i", simp, simp)
       
   675         qed
       
   676         ultimately show ?thesis by simp
       
   677       qed
       
   678     } thus ?case by auto
       
   679   qed
       
   680   ultimately show "sts_disj (sts2 - sts1) (sts3 - sts2)" and
       
   681                   "(sts3 - sts1) = (sts2 - sts1) + (sts3 - sts2)" by auto
       
   682 qed
       
   683 
       
   684 lemma wf_cpg_test_correct: 
       
   685   assumes "wf_cpg_test sts cpg = (True, sts')"
       
   686   shows "(\<forall> i. \<exists> j. (c2p (sts' - sts) i cpg j))" 
       
   687   using assms
       
   688 proof(induct cpg arbitrary:sts sts')
       
   689   case (CInstr instr sts sts')
       
   690   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
   691     by (metis surj_pair tstate.exhaust)
       
   692   show ?case 
       
   693   proof(unfold eq_instr c2p_def, clarsimp simp:tassemble_to.simps)
       
   694     fix i
       
   695     let ?a = "(Suc i)" and ?f = "\<lambda> i k. St i"
       
   696     show "\<exists>a f. \<forall>x. length x = length (sts' - sts) \<and>
       
   697                   (\<forall>k<length (sts' - sts). (sts' - sts) ! k = Bound \<longrightarrow> x ! k = f i k) \<longrightarrow>
       
   698                   Ex (sg {TC i ((a0, (x ! l0)), a1, (x ! l1))} \<and>* <(a = (Suc i))>)"
       
   699     proof(rule_tac x = ?a in exI, rule_tac x = ?f in exI, default, clarsimp)
       
   700       fix x
       
   701       let ?j = "Suc i"
       
   702       let ?s = " {TC i ((a0, x ! l0), a1, x ! l1)}"
       
   703       have "(sg {TC i ((a0, x ! l0), a1, x ! l1)} \<and>* <(Suc i = Suc i)>) ?s"
       
   704         by (simp add:tassemble_to.simps sg_def)
       
   705       thus "Ex (sg {TC i ((a0, (x ! l0)), a1, (x ! l1))})"
       
   706         by auto
       
   707     qed
       
   708   qed
       
   709 next
       
   710   case (CLabel l sts sts')
       
   711   show ?case
       
   712   proof
       
   713     fix i
       
   714     from CLabel 
       
   715     have h1: "l < length sts" 
       
   716       and h2: "sts ! l = Free"
       
   717       and h3: "sts[l := Bound] = sts'" by auto
       
   718     let ?f = "\<lambda> i k. St i"
       
   719     have "\<exists>a f. \<forall>x. length x = length (sts' - sts) \<and>
       
   720                   (\<forall>k<length (sts' - sts). (sts' - sts) ! k = Bound \<longrightarrow> x ! k = f (i::nat) k) \<longrightarrow>
       
   721                   Ex (<(i = a \<and> a = nat_of (x ! l))>)"
       
   722     proof(rule_tac x = i in exI, rule_tac x = ?f in exI, clarsimp)
       
   723       fix x
       
   724       assume h[rule_format]:
       
   725         "\<forall>k<length (sts' - sts). (sts' - sts) ! k = Bound \<longrightarrow> x ! k = St i"
       
   726       from h1 h3 have p1: "l < length (sts' - sts)"
       
   727         by (metis length_list_update min_max.inf.idem minus_list_len)
       
   728       from p1 h2 h3 have p2: "(sts' - sts)!l = Bound"
       
   729         by (metis h1 minus_status.simps(2) nth_list_update_eq nth_sts_minus)
       
   730       from h[OF p1 p2] have "(<(i = nat_of (x ! l))>) 0" 
       
   731         by (simp add:set_ins_def)
       
   732       thus "\<exists> s.  (<(i = nat_of (x ! l))>) s" by auto
       
   733     qed 
       
   734     thus "\<exists>a. c2p (sts' - sts) i (CLabel l) a"
       
   735       by (auto simp:c2p_def tassemble_to.simps)
       
   736   qed
       
   737 next
       
   738   case (CSeq cpg1 cpg2 sts sts')
       
   739   show ?case
       
   740   proof
       
   741     fix i
       
   742     from CSeq(3)[unfolded wf_cpg_test.simps]
       
   743     obtain b1 sts1
       
   744     where LetE: "(let (b2, y) = wf_cpg_test sts1 cpg2 in (b1 \<and> b2, y)) = (True, sts')"
       
   745           "(b1, sts1) = wf_cpg_test sts cpg1"
       
   746       by (auto simp:Let_def split:prod.splits)
       
   747     show "\<exists> j. c2p (sts' - sts) i (CSeq cpg1 cpg2) j"
       
   748     proof -
       
   749       from LetE(1)
       
   750       obtain b2 where h: "(b2, sts') = wf_cpg_test sts1 cpg2" "b1=True" "b2=True" 
       
   751         by (atomize_elim, unfold Let_def, auto split:prod.splits)
       
   752       from wf_cpg_test_le[OF LetE(2)[symmetric, unfolded h(2)]]
       
   753       have sts_le1: "sts \<le> sts1" .
       
   754       from CSeq(1)[OF LetE(2)[unfolded h(2), symmetric], rule_format, of i]
       
   755       obtain j1 where h1: "(c2p (sts1 - sts) i cpg1 j1)" by blast
       
   756       from wf_cpg_test_le[OF h(1)[symmetric, unfolded h(3)]]
       
   757       have sts_le2: "sts1 \<le> sts'" .
       
   758       from sts_le_comb[OF sts_le1 sts_le2]
       
   759       have hh: "sts_disj (sts1 - sts) (sts' - sts1)"
       
   760                "sts' - sts = (sts1 - sts) + (sts' - sts1)" .
       
   761       from CSeq(2)[OF h(1)[symmetric, unfolded h(3)], rule_format, of j1]
       
   762       obtain j2 where h2: "(c2p (sts' - sts1) j1 cpg2 j2)" by blast
       
   763       have "c2p (sts' - sts) i (CSeq cpg1 cpg2) j2"
       
   764         by(unfold hh(2), rule c2p_seq[OF h1 h2 hh(1)])
       
   765       thus ?thesis by blast 
       
   766     qed
       
   767   qed
       
   768 next
       
   769   case (CLocal body sts sts')
       
   770   from this(2) obtain b sts1 s where 
       
   771       h: "wf_cpg_test (Free # sts) body = (True, sts1)"
       
   772          "sts' = tl sts1" 
       
   773     by (unfold wf_cpg_test.simps, auto split:prod.splits)
       
   774   from wf_cpg_test_le[OF h(1), unfolded less_eq_list_def] h(2)
       
   775   obtain s where eq_sts1: "sts1 = s#sts'"
       
   776     by (metis Suc_length_conv list.size(4) tl.simps(2))
       
   777   from CLocal(1)[OF h(1)] have p1: "\<forall>i. \<exists>a. c2p (sts1 - (Free # sts)) i body a" .
       
   778   show ?case
       
   779   proof
       
   780     fix i
       
   781     from p1[rule_format, of i] obtain j where "(c2p (sts1 - (Free # sts)) i body) j" by blast
       
   782     then obtain f where hh [rule_format]: 
       
   783            "\<forall>x. length x = length (sts1 - (Free # sts)) \<and>
       
   784                 (\<forall>k<length (sts1 - (Free # sts)). (sts1 - (Free # sts)) ! k = Bound \<longrightarrow> x ! k = f i k) \<longrightarrow>
       
   785                         (\<exists>s. (i :[ c2t x body ]: j) s)"
       
   786       by (auto simp:c2p_def)
       
   787     let ?f = "\<lambda> i k. f i (Suc k)"
       
   788     have "\<exists>j f. \<forall>x. length x = length (sts' - sts) \<and>
       
   789               (\<forall>k<length (sts' - sts). (sts' - sts) ! k = Bound \<longrightarrow> x ! k = f i k) \<longrightarrow>
       
   790           (\<exists>s. (i :[ (TL xa. c2t (xa # x) body) ]: j) s)"
       
   791     proof(rule_tac x = j in exI, rule_tac x = ?f in exI, default, clarsimp)
       
   792       fix x
       
   793       assume h1: "length x = length (sts' - sts)"
       
   794         and h2: "\<forall>k<length (sts' - sts). (sts' - sts) ! k = Bound \<longrightarrow> x ! k = f i (Suc k)"
       
   795       let ?l = "f i 0" let ?x = " ?l#x"
       
   796       from wf_cpg_test_le[OF h(1)] have "length (Free#sts) = length sts1"
       
   797         by (unfold less_eq_list_def, simp)
       
   798       with h1 h(2) have q1: "length (?l # x) = length (sts1 - (Free # sts))"
       
   799         by (smt Suc_length_conv length_Suc_conv list.inject list.size(4) 
       
   800                 minus_list.simps(3) minus_list_len tl.simps(2))
       
   801       have q2: "(\<forall>k<length (sts1 - (Free # sts)). 
       
   802                   (sts1 - (Free # sts)) ! k = Bound \<longrightarrow> (f i 0 # x) ! k = f i k)" 
       
   803       proof -
       
   804         { fix k
       
   805           assume lt_k: "k<length (sts1 - (Free # sts))"
       
   806             and  bd_k: "(sts1 - (Free # sts)) ! k = Bound"
       
   807           have "(f i 0 # x) ! k = f i k"
       
   808           proof(cases "k")
       
   809             case (Suc k')
       
   810             moreover have "x ! k' = f i (Suc k')"
       
   811             proof(rule h2[rule_format])
       
   812               from bd_k Suc eq_sts1 show "(sts' - sts) ! k' = Bound" by simp
       
   813             next
       
   814               from Suc lt_k eq_sts1 show "k' < length (sts' - sts)" by simp
       
   815             qed
       
   816             ultimately show ?thesis by simp
       
   817           qed simp
       
   818         } thus ?thesis by auto
       
   819       qed
       
   820       from conjI[THEN hh[of ?x], OF q1 q2] obtain s 
       
   821         where h_s: "(i :[ c2t (f i 0 # x) body ]: j) s" by blast
       
   822       thus "(\<exists>s. (i :[ (TL xa. c2t (xa # x) body) ]: j) s)"
       
   823         apply (simp add:tassemble_to.simps)
       
   824         by (rule_tac x = s in exI, rule_tac x = "?l::tstate" in EXS_intro, simp)
       
   825     qed
       
   826     thus "\<exists>j. c2p (sts' - sts) i (CLocal body) j" 
       
   827       by (auto simp:c2p_def)
       
   828   qed
       
   829 qed
       
   830 
       
   831 lemma 
       
   832   assumes "wf_cpg_test [] cpg = (True, sts')"
       
   833   and "tpg = c2t [] cpg"
       
   834   shows "\<forall> i. \<exists> j s.  ((i:[tpg]:j) s)"
       
   835 proof
       
   836   fix i
       
   837   have eq_sts_minus: "(sts' - []) = []"
       
   838     by (metis list.exhaust minus_list.simps(1) minus_list.simps(2))
       
   839   from wf_cpg_test_correct[OF assms(1), rule_format, of i]
       
   840   obtain j where "c2p (sts' - []) i cpg j" by auto
       
   841   from c2p_assert [OF this[unfolded eq_sts_minus]]
       
   842   obtain s where "(i :[ c2t [] cpg ]: j) s" by blast
       
   843   from this[folded assms(2)]
       
   844   show " \<exists> j s.  ((i:[tpg]:j) s)" by blast
       
   845 qed
       
   846 
       
   847 lemma replicate_nth: "(replicate n x @ sts) ! (l + n)  = sts!l"
       
   848   by (smt length_replicate nth_append)
       
   849 
       
   850 lemma replicate_update: 
       
   851   "(replicate n x @ sts)[l + n := v] = replicate n x @ sts[l := v]"
       
   852   by (smt length_replicate list_update_append)
       
   853 
       
   854 lemma nth_app: "length xs \<le> a \<Longrightarrow> (xs @ ys)!a = ys!(a - length xs)"
       
   855   by (metis not_less nth_append)
       
   856 
       
   857 lemma l_n_v_orig:
       
   858   assumes "l0 < length env"
       
   859   and "t \<le> l0"
       
   860   shows "(take t env @ es @ drop t env) ! (l0 + length es) = env ! l0"
       
   861 proof -
       
   862   from assms(1, 2) have "t < length env" by auto
       
   863   hence h: "env = take t env @ drop t env" 
       
   864            "length (take t env) = t"
       
   865     apply (metis append_take_drop_id)
       
   866     by (smt `t < length env` length_take)
       
   867   with assms(2) have eq_sts_l: "env!l0 = (drop t env)!(l0 - t)"
       
   868     by (metis nth_app)
       
   869   from h(2) have "length (take t env @ es) = t + length es"
       
   870     by (metis length_append length_replicate nat_add_commute)
       
   871   moreover from assms(2) have "t + (length es) \<le> l0 + (length es)" by auto
       
   872   ultimately have "((take t env @ es) @ drop t env)!(l0 + length es) = 
       
   873                           (drop t env)!(l0+ length es - (t + length es))"
       
   874     by (smt length_replicate length_splice nth_append)
       
   875   with eq_sts_l[symmetric, unfolded assms]
       
   876   show ?thesis by auto
       
   877 qed
       
   878 
       
   879 lemma l_n_v:
       
   880   assumes "l < length sts"
       
   881   and "sts!l = v"
       
   882   and "t \<le> l"
       
   883   shows "(take t sts @ replicate n x @ drop t sts) ! (l + n) = v"
       
   884 proof -
       
   885   from l_n_v_orig[OF assms(1) assms(3), of "replicate n x"]
       
   886   and assms(2)
       
   887   show ?thesis by auto
       
   888 qed
       
   889 
       
   890 lemma l_n_v_s:
       
   891   assumes "l < length sts"
       
   892   and "t \<le> l"
       
   893   shows "(take t sts @ sts0 @ drop t sts)[l + length sts0 := v] = 
       
   894           take t (sts[l:=v])@ sts0 @ drop t (sts[l:=v])"
       
   895 proof -
       
   896   let ?n = "length sts0"
       
   897   from assms(1, 2) have "t < length sts" by auto
       
   898   hence h: "sts = take t sts @ drop t sts" 
       
   899            "length (take t sts) = t"
       
   900     apply (metis append_take_drop_id)
       
   901     by (smt `t < length sts` length_take)
       
   902   with assms(2) have eq_sts_l: "sts[l:=v] = take t sts @ drop t sts [(l - t) := v]"
       
   903     by (smt list_update_append)
       
   904   with h(2) have eq_take_drop_t: "take t (sts[l:=v]) = take t sts"
       
   905                                  "drop t (sts[l:=v]) = (drop t sts)[l - t:=v]"
       
   906     apply (metis append_eq_conv_conj)
       
   907     by (metis append_eq_conv_conj eq_sts_l h(2))
       
   908   from h(2) have "length (take t sts @ sts0) = t + ?n"
       
   909     by (metis length_append length_replicate nat_add_commute)
       
   910   moreover from assms(2) have "t + ?n \<le> l + ?n" by auto
       
   911   ultimately have "((take t sts @ sts0) @ drop t sts)[l + ?n := v] = 
       
   912                    (take t sts @ sts0) @ (drop t sts)[(l + ?n - (t + ?n)) := v]"
       
   913     by (smt list_update_append replicate_nth)
       
   914   with eq_take_drop_t
       
   915   show ?thesis by auto
       
   916 qed
       
   917 
       
   918 lemma l_n_v_s1: 
       
   919   assumes "l < length sts"
       
   920       and "\<not> t \<le> l"
       
   921   shows "(take t sts @ sts0 @ drop t sts)[l := v] =
       
   922          take t (sts[l := v]) @ sts0 @ drop t (sts[l := v])"
       
   923 proof(cases "t < length sts")
       
   924   case False
       
   925   hence h: "take t sts = sts" "drop t sts = []"
       
   926            "take t (sts[l:=v]) = sts [l:=v]"
       
   927            "drop t (sts[l:=v]) = []"
       
   928     by auto
       
   929   with assms(1)
       
   930   show ?thesis 
       
   931     by (metis list_update_append)
       
   932 next
       
   933   case True
       
   934   with assms(2)
       
   935   have h: "(take t sts)[l:=v] = take t (sts[l:=v])"
       
   936           "(sts[l:=v]) = (take t sts)[l:=v]@drop t sts"
       
   937           "length (take t sts) = t"
       
   938     apply (smt length_list_update length_take nth_equalityI nth_list_update nth_take)
       
   939     apply (smt True append_take_drop_id assms(2) length_take list_update_append1)
       
   940     by (smt True length_take)
       
   941   from h(2,3) have "drop t (sts[l := v]) = drop t sts"
       
   942     by (metis append_eq_conv_conj length_list_update)
       
   943   with h(1)
       
   944   show ?thesis
       
   945     apply simp
       
   946     by (metis assms(2) h(3) list_update_append1 not_leE)
       
   947 qed
       
   948 
       
   949 lemma l_n_v_s2:
       
   950   assumes "l0 < length env"
       
   951   and "t \<le> l0"
       
   952   and "\<not> t \<le> l1"
       
   953   shows "(take t env @ es @ drop t env) ! l1 = env ! l1"
       
   954 proof -
       
   955   from assms(1, 2) have "t < length env" by auto
       
   956   hence  h: "env = take t env @ drop t env" 
       
   957             "length (take t env) = t"
       
   958     apply (metis append_take_drop_id)
       
   959     by (smt `t < length env` length_take)
       
   960   with assms(3) show ?thesis
       
   961     by (smt nth_append)
       
   962 qed
       
   963 
       
   964 lemma l_n_v_s3:
       
   965   assumes "l0 < length env"
       
   966   and "\<not> t \<le> l0"
       
   967   shows "(take t env @ es @ drop t env) ! l0 = env ! l0"
       
   968 proof(cases "t < length env")
       
   969   case True
       
   970    hence  h: "env = take t env @ drop t env" 
       
   971             "length (take t env) = t"
       
   972     apply (metis append_take_drop_id)
       
   973     by (smt `t < length env` length_take)
       
   974   with assms(2)  show ?thesis
       
   975     by (smt nth_append)
       
   976 next
       
   977   case False
       
   978   hence "take t env = env" by auto
       
   979   with assms(1) show ?thesis
       
   980     by (metis nth_append)
       
   981 qed
       
   982 
       
   983 subsection {* Invariant under lifts and perms *}
       
   984 
       
   985 definition "lift_b t i j = (if (j \<ge> t) then (j + i) else j)"
       
   986 
       
   987 fun lift_t :: "nat \<Rightarrow> nat \<Rightarrow> cpg \<Rightarrow> cpg"
       
   988 where "lift_t t i (CInstr ((act0, l0), (act1, l1))) = 
       
   989                            (CInstr ((act0, lift_b t i (nat_of l0)), 
       
   990                                     (act1, lift_b t i (nat_of l1))))" |
       
   991       "lift_t t i (CLabel l) = CLabel (lift_b t i l)" |
       
   992       "lift_t t i (CSeq c1 c2) = CSeq (lift_t t i c1) (lift_t t i c2)" |
       
   993       "lift_t t i (CLocal c) = CLocal (lift_t (t + 1) i c)"
       
   994 
       
   995 definition "lift0 (i::nat) cpg = lift_t 0 i cpg"
       
   996 
       
   997 definition "perm_b t i j k = (if ((k::nat) = i \<and> i < t \<and> j < t) then j else 
       
   998                               if (k = j \<and> i < t \<and> j < t) then i else k)"
       
   999 
       
  1000 fun perm :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> cpg \<Rightarrow> cpg"
       
  1001 where "perm t i j (CInstr ((act0, l0), (act1, l1))) = 
       
  1002                            (CInstr ((act0, perm_b t i j l0), (act1, perm_b t i j l1)))" |
       
  1003       "perm t i j (CLabel l) = CLabel (perm_b t i j l)" |
       
  1004       "perm t i j (CSeq c1 c2) = CSeq (perm t i j c1) (perm t i j c2)" |
       
  1005       "perm t i j (CLocal c) = CLocal (perm (t + 1) (i + 1) (j + 1) c)"
       
  1006 
       
  1007 definition "map_idx f sts = map (\<lambda> k. sts!(f (nat k))) [0 .. int (length sts) - 1]"
       
  1008 
       
  1009 definition "perm_s i j sts = map_idx (perm_b (length sts) i j) sts" 
       
  1010 
       
  1011 fun lift_es :: "(tstate list \<times> nat) list \<Rightarrow> tstate list \<Rightarrow> tstate list" where
       
  1012     "lift_es [] env = env"
       
  1013   | "lift_es ((env', t)#ops) env = lift_es ops (take t env @ env' @ drop t env)"
       
  1014 
       
  1015 fun lift_ss :: "(tstate list \<times> nat) list \<Rightarrow> status list \<Rightarrow> status list" where
       
  1016     "lift_ss [] sts = sts"
       
  1017   | "lift_ss ((env', t)#ops) sts = lift_ss ops (take t sts @ map (\<lambda> x. Free) env' @ drop t sts)"
       
  1018 
       
  1019 
       
  1020 fun lift_ts :: "(nat \<times> nat) list \<Rightarrow> cpg \<Rightarrow> cpg" where
       
  1021     "lift_ts [] cpg = cpg"
       
  1022   | "lift_ts ((lenv, t)#ops) cpg = lift_ts ops (lift_t t lenv cpg)"
       
  1023 
       
  1024 fun perm_ss :: "(nat \<times> nat) list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
       
  1025    "perm_ss [] env = env"
       
  1026  | "perm_ss ((i, j)#ops) env = perm_ss ops (perm_s i j env)"
       
  1027 
       
  1028 fun perms :: "nat => (nat \<times> nat) list \<Rightarrow> cpg \<Rightarrow> cpg" where
       
  1029    "perms n [] cpg = cpg"
       
  1030  | "perms n ((i, j)#ops) cpg = perms n ops (perm n i j cpg)"
       
  1031 
       
  1032 definition 
       
  1033  "adjust_cpg len sps lfs cpg =  lift_ts lfs (perms len sps cpg)"
       
  1034 
       
  1035 definition 
       
  1036   "red_lfs lfs = map (apfst length) lfs"
       
  1037 
       
  1038 definition 
       
  1039  "adjust_env sps lfs env = lift_es lfs (perm_ss sps env)"
       
  1040 
       
  1041 definition 
       
  1042  "adjust_sts sps lfs sts = lift_ss lfs (perm_ss sps sts)"
       
  1043 
       
  1044 fun sts_disj_test :: "status list \<Rightarrow> status list \<Rightarrow> bool" where
       
  1045      "sts_disj_test [] [] = True" 
       
  1046   | "sts_disj_test [] (s#ss) = False"
       
  1047   | "sts_disj_test (s#ss) [] = False"
       
  1048   | "sts_disj_test (s1#ss1) (s2#ss2) = (case (s1, s2) of
       
  1049                                          (Bound, Bound) \<Rightarrow> False
       
  1050                                        | _ \<Rightarrow> sts_disj_test ss1 ss2)"
       
  1051 
       
  1052 lemma inj_perm_b: "inj (perm_b t i j)"
       
  1053 proof(induct rule:injI)
       
  1054   case (1 x y)
       
  1055   thus ?case
       
  1056     by (unfold perm_b_def, auto split:if_splits)
       
  1057 qed
       
  1058 
       
  1059 lemma lift_wf_cpg_test:
       
  1060   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1061   shows "wf_cpg_test (take t sts @ sts0 @ drop t sts) (lift_t t (length sts0) cpg) = 
       
  1062                (True, take t sts' @ sts0 @ drop t sts')"
       
  1063   using assms
       
  1064 proof(induct cpg arbitrary:t sts0 sts sts')
       
  1065   case (CInstr instr t sts0 sts sts')
       
  1066   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
  1067     by (metis surj_pair tstate.exhaust) 
       
  1068   from CInstr
       
  1069   show ?case
       
  1070     by (auto simp:eq_instr lift_b_def)
       
  1071 next
       
  1072   case (CLabel l t sts0 sts sts')
       
  1073   thus ?case
       
  1074     apply (auto simp:lift_b_def
       
  1075                    replicate_nth replicate_update l_n_v_orig l_n_v_s)
       
  1076     apply (metis (mono_tags) diff_diff_cancel length_drop length_rev 
       
  1077              linear not_less nth_append nth_take rev_take take_all)
       
  1078     by (simp add:l_n_v_s1)
       
  1079 next
       
  1080   case (CSeq c1 c2 sts0 sts sts')
       
  1081   thus ?case
       
  1082     by (auto simp: lift0_def lift_b_def split:prod.splits)
       
  1083 next
       
  1084   case (CLocal body t sts0 sts sts')
       
  1085   from this(2) obtain sts1 where h: "wf_cpg_test (Free # sts) body = (True, sts1)" "tl sts1 = sts'"
       
  1086     by (auto simp:lift0_def lift_b_def split:prod.splits)
       
  1087   let ?lift_s = "\<lambda> t sts. take t sts @ sts0 @ drop t sts"
       
  1088   have eq_lift_1: "(?lift_s (Suc t) (Free # sts)) = Free#?lift_s t  sts"
       
  1089     by (simp)
       
  1090   from wf_cpg_test_le[OF h(1)] have "length (Free#sts) = length sts1"
       
  1091     by (unfold less_eq_list_def, simp)
       
  1092   hence eq_sts1: "sts1 = hd sts1 # tl sts1"
       
  1093     by (metis append_Nil append_eq_conv_conj hd.simps list.exhaust tl.simps(2))
       
  1094   from CLocal(1)[OF h(1), of "Suc t", of "sts0", unfolded eq_lift_1]
       
  1095   show ?case
       
  1096     apply (simp, subst eq_sts1, simp)
       
  1097     apply (simp add:h(2))
       
  1098     by (subst eq_sts1, simp add:h(2))
       
  1099 qed
       
  1100 
       
  1101 lemma lift_c2t:
       
  1102   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1103   and "length env = length sts"
       
  1104   shows "c2t (take t env @ es @ drop t env) (lift_t t (length es) cpg) = 
       
  1105          c2t env cpg"
       
  1106   using assms
       
  1107 proof(induct cpg arbitrary: t env es sts sts')
       
  1108   case (CInstr instr t env es sts sts')
       
  1109   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
  1110     by (metis nat_of.cases surj_pair)
       
  1111   from CInstr have h: "l0 < length env" "l1 < length env"
       
  1112     by (auto simp:eq_instr)
       
  1113   with CInstr(2)
       
  1114   show ?case
       
  1115     by (auto simp:eq_instr lift_b_def l_n_v_orig l_n_v_s2 l_n_v_s3)
       
  1116 next
       
  1117   case (CLabel l t env es sts sts')
       
  1118   thus ?case
       
  1119     by (auto simp:lift_b_def
       
  1120                 replicate_nth replicate_update l_n_v_orig l_n_v_s3)
       
  1121 next
       
  1122   case (CSeq c1 c2 t env es sts sts')
       
  1123   from CSeq(3) obtain sts1
       
  1124     where h: "wf_cpg_test sts c1 = (True, sts1)" "wf_cpg_test sts1 c2 = (True, sts')"
       
  1125     by (auto split:prod.splits)
       
  1126   from wf_cpg_test_le[OF h(1)] have "length sts = length sts1"
       
  1127     by (auto simp:less_eq_list_def)
       
  1128   from CSeq(4)[unfolded this] have eq_len_env: "length env = length sts1" .
       
  1129   from CSeq(1)[OF h(1) CSeq(4)]
       
  1130        CSeq(2)[OF h(2) eq_len_env]
       
  1131   show ?case
       
  1132     by (auto simp: lift0_def lift_b_def split:prod.splits)
       
  1133 next
       
  1134   case (CLocal body t env es sts sts')
       
  1135   { fix x
       
  1136     from CLocal(2)
       
  1137     obtain sts1 where h1: "wf_cpg_test (Free # sts) body = (True, sts1)"
       
  1138       by (auto split:prod.splits)
       
  1139     from CLocal(3) have "length (x#env) = length (Free # sts)" by simp
       
  1140     from CLocal(1)[OF h1 this, of "Suc t"]
       
  1141     have "c2t (x # take t env @ es @ drop t env) (lift_t (Suc t) (length es) body) =
       
  1142           c2t (x # env) body"
       
  1143       by simp
       
  1144   } thus ?case by simp
       
  1145 qed
       
  1146 
       
  1147 lemma upto_len: "length [i .. j] = (if j < i then 0 else (nat (j - i + 1)))"
       
  1148 proof(induct i j rule:upto.induct)
       
  1149   case (1 i j)
       
  1150   show ?case
       
  1151   proof(cases "j < i")
       
  1152     case True
       
  1153     thus ?thesis by simp
       
  1154   next
       
  1155     case False
       
  1156     hence eq_ij: "[i..j] = i # [i + 1..j]" by (simp add:upto.simps)
       
  1157     from 1 False
       
  1158     show ?thesis
       
  1159       by (auto simp:eq_ij)
       
  1160   qed
       
  1161 qed
       
  1162 
       
  1163 lemma upto_append:
       
  1164   assumes "x \<le> y + 1"
       
  1165   shows  "[x .. y + 1] = [x .. y]@[y + 1]"
       
  1166   using assms
       
  1167   by (induct x y rule:upto.induct, auto simp:upto.simps)
       
  1168 
       
  1169 lemma nth_upto:
       
  1170   assumes "l < length sts"
       
  1171   shows "[0..(int (length sts)) - 1]!l = int l"
       
  1172   using assms
       
  1173 proof(induct sts arbitrary:l)
       
  1174   case Nil
       
  1175   thus ?case by simp
       
  1176 next
       
  1177   case (Cons s sts l)
       
  1178   from Cons(2)
       
  1179   have "0 \<le> (int (length sts) - 1) + 1" by auto
       
  1180   from upto_append[OF this]
       
  1181   have eq_upto: "[0..int (length sts)] = [0..int (length sts) - 1] @ [int (length sts)]"
       
  1182     by simp
       
  1183   show ?case
       
  1184   proof(cases "l < length sts")
       
  1185     case True
       
  1186     with Cons(1)[OF True] eq_upto
       
  1187     show ?thesis
       
  1188       apply simp
       
  1189       by (smt nth_append take_eq_Nil upto_len)
       
  1190   next
       
  1191     case False
       
  1192     with Cons(2) have eq_l: "l = length sts" by simp
       
  1193     show ?thesis
       
  1194     proof(cases sts)
       
  1195       case (Cons x xs)
       
  1196       have "[0..1 + int (length xs)] = [0 .. int (length xs)]@[1 + int (length xs)]"
       
  1197         by (smt upto_append)
       
  1198       moreover have "length [0 .. int (length xs)] = Suc (length xs)"
       
  1199         by (smt upto_len)
       
  1200       moreover note Cons
       
  1201       ultimately show ?thesis
       
  1202         apply (simp add:eq_l)
       
  1203         by (smt nth_Cons' nth_append)
       
  1204     qed (simp add:upto_len upto.simps eq_l)
       
  1205   qed
       
  1206 qed
       
  1207 
       
  1208 lemma map_idx_idx: 
       
  1209   assumes "l < length sts"
       
  1210   shows "(map_idx f sts)!l = sts!(f l)"
       
  1211 proof -
       
  1212   from assms have lt_l: "l < length [0..int (length sts) - 1]"
       
  1213     by (smt upto_len)
       
  1214   show ?thesis
       
  1215     apply (unfold map_idx_def nth_map[OF lt_l])
       
  1216     by (metis assms nat_int nth_upto)
       
  1217 qed
       
  1218 
       
  1219 lemma map_idx_len: "length (map_idx f sts) = length sts"
       
  1220   apply (unfold map_idx_def)
       
  1221   by (smt length_map upto_len)
       
  1222   
       
  1223 lemma map_idx_eq:
       
  1224   assumes "\<forall> l < length sts. f l = g l"
       
  1225   shows "map_idx f sts = map_idx g sts"
       
  1226 proof(induct rule: nth_equalityI)
       
  1227   case 1
       
  1228   show "length (map_idx f sts) = length (map_idx g sts)"
       
  1229     by (metis map_idx_len)
       
  1230 next
       
  1231   case 2
       
  1232   { fix l
       
  1233     assume "l < length (map_idx f sts)"
       
  1234     hence "l < length sts"
       
  1235       by (metis map_idx_len)
       
  1236     from map_idx_idx[OF this] and assms and this
       
  1237     have "map_idx f sts ! l = map_idx g sts ! l"
       
  1238       by (smt list_eq_iff_nth_eq map_idx_idx map_idx_len)
       
  1239   } thus ?case by auto
       
  1240 qed
       
  1241 
       
  1242 lemma perm_s_commut: "perm_s i j sts = perm_s j i sts"
       
  1243   apply (unfold perm_s_def, rule map_idx_eq, unfold perm_b_def)
       
  1244   by smt
       
  1245 
       
  1246 lemma map_idx_id: "map_idx id sts = sts"
       
  1247 proof(induct rule:nth_equalityI)
       
  1248   case 1
       
  1249   from map_idx_len show "length (map_idx id sts) = length sts" .
       
  1250 next
       
  1251   case 2
       
  1252   { fix l
       
  1253     assume "l < length (map_idx id sts)"
       
  1254     from map_idx_idx[OF this[unfolded map_idx_len]]
       
  1255     have "map_idx id sts ! l = sts ! l" by simp
       
  1256   } thus ?case by auto
       
  1257 qed
       
  1258 
       
  1259 lemma perm_s_lt_i: 
       
  1260   assumes "\<not> i < length sts"
       
  1261   shows "perm_s i j sts = sts"
       
  1262 proof -
       
  1263   have "map_idx (perm_b (length sts) i j) sts = map_idx id sts" 
       
  1264   proof(rule map_idx_eq, default, clarsimp)
       
  1265     fix l
       
  1266     assume "l < length sts"
       
  1267     with assms
       
  1268     show "perm_b (length sts) i j l = l"
       
  1269       by (unfold perm_b_def, auto)
       
  1270   qed
       
  1271   with map_idx_id
       
  1272   have "map_idx (perm_b (length sts) i j) sts = sts" by simp
       
  1273   thus ?thesis by (simp add:perm_s_def)
       
  1274 qed
       
  1275 
       
  1276 lemma perm_s_lt:
       
  1277   assumes "\<not> i < length sts \<or> \<not> j < length sts"
       
  1278   shows "perm_s i j sts = sts"
       
  1279   using assms
       
  1280 proof
       
  1281   assume "\<not> i < length sts"
       
  1282   from perm_s_lt_i[OF this] show ?thesis .
       
  1283 next
       
  1284   assume "\<not> j < length sts"
       
  1285   from perm_s_lt_i[OF this, of i, unfolded perm_s_commut]
       
  1286   show ?thesis .
       
  1287 qed
       
  1288 
       
  1289 lemma perm_s_update_i:
       
  1290   assumes "i < length sts" 
       
  1291   and "j < length sts"
       
  1292   shows "sts ! i = perm_s i j sts ! j"
       
  1293 proof -
       
  1294   from map_idx_idx[OF assms(2)]
       
  1295   have "map_idx (perm_b (length sts) i j) sts ! j = sts!(perm_b (length sts) i j j)" .
       
  1296   with assms
       
  1297   show ?thesis 
       
  1298     by (auto simp:perm_s_def perm_b_def)
       
  1299 qed
       
  1300 
       
  1301 lemma nth_perm_s_neq:
       
  1302   assumes "l \<noteq> j"
       
  1303   and "l \<noteq> i"
       
  1304   and "l < length sts"
       
  1305   shows "sts ! l = perm_s i j sts ! l"
       
  1306 proof -
       
  1307   have "map_idx (perm_b (length sts) i j) sts ! l = sts!(perm_b (length sts) i j l)"
       
  1308     by (metis assms(3) map_idx_def map_idx_idx)
       
  1309   with assms
       
  1310   show ?thesis
       
  1311     by (unfold perm_s_def perm_b_def, auto)
       
  1312 qed
       
  1313 
       
  1314 lemma map_idx_update:
       
  1315   assumes "f j = i"
       
  1316   and "inj f"
       
  1317   and "i < length sts"
       
  1318   and "j < length sts"
       
  1319   shows "map_idx f (sts[i:=v]) = map_idx f sts[j := v]"
       
  1320 proof(induct rule:nth_equalityI)
       
  1321   case 1
       
  1322   show "length (map_idx f (sts[i := v])) = length (map_idx f sts[j := v])"
       
  1323     by (metis length_list_update map_idx_len)
       
  1324 next
       
  1325   case 2
       
  1326   { fix l
       
  1327     assume lt_l: "l < length (map_idx f (sts[i := v]))"
       
  1328     have eq_nth: "sts[i := v] ! f l = map_idx f sts[j := v] ! l"
       
  1329     proof(cases "f l = i")
       
  1330       case False
       
  1331       from lt_l have "l < length sts"
       
  1332         by (metis length_list_update map_idx_len)
       
  1333       from map_idx_idx[OF this, of f] have " map_idx f sts ! l = sts ! f l" .
       
  1334       moreover from False assms have "l \<noteq> j" by auto
       
  1335       moreover note False
       
  1336       ultimately show ?thesis by simp
       
  1337     next
       
  1338       case True
       
  1339       with assms have eq_l: "l = j" 
       
  1340         by (metis inj_eq)
       
  1341       moreover from lt_l eq_l 
       
  1342       have "j < length (map_idx f sts[j := v])"
       
  1343         by (metis length_list_update map_idx_len)
       
  1344       moreover note True assms
       
  1345       ultimately show ?thesis by simp
       
  1346     qed
       
  1347     from lt_l have "l < length (sts[i := v])"
       
  1348       by (metis map_idx_len)
       
  1349     from map_idx_idx[OF this] eq_nth
       
  1350     have "map_idx f (sts[i := v]) ! l = map_idx f sts[j := v] ! l" by simp
       
  1351   } thus ?case by auto
       
  1352 qed
       
  1353 
       
  1354 lemma perm_s_update:
       
  1355   assumes "i < length sts"
       
  1356   and "j < length sts"
       
  1357   shows "(perm_s i j sts)[i := v] = perm_s i j (sts[j := v])"
       
  1358 proof -
       
  1359   have "map_idx (perm_b (length (sts[j := v])) i j) (sts[j := v]) = 
       
  1360         map_idx (perm_b (length (sts[j := v])) i j) sts[i := v]"
       
  1361     proof(rule  map_idx_update[OF _ _ assms(2, 1)])
       
  1362       from inj_perm_b show "inj (perm_b (length (sts[j := v])) i j)" .
       
  1363     next
       
  1364       from assms show "perm_b (length (sts[j := v])) i j i = j"
       
  1365         by (auto simp:perm_b_def)
       
  1366     qed
       
  1367   hence "map_idx (perm_b (length sts) i j) sts[i := v] =
       
  1368         map_idx (perm_b (length (sts[j := v])) i j) (sts[j := v])"
       
  1369     by simp
       
  1370   thus ?thesis by (simp add:perm_s_def)
       
  1371 qed
       
  1372 
       
  1373 lemma perm_s_len: "length (perm_s i j sts') = length sts'"
       
  1374   apply (unfold perm_s_def map_idx_def)
       
  1375   by (smt Nil_is_map_conv length_0_conv length_greater_0_conv length_map neq_if_length_neq upto_len)
       
  1376 
       
  1377 lemma perm_s_update_neq:
       
  1378   assumes "l \<noteq> i"
       
  1379   and "l \<noteq> j"
       
  1380   shows "perm_s i j sts[l := v] = perm_s i j (sts[l := v])"
       
  1381 proof(cases "i < length sts \<and> j < length sts")
       
  1382   case False
       
  1383   with perm_s_lt have "perm_s i j sts = sts" by auto
       
  1384   moreover have "perm_s i j (sts[l:=v]) = sts[l:=v]"
       
  1385   proof -
       
  1386     have "length (sts[l:=v]) = length sts" by auto
       
  1387     from False[folded this] perm_s_lt
       
  1388     show ?thesis by metis
       
  1389   qed
       
  1390   ultimately show ?thesis by simp
       
  1391 next
       
  1392   case True
       
  1393   note lt_ij = this
       
  1394   show ?thesis
       
  1395   proof(cases "l < length sts")
       
  1396     case False
       
  1397     hence "sts[l:=v] = sts" by auto
       
  1398     moreover have "perm_s i j sts[l := v] = perm_s i j sts"
       
  1399     proof -
       
  1400       from False and perm_s_len
       
  1401       have "\<not> l < length (perm_s i j sts)" by metis
       
  1402       thus ?thesis by auto
       
  1403     qed
       
  1404     ultimately show ?thesis by simp
       
  1405   next
       
  1406     case True
       
  1407     show ?thesis
       
  1408     proof -
       
  1409       have "map_idx (perm_b (length (sts[l := v])) i j) (sts[l := v]) = 
       
  1410             map_idx (perm_b (length (sts[l := v])) i j) sts[l := v]"
       
  1411       proof(induct rule:map_idx_update [OF _ inj_perm_b True True])
       
  1412         case 1
       
  1413         from assms lt_ij
       
  1414         show ?case
       
  1415           by (unfold perm_b_def, auto)
       
  1416       qed
       
  1417       thus ?thesis
       
  1418         by (unfold perm_s_def, simp)
       
  1419     qed
       
  1420   qed
       
  1421 qed
       
  1422 
       
  1423 lemma perm_sb: "(perm_s i j sts)[perm_b (length sts) i j l := v] = perm_s i j (sts[l := v])"
       
  1424   apply(subst perm_b_def, auto simp:perm_s_len perm_s_lt perm_s_update)
       
  1425   apply (subst perm_s_commut, subst (2) perm_s_commut, rule_tac perm_s_update, auto)
       
  1426   by (rule_tac perm_s_update_neq, auto)
       
  1427 
       
  1428 lemma perm_s_id: "perm_s i i sts = sts" (is "?L = ?R")
       
  1429 proof -
       
  1430   from map_idx_id have "?R = map_idx id sts" by metis
       
  1431   also have "\<dots> = ?L"
       
  1432     by (unfold perm_s_def, rule map_idx_eq, unfold perm_b_def, auto)
       
  1433   finally show ?thesis by simp
       
  1434 qed
       
  1435 
       
  1436 lemma upto_map:
       
  1437   assumes "i \<le> j"
       
  1438   shows "[i .. j] = i # map (\<lambda> x. x + 1) [i .. (j - 1)]"
       
  1439   using assms
       
  1440 proof(induct i j rule:upto.induct)
       
  1441   case (1 i j)
       
  1442   show ?case (is "?L = ?R")
       
  1443   proof -
       
  1444     from 1(2)
       
  1445     have eq_l: "?L = i # [i+1 .. j]" by (simp add:upto.simps)
       
  1446     show ?thesis
       
  1447     proof(cases "i + 1 \<le> j")
       
  1448       case False
       
  1449       with eq_l show ?thesis by (auto simp:upto.simps)
       
  1450     next
       
  1451       case True
       
  1452       have "[i + 1..j] =  map (\<lambda>x. x + 1) [i..j - 1]"
       
  1453         by (smt "1.hyps" Cons_eq_map_conv True upto.simps)
       
  1454       with eq_l
       
  1455       show ?thesis by simp
       
  1456     qed
       
  1457   qed
       
  1458 qed
       
  1459 
       
  1460 lemma perm_s_cons: "(perm_s (Suc i) (Suc j) (s # sts)) = s#perm_s i j sts"
       
  1461 proof -
       
  1462   have le_0: "0 \<le> int (length (s # sts)) - 1" by simp
       
  1463   have "map (\<lambda>k. (s # sts) ! perm_b (length (s # sts)) (Suc i) (Suc j) (nat k))
       
  1464           [0..int (length (s # sts)) - 1] =
       
  1465                  s # map (\<lambda>k. sts ! perm_b (length sts) i j (nat k)) [0..int (length sts) - 1]"
       
  1466     by (unfold upto_map[OF le_0], auto simp:perm_b_def, smt+)
       
  1467   thus ?thesis by (unfold perm_s_def map_idx_def, simp)
       
  1468 qed
       
  1469 
       
  1470 lemma perm_wf_cpg_test:
       
  1471   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1472   shows "wf_cpg_test (perm_s i j sts) (perm (length sts) i j cpg) = 
       
  1473                (True, perm_s i j sts')"
       
  1474   using assms
       
  1475 proof(induct cpg arbitrary:t i j sts sts')
       
  1476   case (CInstr instr i j sts sts')
       
  1477   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
  1478     by (metis surj_pair tstate.exhaust)
       
  1479   from CInstr
       
  1480   show ?case
       
  1481     apply (unfold eq_instr, clarsimp)
       
  1482     by (unfold perm_s_len perm_b_def, clarsimp)
       
  1483 next
       
  1484   case (CLabel l i j sts sts')
       
  1485   have "(perm_s i j sts)[perm_b (length sts) i j l := Bound] = perm_s i j (sts[l := Bound])"
       
  1486     by (metis perm_sb)
       
  1487   with CLabel
       
  1488   show ?case
       
  1489     apply (auto simp:perm_s_len perm_sb)
       
  1490     apply (subst perm_b_def, auto simp:perm_sb)
       
  1491     apply (subst perm_b_def, auto simp:perm_s_lt perm_s_update_i)
       
  1492     apply (unfold perm_s_id, subst perm_s_commut, simp add: perm_s_update_i[symmetric])
       
  1493     apply (simp add:perm_s_update_i[symmetric])
       
  1494     by (simp add: nth_perm_s_neq[symmetric])
       
  1495 next
       
  1496   case (CSeq c1 c2 i j sts sts')
       
  1497   thus ?case
       
  1498     apply (auto  split:prod.splits)
       
  1499     apply (metis (hide_lams, no_types) less_eq_list_def prod.inject wf_cpg_test_le)
       
  1500     by (metis (hide_lams, no_types) less_eq_list_def prod.inject wf_cpg_test_le)
       
  1501 next
       
  1502   case (CLocal body i j sts sts')
       
  1503   from this(2) obtain sts1 where h: "wf_cpg_test (Free # sts) body = (True, sts1)" "tl sts1 = sts'"
       
  1504     by (auto simp:lift0_def lift_b_def split:prod.splits)
       
  1505   from wf_cpg_test_le[OF h(1)] have "length (Free#sts) = length sts1"
       
  1506     by (unfold less_eq_list_def, simp)
       
  1507   hence eq_sts1: "sts1 = hd sts1 # tl sts1"
       
  1508     by (metis append_Nil append_eq_conv_conj hd.simps list.exhaust tl.simps(2))
       
  1509   from CLocal(1)[OF h(1), of "Suc i" "Suc j"] h(2) eq_sts1
       
  1510   show ?case
       
  1511     apply (auto split:prod.splits simp:perm_s_cons)
       
  1512     by (metis perm_s_cons tl.simps(2))
       
  1513 qed
       
  1514 
       
  1515 lemma nth_perm_sb:
       
  1516   assumes "l0 < length env"
       
  1517   shows "perm_s i j env ! perm_b (length env) i j l0 = env ! l0"
       
  1518   by (metis assms nth_perm_s_neq perm_b_def perm_s_commut perm_s_lt perm_s_update_i)
       
  1519   
       
  1520 
       
  1521 lemma perm_c2t:  
       
  1522   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1523   and "length env = length sts"
       
  1524   shows "c2t  (perm_s i j env) (perm (length env) i j cpg)  = 
       
  1525          c2t env cpg"
       
  1526   using assms
       
  1527 proof(induct cpg arbitrary:i j env sts sts')
       
  1528   case (CInstr instr i j env sts sts')
       
  1529   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
  1530     by (metis surj_pair tstate.exhaust) 
       
  1531   from CInstr have h: "l0 < length env" "l1 < length env"
       
  1532     by (auto simp:eq_instr)
       
  1533   with CInstr(2)
       
  1534   show ?case
       
  1535     apply (auto simp:eq_instr)
       
  1536     by (metis nth_perm_sb)+
       
  1537 next
       
  1538   case (CLabel l t env es sts sts')
       
  1539   thus ?case
       
  1540     apply (auto)
       
  1541     by (metis nth_perm_sb)
       
  1542 next
       
  1543   case (CSeq c1 c2 i j env sts sts')
       
  1544   from CSeq(3) obtain sts1
       
  1545     where h: "wf_cpg_test sts c1 = (True, sts1)" "wf_cpg_test sts1 c2 = (True, sts')"
       
  1546     by (auto split:prod.splits)
       
  1547   from wf_cpg_test_le[OF h(1)] have "length sts = length sts1"
       
  1548     by (auto simp:less_eq_list_def)
       
  1549   from CSeq(4)[unfolded this] have eq_len_env: "length env = length sts1" .
       
  1550   from CSeq(1)[OF h(1) CSeq(4)]
       
  1551        CSeq(2)[OF h(2) eq_len_env]
       
  1552   show ?case by auto
       
  1553 next
       
  1554   case (CLocal body i j env sts sts')
       
  1555   { fix x
       
  1556     from CLocal(2, 3)
       
  1557     obtain sts1 where "wf_cpg_test (Free # sts) body = (True, sts1)"
       
  1558                       "length (x#env) = length (Free # sts)"
       
  1559       by (auto split:prod.splits)
       
  1560     from CLocal(1)[OF this]
       
  1561     have "(c2t (x # perm_s i j env) (perm (Suc (length env)) (Suc i) (Suc j) body)) =
       
  1562                  (c2t (x # env) body)"
       
  1563       by (metis Suc_length_conv perm_s_cons)
       
  1564   } thus ?case by simp
       
  1565 qed
       
  1566 
       
  1567 lemma wf_cpg_test_disj_aux1:
       
  1568   assumes "sts_disj sts1 (sts[l := Bound] - sts)"
       
  1569               "l < length sts"
       
  1570               "sts ! l = Free"
       
  1571   shows "(sts1 + sts) ! l = Free"
       
  1572 proof -
       
  1573   from assms(1)[unfolded sts_disj_def]
       
  1574   have h: "length sts1 = length (sts[l := Bound] - sts)"
       
  1575           "(\<forall>i<length sts1. \<not> (sts1 ! i = Bound \<and> (sts[l := Bound] - sts) ! i = Bound))"
       
  1576     by auto
       
  1577   from h(1) assms(2) 
       
  1578   have lt_l: "l < length sts1" 
       
  1579              "l < length (sts[l := Bound] - sts)"
       
  1580              "l < length (sts1 + sts)"
       
  1581     apply (smt length_list_update minus_list_len)
       
  1582     apply (smt assms(2) length_list_update minus_list_len)
       
  1583     by (smt assms(2) h(1) length_list_update length_sts_plus minus_list_len)
       
  1584   from h(2)[rule_format, of l, OF this(1)] 
       
  1585   have " \<not> (sts1 ! l = Bound \<and> (sts[l := Bound] - sts) ! l = Bound)" .
       
  1586   with assms(3) nth_sts_minus[OF lt_l(2)] nth_sts_plus[OF lt_l(3)] assms(2)
       
  1587   show ?thesis
       
  1588     by (cases "sts1!l", auto)
       
  1589 qed
       
  1590 
       
  1591 lemma  wf_cpg_test_disj_aux2: 
       
  1592   assumes "sts_disj sts1 (sts[l := Bound] - sts)"
       
  1593           " l < length sts"
       
  1594   shows "(sts1 + sts)[l := Bound] = sts1 + sts[l := Bound]"
       
  1595 proof -
       
  1596  from assms have lt_l: "l < length (sts1 + sts[l:=Bound])"
       
  1597                        "l < length (sts1 + sts)"
       
  1598    apply (smt length_list_update length_sts_plus minus_list_len sts_disj_def)
       
  1599    by (smt assms(1) assms(2) length_list_update length_sts_plus minus_list_len sts_disj_def)
       
  1600  show ?thesis
       
  1601  proof(induct rule:nth_equalityI)
       
  1602    case 1
       
  1603    show ?case
       
  1604      by (smt assms(1) length_list_update length_sts_plus minus_list_len sts_disj_def)
       
  1605  next
       
  1606    case 2
       
  1607    { fix i 
       
  1608      assume lt_i: "i < length ((sts1 + sts)[l := Bound])"
       
  1609      have " (sts1 + sts)[l := Bound] ! i = (sts1 + sts[l := Bound]) ! i"
       
  1610      proof(cases "i = l")
       
  1611        case True
       
  1612        with nth_sts_plus[OF lt_l(1)] assms(2) nth_sts_plus[OF lt_l(2)] lt_l
       
  1613        show ?thesis
       
  1614          by (cases "sts1 ! l", auto)
       
  1615      next
       
  1616        case False
       
  1617        from lt_i have "i < length (sts1 + sts)" "i < length (sts1 + sts[l := Bound])"
       
  1618          apply auto
       
  1619          by (metis length_list_update plus_list_len)
       
  1620        from nth_sts_plus[OF this(1)] nth_sts_plus[OF this(2)] lt_i lt_l False
       
  1621        show ?thesis
       
  1622          by simp
       
  1623      qed
       
  1624    } thus ?case by auto
       
  1625  qed
       
  1626 qed
       
  1627 
       
  1628 lemma sts_list_plus_commut:
       
  1629   shows "sts1 + sts2 = sts2 + (sts1:: status list)"
       
  1630 proof(induct rule:nth_equalityI)
       
  1631   case 1
       
  1632   show ?case
       
  1633     by (metis min_max.inf.commute plus_list_len)
       
  1634 next
       
  1635   case 2
       
  1636   { fix i
       
  1637     assume lt_i1: "i<length (sts1 + sts2)"
       
  1638     hence lt_i2: "i < length (sts2 + sts1)"
       
  1639       by (smt plus_list_len)
       
  1640     from nth_sts_plus[OF this] nth_sts_plus[OF lt_i1]
       
  1641     have "(sts1 + sts2) ! i = (sts2 + sts1) ! i"
       
  1642       apply simp
       
  1643       apply (cases "sts1!i", cases "sts2!i", auto)
       
  1644       by (cases "sts2!i", auto)
       
  1645   } thus ?case by auto
       
  1646 qed
       
  1647 
       
  1648 lemma sts_disj_cons:
       
  1649   assumes "sts_disj sts1 sts2"
       
  1650   shows "sts_disj (Free # sts1) (s # sts2)"
       
  1651   using assms
       
  1652 proof -
       
  1653   from assms 
       
  1654   have h: "length sts1 = length sts2"
       
  1655           "(\<forall>i<length sts1. \<not> (sts1 ! i = Bound \<and> sts2 ! i = Bound))"
       
  1656     by (unfold sts_disj_def, auto)
       
  1657   from h(1) have "length (Free # sts1) = length (s # sts2)" by simp
       
  1658   moreover {
       
  1659     fix i
       
  1660     assume lt_i: "i<length (Free # sts1)"
       
  1661     have "\<not> ((Free # sts1) ! i = Bound \<and> (s # sts2) ! i = Bound)"
       
  1662     proof(cases "i")
       
  1663       case 0
       
  1664       thus ?thesis by simp
       
  1665     next
       
  1666       case (Suc k)
       
  1667       from h(2)[rule_format, of k] lt_i[unfolded Suc] Suc
       
  1668       show ?thesis by auto
       
  1669     qed
       
  1670   }
       
  1671   ultimately show ?thesis by (auto simp:sts_disj_def)
       
  1672 qed
       
  1673 
       
  1674 lemma sts_disj_uncomb:
       
  1675   assumes "sts_disj sts (sts1 + sts2)"
       
  1676   and "sts_disj sts1 sts2"
       
  1677   shows "sts_disj sts sts1" "sts_disj sts sts2"
       
  1678   using assms
       
  1679   apply  (smt assms(1) assms(2) length_sts_plus nth_sts_plus plus_status.simps(2) sts_disj_def)
       
  1680   by (smt assms(1) assms(2) length_sts_plus nth_sts_plus 
       
  1681        plus_status.simps(2) sts_disj_def sts_list_plus_commut)
       
  1682 
       
  1683 lemma wf_cpg_test_disj:
       
  1684   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1685   and "sts_disj sts1 (sts' - sts)"
       
  1686   shows "wf_cpg_test (sts1 + sts) cpg = (True, sts1 + sts')"
       
  1687   using assms
       
  1688 proof(induct cpg arbitrary:sts sts1 sts')
       
  1689   case (CInstr instr sts sts1 sts')
       
  1690   obtain a0 l0 a1 l1 where eq_instr: "instr = ((a0, St l0), (a1, St l1))"
       
  1691     by (metis nat_of.cases surj_pair)
       
  1692   with CInstr(1) have h: "l0 < length sts" "l1 < length sts" "sts = sts'" by auto
       
  1693   with CInstr eq_instr
       
  1694   show ?case
       
  1695     apply (auto)
       
  1696     by (smt length_sts_plus minus_list_len sts_disj_def)+
       
  1697 next
       
  1698   case (CLabel l sts sts1 sts')
       
  1699   thus ?case
       
  1700     apply auto
       
  1701     apply (smt length_list_update length_sts_plus minus_list_len sts_disj_def)
       
  1702     by (auto simp: wf_cpg_test_disj_aux1 wf_cpg_test_disj_aux2)
       
  1703 next
       
  1704   case (CSeq c1 c2 sts sts1 sts')
       
  1705   from CSeq(3) obtain sts''
       
  1706     where h: "wf_cpg_test sts c1 = (True, sts'')" "wf_cpg_test sts'' c2 = (True, sts')"
       
  1707     by (auto split:prod.splits)
       
  1708   from wf_cpg_test_le[OF h(1)] have "length sts = length sts''"
       
  1709     by (auto simp:less_eq_list_def)
       
  1710   from sts_le_comb[OF wf_cpg_test_le[OF h(1)] wf_cpg_test_le[OF h(2)]]
       
  1711   have " sts' - sts = (sts'' - sts) + (sts' - sts'')" "sts_disj (sts'' - sts) (sts' - sts'')"
       
  1712     by auto
       
  1713   from sts_disj_uncomb[OF CSeq(4)[unfolded this(1)] this(2)]
       
  1714   have "sts_disj sts1 (sts'' - sts)" "sts_disj sts1 (sts' - sts'')" .
       
  1715   from CSeq(1)[OF h(1) this(1)] CSeq(2)[OF h(2) this(2)]
       
  1716   have "wf_cpg_test (sts1 + sts) c1 = (True, sts1 + sts'')"
       
  1717        "wf_cpg_test (sts1 + sts'') c2 = (True, sts1 + sts')" .
       
  1718   thus ?case
       
  1719     by simp
       
  1720 next
       
  1721   case (CLocal body sts sts1 sts')
       
  1722   from this(2)
       
  1723   obtain sts'' where h: "wf_cpg_test (Free # sts) body = (True, sts'')" "sts' = tl sts''"
       
  1724     by (auto split:prod.splits)
       
  1725   from wf_cpg_test_le[OF h(1), unfolded less_eq_list_def] h(2)
       
  1726   obtain s where eq_sts'': "sts'' = s#sts'"
       
  1727     by (metis Suc_length_conv list.size(4) tl.simps(2))
       
  1728   let ?sts = "Free#sts1"
       
  1729   from CLocal(3) have "sts_disj ?sts (sts'' - (Free # sts))"
       
  1730     apply (unfold eq_sts'', simp)
       
  1731     by (metis sts_disj_cons)
       
  1732   from CLocal(1)[OF h(1) this] eq_sts''
       
  1733   show ?case
       
  1734     by (auto split:prod.splits)
       
  1735 qed
       
  1736 
       
  1737 lemma sts_disj_free:
       
  1738   assumes "list_all (op = Free) sts"
       
  1739      and "length sts' = length sts"
       
  1740   shows "sts_disj sts' sts"
       
  1741 by (metis (full_types) assms(1) assms(2) list_all_length 
       
  1742      status.distinct(1) sts_disj_def)
       
  1743 
       
  1744 lemma all_free_plus:
       
  1745   assumes "length sts' = length sts"
       
  1746   and "list_all (op = Free) sts"
       
  1747   shows "sts' + sts = sts'"
       
  1748   using assms
       
  1749 proof(induct sts' arbitrary:sts)
       
  1750   case (Cons s sts' sts)
       
  1751   note cs = Cons
       
  1752   thus ?case
       
  1753   proof(cases "sts")
       
  1754     case (Cons s1 sts1)
       
  1755     with cs
       
  1756     show ?thesis
       
  1757       by (smt list.size(4) list_all_simps(1) 
       
  1758               plus_list.simps(3) plus_status.simps(1) sts_list_plus_commut)
       
  1759   qed auto
       
  1760 qed auto
       
  1761 
       
  1762 lemma wf_cpg_test_extrapo:
       
  1763   assumes "wf_cpg_test sts cpg = (True, sts)"
       
  1764   and "list_all (op = Free) sts"
       
  1765   and "length sts' = length sts"
       
  1766   shows "wf_cpg_test sts' cpg = (True, sts')"
       
  1767 proof -
       
  1768   have "sts_disj sts' (sts - sts)"
       
  1769   proof(rule sts_disj_free)
       
  1770     from assms(2)
       
  1771     show "list_all (op = Free) (sts - sts)"
       
  1772       by (induct sts, auto)
       
  1773   next
       
  1774     from assms(3) show "length sts' = length (sts - sts)"
       
  1775       by (metis length_sts_plus minus_list_len plus_list_len)
       
  1776   qed
       
  1777   from wf_cpg_test_disj [OF assms(1) this]
       
  1778   have "wf_cpg_test (sts' + sts) cpg = (True, sts' + sts)" .
       
  1779   moreover from all_free_plus[OF assms(3, 2)] have "sts' + sts = sts'" .
       
  1780   finally show ?thesis by simp
       
  1781 qed
       
  1782 
       
  1783 lemma perms_wf_cpg_test:
       
  1784   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1785   shows "wf_cpg_test (perm_ss ops sts) (perms (length sts) ops cpg) = 
       
  1786                    (True, perm_ss ops sts')"
       
  1787   using assms
       
  1788 proof(induct ops arbitrary:sts cpg sts')
       
  1789   case (Cons sp ops sts cpg sts')
       
  1790   show ?case
       
  1791   proof(cases "sp")
       
  1792     case (Pair i j)
       
  1793     show ?thesis
       
  1794     proof -
       
  1795       let ?sts = "(perm_s i j sts)" and ?cpg = "(perm (length sts) i j cpg)"
       
  1796       and ?sts' = "perm_s i j sts'"
       
  1797       have "wf_cpg_test (perm_ss ops ?sts) (perms (length ?sts) ops ?cpg) = 
       
  1798                      (True, perm_ss ops ?sts')"
       
  1799       proof(rule Cons(1))
       
  1800         show "wf_cpg_test (perm_s i j sts) (perm (length sts) i j cpg) = (True, perm_s i j sts')"
       
  1801           by (metis Cons.prems perm_wf_cpg_test)
       
  1802       qed
       
  1803       thus ?thesis
       
  1804         apply (unfold Pair)
       
  1805         apply simp
       
  1806         by (metis perm_s_len)
       
  1807     qed
       
  1808   qed
       
  1809 qed auto
       
  1810 
       
  1811 lemma perm_ss_len: "length (perm_ss ops xs) = length xs"
       
  1812 proof(induct ops arbitrary:xs)
       
  1813   case (Cons sp ops xs)
       
  1814   show ?case
       
  1815   proof(cases "sp")
       
  1816     case (Pair i j)
       
  1817     show ?thesis
       
  1818     proof -
       
  1819       let ?xs = "(perm_s i j xs)"
       
  1820       have "length (perm_ss ops ?xs) = length ?xs"
       
  1821         by (metis Cons.hyps)
       
  1822       also have "\<dots> = length xs"
       
  1823         by (metis perm_s_len)
       
  1824       finally show ?thesis
       
  1825         by (unfold Pair, simp)
       
  1826     qed
       
  1827   qed
       
  1828 qed auto
       
  1829 
       
  1830 lemma perms_c2t: 
       
  1831   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1832    and "length env = length sts"
       
  1833   shows "c2t (perm_ss ops env) (perms (length env) ops cpg) = c2t env cpg"
       
  1834   using assms
       
  1835 proof(induct ops arbitrary:sts cpg sts' env)
       
  1836   case (Cons sp ops sts cpg sts' env)
       
  1837   show ?case
       
  1838   proof(cases "sp")
       
  1839     case (Pair i j)
       
  1840     show ?thesis
       
  1841     proof -
       
  1842       let ?env = "(perm_s i j env)" and ?cpg = "(perm (length env) i j cpg)"
       
  1843       have " c2t (perm_ss ops ?env) (perms (length ?env) ops ?cpg) = c2t ?env ?cpg"
       
  1844       proof(rule Cons(1))
       
  1845         from perm_wf_cpg_test[OF Cons(2), of i j, folded Cons(3)]
       
  1846         show "wf_cpg_test (perm_s i j sts) (perm (length env) i j cpg) = (True, perm_s i j sts')" .
       
  1847       next
       
  1848         show "length (perm_s i j env) = length (perm_s i j sts)"
       
  1849           by (metis Cons.prems(2) perm_s_len)
       
  1850       qed
       
  1851       also have "\<dots> = c2t env cpg"
       
  1852         by (metis Cons.prems(1) Cons.prems(2) perm_c2t)
       
  1853       finally show ?thesis
       
  1854         apply (unfold Pair)
       
  1855         apply simp
       
  1856         by (metis perm_s_len)
       
  1857     qed
       
  1858   qed
       
  1859 qed auto
       
  1860 
       
  1861 lemma red_lfs_nil: "red_lfs [] = []"
       
  1862   by (simp add:red_lfs_def)
       
  1863 
       
  1864 lemma red_lfs_cons: "red_lfs ((env, t)#lfs) = (length env, t)#(red_lfs lfs)"
       
  1865   by (simp add:red_lfs_def)
       
  1866 
       
  1867 lemmas red_lfs_simps [simp] = red_lfs_nil red_lfs_cons
       
  1868 
       
  1869 lemma lifts_wf_cpg_test: 
       
  1870   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1871   shows "wf_cpg_test (lift_ss ops sts) (lift_ts (red_lfs ops) cpg) 
       
  1872                 =  (True, lift_ss ops sts')"
       
  1873   using assms
       
  1874 proof(induct ops arbitrary:sts cpg sts')
       
  1875   case (Cons sp ops sts cpg sts')
       
  1876   show ?case
       
  1877   proof(cases "sp")
       
  1878     case (Pair env' t)
       
  1879     thus ?thesis
       
  1880     proof -
       
  1881       let ?sts = "(take t sts @ map (\<lambda>x. Free) env' @ drop t sts)" 
       
  1882       and ?sts' = "(take t sts' @ map (\<lambda>x. Free) env' @ drop t sts')"
       
  1883       and ?cpg = "(lift_t t (length env') cpg)"
       
  1884       have "wf_cpg_test (lift_ss ops ?sts) (lift_ts (red_lfs ops) ?cpg) = (True, lift_ss ops ?sts')"
       
  1885       proof(induct rule: Cons(1))
       
  1886         case 1
       
  1887         show ?case
       
  1888           by (metis Cons.prems length_map lift_wf_cpg_test)
       
  1889       qed
       
  1890       thus ?thesis
       
  1891         by (unfold Pair, simp)
       
  1892     qed
       
  1893   qed
       
  1894 qed auto
       
  1895 
       
  1896 lemma lifts_c2t: 
       
  1897   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1898    and "length env = length sts"
       
  1899   shows "c2t (lift_es ops env) (lift_ts (red_lfs ops) cpg) = c2t env cpg"
       
  1900   using assms
       
  1901 proof(induct ops arbitrary:sts cpg sts' env)
       
  1902   case (Cons sp ops sts cpg sts' env)
       
  1903   show ?case
       
  1904   proof(cases "sp")
       
  1905     case (Pair env' t)
       
  1906     show ?thesis
       
  1907     proof -
       
  1908       let ?env = "(take t env @ env' @ drop t env)" 
       
  1909       and ?cpg = "(lift_t t (length env') cpg)"
       
  1910       have "c2t (lift_es ops ?env) (lift_ts (red_lfs ops) ?cpg) = c2t ?env ?cpg"
       
  1911       proof(rule Cons(1))
       
  1912         from lift_wf_cpg_test[OF Cons(2), of t "map (\<lambda> x. Free) env'", simplified length_map]
       
  1913         show "wf_cpg_test (take t sts @ map (\<lambda>x. Free) env' @ drop t sts) 
       
  1914                   (lift_t t (length env') cpg) =
       
  1915               (True, take t sts' @ map (\<lambda>x. Free) env' @ drop t sts')" .
       
  1916       next
       
  1917         show "length (take t env @ env' @ drop t env) =
       
  1918                 length (take t sts @ map (\<lambda>x. Free) env' @ drop t sts)"
       
  1919           by (metis (full_types) Cons.prems(2) Pair assms(2) length_append 
       
  1920                   length_drop length_map length_take)
       
  1921       qed
       
  1922       also have "\<dots> = c2t env cpg"
       
  1923         by (metis Cons.prems(1) Cons.prems(2) lift_c2t)
       
  1924       finally show ?thesis
       
  1925         by (unfold Pair, simp)
       
  1926     qed
       
  1927   qed
       
  1928 qed auto
       
  1929 
       
  1930 lemma adjust_c2t: 
       
  1931   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1932   and "length env = length sts"
       
  1933   shows "c2t (adjust_env sps lfs env) (adjust_cpg (length sts) sps (red_lfs lfs) cpg) = c2t env cpg"
       
  1934 proof -
       
  1935   let ?cpg = "(perms (length sts) sps cpg)"
       
  1936   and ?env = "(perm_ss sps env)"
       
  1937   have "c2t (lift_es lfs ?env) 
       
  1938                (lift_ts (red_lfs lfs) ?cpg) = c2t ?env ?cpg"
       
  1939   proof (rule lifts_c2t)
       
  1940     from perms_wf_cpg_test[OF assms(1), of sps]
       
  1941     show "wf_cpg_test (perm_ss sps sts) (perms (length sts) sps cpg) = (True, perm_ss sps sts')" .
       
  1942   next
       
  1943     show "length (perm_ss sps env) = length (perm_ss sps sts)"
       
  1944       by (metis assms(2) perm_ss_len)
       
  1945   qed
       
  1946   also have "\<dots> = c2t env cpg"
       
  1947   proof(fold assms(2), rule perms_c2t)
       
  1948     from assms(1) show " wf_cpg_test sts cpg = (True, sts')" .
       
  1949   next
       
  1950     from assms(2) show "length env = length sts" .
       
  1951   qed
       
  1952   finally show ?thesis
       
  1953     by (unfold adjust_env_def adjust_cpg_def, simp)
       
  1954 qed
       
  1955 
       
  1956 lemma adjust_wf_cpg_test:
       
  1957   assumes "wf_cpg_test sts cpg = (True, sts')"
       
  1958   shows "wf_cpg_test (adjust_sts sps lfs sts) (adjust_cpg (length sts) sps (red_lfs lfs) cpg) = 
       
  1959                          (True, adjust_sts sps lfs sts')"
       
  1960 proof -
       
  1961   have " wf_cpg_test (lift_ss lfs (perm_ss sps sts)) (lift_ts (red_lfs lfs) (perms (length sts) sps cpg)) =
       
  1962     (True, lift_ss lfs (perm_ss sps sts'))"
       
  1963   proof(rule lifts_wf_cpg_test)
       
  1964     show " wf_cpg_test (perm_ss sps sts) (perms (length sts) sps cpg) = (True, perm_ss sps sts')"
       
  1965       by (rule perms_wf_cpg_test[OF assms])
       
  1966   qed
       
  1967   thus ?thesis
       
  1968     by (unfold adjust_sts_def adjust_cpg_def, simp)
       
  1969 qed
       
  1970 
       
  1971 lemma sts_disj_test_correct:
       
  1972   assumes "sts_disj_test sts1 sts2"
       
  1973   shows "sts_disj sts1 sts2"
       
  1974   using assms
       
  1975 proof(induct sts1 arbitrary:sts2)
       
  1976   case (Nil sts2)
       
  1977   note Nil_1 = Nil
       
  1978   show ?case
       
  1979   proof(cases sts2)
       
  1980     case Nil
       
  1981     with Nil_1
       
  1982     show ?thesis by (simp add:sts_disj_def)
       
  1983   next
       
  1984     case (Cons s2 ss2)
       
  1985     with Nil_1 show ?thesis by simp
       
  1986   qed
       
  1987 next
       
  1988   case (Cons s1 ss1 sts2)
       
  1989   note Cons_1 = Cons
       
  1990   show ?case
       
  1991   proof(cases "sts2")
       
  1992     case Nil
       
  1993     with Cons_1 show ?thesis by simp
       
  1994   next
       
  1995     case (Cons s2 ss2)
       
  1996     show ?thesis
       
  1997     proof(cases "s1 = Bound \<and> s2 = Bound")
       
  1998       case True
       
  1999       with Cons_1 Cons
       
  2000       show ?thesis by simp
       
  2001     next
       
  2002       case False
       
  2003       with Cons_1 Cons
       
  2004       have "sts_disj_test ss1 ss2" by (auto split:status.splits)
       
  2005       from Cons_1(1) [OF this] False
       
  2006       show ?thesis
       
  2007         apply (unfold Cons)
       
  2008         apply (unfold sts_disj_def)
       
  2009         by (smt False length_Suc_conv list.size(4) nth_Cons')
       
  2010     qed      
       
  2011   qed
       
  2012 qed
       
  2013 
       
  2014 lemma sts_minus_free:
       
  2015   assumes "length sts1 = length sts2"
       
  2016   and "list_all (op = Free) sts2"
       
  2017   shows "sts1 - sts2 = sts1"
       
  2018   using assms
       
  2019 proof(induct sts1 arbitrary:sts2)
       
  2020   case (Nil sts2)
       
  2021   thus ?case by simp
       
  2022 next
       
  2023   case (Cons s1 ss1 sts2)
       
  2024   note Cons_1 = Cons
       
  2025   thus ?case
       
  2026   proof(cases sts2)
       
  2027     case Nil
       
  2028     with Cons
       
  2029     show ?thesis by simp
       
  2030   next
       
  2031     case (Cons s2 ss2)
       
  2032     have "ss1 - ss2 = ss1"
       
  2033     proof(rule Cons_1(1))
       
  2034       show "length ss1 = length ss2"
       
  2035         by (metis Cons Cons_1(2) Suc_length_conv list.inject)
       
  2036     next
       
  2037       show "list_all (op = Free) ss2"
       
  2038         by (metis Cons Cons_1(3) list_all_simps(1))
       
  2039     qed
       
  2040     moreover from Cons_1(3) Cons have "s2 = Free"
       
  2041       by (metis (full_types) list_all_simps(1))
       
  2042     ultimately show ?thesis using Cons
       
  2043       apply simp
       
  2044       by (metis (hide_lams, mono_tags) minus_status.simps(2) minus_status.simps(3) status.exhaust)
       
  2045   qed
       
  2046 qed
       
  2047 
       
  2048 lemma st_simp [simp]: "St (nat_of x) = x"
       
  2049   by (metis nat_of.simps tstate.exhaust)
       
  2050   
       
  2051 lemma wf_cpg_test_len:
       
  2052   assumes "wf_cpg_test sts cpg = (b, sts')"
       
  2053   shows "length sts' = length sts"
       
  2054   using assms
       
  2055 proof(induct cpg arbitrary:sts sts' b)
       
  2056   case (CInstr instr sts sts' b)
       
  2057   then obtain a1 s1 a2 s2 where
       
  2058     eq_instr: "instr = ((a1, St s1), (a2, St s2))"
       
  2059     by (metis st_simp surj_pair) 
       
  2060   with CInstr
       
  2061   show ?case by simp
       
  2062 qed (auto split:prod.splits)
       
  2063 
       
  2064 lemma wf_cpg_test_seq:
       
  2065   assumes "wf_cpg_test sts1 c1 = (True, sts1')"
       
  2066   and "wf_cpg_test sts2 c2 = (True, sts2')"
       
  2067   and "length sts1 = length sts2"
       
  2068   and "list_all (op = Free) sts1"
       
  2069   and "list_all (op = Free) sts2"
       
  2070   and "sts_disj_test sts1' sts2'"
       
  2071   shows "wf_cpg_test sts1 (CSeq c1 c2) = (True, sts1' + sts2')"
       
  2072 proof -
       
  2073   have "wf_cpg_test (sts1' + sts2) c2 = (True, sts1' + sts2')"
       
  2074     by (metis add_imp_eq assms(2) assms(5) assms(6) length_sts_plus 
       
  2075          plus_list_len sts_disj_test_correct sts_minus_free wf_cpg_test_disj wf_cpg_test_extrapo wf_cpg_test_len)
       
  2076   hence "wf_cpg_test sts1' c2 = (True, sts1' + sts2')"
       
  2077     by (metis all_free_plus assms(1) assms(3) assms(5) wf_cpg_test_len)
       
  2078   with assms(1)
       
  2079   show ?thesis by simp
       
  2080 qed
       
  2081 
       
  2082 lemma c2t_seq:
       
  2083   assumes "c2t env c1 = t1"
       
  2084   and "c2t env c2 = t2"
       
  2085   shows "c2t env (CSeq c1 c2) = (t1; t2)"
       
  2086   using assms by simp
       
  2087 
       
  2088 lemma c2t_local:
       
  2089   assumes "\<And>x. (c2t (x#xs) cpg = body x)"
       
  2090   shows "c2t xs (CLocal cpg) = (TL x. body x)"
       
  2091   using assms
       
  2092   by simp
       
  2093 
       
  2094 lemma wf_cpg_test_local:
       
  2095   assumes "wf_cpg_test (Free#sts) cpg = (b, s'#sts')"
       
  2096   shows "wf_cpg_test sts (CLocal cpg) = (b, sts')"
       
  2097   by (simp add:assms)
       
  2098 
       
  2099 lemma wf_c2t_combined:
       
  2100   assumes "wf_cpg_test sts cpg = (True, sts)"
       
  2101   and "c2t env cpg = tpg"
       
  2102   and  "list_all (op = Free) sts"
       
  2103   and "length env = length sts"
       
  2104   shows "\<forall> i. \<exists> j s.  ((i:[tpg]:j) s)"
       
  2105 proof
       
  2106   fix i
       
  2107   from wf_cpg_test_correct[OF assms(1), rule_format, of i]
       
  2108   obtain j where "c2p (sts - sts) i cpg j" by metis
       
  2109   from this[unfolded c2p_def]
       
  2110   obtain f where h: "\<forall>x. length x = length (sts - sts) \<and>
       
  2111           (\<forall>k<length (sts - sts). (sts - sts) ! k = Bound \<longrightarrow> x ! k = f i k) \<longrightarrow>
       
  2112           Ex (i :[ c2t x cpg ]: j)" by metis
       
  2113   have "\<exists> s. (i :[ c2t env cpg ]: j) s"
       
  2114   proof(rule h[rule_format], rule conjI)
       
  2115     show "length env = length (sts - sts)"
       
  2116     by (smt assms(4) minus_list_len)
       
  2117   next
       
  2118     show "\<forall>k<length (sts - sts). (sts - sts) ! k = Bound \<longrightarrow> env ! k = f i k"
       
  2119       by (metis assms(3) minus_status.simps(1) nth_sts_minus status.distinct(1) sts_minus_free)
       
  2120   qed
       
  2121   show "\<exists> j s.  ((i:[tpg]:j) s)"
       
  2122     by (metis `\<exists>s. (i :[ c2t env cpg ]: j) s` assms(2))
       
  2123 qed
       
  2124 
       
  2125 subsection {* The Checker *}
       
  2126 
       
  2127 ML {*
       
  2128   print_depth 200
       
  2129 *}
       
  2130 
       
  2131 subsubsection {* Auxilary functions *}
       
  2132 
       
  2133 ML {*
       
  2134 local
       
  2135   fun clear_binds ctxt = (ctxt |> Variable.binds_of |> Vartab.keys |> map (fn xi => (xi, NONE))
       
  2136                                |> fold Variable.bind_term) ctxt 
       
  2137   fun get_binds ctxt = ctxt |> Variable.binds_of |> Vartab.dest |> map (fn (xi, (_, tm)) => (xi, SOME tm))
       
  2138   fun set_binds blist ctxt = (fold Variable.bind_term blist) (clear_binds ctxt)
       
  2139 in
       
  2140   fun blocalM f =      liftM (m2M (fn ctxt => returnM (get_binds ctxt)))
       
  2141                 :|-- (fn binds => 
       
  2142                            f
       
  2143                       :|-- (fn result =>
       
  2144                                liftM (m2M (fn ctxt' => s2M (set_binds binds ctxt') |-- returnM result
       
  2145                                      )))
       
  2146                      )
       
  2147 end
       
  2148 
       
  2149   fun condM bf scan = (fn v => m0M (fn st => if (bf (v, st)) then scan v else returnM v))
       
  2150 
       
  2151   local 
       
  2152     val counter = Unsynchronized.ref 0
       
  2153   in 
       
  2154     fun init_counter n = (counter := n)
       
  2155     fun counter_test x = 
       
  2156         if !counter <= 1 then true
       
  2157         else (counter := !counter - 1; false)
       
  2158   end
       
  2159 
       
  2160   (* break point monad *)
       
  2161   fun bpM v' = (fn v => m0M (fn st => raiseM (v', (v, st))))
       
  2162 
       
  2163   fun the_theory () = ML_Context.the_local_context () |> Proof_Context.theory_of 
       
  2164   fun the_context () = ML_Context.the_local_context ()
       
  2165 
       
  2166   (* Calculating the numberal of integer [i] *)
       
  2167   fun nat_of i = if i = 0 then @{term "0::nat"} else
       
  2168                    (Const ("Num.numeral_class.numeral", @{typ "num \<Rightarrow> nat"}) $ 
       
  2169                      (Numeral.mk_cnumeral i |> term_of))
       
  2170 
       
  2171   fun vfixM nm typ = (m2M' (fn ctxt => let
       
  2172          val ([x], ctxt') = Variable.variant_fixes [nm] ctxt
       
  2173          val tm_x = Free (x, typ)
       
  2174    in s2M ctxt' |-- returnM tm_x end))
       
  2175   fun fixM nm typ = (m2M' (fn ctxt => let
       
  2176          val ([x], ctxt') = Variable.add_fixes [nm] ctxt
       
  2177          val tm_x = Free (x, typ)
       
  2178    in s2M ctxt' |-- returnM tm_x end))
       
  2179   local
       
  2180     fun mk_listM l = 
       
  2181      case l of 
       
  2182        [] => @{fterm "[]"}
       
  2183      | (tm::tms) => localM (@{match "?x"} tm
       
  2184                             |-- (mk_listM tms)
       
  2185                            :|-- @{match "?xs"}
       
  2186                             |-- @{fterm "?x#?xs"})
       
  2187   in
       
  2188     fun mk_list_term ctxt l = [((), ctxt)] |> mk_listM l |> normVal |> fst
       
  2189   end
       
  2190   fun term_name (Const (x, _)) = Long_Name.base_name x
       
  2191     | term_name (Free (x, _)) = x
       
  2192     | term_name (Var ((x, _), _)) = x
       
  2193     | term_name _ = Name.uu;
       
  2194 
       
  2195   val rew_conv = Raw_Simplifier.rewrite_cterm (true, false, false) (K (K NONE));
       
  2196 
       
  2197    fun simpl_conv ss thl ctm =
       
  2198             rew_conv (ss addsimps thl) ctm RS meta_eq_to_obj_eq;
       
  2199 
       
  2200   fun find_thms ctxt pats = 
       
  2201        Find_Theorems.find_theorems ctxt NONE NONE true
       
  2202                (map (fn pat =>(true, Find_Theorems.Pattern 
       
  2203                        (Proof_Context.read_term_pattern ctxt pat))) pats) |> snd |> map snd
       
  2204 
       
  2205 
       
  2206   fun local_on arg rhs = [((), @{context})] |>
       
  2207                          @{match "?body"} (Term.lambda arg rhs) |--
       
  2208                          @{fterm "TL x. ?body x"} |> normVal |> fst
       
  2209   fun find_idx vars l = (nat_of (find_index (equal l) vars))
       
  2210 
       
  2211  local
       
  2212     fun mk_pair_term (i, j) = [((), @{context})] |> 
       
  2213             @{match "?i"} (nat_of i) 
       
  2214         |-- @{match "?j"} (nat_of j) 
       
  2215         |-- @{fterm "(?i, ?j)"} |> normVal |> fst 
       
  2216  in
       
  2217     fun mk_npair_list_term ctxt pair_list = 
       
  2218           if pair_list = [] then @{term "[]::(nat \<times> nat) list"}
       
  2219           else pair_list |> map mk_pair_term |> mk_list_term ctxt
       
  2220  end
       
  2221 
       
  2222   fun list_of_array ary = let 
       
  2223      val len = Array.length ary
       
  2224      val idx = upto (0, len - 1)
       
  2225   in map (fn i => Array.sub (ary, i)) idx  end
       
  2226 
       
  2227 local
       
  2228     fun mk_env_term ctxt lst = 
       
  2229       if lst = [] then @{term "[]::tstate list"} else (mk_list_term ctxt lst)
       
  2230     fun mk_pair_term ctxt (i, j) = [((), ctxt)] |> 
       
  2231             @{match "?i"} (mk_env_term ctxt i)
       
  2232         |-- @{match "?j"} (nat_of j) 
       
  2233         |-- @{fterm "(?i, ?j)"} |> normVal |> fst 
       
  2234 in
       
  2235     fun mk_tpair_list_term ctxt pair_list = 
       
  2236        if pair_list = [] then @{term "[] :: (tstate list \<times> nat) list"}
       
  2237        else pair_list |> map (mk_pair_term ctxt) |> mk_list_term ctxt
       
  2238 end
       
  2239 
       
  2240 *}
       
  2241 
       
  2242 subsubsection {* The reifier *} 
       
  2243 
       
  2244 ML {*
       
  2245   fun locM (c2t_thm, test_thm) = (m1M' (fn env => 
       
  2246   let
       
  2247     val Free (x, _) = hd env 
       
  2248     val c2t_thm = Drule.generalize ([], [x]) c2t_thm
       
  2249     val c2t_thm = @{thm c2t_local} OF [c2t_thm]
       
  2250     val test_thm = @{thm wf_cpg_test_local} OF [test_thm]
       
  2251   in
       
  2252     s1M (tl env) |-- returnM (c2t_thm, test_thm)
       
  2253   end))
       
  2254 
       
  2255   fun reify_local reify t = 
       
  2256       (      @{match "TL x . ?body (x::tstate)"} t 
       
  2257          |-- vfixM "x" @{typ "tstate"}
       
  2258         :|-- @{match "?x"}
       
  2259         :|-- (fn tmx => m1M' (fn env => s1M (tmx::env)))
       
  2260          |-- @{fterm "?body ?x"}
       
  2261         :|-- reify 
       
  2262         :|-- locM 
       
  2263         (* :|-- condM counter_test (bpM ("local", t))  *)
       
  2264       )
       
  2265  
       
  2266   fun labelM exp = m0M' (fn (env, ctxt) => let
       
  2267   (* The following three lines are used for debugging purpose
       
  2268        (* (* The following two lines are used to set breakpoint counter
       
  2269                  and invoke the reifyer in debug mode *)
       
  2270          val _ = init_counter 3
       
  2271          val t = reify tpg_def_rhs [(rev tpg_def_largs_sufx, ctxt_tpg_def)] |> normExcp 
       
  2272        *)
       
  2273        (* The following line is used to extract break point information and 
       
  2274           establish the environment to execute body statements *)
       
  2275        val ((brc, exp), (_, (env, ctxt)::_)) = t 
       
  2276   *)
       
  2277   val c2t_thm = [((), ctxt)] |>
       
  2278            @{match "?cpg"} exp
       
  2279         |-- @{match "?env"} (env |> mk_list_term ctxt)
       
  2280         |-- @{fterm "c2t ?env ?cpg"} |> normVal |> fst |> cterm_of (Proof_Context.theory_of ctxt) 
       
  2281                      |> simpl_conv (simpset_of ctxt) []
       
  2282   val test_thm = [((), ctxt)] |>
       
  2283            @{match "?cpg"} exp
       
  2284         |-- @{match "?sts"} (env |> map (fn _ => @{term "Free"}) |> mk_list_term ctxt)
       
  2285         |-- @{fterm "wf_cpg_test ?sts ?cpg"} |> normVal |> fst |> cterm_of (Proof_Context.theory_of ctxt) 
       
  2286                      |> simpl_conv (simpset_of ctxt) []
       
  2287    in returnM (c2t_thm, test_thm) end)
       
  2288 
       
  2289    fun reify_label t = 
       
  2290              @{match "TLabel ?L"} t 
       
  2291          |-- @{fterm "?L"} 
       
  2292         :|-- (fn l => m1M' (fn st => returnM (find_idx st l))) 
       
  2293         :|-- @{match ?L1} 
       
  2294          |-- @{fterm "CLabel ?L1"}
       
  2295         (* :|-- condM counter_test (bpM ("label", t)) *)
       
  2296         :|-- labelM
       
  2297 
       
  2298   fun seqM ((c2t_thm1, test_thm1), (c2t_thm2, test_thm2)) =
       
  2299   m0M' (fn (env, ctxt) =>
       
  2300   let
       
  2301      val simp_trans = (simpset_of ctxt) delsimps @{thms wf_cpg_test.simps c2t.simps} |> full_simplify
       
  2302      val ct2_thm = (@{thm c2t_seq} OF [c2t_thm1, c2t_thm2]) |> simp_trans
       
  2303      val test_thm =  (@{thm wf_cpg_test_seq} OF [test_thm1, test_thm2]) |> simp_trans
       
  2304   in returnM (ct2_thm, test_thm) end)
       
  2305 
       
  2306    fun reify_seq reify t = 
       
  2307              @{match "?c1; ?c2"} t 
       
  2308          |-- ((@{fterm "?c1"} :|-- reify) -- 
       
  2309               (@{fterm "?c2"} :|-- reify))
       
  2310         (* :|-- condM counter_test (bpM ("seq", t))  *)
       
  2311         :|-- seqM
       
  2312 
       
  2313   fun reify_instr t = 
       
  2314              @{match "\<guillemotright> ((?A0, ?L0), (?A1, ?L1))"} t 
       
  2315          |-- @{fterm "?L0"} 
       
  2316         :|-- (fn l => m1M' (fn st => returnM (find_idx st l))) 
       
  2317         :|-- @{match ?L0'} 
       
  2318          |-- @{fterm "?L1"} 
       
  2319         :|-- (fn l => m1M' (fn st => returnM (find_idx st l))) 
       
  2320         :|-- @{match ?L1'} 
       
  2321          |-- @{fterm "CInstr ((?A0, ?L0'), (?A1, St ?L1'))"}
       
  2322         :|-- labelM
       
  2323         (* :|-- condM counter_test (bpM ("instr", t)) *)
       
  2324 
       
  2325   fun reify_var var = 
       
  2326     (* condM counter_test (bpM ("var", var)) () |--  *)
       
  2327   (m0M' (fn (env, ctxt) => let
       
  2328   (* The following three lines are used for debugging purpose
       
  2329        (* (* The following two lines are used to set breakpoint counter
       
  2330                  and invoke the reifyer in debug mode *)
       
  2331          val _ = init_counter 3
       
  2332          val t = reify tpg_def_rhs [(rev tpg_def_largs_sufx, ctxt_tpg_def)] |> normExcp 
       
  2333        *)
       
  2334        (* The following line is used to extract break point information and 
       
  2335           establish the environment to execute body statements *)
       
  2336        val ((brc, var), (_, (env, ctxt)::_)) = t 
       
  2337   *)
       
  2338   val (var_hd, var_args) = Term.strip_comb var
       
  2339   val (var_args_prefx, var_args_sufx) = 
       
  2340             take_suffix (fn tm => type_of tm = @{typ "tstate"}) var_args
       
  2341   val var_skel_hd_typ = var_args_prefx |> map type_of |> (fn typs => typs ---> @{typ "cpg"})
       
  2342   (* We discriminate two cases, one for tpg constants; the other for argument variable *)
       
  2343   val  ([var_skel_hd_name], ctxt1) = 
       
  2344       case var_hd of
       
  2345         (Const (nm, _)) => ([((nm |> Long_Name.base_name)^"_skel")], ctxt)
       
  2346       | _ =>  Variable.variant_fixes [(term_name var_hd^"_skel_")] ctxt
       
  2347   (* If [var_hd] is a constant, a corresponding skeleton constant is assumed to exist alrady *)
       
  2348   val var_skel_hd = if (Term.is_Const var_hd) then  Syntax.read_term ctxt1 var_skel_hd_name
       
  2349                     else Free (var_skel_hd_name, var_skel_hd_typ)
       
  2350   (* [skel_tm] is the skeleton object the properties of which will either be assumed (in case of 
       
  2351      argument variable), or proved (in case of global constants ) *)
       
  2352   val skel_tm = Term.list_comb (var_skel_hd, var_args_prefx) 
       
  2353   (* Start to prove or assume [c2t] property (named [c2t_thm]) of the skeleton object, 
       
  2354      since the [c2t] property needs to be universally qantified, we 
       
  2355      need to invent quantifier names: *)
       
  2356   val (var_skel_args_sufx_names, ctxt2) = 
       
  2357               Variable.variant_fixes (var_args_sufx |> map term_name) ctxt1
       
  2358   val var_skel_args_sufx = var_skel_args_sufx_names |> map (fn nm => Free (nm, @{typ "tstate"}))
       
  2359   val c2t_rhs = Term.list_comb (var_hd, var_args_prefx@var_skel_args_sufx)
       
  2360   val c2t_env = mk_list_term ctxt2 (var_skel_args_sufx |> rev) 
       
  2361   val eqn = [((), ctxt2)] |>
       
  2362            @{match ?env} c2t_env
       
  2363        |-- @{match ?skel_tm} skel_tm
       
  2364        |-- @{match ?c2t_rhs} c2t_rhs
       
  2365        |-- @{fterm "Trueprop (c2t ?env ?skel_tm = ?c2t_rhs)"} |> normVal |> fst 
       
  2366   fun all_on ctxt arg body = Const ("all", dummyT) $ (Term.lambda arg body) |> 
       
  2367             Syntax.check_term ctxt
       
  2368   val c2t_eqn = fold (all_on ctxt2) (rev var_skel_args_sufx) eqn |> cterm_of (Proof_Context.theory_of ctxt2)
       
  2369   val ([c2t_thm], ctxt3) = 
       
  2370        if (Term.is_Const var_hd) then 
       
  2371           (* if [var_hd] is an constant, try to prove [c2t_eqn] by searching 
       
  2372              into the facts database *)
       
  2373           let
       
  2374                val pat_skel_args = fold (curry (op ^)) (map (K  " _ ")  var_args_prefx) ""
       
  2375                val pat_skel_str = "( "^ var_skel_hd_name ^ pat_skel_args ^" )"
       
  2376                val test_pat = ("wf_cpg_test _ "^ pat_skel_str ^" = (True, _)")
       
  2377                val c2t_pat = ("c2t _ "^ pat_skel_str ^" = _")
       
  2378                val (wf_test_thms, c2t_thms) = ([test_pat], [c2t_pat]) |> pairself (find_thms ctxt2)
       
  2379           in
       
  2380              ([([((0, @{thm "refl"}), ctxt2)] |>
       
  2381                   goalM (c2t_eqn |> term_of)
       
  2382                |-- tacM (fn ctxt => (Simplifier.simp_tac ((simpset_of ctxt) addsimps c2t_thms) 1))
       
  2383                >> Goal.conclude |> normVal |> fst |> Raw_Simplifier.norm_hhf)], ctxt2)
       
  2384           end
       
  2385        else (* Otherwise, make [c2t_eqn] an assumption *) 
       
  2386           Assumption.add_assumes [c2t_eqn] ctxt2
       
  2387   (* Start to prove or assume [wf_cpg_test] property (named [wf_test_thm]) of the skeleton object. *)
       
  2388   val sts = map (fn tm => @{term "Free"}) var_args_sufx |> mk_list_term ctxt3 
       
  2389   val wf_test_eqn = [((), ctxt3)] |>
       
  2390            @{match ?cpg} skel_tm
       
  2391        |-- @{match ?sts} sts
       
  2392        |-- @{fterm "Trueprop (wf_cpg_test ?sts ?cpg = (True, ?sts))"} |> normVal |> fst 
       
  2393               |> cterm_of (Proof_Context.theory_of ctxt3)
       
  2394   val ([wf_test_thm], ctxt4) =
       
  2395        if (Term.is_Const var_hd) then 
       
  2396           let
       
  2397                val pat_skel_args = fold (curry (op ^)) (map (K  " _ ")  var_args_prefx) ""
       
  2398                val pat_skel_str = "( "^ var_skel_hd_name ^ pat_skel_args ^ " )"
       
  2399                val test_pat = ("wf_cpg_test _ "^ pat_skel_str ^" = (True, _)")
       
  2400                val c2t_pat = ("c2t _ "^ pat_skel_str ^" = _")
       
  2401                val wf_test_thms = [test_pat] |> (find_thms ctxt2)
       
  2402           in
       
  2403              ([([((0, @{thm "refl"}), ctxt2)] |>
       
  2404                   goalM (wf_test_eqn |> term_of)
       
  2405                |-- tacM (fn ctxt => (Simplifier.simp_tac ((simpset_of ctxt) addsimps wf_test_thms) 1))
       
  2406                >> Goal.conclude |> normVal |> fst |> Raw_Simplifier.norm_hhf)], ctxt3)
       
  2407           end
       
  2408        else Assumption.add_assumes [wf_test_eqn] ctxt3
       
  2409   (* Start the derivation of the length theorem *)
       
  2410   val length_env = mk_list_term ctxt4 (var_args_sufx  |> rev)
       
  2411   val length_thm = [((0, @{thm "init"}), ctxt4)] |>
       
  2412           @{match "(?env)"} length_env
       
  2413        |-- @{match "(?sts)"} sts
       
  2414        |-- @{fterm "Trueprop (length (?env::tstate list) = length (?sts::status list))"}
       
  2415       :|-- goalM
       
  2416        |-- tacM (fn ctxt => (Simplifier.simp_tac (simpset_of ctxt) 1))
       
  2417             >> Goal.conclude |> normVal |> fst 
       
  2418   (* Start compute two adjust operations, namely [sps] and [lfs] *)
       
  2419   val locs = var_args_sufx |> map (fn arg => find_index (equal arg) env) |> rev
       
  2420   val swaps = swaps_of locs
       
  2421   val sps = swaps |> mk_npair_list_term @{context} 
       
  2422   val locs' = sexec swaps (Array.fromList locs) |> list_of_array
       
  2423   val pairs = ((~1::locs') ~~ (locs' @ [length env]))
       
  2424   fun lfs_of (t, ops) [] = ops |> rev
       
  2425     | lfs_of (t, ops) ((i, j)::pairs) = let
       
  2426           val stuf = upto (i + 1, j - 1) |> map (fn idx => nth env idx)
       
  2427       in if (stuf <> []) then lfs_of (t + length stuf + 1, (stuf, t)::ops) pairs 
       
  2428                         else lfs_of (t + length stuf + 1, ops) pairs 
       
  2429       end
       
  2430   val lfs = lfs_of (0, []) pairs |> mk_tpair_list_term @{context} 
       
  2431   (* [simp_trans] is the simplification procedure used to simply the theorem after 
       
  2432      instantiation.
       
  2433   *)
       
  2434   val simp_trans =  full_simplify ((simpset_of @{context}) addsimps @{thms adjust_sts_def
       
  2435                                adjust_env_def perm_s_def perm_b_def map_idx_len 
       
  2436                                      map_idx_def upto_map upto_empty} @ [c2t_thm])
       
  2437   (* Instantiating adjust theorems *)
       
  2438   val adjust_c2t_thm = [((), ctxt4)] |>  
       
  2439                 @{match "?sps"} sps 
       
  2440             |-- @{match "?lfs"} lfs 
       
  2441             |-- thm_instM (@{thm adjust_c2t} OF [wf_test_thm, length_thm]) 
       
  2442                    |> normVal |> fst |> simp_trans
       
  2443   val adjust_test_thm = [((), ctxt4)] |>  
       
  2444                 @{match "?sps"} sps 
       
  2445             |-- @{match "?lfs"} lfs 
       
  2446             |-- thm_instM (@{thm adjust_wf_cpg_test} OF [wf_test_thm]) 
       
  2447                    |> normVal |> fst |> simp_trans
       
  2448  in 
       
  2449     (* s2M ctxt4 |-- *) returnM (adjust_c2t_thm, adjust_test_thm)
       
  2450 end)) 
       
  2451 
       
  2452   fun reify t = 
       
  2453       localM (reify_seq reify t || 
       
  2454       reify_local reify t ||
       
  2455       reify_label t || 
       
  2456       reify_instr t ||
       
  2457       reify_var t
       
  2458      )
       
  2459 *}
       
  2460 
       
  2461 subsubsection {* The Checker packed up as the asmb attribute *}
       
  2462 
       
  2463 ML {*
       
  2464  fun asmb_attrib def_thm = 
       
  2465   Context.cases (fn thy =>
       
  2466   (* val thy = @{theory} *) let 
       
  2467   fun thy_exit ctxt = 
       
  2468        Context.Theory (Local_Theory.exit_global (Local_Theory.assert_bottom true ctxt))
       
  2469   val ctxt0 = Named_Target.theory_init thy
       
  2470   val (((x, y), [tpg_def]), ctxt_tpg_def) = Variable.import true [def_thm] ctxt0
       
  2471   val (tpg_def_lhs, tpg_def_rhs) = [((), ctxt_tpg_def)] |> 
       
  2472                    @{match "Trueprop (?L = ?R)"} (prop_of tpg_def) 
       
  2473                |-- @{fterm "?L"} -- @{fterm "?R"} |> normVal |> fst
       
  2474   val (tpg_def_lhd, tpg_def_largs) = Term.strip_comb tpg_def_lhs
       
  2475   val (tpg_def_largs_prefx, tpg_def_largs_sufx) = 
       
  2476                  take_suffix (fn tm => type_of tm = @{typ "tstate"}) tpg_def_largs
       
  2477   (* Invoking the reifyer in normal mode *)
       
  2478   val ((c2t_thm_1, test_thm_1), ((_, ctxt_r)::y)) = 
       
  2479           reify tpg_def_rhs [(rev tpg_def_largs_sufx, ctxt_tpg_def)] 
       
  2480             |> normVal
       
  2481   val asmb_thm_1 = (@{thm wf_c2t_combined} OF [test_thm_1, c2t_thm_1]) |> (full_simplify (simpset_of ctxt_r))
       
  2482   val (r_cpg, r_tpg) = [((), ctxt_r)] |> 
       
  2483              @{match "Trueprop (c2t _ ?X = ?tpg)"} (c2t_thm_1 |> prop_of)
       
  2484           |-- (@{fterm "?X"} -- @{fterm "?tpg"}) |> normVal |> fst 
       
  2485   val tpg_def_params = Variable.add_fixed ctxt_tpg_def (tpg_def_lhs) [] |> map fst
       
  2486           |> sort (Variable.fixed_ord ctxt_tpg_def)
       
  2487   val r_cpg_frees = Term.add_frees r_cpg []
       
  2488   local fun condense [] = []
       
  2489           | condense xs = [hd xs]
       
  2490   in
       
  2491   val skel_def_params = 
       
  2492             tpg_def_params |> map (fn nm => condense 
       
  2493                                           (filter (fn (tnm, _) => String.isPrefix nm tnm) r_cpg_frees))
       
  2494                 |> flat |> map Free
       
  2495   end      
       
  2496   val skel_def_rhs = fold Term.lambda (skel_def_params |> rev) r_cpg 
       
  2497   local
       
  2498      val Const (nm, _) = tpg_def_lhs |> Term.head_of 
       
  2499   in
       
  2500      val tpg_def_name = nm |> Long_Name.base_name
       
  2501      val skel_def_lhs = Free (tpg_def_name^"_skel", type_of skel_def_rhs)
       
  2502   end
       
  2503   val skel_def_eqn = [((), ctxt_r)] |> 
       
  2504              @{match "?lhs"} skel_def_lhs
       
  2505          |-- @{match "?rhs"} skel_def_rhs
       
  2506          |-- @{fterm "Trueprop (?lhs = ?rhs)"} |> normVal |> fst 
       
  2507   val ((skel_def_lhs, (skel_def_name, skel_def_thm)), lthy2) = 
       
  2508        Specification.definition (NONE, (Attrib.empty_binding, skel_def_eqn)) ctxt_r
       
  2509   val c2t_thm_final = [((0, @{thm refl}), lthy2)] |> 
       
  2510             @{match "?env"} (mk_list_term lthy2 (rev tpg_def_largs_sufx))
       
  2511         |-- @{match "?skel"} (Term.list_comb (skel_def_lhs, skel_def_params))
       
  2512   val c2t_thm_final = [((0, @{thm refl}), lthy2)] |> 
       
  2513             @{match "?env"} (mk_list_term lthy2 (rev tpg_def_largs_sufx))
       
  2514         |-- @{match "?skel"} (Term.list_comb (skel_def_lhs, skel_def_params))
       
  2515         |-- @{match "?tpg"} tpg_def_lhs
       
  2516         |-- @{fterm "Trueprop (c2t ?env ?skel = ?tpg)"} 
       
  2517        :|-- goalM
       
  2518         |-- tacM (fn ctxt => (Simplifier.simp_tac ((simpset_of ctxt |> Simplifier.clear_ss) 
       
  2519                             addsimps [skel_def_thm, c2t_thm_1]) 1))
       
  2520         |-- tacM (fn  ctxt => (Simplifier.simp_tac ((simpset_of ctxt |> Simplifier.clear_ss) 
       
  2521                             addsimps [def_thm]) 1))
       
  2522             >> Goal.conclude |> normVal |> fst
       
  2523   val test_thm_final = [((0, @{thm refl}), lthy2)] |> 
       
  2524             @{match "?sts"} (tpg_def_largs_sufx |> map (fn _ => @{term "Free"}) |> mk_list_term lthy2)
       
  2525         |-- @{match "?skel"} (Term.list_comb (skel_def_lhs, skel_def_params))
       
  2526         |-- @{fterm "Trueprop (wf_cpg_test ?sts ?skel = (True, ?sts))"} 
       
  2527        :|-- goalM
       
  2528         |-- tacM (fn ctxt => (Simplifier.simp_tac ((simpset_of ctxt |> Simplifier.clear_ss) 
       
  2529                             addsimps [skel_def_thm, test_thm_1]) 1))
       
  2530               >> Goal.conclude |> normVal |> fst 
       
  2531   val asmb_thm_final = [((0, @{thm refl}), lthy2)] |> 
       
  2532             @{match "?tpg"} tpg_def_lhs
       
  2533         |-- @{fterm "Trueprop (\<forall> i. \<exists> j s. (i:[?tpg]:j) s)"} 
       
  2534        :|-- goalM
       
  2535         |-- tacM (fn ctxt => (Simplifier.simp_tac ((simpset_of ctxt) 
       
  2536                             addsimps [tpg_def, asmb_thm_1]) 1))
       
  2537          >> Goal.conclude |> normVal |> fst 
       
  2538   fun generalize thm = let
       
  2539     val hyps = (#hyps (thm |> Thm.crep_thm))
       
  2540     val thm' =  if (length hyps = 0) then thm 
       
  2541                 else (fold Thm.implies_intr (#hyps (thm |> Thm.crep_thm) |> rev |> tl |> rev) thm)
       
  2542   in
       
  2543       thm' |> Thm.forall_intr_frees 
       
  2544   end
       
  2545   val lthy3 = 
       
  2546          Local_Theory.note ((Binding.name ("c2t_" ^ tpg_def_name ^ "_skel"), []), 
       
  2547                       [c2t_thm_final |> generalize]) lthy2 |> snd
       
  2548   val lthy4 = 
       
  2549          Local_Theory.note ((Binding.name ("wf_" ^ tpg_def_name ^ "_skel"), []), 
       
  2550                       [test_thm_final |> generalize]) lthy3 |> snd
       
  2551   val lthy5 = 
       
  2552          Local_Theory.note ((Binding.name ("asmb_" ^ tpg_def_name), []), 
       
  2553                       [asmb_thm_final |> Drule.export_without_context]) lthy4 |> snd
       
  2554 in 
       
  2555   thy_exit lthy5
       
  2556 end) (fn ctxt => Context.Proof ctxt)
       
  2557 *}
       
  2558 
       
  2559 setup {*
       
  2560   Attrib.setup @{binding asmb} (Scan.succeed (Thm.declaration_attribute asmb_attrib)) "asmb attribute"
       
  2561 *}
       
  2562 
       
  2563 
       
  2564 section {* Basic macros for TM *}
       
  2565 
       
  2566 definition [asmb]: "write_zero = (TL exit. \<guillemotright>((W0, exit), (W0, exit)); TLabel exit)"
       
  2567 
       
  2568 definition [asmb]: "write_one = (TL exit. \<guillemotright>((W1, exit), (W1, exit)); TLabel exit)"
       
  2569 
       
  2570 definition [asmb]: "move_left = (TL exit . \<guillemotright>((L, exit), (L, exit)); TLabel exit)"
       
  2571 
       
  2572 definition [asmb]: "move_right = (TL exit . \<guillemotright>((R, exit), (R, exit)); TLabel exit)"
       
  2573 
       
  2574 definition [asmb]: "if_one e = (TL exit . \<guillemotright>((W0, exit), (W1, e)); TLabel exit)"
       
  2575 
       
  2576 definition [asmb]: "if_zero e = (TL exit . \<guillemotright>((W0, e), (W1, exit)); TLabel exit)"
       
  2577 
       
  2578 definition [asmb]: "jmp e = \<guillemotright>((W0, e), (W1, e))"
       
  2579 
       
  2580 definition [asmb]: 
       
  2581           "right_until_zero = 
       
  2582                  (TL start exit. 
       
  2583                   TLabel start;
       
  2584                      if_zero exit;
       
  2585                      move_right;
       
  2586                      jmp start;
       
  2587                   TLabel exit
       
  2588                  )"
       
  2589 
       
  2590 definition [asmb]: 
       
  2591        "left_until_zero = 
       
  2592                  (TL start exit. 
       
  2593                   TLabel start;
       
  2594                     if_zero exit;
       
  2595                     move_left;
       
  2596                     jmp start;
       
  2597                   TLabel exit
       
  2598                  )"
       
  2599 
       
  2600 definition [asmb]: 
       
  2601        "right_until_one = 
       
  2602                  (TL start exit. 
       
  2603                   TLabel start;
       
  2604                      if_one exit;
       
  2605                      move_right;
       
  2606                      jmp start;
       
  2607                   TLabel exit
       
  2608                  )"
       
  2609 
       
  2610 definition [asmb]: 
       
  2611           "left_until_one = 
       
  2612                  (TL start exit. 
       
  2613                   TLabel start;
       
  2614                     if_one exit;
       
  2615                     move_left;
       
  2616                     jmp start;
       
  2617                   TLabel exit
       
  2618                  )"
       
  2619 
       
  2620 definition [asmb]: 
       
  2621     "left_until_double_zero = 
       
  2622             (TL start exit.
       
  2623               TLabel start;
       
  2624               if_zero exit;
       
  2625               left_until_zero;
       
  2626               move_left;
       
  2627               if_one start;
       
  2628               TLabel exit)"
       
  2629 
       
  2630 definition [asmb]: 
       
  2631         "shift_right =
       
  2632             (TL start exit.
       
  2633               TLabel start;
       
  2634                  if_zero exit;
       
  2635                  write_zero;
       
  2636                  move_right;
       
  2637                  right_until_zero;
       
  2638                  write_one;
       
  2639                  move_right;
       
  2640                  jmp start;
       
  2641               TLabel exit
       
  2642             )"
       
  2643 
       
  2644 definition [asmb]: 
       
  2645         "clear_until_zero = 
       
  2646              (TL start exit.
       
  2647               TLabel start;
       
  2648                  if_zero exit;
       
  2649                  write_zero;
       
  2650                  move_right;
       
  2651                  jmp start;
       
  2652               TLabel exit)"
       
  2653 
       
  2654 definition [asmb]: 
       
  2655       "shift_left = 
       
  2656             (TL start exit.
       
  2657               TLabel start;
       
  2658                  if_zero exit;
       
  2659                  move_left;
       
  2660                  write_one;
       
  2661                  right_until_zero;
       
  2662                  move_left;
       
  2663                  write_zero;
       
  2664                  move_right;
       
  2665                  move_right;
       
  2666                  jmp start;
       
  2667               TLabel exit)
       
  2668            "
       
  2669 
       
  2670 definition [asmb]: 
       
  2671        "bone c1 c2 = (TL exit l_one.
       
  2672                                 if_one l_one;
       
  2673                                   (c1;
       
  2674                                    jmp exit);
       
  2675                                 TLabel l_one;
       
  2676                                       c2;
       
  2677                                 TLabel exit
       
  2678                               )"
       
  2679 
       
  2680 definition [asmb]: 
       
  2681              "cfill_until_one = (TL start exit.
       
  2682                                 TLabel start;
       
  2683                                   if_one exit;
       
  2684                                   write_one;
       
  2685                                   move_left;
       
  2686                                   jmp start;
       
  2687                                 TLabel exit
       
  2688                                )"
       
  2689 
       
  2690 definition [asmb]:
       
  2691           "cmove = (TL start exit.
       
  2692                        TLabel start;
       
  2693                          left_until_zero;
       
  2694                          left_until_one;
       
  2695                          move_left;
       
  2696                          if_zero exit;
       
  2697                          move_right;
       
  2698                          write_zero;
       
  2699                          right_until_one;
       
  2700                          right_until_zero;
       
  2701                          write_one;
       
  2702                          jmp start;
       
  2703                      TLabel exit
       
  2704                     )"
       
  2705 
       
  2706 definition [asmb]: 
       
  2707            "cinit = (right_until_zero; move_right; write_one)"
       
  2708 
       
  2709 definition [asmb]:
       
  2710            "copy = (cinit; cmove; move_right; move_right; right_until_one; 
       
  2711                move_left; move_left; cfill_until_one)"
       
  2712 
       
  2713 definition  
       
  2714          "bzero c1 c2 = (TL exit l_zero.
       
  2715                                 if_zero l_zero;
       
  2716                                   (c1;
       
  2717                                    jmp exit);
       
  2718                                 TLabel l_zero;
       
  2719                                       c2;
       
  2720                                 TLabel exit
       
  2721                               )"
       
  2722 
       
  2723 definition  "if_reps_nz e = (move_right;
       
  2724                               bzero (move_left; jmp e) (move_left)
       
  2725                            )"
       
  2726 
       
  2727 declare if_reps_nz_def[unfolded bzero_def, asmb]
       
  2728 
       
  2729 definition "if_reps_z e = (move_right;
       
  2730                               bone (move_left; jmp e) (move_left)
       
  2731                              )"
       
  2732 
       
  2733 declare if_reps_z_def [unfolded bone_def, asmb]
       
  2734 
       
  2735 definition 
       
  2736            "skip_or_set = bone (write_one; move_right; move_right)
       
  2737                                (right_until_zero; move_right)"
       
  2738 
       
  2739 declare skip_or_set_def[unfolded bone_def, asmb]
       
  2740 
       
  2741 definition "tpg_fold tpgs = foldr TSeq (butlast tpgs) (last tpgs)"
       
  2742 
       
  2743 definition "cpg_fold cpgs = foldr CSeq (butlast cpgs) (last cpgs)"
       
  2744 
       
  2745 definition "skip_or_sets n = tpg_fold (replicate n skip_or_set)"
       
  2746 
       
  2747 definition "skip_or_sets_skel n = cpg_fold (replicate n skip_or_set_skel)"
       
  2748 
       
  2749 lemma c2t_skip_or_sets_skel: 
       
  2750     "c2t [] (skip_or_sets_skel (Suc n)) = skip_or_sets (Suc n)"
       
  2751 proof(induct n)
       
  2752   case (Suc k)
       
  2753   thus ?case 
       
  2754     apply (unfold skip_or_sets_skel_def cpg_fold_def skip_or_sets_def tpg_fold_def)
       
  2755     my_block
       
  2756       fix x k
       
  2757       have "(last (replicate (Suc k) x)) = x"
       
  2758         by (metis Suc_neq_Zero last_replicate)
       
  2759     my_block_end
       
  2760     apply (unfold this)
       
  2761     my_block
       
  2762       fix x k
       
  2763       have "(butlast (replicate (Suc k) x)) = replicate k x"
       
  2764         by (metis butlast_snoc replicate_Suc replicate_append_same)
       
  2765     my_block_end
       
  2766     apply (unfold this)
       
  2767     my_block
       
  2768       fix x k f y
       
  2769       have "foldr f (replicate (Suc k) x) y =  f x (foldr f (replicate k x) y)"
       
  2770         by simp
       
  2771     my_block_end
       
  2772     apply (unfold this)
       
  2773     by (simp add:c2t_skip_or_set_skel)
       
  2774 next
       
  2775   case 0
       
  2776   show ?case
       
  2777    by (simp add:skip_or_sets_skel_def cpg_fold_def skip_or_sets_def tpg_fold_def
       
  2778              c2t_skip_or_set_skel)
       
  2779 qed
       
  2780 
       
  2781 lemma wf_skip_or_sets_skel: 
       
  2782     "wf_cpg_test [] (skip_or_sets_skel (Suc n)) = (True, [])"
       
  2783 proof(induct n)
       
  2784   case (Suc k)
       
  2785   thus ?case
       
  2786    apply (unfold skip_or_sets_skel_def cpg_fold_def)
       
  2787     my_block
       
  2788       fix x k
       
  2789       have "(last (replicate (Suc k) x)) = x"
       
  2790         by (metis Suc_neq_Zero last_replicate)
       
  2791     my_block_end
       
  2792     apply (unfold this)
       
  2793     my_block
       
  2794       fix x k
       
  2795       have "(butlast (replicate (Suc k) x)) = replicate k x"
       
  2796         by (metis butlast_snoc replicate_Suc replicate_append_same)
       
  2797     my_block_end
       
  2798     apply (unfold this)
       
  2799     my_block
       
  2800       fix x k f y
       
  2801       have "foldr f (replicate (Suc k) x) y =  f x (foldr f (replicate k x) y)"
       
  2802         by simp
       
  2803     my_block_end
       
  2804     apply (unfold this)
       
  2805     by (simp add:wf_skip_or_set_skel)
       
  2806 next
       
  2807   case 0
       
  2808   thus ?case
       
  2809     apply (unfold skip_or_sets_skel_def cpg_fold_def)
       
  2810     by (simp add:wf_skip_or_set_skel)
       
  2811 qed
       
  2812 
       
  2813 lemma asmb_skip_or_sets: 
       
  2814    "\<forall>i. \<exists>j s. (i :[ skip_or_sets (Suc n) ]: j) s"
       
  2815   by (rule wf_c2t_combined[OF wf_skip_or_sets_skel c2t_skip_or_sets_skel], auto)
       
  2816 
       
  2817 definition [asmb]: "locate n = (skip_or_sets (Suc n);
       
  2818                         move_left;
       
  2819                         move_left;
       
  2820                         left_until_zero;
       
  2821                         move_right
       
  2822                        )"
       
  2823 
       
  2824 definition [asmb]: "Inc a = locate a; 
       
  2825                     right_until_zero; 
       
  2826                     move_right;
       
  2827                     shift_right;
       
  2828                     move_left;
       
  2829                     left_until_double_zero;
       
  2830                     write_one;
       
  2831                     left_until_double_zero;
       
  2832                     move_right;
       
  2833                     move_right
       
  2834                     "
       
  2835 
       
  2836 definition [asmb]: "Dec a e  = (TL continue. 
       
  2837                           (locate a; 
       
  2838                            if_reps_nz continue;
       
  2839                            left_until_double_zero;
       
  2840                            move_right;
       
  2841                            move_right;
       
  2842                            jmp e);
       
  2843                           (TLabel continue;
       
  2844                            right_until_zero; 
       
  2845                            move_left;
       
  2846                            write_zero;
       
  2847                            move_right;
       
  2848                            move_right;
       
  2849                            shift_left;
       
  2850                            move_left;
       
  2851                            move_left;
       
  2852                            move_left;
       
  2853                            left_until_double_zero;
       
  2854                            move_right;
       
  2855                            move_right))"
       
  2856 
       
  2857 end