thys/Hoare_tm.thy
changeset 12 457240e42972
parent 11 f8b2bf858caf
child 13 e6e412406a2d
equal deleted inserted replaced
11:f8b2bf858caf 12:457240e42972
    23   (val name = @{binding "fwd"}
    23   (val name = @{binding "fwd"}
    24    val description = "Theorems for fwd derivation of seperation implication")
    24    val description = "Theorems for fwd derivation of seperation implication")
    25 *}
    25 *}
    26 
    26 
    27 setup {* StepRules.setup *}
    27 setup {* StepRules.setup *}
    28 
       
    29 setup {* FwdRules.setup *}
    28 setup {* FwdRules.setup *}
    30 
    29 
    31 method_setup prune = 
    30 method_setup prune = 
    32   {* Scan.succeed (SIMPLE_METHOD' o (K (K prune_params_tac))) *} 
    31   {* Scan.succeed (SIMPLE_METHOD' o (K (K prune_params_tac))) *} 
    33   "pruning parameters"
    32   "pruning parameters"
   126  | TSeq tpg tpg
   125  | TSeq tpg tpg
   127  | TLocal "nat \<Rightarrow> tpg"
   126  | TLocal "nat \<Rightarrow> tpg"
   128 
   127 
   129 notation TLocal (binder "TL " 10)
   128 notation TLocal (binder "TL " 10)
   130 
   129 
   131 abbreviation tprog_instr :: "tm_inst \<Rightarrow> tpg" ("\<guillemotright> _" [61] 61)
   130 abbreviation 
       
   131   tprog_instr :: "tm_inst \<Rightarrow> tpg" ("\<guillemotright> _" [61] 61)
   132 where "\<guillemotright> i \<equiv> TInstr i"
   132 where "\<guillemotright> i \<equiv> TInstr i"
   133 
   133 
   134 abbreviation tprog_seq :: "tpg \<Rightarrow> tpg \<Rightarrow> tpg" (infixr ";" 52)
   134 abbreviation tprog_seq :: 
       
   135   "tpg \<Rightarrow> tpg \<Rightarrow> tpg" (infixr ";" 52)
   135 where "c1 ; c2 \<equiv> TSeq c1 c2"
   136 where "c1 ; c2 \<equiv> TSeq c1 c2"
   136 
   137 
   137 definition "sg e = (\<lambda> s. s = e)"
   138 definition "sg e = (\<lambda>s. s = e)"
   138 
   139 
   139 type_synonym tassert = "tresource set \<Rightarrow> bool"
   140 type_synonym tassert = "tresource set \<Rightarrow> bool"
   140 
   141 
   141 abbreviation t_hoare :: "tassert \<Rightarrow> tassert  \<Rightarrow> tassert \<Rightarrow> bool" ("(\<lbrace>(1_)\<rbrace>/ (_)/ \<lbrace>(1_)\<rbrace>)" 50)
   142 abbreviation 
   142   where "\<lbrace>p\<rbrace> c \<lbrace>q\<rbrace> == sep_exec.Hoare_gen tstep trset_of p c q"
   143   t_hoare :: "tassert \<Rightarrow> tassert  \<Rightarrow> tassert \<Rightarrow> bool" ("(\<lbrace>(1_)\<rbrace>/ (_)/ \<lbrace>(1_)\<rbrace>)" 50)
       
   144 where 
       
   145   "\<lbrace>p\<rbrace> c \<lbrace>q\<rbrace> == sep_exec.Hoare_gen tstep trset_of p c q"
   143 
   146 
   144 abbreviation it_hoare ::
   147 abbreviation it_hoare ::
   145   "('a::sep_algebra \<Rightarrow> tresource set \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> (tresource set \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
   148   "('a::sep_algebra \<Rightarrow> tresource set \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> (tresource set \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool"
   146       ("(1_).(\<lbrace>(1_)\<rbrace>/ (_)/ \<lbrace>(1_)\<rbrace>)" 50)
   149       ("(1_).(\<lbrace>(1_)\<rbrace>/ (_)/ \<lbrace>(1_)\<rbrace>)" 50)
   147 where "I. \<lbrace>P\<rbrace> c \<lbrace>Q\<rbrace> == sep_exec.IHoare tstep trset_of I P c Q"
   150 where "I. \<lbrace>P\<rbrace> c \<lbrace>Q\<rbrace> == sep_exec.IHoare tstep trset_of I P c Q"
   163 
   166 
   164 declare tassemble_to.simps [simp del]
   167 declare tassemble_to.simps [simp del]
   165 
   168 
   166 lemmas tasmp = tassemble_to.simps (2, 3, 4)
   169 lemmas tasmp = tassemble_to.simps (2, 3, 4)
   167 
   170 
   168 abbreviation tasmb_to :: "nat \<Rightarrow> tpg \<Rightarrow> nat \<Rightarrow> tassert" ("_ :[ _ ]: _" [60, 60, 60] 60)
   171 abbreviation 
   169   where "i :[ tpg ]: j \<equiv> tassemble_to tpg i j"
   172   tasmb_to :: "nat \<Rightarrow> tpg \<Rightarrow> nat \<Rightarrow> tassert" ("_ :[ _ ]: _" [60, 60, 60] 60)
       
   173   where 
       
   174   "i :[ tpg ]: j \<equiv> tassemble_to tpg i j"
   170 
   175 
   171 lemma EXS_intro: 
   176 lemma EXS_intro: 
   172   assumes h: "(P x) s"
   177   assumes h: "(P x) s"
   173   shows "(EXS x. P(x)) s"
   178   shows "(EXS x. P(x)) s"
   174   by (smt h pred_ex_def sep_conj_impl)
   179   by (smt h pred_ex_def sep_conj_impl)
   200   qed
   205   qed
   201 qed
   206 qed
   202 
   207 
   203 definition "tpg_fold tpgs = foldr TSeq (butlast tpgs) (last tpgs)"
   208 definition "tpg_fold tpgs = foldr TSeq (butlast tpgs) (last tpgs)"
   204 
   209 
   205 lemma tpg_fold_sg: "tpg_fold [tpg] = tpg"
   210 lemma tpg_fold_sg: 
       
   211   "tpg_fold [tpg] = tpg"
   206   by (simp add:tpg_fold_def)
   212   by (simp add:tpg_fold_def)
   207 
   213 
   208 lemma tpg_fold_cons: 
   214 lemma tpg_fold_cons: 
   209   assumes h: "tpgs \<noteq> []"
   215   assumes h: "tpgs \<noteq> []"
   210   shows "tpg_fold (tpg#tpgs) = (tpg; (tpg_fold tpgs))"
   216   shows "tpg_fold (tpg#tpgs) = (tpg; (tpg_fold tpgs))"
   350 
   356 
   351 subsection {* Assertions and program logic for this assembly language *}
   357 subsection {* Assertions and program logic for this assembly language *}
   352 
   358 
   353 definition "st l = sg (tpc_set l)"
   359 definition "st l = sg (tpc_set l)"
   354 definition "ps p = sg (tpos_set p)" 
   360 definition "ps p = sg (tpos_set p)" 
   355 definition "tm a v =sg ({TM a v})"
   361 definition "tm a v = sg ({TM a v})"
   356 definition "one i = tm i Oc"
   362 definition "one i = tm i Oc"
   357 definition "zero i= tm i Bk"
   363 definition "zero i= tm i Bk"
   358 definition "any i = (EXS v. tm i v)"
   364 definition "any i = (EXS v. tm i v)"
   359 
   365 
   360 declare trset_of.simps[simp del]
   366 declare trset_of.simps[simp del]
   361 
   367 
   362 lemma stimes_sgD: "(sg x ** q) s \<Longrightarrow> q (s - x) \<and> x \<subseteq> s"
   368 lemma stimes_sgD: 
       
   369   "(sg x \<and>* q) s \<Longrightarrow> q (s - x) \<and> x \<subseteq> s"
   363   apply(erule_tac sep_conjE)
   370   apply(erule_tac sep_conjE)
   364   apply(unfold set_ins_def sg_def)
   371   apply(unfold set_ins_def sg_def)
   365   by (metis Diff_Int2 Diff_Int_distrib2 Diff_Un Diff_cancel 
   372   by (metis Diff_Int Diff_cancel Diff_empty Un_Diff sup.cobounded1 sup_bot.left_neutral sup_commute)
   366     Diff_empty Diff_idemp Diff_triv Int_Diff Un_Diff 
   373   
   367     Un_Diff_cancel inf_commute inf_idem sup_bot_right sup_commute sup_ge2)
   374 lemma stD: 
   368 
   375   "(st i \<and>* r) (trset_of (ft, prog, i', pos, mem)) \<Longrightarrow> i' = i"
   369 lemma stD: "(st i ** r) (trset_of (ft, prog, i', pos, mem))
       
   370        \<Longrightarrow> i' = i"
       
   371 proof -
   376 proof -
   372   assume "(st i ** r) (trset_of (ft, prog, i', pos, mem))"
   377   assume "(st i \<and>* r) (trset_of (ft, prog, i', pos, mem))"
   373   from stimes_sgD [OF this[unfolded st_def], unfolded trset_of.simps]
   378   from stimes_sgD [OF this[unfolded st_def], unfolded trset_of.simps]
   374   have "tpc_set i \<subseteq> tprog_set prog \<union> tpc_set i' \<union> tpos_set pos \<union>  
   379   have "tpc_set i \<subseteq> tprog_set prog \<union> tpc_set i' \<union> tpos_set pos \<union>  
   375             tmem_set mem \<union> tfaults_set ft" by auto
   380             tmem_set mem \<union> tfaults_set ft" by auto
   376   thus ?thesis
   381   thus ?thesis
   377     by (unfold tpn_set_def, auto)
   382     by (unfold tpn_set_def, auto)
   378 qed
   383 qed
   379 
   384 
   380 lemma psD: "(ps p ** r) (trset_of (ft, prog, i', pos, mem))
   385 lemma psD: 
   381        \<Longrightarrow> pos = p"
   386   "(ps p \<and>* r) (trset_of (ft, prog, i', pos, mem)) \<Longrightarrow> pos = p"
   382 proof -
   387 proof -
   383   assume "(ps p ** r) (trset_of (ft, prog, i', pos, mem))"
   388   assume "(ps p ** r) (trset_of (ft, prog, i', pos, mem))"
   384   from stimes_sgD [OF this[unfolded ps_def], unfolded trset_of.simps]
   389   from stimes_sgD [OF this[unfolded ps_def], unfolded trset_of.simps]
   385   have "tpos_set p \<subseteq> tprog_set prog \<union> tpc_set i' \<union> 
   390   have "tpos_set p \<subseteq> tprog_set prog \<union> tpc_set i' \<union> 
   386                        tpos_set pos \<union> tmem_set mem \<union> tfaults_set ft"
   391                        tpos_set pos \<union> tmem_set mem \<union> tfaults_set ft"
   406     {TPos pos} \<union> {TM i n |i n. mem i = Some n} \<union> {TFaults ft}" by simp
   411     {TPos pos} \<union> {TM i n |i n. mem i = Some n} \<union> {TFaults ft}" by simp
   407   thus ?thesis by auto
   412   thus ?thesis by auto
   408 qed
   413 qed
   409 
   414 
   410 lemma t_hoare_seq: 
   415 lemma t_hoare_seq: 
   411   "\<lbrakk>\<And> i j. \<lbrace>st i ** p\<rbrace> i:[c1]:j \<lbrace>st j ** q\<rbrace>; 
   416   assumes a1: "\<And> i j. \<lbrace>st i \<and>* p\<rbrace> i:[c1]:j \<lbrace>st j \<and>* q\<rbrace>"
   412     \<And> j k. \<lbrace>st j ** q\<rbrace> j:[c2]:k \<lbrace>st k ** r\<rbrace>\<rbrakk> \<Longrightarrow>  \<lbrace>st i ** p\<rbrace> i:[(c1 ; c2)]:k \<lbrace>st k ** r\<rbrace>"
   417   and     a2: "\<And> j k. \<lbrace>st j ** q\<rbrace> j:[c2]:k \<lbrace>st k ** r\<rbrace>" 
   413 proof -
   418   shows "\<lbrace>st i \<and>* p\<rbrace> i:[(c1 ; c2)]:k \<lbrace>st k \<and>* r\<rbrace>"
   414   assume h: "\<And> i j. \<lbrace>st i ** p\<rbrace> i:[c1]:j \<lbrace>st j ** q\<rbrace>" 
   419 proof(subst tassemble_to.simps, rule tm.code_exI)
   415             "\<And> j k. \<lbrace>st j ** q\<rbrace> j:[c2]:k \<lbrace>st k ** r\<rbrace>"
   420   fix j'
   416   show "\<lbrace>st i ** p\<rbrace> i:[(c1 ; c2)]:k \<lbrace>st k ** r\<rbrace>"
   421   show "\<lbrace>st i \<and>* p\<rbrace>  i:[ c1 ]:j' \<and>* j':[ c2 ]:k \<lbrace>st k \<and>* r\<rbrace>"
   417   proof(subst tassemble_to.simps, rule tm.code_exI)
   422   proof(rule tm.composition)
   418     fix j'
   423     from a1 show "\<lbrace>st i \<and>* p\<rbrace>  i:[ c1 ]:j' \<lbrace>st j' \<and>* q\<rbrace>" by auto
   419     show "\<lbrace>st i \<and>* p\<rbrace>  i :[ c1 ]: j' \<and>* j' :[ c2 ]: k \<lbrace>st k \<and>* r\<rbrace>"
   424   next
   420     proof(rule tm.composition)
   425     from a2 show "\<lbrace>st j' \<and>* q\<rbrace>  j':[ c2 ]:k \<lbrace>st k \<and>* r\<rbrace>" by auto
   421       from h(1) show "\<lbrace>st i \<and>* p\<rbrace>  i :[ c1 ]: j' \<lbrace> st j' \<and>* q \<rbrace>" by auto
       
   422     next
       
   423       from h(2) show "\<lbrace>st j' \<and>* q\<rbrace>  j' :[ c2 ]: k \<lbrace>st k \<and>* r\<rbrace>" by auto
       
   424     qed
       
   425   qed
   426   qed
   426 qed
   427 qed
   427 
   428 
       
   429 
   428 lemma t_hoare_seq1:
   430 lemma t_hoare_seq1:
   429    "\<lbrakk>\<And>j'. \<lbrace>st i ** p\<rbrace> i:[c1]:j' \<lbrace>st j' ** q\<rbrace>;
   431   assumes a1: "\<And>j'. \<lbrace>st i \<and>* p\<rbrace> i:[c1]:j' \<lbrace>st j' \<and>* q\<rbrace>"
   430     \<And>j'. \<lbrace>st j' ** q\<rbrace> j':[c2]:k \<lbrace>st k' ** r\<rbrace>\<rbrakk> \<Longrightarrow>  
   432   assumes a2: "\<And>j'. \<lbrace>st j' \<and>* q\<rbrace> j':[c2]:k \<lbrace>st k' \<and>* r\<rbrace>"
   431            \<lbrace>st i ** p\<rbrace> i:[(c1 ; c2)]:k \<lbrace>st k' ** r\<rbrace>"
   433   shows "\<lbrace>st i \<and>* p\<rbrace> i:[(c1 ; c2)]:k \<lbrace>st k' \<and>* r\<rbrace>"
   432 proof -
   434 proof(subst tassemble_to.simps, rule tm.code_exI)
   433   assume h: "\<And>j'. \<lbrace>st i \<and>* p\<rbrace>  i :[ c1 ]: j' \<lbrace>st j' \<and>* q\<rbrace>" 
   435   fix j'
   434             "\<And>j'. \<lbrace>st j' \<and>* q\<rbrace>  j' :[ c2 ]: k \<lbrace>st k' \<and>* r\<rbrace>"
   436   show "\<lbrace>st i \<and>* p\<rbrace>  i:[ c1 ]:j' \<and>* j':[ c2 ]:k \<lbrace>st k' \<and>* r\<rbrace>"
   435   show "\<lbrace>st i \<and>* p\<rbrace>  i :[ (c1 ; c2) ]: k \<lbrace>st k' \<and>* r\<rbrace>"
   437   proof(rule tm.composition)
   436   proof(subst tassemble_to.simps, rule tm.code_exI)
   438     from a1 show "\<lbrace>st i \<and>* p\<rbrace>  i:[ c1 ]:j' \<lbrace>st j' \<and>* q\<rbrace>" by auto
   437     fix j'
   439   next
   438     show "\<lbrace>st i \<and>* p\<rbrace>  i :[ c1 ]: j' \<and>* j' :[ c2 ]: k \<lbrace>st k' \<and>* r\<rbrace>"
   440     from a2 show " \<lbrace>st j' \<and>* q\<rbrace>  j':[ c2 ]:k \<lbrace>st k' \<and>* r\<rbrace>" by auto
   439     proof(rule tm.composition)
       
   440       from h(1) show "\<lbrace>st i \<and>* p\<rbrace>  i :[ c1 ]: j' \<lbrace> st j' \<and>* q \<rbrace>" by auto
       
   441     next
       
   442       from h(2) show " \<lbrace>st j' \<and>* q\<rbrace>  j' :[ c2 ]: k \<lbrace>st k' \<and>* r\<rbrace>" by auto
       
   443     qed
       
   444   qed
   441   qed
   445 qed
   442 qed
   446 
   443 
   447 lemma t_hoare_seq2:
   444 lemma t_hoare_seq2:
   448  assumes h: "\<And>j. \<lbrace>st i ** p\<rbrace> i:[c1]:j \<lbrace>st k' \<and>* r\<rbrace>"
   445   assumes h: "\<And>j. \<lbrace>st i ** p\<rbrace> i:[c1]:j \<lbrace>st k' \<and>* r\<rbrace>"
   449  shows "\<lbrace>st i ** p\<rbrace> i:[(c1 ; c2)]:j \<lbrace>st k' ** r\<rbrace>"
   446   shows "\<lbrace>st i ** p\<rbrace> i:[(c1 ; c2)]:j \<lbrace>st k' ** r\<rbrace>"
   450   apply (unfold tassemble_to.simps, rule tm.code_exI)
   447   apply (unfold tassemble_to.simps, rule tm.code_exI)
   451   by (rule tm.code_extension, rule h)
   448   by (rule tm.code_extension, rule h)
   452 
   449 
   453 lemma t_hoare_local: 
   450 lemma t_hoare_local: 
   454   assumes h: "(\<And>l. \<lbrace>st i \<and>* p\<rbrace>  i :[ c l ]: j \<lbrace>st k \<and>* q\<rbrace>)"
   451   assumes h: "(\<And>l. \<lbrace>st i \<and>* p\<rbrace>  i :[ c l ]: j \<lbrace>st k \<and>* q\<rbrace>)"
   455   shows "\<lbrace>st i ** p\<rbrace> i:[TLocal c]:j \<lbrace>st k ** q\<rbrace>" using h
   452   shows "\<lbrace>st i ** p\<rbrace> i:[TLocal c]:j \<lbrace>st k ** q\<rbrace>" using h
   456   by (unfold tassemble_to.simps, intro tm.code_exI, simp)
   453   by (unfold tassemble_to.simps, intro tm.code_exI, simp)
   457 
   454 
   458 lemma t_hoare_label: 
   455 lemma t_hoare_label: 
   459       "(\<And>l. l = i \<Longrightarrow> \<lbrace>st l \<and>* p\<rbrace>  l :[ c l ]: j \<lbrace>st k \<and>* q\<rbrace>) \<Longrightarrow>
   456   assumes "\<And>l. l = i \<Longrightarrow> \<lbrace>st l \<and>* p\<rbrace>  l:[ c l ]:j \<lbrace>st k \<and>* q\<rbrace>"
   460              \<lbrace>st i \<and>* p \<rbrace> 
   457   shows "\<lbrace>st i \<and>* p\<rbrace> i:[(TLabel l; c l)]:j \<lbrace>st k \<and>* q\<rbrace>"
   461                i:[(TLabel l; c l)]:j
   458 using assms
   462              \<lbrace>st k \<and>* q\<rbrace>"
       
   463 by (unfold tassemble_to.simps, intro tm.code_exI tm.code_condI, clarify, auto)
   459 by (unfold tassemble_to.simps, intro tm.code_exI tm.code_condI, clarify, auto)
   464 
   460 
   465 primrec t_split_cmd :: "tpg \<Rightarrow> (tpg \<times> tpg option)"
   461 primrec t_split_cmd :: "tpg \<Rightarrow> (tpg \<times> tpg option)"
   466   where "t_split_cmd (\<guillemotright>inst) = (\<guillemotright>inst, None)" |
   462   where "t_split_cmd (\<guillemotright>inst) = (\<guillemotright>inst, None)" |
   467         "t_split_cmd (TLabel l) = (TLabel l, None)" |
   463         "t_split_cmd (TLabel l) = (TLabel l, None)" |
   468         "t_split_cmd (TSeq c1 c2) = (case (t_split_cmd c2) of
   464         "t_split_cmd (TSeq c1 c2) = (case (t_split_cmd c2) of
   469                                       (c21, Some c22) \<Rightarrow> (TSeq c1 c21, Some c22) |
   465                                       (c21, Some c22) \<Rightarrow> (TSeq c1 c21, Some c22) |
   470                                       (c21, None) \<Rightarrow> (c1, Some c21))" |
   466                                       (c21, None) \<Rightarrow> (c1, Some c21))" |
   471         "t_split_cmd (TLocal c) = (TLocal c, None)"
   467         "t_split_cmd (TLocal c) = (TLocal c, None)"
   472 
   468 
   473 definition "t_last_cmd tpg = (snd (t_split_cmd tpg))"
   469 definition "t_last_cmd tpg = snd (t_split_cmd tpg)"
   474 
   470 
   475 declare t_last_cmd_def [simp]
   471 declare t_last_cmd_def [simp]
   476 
   472 
   477 definition "t_blast_cmd tpg = (fst (t_split_cmd tpg))"
   473 definition "t_blast_cmd tpg = fst (t_split_cmd tpg)"
   478 
   474 
   479 declare t_blast_cmd_def [simp]
   475 declare t_blast_cmd_def [simp]
   480 
   476 
   481 lemma "t_last_cmd (c1; c2; (TLabel l)) = (Some (TLabel l))"
   477 lemma "t_last_cmd (c1; c2; TLabel l) = Some (TLabel l)"
   482   by simp
   478   by simp
   483 
   479 
   484 lemma "t_blast_cmd (c1; c2; TLabel l) = (c1; c2)"
   480 lemma "t_blast_cmd (c1; c2; TLabel l) = (c1; c2)"
   485   by simp
   481   by simp
   486 
   482 
   487 lemma t_split_cmd_eq:
   483 lemma t_split_cmd_eq:
   488   assumes "t_split_cmd c = (c1, Some c2)"
   484   assumes "t_split_cmd c = (c1, Some c2)"
   489   shows "(i:[c]:j) = (i:[(c1; c2)]:j)"
   485   shows "i:[c]:j = i:[(c1; c2)]:j"
   490   using assms
   486   using assms
   491 proof(induct c arbitrary: c1 c2 i j)
   487 proof(induct c arbitrary: c1 c2 i j)
   492   case (TSeq cx cy)
   488   case (TSeq cx cy)
   493   from `t_split_cmd (cx ; cy) = (c1, Some c2)`
   489   from `t_split_cmd (cx ; cy) = (c1, Some c2)`
   494   show ?case
   490   show ?case
   503         by (simp add:pred_ex_def, default, auto)
   499         by (simp add:pred_ex_def, default, auto)
   504     qed
   500     qed
   505 qed auto
   501 qed auto
   506 
   502 
   507 lemma t_hoare_label_last_pre: 
   503 lemma t_hoare_label_last_pre: 
   508   fixes l
       
   509   assumes h1: "t_split_cmd c = (c', Some (TLabel l))"
   504   assumes h1: "t_split_cmd c = (c', Some (TLabel l))"
   510   and h2: "l = j \<Longrightarrow> \<lbrace>p\<rbrace> i:[c']:j \<lbrace>q\<rbrace>"
   505   and h2: "l = j \<Longrightarrow> \<lbrace>p\<rbrace> i:[c']:j \<lbrace>q\<rbrace>"
   511   shows "\<lbrace>p\<rbrace> i:[c]:j \<lbrace>q\<rbrace>"
   506   shows "\<lbrace>p\<rbrace> i:[c]:j \<lbrace>q\<rbrace>"
   512 by (unfold t_split_cmd_eq[OF h1], 
   507 by (unfold t_split_cmd_eq[OF h1], 
   513     simp only:tassemble_to.simps sep_conj_cond, 
   508     simp only:tassemble_to.simps sep_conj_cond, 
   514     intro tm.code_exI tm.code_condI, insert h2, auto)
   509     intro tm.code_exI tm.code_condI, insert h2, auto)
   515 
   510 
   516 lemma t_hoare_label_last: 
   511 lemma t_hoare_label_last: 
   517   fixes l
       
   518   assumes h1: "t_last_cmd c = Some (TLabel l)"
   512   assumes h1: "t_last_cmd c = Some (TLabel l)"
   519   and h2: "l = j \<Longrightarrow> \<lbrace>p\<rbrace> i:[t_blast_cmd c]:j \<lbrace>q\<rbrace>"
   513   and h2: "l = j \<Longrightarrow> \<lbrace>p\<rbrace> i:[t_blast_cmd c]:j \<lbrace>q\<rbrace>"
   520   shows "\<lbrace>p\<rbrace> i:[c]:j \<lbrace>q\<rbrace>"
   514   shows "\<lbrace>p\<rbrace> i:[c]:j \<lbrace>q\<rbrace>"
   521 proof -
   515 proof -
   522     have "t_split_cmd c = (t_blast_cmd c, t_last_cmd c)"
   516     have "t_split_cmd c = (t_blast_cmd c, t_last_cmd c)"