| Proc_CFG_WhileBody: "[c' ⊨ n -et→p n'; n ≠ Entry; n' ≠ Exit] ==> while (b) c' ⊨ n ⊕ 2 -et→p n' ⊕ 2"
| Proc_CFG_WhileBodyExit: "[c' ⊨ n -et→p Exit; n ≠ Entry]==> while (b) c' ⊨ n ⊕ 2 -et→p Label 0"
| Proc_CFG_Call: "Call p es rets ⊨ Label 0 -CEdge (p,es,rets)→p Label 1"
| Proc_CFG_CallSkip: "Call p es rets ⊨ Label 1 -IEdge ⇑id→p Exit"
subsubsection‹Some lemmas about the procedure CFG›
lemma Proc_CFG_Exit_no_sourcenode [dest]: "prog ⊨ Exit -et→p n' ==> False" by(induct prog n≡"Exit" et n' rule:Proc_CFG.induct,auto)
lemma Proc_CFG_Entry_no_targetnode [dest]: "prog ⊨ n -et→p Entry ==> False" by(induct prog n et n'≡"Entry" rule:Proc_CFG.induct,auto)
lemma Proc_CFG_IEdge_intra_kind: "prog ⊨ n -IEdge et→p n' ==> intra_kind et" by(induct prog n x≡"IEdge et" n' rule:Proc_CFG.induct,auto simp:intra_kind_def)
lemma [dest]:"prog ⊨ n -IEdge (Q:r↪fs)→p n' ==> False" by(fastforce dest:Proc_CFG_IEdge_intra_kind simp:intra_kind_def)
lemma [dest]:"prog ⊨ n -IEdge (Q↩f)→p n' ==> False" by(fastforce dest:Proc_CFG_IEdge_intra_kind simp:intra_kind_def)
lemma Proc_CFG_sourcelabel_less_num_nodes: "prog ⊨ Label l -et→p n' ==> l < #:prog" proof(induct prog "Label l" et n' arbitrary:l rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 et n' c2 l) thus ?caseby simp next case (Proc_CFG_SeqConnect c1 et c2 l) thus ?caseby simp next case (Proc_CFG_SeqSecond c2 n et n' c1 l) note n = ‹n ⊕ #:c1 = Label l› note IH = ‹∧l. n = Label l ==> l < #:c2› from n obtain l' where l':"n = Label l'"by(cases n) auto from IH[OF this] have"l' < #:c2" . with n l' show ?caseby simp next case (Proc_CFG_CondThen c1 n et n' b c2 l) note n = ‹n ⊕ 1 = Label l› note IH = ‹∧l. n = Label l ==> l < #:c1› from n obtain l' where l':"n = Label l'"by(cases n) auto from IH[OF this] have"l' < #:c1" . with n l' show ?caseby simp next case (Proc_CFG_CondElse c2 n et n' b c1 l) note n = ‹n ⊕ (#:c1 + 1) = Label l› note IH = ‹∧l. n = Label l ==> l < #:c2› from n obtain l' where l':"n = Label l'"by(cases n) auto from IH[OF this] have"l' < #:c2" . with n l' show ?caseby simp next case (Proc_CFG_WhileBody c' n et n' b l) note n = ‹n ⊕ 2 = Label l› note IH = ‹∧l. n = Label l ==> l < #:c'› from n obtain l' where l':"n = Label l'"by(cases n) auto from IH[OF this] have"l' < #:c'" . with n l' show ?caseby simp next case (Proc_CFG_WhileBodyExit c' n et b l) note n = ‹n ⊕ 2 = Label l› note IH = ‹∧l. n = Label l ==> l < #:c'› from n obtain l' where l':"n = Label l'"by(cases n) auto from IH[OF this] have"l' < #:c'" . with n l' show ?caseby simp qed (auto simp:num_inner_nodes_gr_0)
lemma Proc_CFG_targetlabel_less_num_nodes: "prog ⊨ n -et→p Label l ==> l < #:prog" proof(induct prog n et "Label l" arbitrary:l rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n et c2 l) thus ?caseby simp next case (Proc_CFG_SeqSecond c2 n et n' c1 l) note n' = ‹n' ⊕ #:c1 = Label l› note IH = ‹∧l. n' = Label l ==> l < #:c2› from n' obtain l' where l':"n' = Label l'"by(cases n') auto from IH[OF this] have"l' < #:c2" . with n' l' show ?caseby simp next case (Proc_CFG_CondThen c1 n et n' b c2 l) note n' = ‹n' ⊕ 1 = Label l› note IH = ‹∧l. n' = Label l ==> l < #:c1› from n' obtain l' where l':"n' = Label l'"by(cases n') auto from IH[OF this] have"l' < #:c1" . with n' l' show ?caseby simp next case (Proc_CFG_CondElse c2 n et n' b c1 l) note n' = ‹n' ⊕ (#:c1 + 1) = Label l› note IH = ‹∧l. n' = Label l ==> l < #:c2› from n' obtain l' where l':"n' = Label l'"by(cases n') auto from IH[OF this] have"l' < #:c2" . with n' l' show ?caseby simp next case (Proc_CFG_WhileBody c' n et n' b l) note n' = ‹n' ⊕ 2 = Label l› note IH = ‹∧l. n' = Label l ==> l < #:c'› from n' obtain l' where l':"n' = Label l'"by(cases n') auto from IH[OF this] have"l' < #:c'" . with n' l' show ?caseby simp qed (auto simp:num_inner_nodes_gr_0)
lemma Proc_CFG_EntryD: "prog ⊨ Entry -et→p n' ==> (n' = Exit ∧ et = IEdge(λs. False)\<surd>) ∨ (n' = Label 0 ∧ et = IEdge (λs. True)\<surd>)" by(induct prog n≡"Entry" et n' rule:Proc_CFG.induct,auto)
lemma Proc_CFG_Exit_edge: obtains l et where"prog ⊨ Label l -IEdge et→p Exit"and"l ≤ #:prog" proof(atomize_elim) show"∃l et. prog ⊨ Label l -IEdge et→p Exit ∧ l ≤ #:prog" proof(induct prog) case Skip have"Skip ⊨ Label 0 -IEdge ⇑id→p Exit"by(rule Proc_CFG_Skip) thus ?caseby fastforce next case (LAss V e) have"V:=e ⊨ Label 1 -IEdge ⇑id→p Exit"by(rule Proc_CFG_LAssSkip) thus ?caseby fastforce next case (Seq c1 c2) from‹∃l et. c2⊨ Label l -IEdge et→p Exit ∧ l ≤ #:c2› obtain l et where"c2⊨ Label l -IEdge et→p Exit"and"l ≤ #:c2"by blast hence"c1;;c2⊨ Label l ⊕ #:c1 -IEdge et→p Exit ⊕ #:c1" by(fastforce intro:Proc_CFG_SeqSecond) with‹l ≤ #:c2›show ?caseby fastforce next case (Cond b c1 c2) from‹∃l et. c1⊨ Label l -IEdge et→p Exit ∧ l ≤ #:c1› obtain l et where"c1⊨ Label l -IEdge et→p Exit"and"l ≤ #:c1"by blast hence"if (b) c1 else c2⊨ Label l ⊕ 1 -IEdge et→p Exit ⊕ 1" by(fastforce intro:Proc_CFG_CondThen) with‹l ≤ #:c1›show ?caseby fastforce next case (While b c') have"while (b) c' ⊨ Label 1 -IEdge ⇑id→p Exit"by(rule Proc_CFG_WhileFalseSkip) thus ?caseby fastforce next case (Call p es rets) have"Call p es rets ⊨ Label 1 -IEdge ⇑id→p Exit"by(rule Proc_CFG_CallSkip) thus ?caseby fastforce qed qed
text‹Lots of lemmas for call edges ‹…››
lemma Proc_CFG_Call_Labels: "prog ⊨ n -CEdge (p,es,rets)→p n' ==>∃l. n = Label l ∧ n' = Label (Suc l)" by(induct prog n et≡"CEdge (p,es,rets)" n' rule:Proc_CFG.induct,auto)
lemma Proc_CFG_Call_target_0: "prog ⊨ n -CEdge (p,es,rets)→p Label 0 ==> n = Entry" by(induct prog n et≡"CEdge (p,es,rets)" n'≡"Label 0" rule:Proc_CFG.induct)
(auto dest:Proc_CFG_Call_Labels)
lemma Proc_CFG_Call_Intra_edge_not_same_source: "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n -IEdge et→p n'']==> False" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n -IEdge et→p n'' ==> False› from‹c1;;c2⊨ n -IEdge et→p n''›‹c1⊨ n -CEdge (p, es, rets)→p n'› ‹n' ≠ Exit› obtain nx where"c1⊨ n -IEdge et→p nx" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG_Entry_Exit Proc_CFG_Entry) by(case_tac n)(auto dest:Proc_CFG_sourcelabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n -IEdge et→p n'' ==> False› from‹c1;;c2⊨ n ⊕ #:c1 -IEdge et→p n''›‹c2⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c2⊨ n -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n) apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) apply(cases n) apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(cases n,auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n -IEdge et→p n'' ==> False› from‹if (b) c1 else c2⊨ n ⊕ 1 -IEdge et→p n''›‹c1⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c1⊨ n -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n) apply auto apply(case_tac n) apply auto apply(cases n) apply auto by(case_tac n)(auto dest:Proc_CFG_sourcelabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n -IEdge et→p n'' ==> False› from‹if (b) c1 else c2⊨ n ⊕ #:c1 + 1 -IEdge et→p n''›‹c2⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c2⊨ n -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n) apply auto apply(case_tac n) apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(cases n,auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n -IEdge et→p n'' ==> False› from‹while (b) c' ⊨ n ⊕ 2 -IEdge et→p n''›‹c' ⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry›‹n' ≠ Exit› obtain nx where"c' ⊨ n -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(drule label_incr_ge[OF sym]) apply simp apply(cases n) apply auto apply(case_tac n) apply auto by(cases n,auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBodyExit c' n b) from‹c' ⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case Proc_CFG_Call from‹Call p es rets ⊨ Label 0 -IEdge et→p n''› show ?caseby(fastforce elim:Proc_CFG.cases) qed
lemma Proc_CFG_Call_Intra_edge_not_same_target: "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n'' -IEdge et→p n']==> False" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n'' -IEdge et→p n' ==> False› from‹c1;;c2⊨ n'' -IEdge et→p n'›‹c1⊨ n -CEdge (p, es, rets)→p n'› ‹n' ≠ Exit› have"c1⊨ n'' -IEdge et→p n'" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG_Entry dest:Proc_CFG_targetlabel_less_num_nodes) by(case_tac n')(auto dest:Proc_CFG_targetlabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n'' -IEdge et→p n' ==> False› from‹c1;;c2⊨ n'' -IEdge et→p n' ⊕ #:c1›‹c2⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c2⊨ nx -IEdge et→p n'" apply - apply(erule Proc_CFG.cases,auto) apply(fastforce intro:Proc_CFG_Entry_Exit) apply(cases n') apply(auto dest:Proc_CFG_targetlabel_less_num_nodes) apply(cases n') apply(auto dest:Proc_CFG_Call_target_0) apply(cases n') apply(auto dest:Proc_CFG_Call_Labels) by(case_tac n') auto thenshow ?caseby (rule IH) next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n'' -IEdge et→p n' ==> False› from‹if (b) c1 else c2⊨ n'' -IEdge et→p n' ⊕ 1›‹c1⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c1⊨ nx -IEdge et→p n'" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply(auto intro:Proc_CFG_Entry_Exit) apply(cases n') apply(auto dest:Proc_CFG_Call_target_0) apply(cases n') apply(auto dest:Proc_CFG_targetlabel_less_num_nodes) apply(cases n') apply auto apply(case_tac n') apply auto apply(cases n') apply auto apply(case_tac n') apply(auto dest:Proc_CFG_targetlabel_less_num_nodes) by(case_tac n')(auto dest:Proc_CFG_Call_Labels) thenshow ?caseby (rule IH) next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n'' -IEdge et→p n' ==> False› from‹if (b) c1 else c2⊨ n'' -IEdge et→p n' ⊕ #:c1 + 1›‹c2⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry› obtain nx where"c2⊨ nx -IEdge et→p n'" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply(auto intro:Proc_CFG_Entry_Exit) apply(cases n') apply(auto dest:Proc_CFG_Call_target_0) apply(cases n') apply(auto dest:Proc_CFG_Call_target_0) apply(cases n') apply auto apply(case_tac n') apply(auto dest:Proc_CFG_targetlabel_less_num_nodes) apply(case_tac n') apply(auto dest:Proc_CFG_Call_Labels) by(cases n',auto,case_tac n',auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n'' -IEdge et→p n' ==> False› from‹while (b) c' ⊨ n'' -IEdge et→p n' ⊕ 2›‹c' ⊨ n -CEdge (p, es, rets)→p n'› ‹n ≠ Entry›‹n' ≠ Exit› obtain nx where"c' ⊨ nx -IEdge et→p n'" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply(auto dest:Proc_CFG_Call_target_0) apply(cases n') apply auto by(cases n',auto,case_tac n',auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBodyExit c' n b) from‹c' ⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case Proc_CFG_Call from‹Call p es rets ⊨ n'' -IEdge et→p Label 1› show ?caseby(fastforce elim:Proc_CFG.cases) qed
lemma Proc_CFG_Call_nodes_eq: "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n -CEdge (p',es',rets')→p n''] ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n -CEdge (p',es',rets')→p n'' ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹c1;; c2⊨ n -CEdge (p',es',rets')→p n''›‹c1⊨ n -CEdge (p,es,rets)→p n'› have"c1⊨ n -CEdge (p',es',rets')→p n''" apply - apply(erule Proc_CFG.cases,auto) apply(fastforce dest:Proc_CFG_Call_Labels) by(case_tac n,(fastforce dest:Proc_CFG_sourcelabel_less_num_nodes)+) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p,es,rets)→p Exit›have False by(fastforce dest:Proc_CFG_Call_Labels) thus ?caseby simp next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n -CEdge (p',es',rets')→p n'' ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹c1;;c2⊨ n ⊕ #:c1 -CEdge (p',es',rets')→p n''›‹n ≠ Entry› obtain nx where edge:"c2⊨ n -CEdge (p',es',rets')→p nx"and nx:"nx ⊕ #:c1 = n''" apply - apply(erule Proc_CFG.cases,auto) by(cases n,auto dest:Proc_CFG_sourcelabel_less_num_nodes label_incr_inj)+ from edge have"n' = nx ∧ p = p' ∧ es = es' ∧ rets = rets'"by (rule IH) with nx show ?caseby auto next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n -CEdge (p',es',rets')→p n'' ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹if (b) c1 else c2⊨ n ⊕ 1 -CEdge (p',es',rets')→p n''› obtain nx where"c1⊨ n -CEdge (p',es',rets')→p nx ∧ nx ⊕ 1 = n''" proof(rule Proc_CFG.cases) fix c2' nx etx nx' bx c1' assume"if (b) c1 else c2 = if (bx) c1' else c2'" and"n ⊕ 1 = nx ⊕ #:c1' + 1"and"nx ≠ Entry" with‹c1⊨ n -CEdge (p,es,rets)→p n'›obtain l where"n = Label l"and"l ≥ #:c1" by(cases n,auto,cases nx,auto) with‹c1⊨ n -CEdge (p,es,rets)→p n'›have False by(fastforce dest:Proc_CFG_sourcelabel_less_num_nodes) thus ?thesis by simp qed (auto dest:label_incr_inj) thenobtain nx where edge:"c1⊨ n -CEdge (p',es',rets')→p nx" and nx:"nx ⊕ 1 = n''"by blast from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n -CEdge (p',es',rets')→p n'' ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹if (b) c1 else c2⊨ n ⊕ #:c1 + 1 -CEdge (p',es',rets')→p n''› obtain nx where"c2⊨ n -CEdge (p',es',rets')→p nx ∧ nx ⊕ #:c1 + 1 = n''" proof(rule Proc_CFG.cases) fix c1' nx etx nx' bx c2' assume ifs:"if (b) c1 else c2 = if (bx) c1' else c2'" and"n ⊕ #:c1 + 1 = nx ⊕ 1"and"nx ≠ Entry" and edge:"c1' ⊨ nx -etx→p nx'" thenobtain l where"nx = Label l"and"l ≥ #:c1" by(cases n,auto,cases nx,auto) with edge ifs have False by(fastforce dest:Proc_CFG_sourcelabel_less_num_nodes) thus ?thesis by simp qed (auto dest:label_incr_inj) thenobtain nx where edge:"c2⊨ n -CEdge (p',es',rets')→p nx" and nx:"nx ⊕ #:c1 + 1 = n''" by blast from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n -CEdge (p',es',rets')→p n'' ==> n' = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹while (b) c' ⊨ n ⊕ 2 -CEdge (p',es',rets')→p n''› obtain nx where"c' ⊨ n -CEdge (p',es',rets')→p nx ∧ nx ⊕ 2 = n''" by(rule Proc_CFG.cases,auto dest:label_incr_inj Proc_CFG_Call_Labels) thenobtain nx where edge:"c' ⊨ n -CEdge (p',es',rets')→p nx" and nx:"nx ⊕ 2 = n''"by blast from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_WhileBodyExit c' n b) from‹c' ⊨ n -CEdge (p,es,rets)→p Exit›have False by(fastforce dest:Proc_CFG_Call_Labels) thus ?caseby simp next case Proc_CFG_Call from‹Call p es rets ⊨ Label 0 -CEdge (p',es',rets')→p n''› have"p = p' ∧ es = es' ∧ rets = rets' ∧ n'' = Label 1" by(auto elim:Proc_CFG.cases) thenshow ?caseby simp qed
lemma Proc_CFG_Call_nodes_eq': "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n'' -CEdge (p',es',rets')→p n'] ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n'' -CEdge (p',es',rets')→p n' ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹c1;;c2⊨ n'' -CEdge (p',es',rets')→p n'›‹c1⊨ n -CEdge (p,es,rets)→p n'› have"c1⊨ n'' -CEdge (p',es',rets')→p n'" apply - apply(erule Proc_CFG.cases,auto) apply(fastforce dest:Proc_CFG_Call_Labels) by(case_tac n',auto dest:Proc_CFG_targetlabel_less_num_nodes Proc_CFG_Call_Labels) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p,es,rets)→p Exit›have False by(fastforce dest:Proc_CFG_Call_Labels) thus ?caseby simp next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n'' -CEdge (p',es',rets')→p n' ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹c1;;c2⊨ n'' -CEdge (p',es',rets')→p n' ⊕ #:c1› obtain nx where edge:"c2⊨ nx -CEdge (p',es',rets')→p n'"and nx:"nx ⊕ #:c1 = n''" apply - apply(erule Proc_CFG.cases,auto) by(cases n',
auto dest:Proc_CFG_targetlabel_less_num_nodes Proc_CFG_Call_Labels
label_incr_inj) from edge have"n = nx ∧ p = p' ∧ es = es' ∧ rets = rets'"by (rule IH) with nx show ?caseby auto next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n'' -CEdge (p',es',rets')→p n' ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹if (b) c1 else c2⊨ n'' -CEdge (p',es',rets')→p n' ⊕ 1› obtain nx where"c1⊨ nx -CEdge (p',es',rets')→p n' ∧ nx ⊕ 1 = n''" proof(cases) case (Proc_CFG_CondElse nx nx') from‹n' ⊕ 1 = nx' ⊕ #:c1 + 1› ‹c1⊨ n -CEdge (p,es,rets)→p n'› obtain l where"n' = Label l"and"l ≥ #:c1" by(cases n', auto dest:Proc_CFG_Call_Labels,cases nx',auto) with‹c1⊨ n -CEdge (p,es,rets)→p n'›have False by(fastforce dest:Proc_CFG_targetlabel_less_num_nodes) thus ?thesis by simp qed (auto dest:label_incr_inj) thenobtain nx where edge:"c1⊨ nx -CEdge (p',es',rets')→p n'" and nx:"nx ⊕ 1 = n''" by blast from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n'' -CEdge (p',es',rets')→p n' ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹if (b) c1 else c2⊨ n'' -CEdge (p',es',rets')→p n' ⊕ #:c1 + 1› obtain nx where"c2⊨ nx -CEdge (p',es',rets')→p n' ∧ nx ⊕ #:c1 + 1 = n''" proof(cases) case (Proc_CFG_CondThen nx nx') from‹n' ⊕ #:c1 + 1 = nx' ⊕ 1› ‹c1⊨ nx -CEdge (p',es',rets')→p nx'› obtain l where"nx' = Label l"and"l ≥ #:c1" by(cases n',auto,cases nx',auto dest:Proc_CFG_Call_Labels) with‹c1⊨ nx -CEdge (p',es',rets')→p nx'› have False by(fastforce dest:Proc_CFG_targetlabel_less_num_nodes) thus ?thesis by simp qed (auto dest:label_incr_inj) thenobtain nx where edge:"c2⊨ nx -CEdge (p',es',rets')→p n'" and nx:"nx ⊕ #:c1 + 1 = n''" by blast from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n'' -CEdge (p',es',rets')→p n' ==> n = n'' ∧ p = p' ∧ es = es' ∧ rets = rets'› from‹while (b) c' ⊨ n'' -CEdge (p',es',rets')→p n' ⊕ 2› obtain nx where edge:"c' ⊨ nx -CEdge (p',es',rets')→p n'"and nx:"nx ⊕ 2 = n''" by(rule Proc_CFG.cases,auto dest:label_incr_inj) from IH[OF edge] nx show ?caseby simp next case (Proc_CFG_WhileBodyExit c' n b) from‹c' ⊨ n -CEdge (p,es,rets)→p Exit› have False by(fastforce dest:Proc_CFG_Call_Labels) thus ?caseby simp next case Proc_CFG_Call from‹Call p es rets ⊨ n'' -CEdge (p',es',rets')→p Label 1› have"p = p' ∧ es = es' ∧ rets = rets' ∧ n'' = Label 0" by(auto elim:Proc_CFG.cases) thenshow ?caseby simp qed
lemma Proc_CFG_Call_targetnode_no_Call_sourcenode: "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n' -CEdge (p',es',rets')→p n''] ==> False" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n' -CEdge (p', es', rets')→p n'' ==> False› from‹c1;; c2⊨ n' -CEdge (p',es',rets')→p n''›‹c1⊨ n -CEdge (p,es,rets)→p n'› have"c1⊨ n' -CEdge (p',es',rets')→p n''" apply - apply(erule Proc_CFG.cases,auto) apply(fastforce dest:Proc_CFG_Call_Labels) by(case_tac n)(auto dest:Proc_CFG_targetlabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p,es,rets)→p Exit›have False by(fastforce dest:Proc_CFG_Call_Labels) thus ?caseby simp next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n' -CEdge (p', es', rets')→p n'' ==> False› from‹c1;; c2⊨ n' ⊕ #:c1 -CEdge (p', es', rets')→p n''›‹c2⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c2⊨ n' -CEdge (p',es',rets')→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) apply(fastforce dest:Proc_CFG_Call_Labels) by(cases n',auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n' -CEdge (p',es',rets')→p n'' ==> False› from‹if (b) c1 else c2⊨ n' ⊕ 1 -CEdge (p', es', rets')→p n''›‹c1⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c1⊨ n' -CEdge (p',es',rets')→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply auto apply(case_tac n) apply auto apply(cases n') apply auto by(case_tac n)(auto dest:Proc_CFG_targetlabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n' -CEdge (p',es',rets')→p n'' ==> False› from‹if (b) c1 else c2⊨ n' ⊕ #:c1 + 1 -CEdge (p', es', rets')→p n''› ‹c2⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c2⊨ n' -CEdge (p',es',rets')→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply auto apply(case_tac n) apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(cases n',auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n' -CEdge (p',es',rets')→p n'' ==> False› from‹while (b) c' ⊨ n' ⊕ 2 -CEdge (p', es', rets')→p n''›‹c' ⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c' ⊨ n' -CEdge (p',es',rets')→p nx" apply - apply(erule Proc_CFG.cases,auto) by(cases n',auto,case_tac n,auto)+ thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBodyExit c' n b) from‹c' ⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case Proc_CFG_Call from‹Call p es rets ⊨ Label 1 -CEdge (p', es', rets')→p n''› show ?caseby(fastforce elim:Proc_CFG.cases) qed
lemma Proc_CFG_Call_follows_id_edge: "[prog ⊨ n -CEdge (p,es,rets)→p n'; prog ⊨ n' -IEdge et→p n'']==> et = ⇑id" proof(induct prog n "CEdge (p,es,rets)" n' arbitrary:n'' rule:Proc_CFG.induct) case (Proc_CFG_SeqFirst c1 n n' c2) note IH = ‹∧n''. c1⊨ n' -IEdge et→p n'' ==> et = ⇑id› from‹c1;;c2⊨ n' -IEdge et→p n''›‹c1⊨ n -CEdge (p,es,rets)→p n'›‹n' ≠ Exit› obtain nx where"c1⊨ n' -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) by(case_tac n)(auto dest:Proc_CFG_targetlabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_SeqConnect c1 n c2) from‹c1⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case (Proc_CFG_SeqSecond c2 n n' c1) note IH = ‹∧n''. c2⊨ n' -IEdge et→p n'' ==> et = ⇑id› from‹c1;;c2⊨ n' ⊕ #:c1 -IEdge et→p n''›‹c2⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c2⊨ n' -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) apply(cases n') apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(cases n',auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_CondThen c1 n n' b c2) note IH = ‹∧n''. c1⊨ n' -IEdge et→p n'' ==> et = ⇑id› from‹if (b) c1 else c2⊨ n' ⊕ 1 -IEdge et→p n''›‹c1⊨ n -CEdge (p,es,rets)→p n'› ‹n ≠ Entry› obtain nx where"c1⊨ n' -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply auto apply(case_tac n) apply auto apply(cases n') apply auto by(case_tac n)(auto dest:Proc_CFG_targetlabel_less_num_nodes) thenshow ?caseby (rule IH) next case (Proc_CFG_CondElse c2 n n' b c1) note IH = ‹∧n''. c2⊨ n' -IEdge et→p n'' ==> et = ⇑id› from‹if (b) c1 else c2⊨ n' ⊕ #:c1 + 1 -IEdge et→p n''›‹c2⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c2⊨ n' -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply auto apply(case_tac n) apply(auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(cases n',auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBody c' n n' b) note IH = ‹∧n''. c' ⊨ n' -IEdge et→p n'' ==> et = ⇑id› from‹while (b) c' ⊨ n' ⊕ 2 -IEdge et→p n''›‹c' ⊨ n -CEdge (p,es,rets)→p n'› obtain nx where"c' ⊨ n' -IEdge et→p nx" apply - apply(erule Proc_CFG.cases,auto) apply(cases n') apply auto apply(cases n') apply auto apply(case_tac n) apply auto by(cases n',auto,case_tac n,auto) thenshow ?caseby (rule IH) next case (Proc_CFG_WhileBodyExit c' n et' b) from‹c' ⊨ n -CEdge (p, es, rets)→p Exit› show ?caseby(fastforce dest:Proc_CFG_Call_Labels) next case Proc_CFG_Call from‹Call p es rets ⊨ Label 1 -IEdge et→p n''›show ?case by(fastforce elim:Proc_CFG.cases) qed
lemma Proc_CFG_edge_det: "[prog ⊨ n -et→p n'; prog ⊨ n -et'→p n']==> et = et'" proof(induct rule:Proc_CFG.induct) case Proc_CFG_Entry_Exit thus ?caseby(fastforce dest:Proc_CFG_EntryD) next case Proc_CFG_Entry thus ?caseby(fastforce dest:Proc_CFG_EntryD) next case Proc_CFG_Skip thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_LAss thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_LAssSkip thus ?caseby(fastforce elim:Proc_CFG.cases) next case (Proc_CFG_SeqFirst c1 n et n' c2) note edge = ‹c1⊨ n -et→p n'› note IH = ‹c1⊨ n -et'→p n' ==> et = et'› from edge ‹n' ≠ Exit›obtain l where l:"n' = Label l"by (cases n') auto with edge have"l < #:c1"by(fastforce intro:Proc_CFG_targetlabel_less_num_nodes) with‹c1;;c2⊨ n -et'→p n'› l have"c1⊨ n -et'→p n'" by(fastforce elim:Proc_CFG.cases intro:Proc_CFG.intros dest:label_incr_ge) from IH[OF this] show ?case . next case (Proc_CFG_SeqConnect c1 n et c2) note edge = ‹c1⊨ n -et→p Exit› note IH = ‹c1⊨ n -et'→p Exit ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have"l < #:c1"by(fastforce intro: Proc_CFG_sourcelabel_less_num_nodes) with‹c1;;c2⊨ n -et'→p Label #:c1› l have"c1⊨ n -et'→p Exit" by(fastforce elim:Proc_CFG.cases
dest:Proc_CFG_targetlabel_less_num_nodes label_incr_ge) from IH[OF this] show ?case . next case (Proc_CFG_SeqSecond c2 n et n' c1) note edge = ‹c2⊨ n -et→p n'› note IH = ‹c2⊨ n -et'→p n' ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have"l < #:c2"by(fastforce intro:Proc_CFG_sourcelabel_less_num_nodes) with‹c1;;c2⊨ n ⊕ #:c1 -et'→p n' ⊕ #:c1› l have"c2⊨ n -et'→p n'" by -(erule Proc_CFG.cases,
(fastforce dest:Proc_CFG_sourcelabel_less_num_nodes label_incr_ge
dest!:label_incr_inj)+) from IH[OF this] show ?case . next case Proc_CFG_CondTrue thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_CondFalse thus ?caseby(fastforce elim:Proc_CFG.cases) next case (Proc_CFG_CondThen c1 n et n' b c2) note edge = ‹c1⊨ n -et→p n'› note IH = ‹c1⊨ n -et'→p n' ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have"l < #:c1"by(fastforce intro:Proc_CFG_sourcelabel_less_num_nodes) with‹if (b) c1 else c2⊨ n ⊕ 1 -et'→p n' ⊕ 1› l have"c1⊨ n -et'→p n'" by -(erule Proc_CFG.cases,(fastforce dest:label_incr_ge label_incr_inj)+) from IH[OF this] show ?case . next case (Proc_CFG_CondElse c2 n et n' b c1) note edge = ‹c2⊨ n -et→p n'› note IH = ‹c2⊨ n -et'→p n' ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have"l < #:c2"by(fastforce intro:Proc_CFG_sourcelabel_less_num_nodes) with‹if (b) c1 else c2⊨ n ⊕ (#:c1 + 1) -et'→p n' ⊕ (#:c1 + 1)› l have"c2⊨ n -et'→p n'" by -(erule Proc_CFG.cases,(fastforce dest:Proc_CFG_sourcelabel_less_num_nodes
label_incr_inj label_incr_ge label_incr_simp_rev)+) from IH[OF this] show ?case . next case Proc_CFG_WhileTrue thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_WhileFalse thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_WhileFalseSkip thus ?caseby(fastforce elim:Proc_CFG.cases) next case (Proc_CFG_WhileBody c' n et n' b) note edge = ‹c' ⊨ n -et→p n'› note IH = ‹c' ⊨ n -et'→p n' ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have less:"l < #:c'" by(fastforce intro:Proc_CFG_sourcelabel_less_num_nodes) from edge ‹n' ≠ Exit›obtain l' where l':"n' = Label l'"by (cases n') auto with edge have"l' < #:c'"by(fastforce intro:Proc_CFG_targetlabel_less_num_nodes) with‹while (b) c' ⊨ n ⊕ 2 -et'→p n' ⊕ 2› l less l' have"c' ⊨ n -et'→p n'" by(fastforce elim:Proc_CFG.cases dest:label_incr_start_Node_smaller) from IH[OF this] show ?case . next case (Proc_CFG_WhileBodyExit c' n et b) note edge = ‹c' ⊨ n -et→p Exit› note IH = ‹c' ⊨ n -et'→p Exit ==> et = et'› from edge ‹n ≠ Entry›obtain l where l:"n = Label l"by (cases n) auto with edge have"l < #:c'"by(fastforce intro:Proc_CFG_sourcelabel_less_num_nodes) with‹while (b) c' ⊨ n ⊕ 2 -et'→p Label 0› l have"c' ⊨ n -et'→p Exit" by -(erule Proc_CFG.cases,auto dest:label_incr_start_Node_smaller) from IH[OF this] show ?case . next case Proc_CFG_Call thus ?caseby(fastforce elim:Proc_CFG.cases) next case Proc_CFG_CallSkip thus ?caseby(fastforce elim:Proc_CFG.cases) qed
lemma WCFG_deterministic: "[prog ⊨ n1 -et1→p n1'; prog ⊨ n2 -et2→p n2'; n1 = n2; n1' ≠ n2'] ==>∃Q Q'. et1 = IEdge (Q)\<surd> ∧ et2 = IEdge (Q')\<surd> ∧ (∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))" proof(induct arbitrary:n2 n2' rule:Proc_CFG.induct) case (Proc_CFG_Entry_Exit prog) from‹prog ⊨ n2 -et2→p n2'›‹Entry = n2›‹Exit ≠ n2'› have"et2 = IEdge (λs. True)\<surd>"by(fastforce dest:Proc_CFG_EntryD) thus ?caseby simp next case (Proc_CFG_Entry prog) from‹prog ⊨ n2 -et2→p n2'›‹Entry = n2›‹Label 0 ≠ n2'› have"et2 = IEdge (λs. False)\<surd>"by(fastforce dest:Proc_CFG_EntryD) thus ?caseby simp next case Proc_CFG_Skip from‹Skip ⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Exit ≠ n2'› have False by(fastforce elim:Proc_CFG.cases) thus ?caseby simp next case (Proc_CFG_LAss V e) from‹V:=e ⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Label 1 ≠ n2'› have False by -(erule Proc_CFG.cases,auto) thus ?caseby simp next case (Proc_CFG_LAssSkip V e) from‹V:=e ⊨ n2 -et2→p n2'›‹Label 1 = n2›‹Exit ≠ n2'› have False by -(erule Proc_CFG.cases,auto) thus ?caseby simp next case (Proc_CFG_SeqFirst c1 n et n' c2) note IH = ‹∧n2 n2'. [c1⊨ n2 -et2→p n2'; n = n2; n' ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹c1;;c2⊨ n2 -et2→p n2'›‹c1⊨ n -et→p n'›‹n = n2›‹n' ≠ n2'› have"c1⊨ n2 -et2→p n2' ∨ (c1⊨ n2 -et2→p Exit ∧ n2' = Label #:c1)" apply hypsubst_thin apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros) by(case_tac n,auto dest:Proc_CFG_sourcelabel_less_num_nodes)+ thus ?case proof assume"c1⊨ n2 -et2→p n2'" from IH[OF this ‹n = n2›‹n' ≠ n2'›] show ?case . next assume"c1⊨ n2 -et2→p Exit ∧ n2' = Label #:c1" hence edge:"c1⊨ n2 -et2→p Exit"and n2':"n2' = Label #:c1"by simp_all from IH[OF edge ‹n = n2›‹n' ≠ Exit›] show ?case . qed next case (Proc_CFG_SeqConnect c1 n et c2) note IH = ‹∧n2 n2'. [c1⊨ n2 -et2→p n2'; n = n2; Exit ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹c1;;c2⊨ n2 -et2→p n2'›‹c1⊨ n -et→p Exit›‹n = n2›‹n ≠ Entry› ‹Label #:c1≠ n2'›have"c1⊨ n2 -et2→p n2' ∧ Exit ≠ n2'" apply hypsubst_thin apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros) by(case_tac n,auto dest:Proc_CFG_sourcelabel_less_num_nodes)+ from IH[OF this[THEN conjunct1] ‹n = n2› this[THEN conjunct2]] show ?case . next case (Proc_CFG_SeqSecond c2 n et n' c1) note IH = ‹∧n2 n2'. [c2⊨ n2 -et2→p n2'; n = n2; n' ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹c1;;c2⊨ n2 -et2→p n2'›‹c2⊨ n -et→p n'›‹n ⊕ #:c1 = n2› ‹n' ⊕ #:c1≠ n2'›‹n ≠ Entry› obtain nx where"c2⊨ n -et2→p nx ∧ nx ⊕ #:c1 = n2'" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros) apply(cases n,auto dest:Proc_CFG_sourcelabel_less_num_nodes) apply(cases n,auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(fastforce dest:label_incr_inj) with‹n' ⊕ #:c1≠ n2'›have edge:"c2⊨ n -et2→p nx"and neq:"n' ≠ nx" by auto from IH[OF edge _ neq] show ?caseby simp next case (Proc_CFG_CondTrue b c1 c2) from‹if (b) c1 else c2⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Label 1 ≠ n2'› show ?caseby -(erule Proc_CFG.cases,auto) next case (Proc_CFG_CondFalse b c1 c2) from‹if (b) c1 else c2⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Label (#:c1 + 1) ≠ n2'› show ?caseby -(erule Proc_CFG.cases,auto) next case (Proc_CFG_CondThen c1 n et n' b c2) note IH = ‹∧n2 n2'. [c1⊨ n2 -et2→p n2'; n = n2; n' ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹if (b) c1 else c2⊨ n2 -et2→p n2'›‹c1⊨ n -et→p n'›‹n ≠ Entry› ‹n ⊕ 1 = n2›‹n' ⊕ 1 ≠ n2'› obtain nx where"c1⊨ n -et2→p nx ∧ n' ≠ nx" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros simp del:One_nat_def) apply(drule label_incr_inj) apply(auto simp del:One_nat_def) apply(drule label_incr_simp_rev[OF sym]) by(case_tac na,auto dest:Proc_CFG_sourcelabel_less_num_nodes) from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?caseby simp next case (Proc_CFG_CondElse c2 n et n' b c1) note IH = ‹∧n2 n2'. [c2⊨ n2 -et2→p n2'; n = n2; n' ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹if (b) c1 else c2⊨ n2 -et2→p n2'›‹c2⊨ n -et→p n'›‹n ≠ Entry› ‹n ⊕ #:c1 + 1 = n2›‹n' ⊕ #:c1 + 1 ≠ n2'› obtain nx where"c2⊨ n -et2→p nx ∧ n' ≠ nx" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros simp del:One_nat_def) apply(drule label_incr_simp_rev) apply(case_tac na,auto,cases n,auto dest:Proc_CFG_sourcelabel_less_num_nodes) by(fastforce dest:label_incr_inj) from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?caseby simp next case (Proc_CFG_WhileTrue b c') from‹while (b) c' ⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Label 2 ≠ n2'› show ?caseby -(erule Proc_CFG.cases,auto) next case (Proc_CFG_WhileFalse b c') from‹while (b) c' ⊨ n2 -et2→p n2'›‹Label 0 = n2›‹Label 1 ≠ n2'› show ?caseby -(erule Proc_CFG.cases,auto) next case (Proc_CFG_WhileFalseSkip b c') from‹while (b) c' ⊨ n2 -et2→p n2'›‹Label 1 = n2›‹Exit ≠ n2'› show ?caseby -(erule Proc_CFG.cases,auto dest:label_incr_ge) next case (Proc_CFG_WhileBody c' n et n' b) note IH = ‹∧n2 n2'. [c' ⊨ n2 -et2→p n2'; n = n2; n' ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹while (b) c' ⊨ n2 -et2→p n2'›‹c' ⊨ n -et→p n'›‹n ≠ Entry› ‹n' ≠ Exit›‹n ⊕ 2 = n2›‹n' ⊕ 2 ≠ n2'› obtain nx where"c' ⊨ n -et2→p nx ∧ n' ≠ nx" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros) apply(fastforce dest:label_incr_ge[OF sym]) apply(fastforce dest:label_incr_inj) by(fastforce dest:label_incr_inj) from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?caseby simp next case (Proc_CFG_WhileBodyExit c' n et b) note IH = ‹∧n2 n2'. [c' ⊨ n2 -et2→p n2'; n = n2; Exit ≠ n2'] ==>∃Q Q'. et = IEdge (Q)\√∧ et2 = IEdge (Q')\√∧
(∀s. (Q s ⟶¬ Q' s) ∧ (Q' s ⟶¬ Q s))› from‹while (b) c' ⊨ n2 -et2→p n2'›‹c' ⊨ n -et→p Exit›‹n ≠ Entry› ‹n ⊕ 2 = n2›‹Label 0 ≠ n2'› obtain nx where"c' ⊨ n -et2→p nx ∧ Exit ≠ nx" apply - apply(erule Proc_CFG.cases) apply(auto intro:Proc_CFG.intros) apply(fastforce dest:label_incr_ge[OF sym]) by(fastforce dest:label_incr_inj) from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?caseby simp next case Proc_CFG_Call thus ?caseby -(erule Proc_CFG.cases,auto) next case Proc_CFG_CallSkip thus ?caseby -(erule Proc_CFG.cases,auto) qed
subsection‹And now: the interprocedural CFG›
subsubsection‹Statements containing calls›
text‹A procedure is a tuple composed of its name, its input and output variables
and its method body›
type_synonym proc = "(pname × vname list × vname list × cmd)" type_synonym procs = "proc list"
text‹‹containsCall› guarantees that a call to procedure p is in
a certain statement.›
declare conj_cong[fundef_cong]
function containsCall :: "procs ==> cmd ==> pname list ==> pname ==> bool" where"containsCall procs Skip ps p ⟷ False"
| "containsCall procs (V:=e) ps p ⟷ False"
| "containsCall procs (c1;;c2) ps p ⟷ containsCall procs c1 ps p ∨ containsCall procs c2 ps p"
| "containsCall procs (if (b) c1 else c2) ps p ⟷ containsCall procs c1 ps p ∨ containsCall procs c2 ps p"
| "containsCall procs (while (b) c) ps p ⟷ containsCall procs c ps p"
| "containsCall procs (Call q es' rets') ps p ⟷ p = q ∧ ps = [] ∨ (∃ins outs c ps'. ps = q#ps' ∧ (q,ins,outs,c) ∈ set procs ∧ containsCall procs c ps' p)" by pat_completeness auto termination containsCall by(relation "measures [λ(procs,c,ps,p). length ps, λ(procs,c,ps,p). size c]") auto
lemmas containsCall_induct[case_names Skip LAss Seq Cond While Call] =
containsCall.induct
lemma containsCallcases: "containsCall procs prog ps p ==> ps = [] ∧ containsCall procs prog ps p ∨ (∃q ins outs c ps'. ps = ps'@[q] ∧ (q,ins,outs,c) ∈ set procs ∧ containsCall procs c [] p ∧ containsCall procs prog ps' q)" proof(induct procs prog ps p rule:containsCall_induct) case (Call procs q es' rets' ps p) note IH = ‹∧x y z ps'. [ps = q#ps'; (q,x,y,z) ∈ set procs;
containsCall procs z ps' p] ==> ps' = [] ∧ containsCall procs z ps' p ∨
(∃qx ins outs c psx. ps' = psx@[qx] ∧ (qx,ins,outs,c) ∈ set procs ∧
containsCall procs c [] p ∧
containsCall procs z psx qx)› from‹containsCall procs (Call q es' rets') ps p› have"p = q ∧ ps = [] ∨ (∃ins outs c ps'. ps = q#ps' ∧ (q,ins,outs,c) ∈ set procs ∧ containsCall procs c ps' p)"by simp thus ?case proof assume assms:"p = q ∧ ps = []" hence"containsCall procs (Call q es' rets') ps p"by simp with assms show ?thesis by simp next assume"∃ins outs c ps'. ps = q#ps' ∧ (q,ins,outs,c) ∈ set procs ∧ containsCall procs c ps' p" thenobtain ins outs c ps' where"ps = q#ps'"and"(q,ins,outs,c) ∈ set procs" and"containsCall procs c ps' p"by blast from IH[OF this] have"ps' = [] ∧ containsCall procs c ps' p ∨ (∃qx insx outsx cx psx. ps' = psx @ [qx] ∧ (qx,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx [] p ∧ containsCall procs c psx qx)" . thus ?thesis proof assume assms:"ps' = [] ∧ containsCall procs c ps' p" have"containsCall procs (Call q es' rets') [] q"by simp with assms ‹ps = q#ps'›‹(q,ins,outs,c) ∈ set procs›show ?thesis by fastforce next assume"∃qx insx outsx cx psx. ps' = psx@[qx] ∧ (qx,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx [] p ∧ containsCall procs c psx qx" thenobtain qx insx outsx cx psx where"ps' = psx@[qx]"and"(qx,insx,outsx,cx) ∈ set procs" and"containsCall procs cx [] p" and"containsCall procs c psx qx"by blast from‹(q,ins,outs,c) ∈ set procs›‹containsCall procs c psx qx› have"containsCall procs (Call q es' rets') (q#psx) qx"by fastforce with‹ps' = psx@[qx]›‹ps = q#ps'›‹(qx,insx,outsx,cx) ∈ set procs› ‹containsCall procs cx [] p›show ?thesis by fastforce qed qed qed auto
lemma containsCallE: "[containsCall procs prog ps p; [ps = []; containsCall procs prog ps p]==> P procs prog ps p; ∧q ins outs c es' rets' ps'. [ps = ps'@[q]; (q,ins,outs,c) ∈ set procs; containsCall procs c [] p; containsCall procs prog ps' q] ==> P procs prog ps p]==> P procs prog ps p" by(auto dest:containsCallcases)
lemma containsCall_in_proc: "[containsCall procs prog qs q; (q,ins,outs,c) ∈ set procs; containsCall procs c [] p] ==> containsCall procs prog (qs@[q]) p" proof(induct procs prog qs q rule:containsCall_induct) case (Call procs qx esx retsx ps p') note IH = ‹∧x y z psx. [ps = qx#psx; (qx,x,y,z) ∈ set procs;
containsCall procs z psx p'; (p',ins,outs,c) ∈ set procs;
containsCall procs c [] p]==> containsCall procs z (psx@[p']) p› from‹containsCall procs (Call qx esx retsx) ps p'› have"p' = qx ∧ ps = [] ∨ (∃insx outsx cx psx. ps = qx#psx ∧ (qx,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx psx p')"by simp thus ?case proof assume assms:"p' = qx ∧ ps = []" with‹(p', ins, outs, c) ∈ set procs›‹containsCall procs c [] p› have"containsCall procs (Call qx esx retsx) [p'] p"by fastforce with assms show ?thesis by simp next assume"∃insx outsx cx psx. ps = qx#psx ∧ (qx,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx psx p'" thenobtain insx outsx cx psx where"ps = qx#psx" and"(qx,insx,outsx,cx) ∈ set procs" and"containsCall procs cx psx p'"by blast from IH[OF this ‹(p', ins, outs, c) ∈ set procs› ‹containsCall procs c [] p›] have"containsCall procs cx (psx @ [p']) p" . with‹ps = qx#psx›‹(qx,insx,outsx,cx) ∈ set procs› show ?thesis by fastforce qed qed auto
lemma containsCall_indirection: "[containsCall procs prog qs q; containsCall procs c ps p; (q,ins,outs,c) ∈ set procs] ==> containsCall procs prog (qs@q#ps) p" proof(induct procs prog qs q rule:containsCall_induct) case (Call procs px esx retsx ps' p') note IH = ‹∧x y z psx. [ps' = px # psx; (px, x, y, z) ∈ set procs;
containsCall procs z psx p'; containsCall procs c ps p;
(p', ins, outs, c) ∈ set procs] ==> containsCall procs z (psx @ p' # ps) p› from‹containsCall procs (Call px esx retsx) ps' p'› have"p' = px ∧ ps' = [] ∨ (∃insx outsx cx psx. ps' = px#psx ∧ (px,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx psx p')"by simp thus ?case proof assume"p' = px ∧ ps' = []" with‹containsCall procs c ps p›‹(p', ins, outs, c) ∈ set procs› show ?thesis by fastforce next assume"∃insx outsx cx psx. ps' = px#psx ∧ (px,insx,outsx,cx) ∈ set procs ∧ containsCall procs cx psx p'" thenobtain insx outsx cx psx where"ps' = px#psx" and"(px,insx,outsx,cx) ∈ set procs" and"containsCall procs cx psx p'"by blast from IH[OF this ‹containsCall procs c ps p› ‹(p', ins, outs, c) ∈ set procs›] have"containsCall procs cx (psx @ p' # ps) p" . with‹ps' = px#psx›‹(px,insx,outsx,cx) ∈ set procs› show ?thesis by fastforce qed qed auto
lemma Proc_CFG_Call_containsCall: "prog ⊨ n -CEdge (p,es,rets)→p n' ==> containsCall procs prog [] p" by(induct prog n et≡"CEdge (p,es,rets)" n' rule:Proc_CFG.induct,auto)
lemma containsCall_empty_Proc_CFG_Call_edge: assumes"containsCall procs prog [] p" obtains l es rets l' where"prog ⊨ Label l -CEdge (p,es,rets)→p Label l'" proof(atomize_elim) from‹containsCall procs prog [] p› show"∃l es rets l'. prog ⊨ Label l -CEdge (p,es,rets)→p Label l'" proof(induct procs prog ps≡"[]::pname list" p rule:containsCall_induct) case Seq thus ?case by auto(fastforce dest:Proc_CFG_SeqFirst,fastforce dest:Proc_CFG_SeqSecond) next case Cond thus ?case by auto(fastforce dest:Proc_CFG_CondThen,fastforce dest:Proc_CFG_CondElse) next case While thus ?caseby(fastforce dest:Proc_CFG_WhileBody) next case Call thus ?caseby(fastforce intro:Proc_CFG_Call) qed auto qed
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.