header {* \isaheader{Annotated Control Flow Paths} *} theory CFG = SafetyPolicy + AuxBox: section {* Annotated Control Flow Graphs *} consts enoughAn::"('prog \ 'pos \ ('pos\'form) list) \ 'prog \ ('prog \ 'pos \ 'form option) \ bool" locale CFG = SafetyPolicy + fixes domC:: "'prog \ 'pos list" fixes ipc:: "'prog \ 'pos" fixes anF:: "'prog \ ('pos \ 'form option)" fixes aF::"'prog \ 'pos \ 'form" defines "aF \ \ \ p. (case anF \ p of None \ \ | Some An \ An)" fixes domA:: "'prog \ 'pos list" defines "domA \ \ \. [pc\ domC \. (anF \ pc) \ None]" fixes succsF:: "'prog \ 'pos \ ('pos \ 'form) list" fixes wf::" 'prog \ bool" assumes wf_anF: "wf \ \ enoughAn succsF \ anF" fixes correctAn::"'prog \ bool" defines "correctAn \ \ \. \s \ Reachables \. \,s \ aF \ (fst s)" fixes saF::"'prog \ 'pos \ 'form" defines "saF \ \ \ p. \ [safeF \ p, aF \ p]" section {* Auxiliary definitions *} text {* This theory defines notions for paths and loops in a program. These are required to state the wellformedness condition wf Pi, which checks wether a program has at least one annotation per loop. *} subsection {* Index of list elements *} consts idx::"'a list \ 'a \ nat" primrec "idx [] a = 0" "idx (l#ls) a = (if l=a then 0 else Suc (idx ls a) )" subsection {* Paths *} text {* The set of all control flow paths of a given program *} consts paths::"('a \ ('a \ 'b) list) \ ('a list) set" inductive "(paths sc)" intros start: "\ (p',B) \ set (sc p) \ \ [p,p'] \ (paths sc)" step: "\ l@[p] \ (paths sc); (p',B) \ set (sc p) \ \ l@[p]@[p'] \ (paths sc)" (* deprecated consts paths::" 'prog \ ( 'prog \ 'pos \ ('pos \ 'form) list) \ ('pos list) set" inductive "(paths \ succsF')" intros start: "\ (pc',B) \ set (succsF' \ pc) \ \ [pc,pc'] \ (paths \ succsF')" step: "\ l@[pc]\ (paths \ succsF') ; (pc',B) \ set (succsF' \ pc) \ \ l@[pc]@[pc'] \ (paths \ succsF')" *) subsection {* Cycles *} text {* A path is a cycle if the first position equals the last position. *} constdefs isCycle::"('prog \ 'pos \ ('pos\'form) list) \ 'prog \ ('pos list) \ bool" "isCycle succsF \ l \ (l\ paths (succsF \) \ (hd l = last l))" constdefs noAnn::"'pos list \ ('pos \ 'form option) \ bool" "noAnn l pan \ (\ p. p\ set l \ pan p = None)" defs enoughAn_def: "enoughAn succsF \ an \ (\ l. isCycle succsF \ l \ \ (noAnn l (an \)))" constdefs noAnnOnWay::"('prog \ 'pos \ ('pos\'form) list) \ ('prog \ 'pos \ 'form option) \ 'prog \ 'pos \ 'pos \ bool" "noAnnOnWay succsF an \ pc pc' \ \ l. ((pc#l)@[pc'])\(paths (succsF \)) \ (noAnn (pc#l) (an \))" section {* Lemmas *} lemma idx_nth: "a\ set l \ l!(idx l a) = a" by (induct l, auto) lemma idx_not_nth: "a \ set l \ idx l a = length l" by (induct l, auto) lemma paths_append: "\ ps@(p#ps') \ paths (succsF \); ps \ []; ps' \ [] \ \ (p#ps') \ (paths (succsF \))" (*<*) apply (induct ps' rule: rev_induct) apply simp apply atomize apply (erule paths.elims) apply simp apply (case_tac "ps") apply simp apply simp apply simp apply (case_tac "xs") apply simp apply (rule paths.start) apply simp apply simp apply (rule_tac xs="list" in rev_cases) apply simp apply (subgoal_tac "([p]@[pa]@[p']) \ paths (succsF \)") prefer 2 apply (rule paths.step) apply simp apply simp apply simp apply simp apply (subgoal_tac "(p # a # ys) @ [pa] @ [p'] \ paths (succsF \)") prefer 2 apply (rule paths.step) apply simp apply simp apply simp done (*>*) lemma path_succsF: "\ l \ paths (succsF \); k+1 \ \B. (l!(k+1),B) \ set (succsF \ (l!k))" (*<*) apply (rotate_tac 1) apply (erule rev_mp) apply (rule_tac sc="succsF \" in paths.induct) apply assumption apply simp apply (rule impI) apply (rule_tac x="B" in exI) apply assumption apply (case_tac "k= length (la)") apply simp apply (rule_tac x="B" in exI) apply (simp add: nth_append) apply (case_tac "k + 1 = length la") apply (simp add: nth_append) apply (simp add: nth_append) done (*>*) lemma less_chain_simp: "\ \k. length l <= k+1 \ idx L (l!k) < idx L (l!(k+1)); 1 < length (l::'pos list) \ \ idx L (hd l) < idx L (last l)" (*<*) apply (erule rev_mp) apply (erule rev_mp) apply (induct l) apply simp apply (case_tac l) apply simp apply (case_tac list) apply simp apply (rule impI) apply (erule_tac x="0" in allE) apply simp apply (rule impI) apply (rule impI) apply hypsubst apply simp apply (rule conjI) apply (rule impI) apply simp apply (frule_tac x="0" and P="\ k. Suc (Suc 0) <= k \ (?Q k)" in spec) apply (frule_tac x="1" and P="\ k. Suc (Suc 0) <= k \ (?Q k)" in spec) apply simp apply (frule_tac x="0" and P="\ k. Suc (Suc (length lista)) <= k \ (?Q k)" in spec) apply simp apply (rule impI) apply simp apply (subgoal_tac "(\k. Suc (length lista) \ k \ idx L ((aa # ab # lista) ! k) < idx L ((ab # lista) ! k))") prefer 2 apply (rule allI) apply (case_tac "Suc (length lista) \ k") apply simp apply (erule_tac x="Suc k" in allE) apply simp apply simp done (*>*) lemma path_length: "\ l \ paths (succsF \) \ \ 1 < length l" (*<*) apply (rule_tac sc="succsF \" in paths.induct) apply assumption apply simp apply simp done (*>*) lemma loop_has_back_jump: "\ l \ paths (succsF \); hd l = last l \ \ \k. (k+1) idx L (l!(k+1)) <= idx L (l!k)" (*<*) apply (frule path_length) apply (rule classical) apply (simp only: not_ex) apply (simp only: de_Morgan_conj) apply (simp only: linorder_not_less linorder_not_le) apply (drule less_chain_simp) apply simp apply simp done (*>*) (*<*) lemma noAnn_ext: "\ noAnn l pan; pan p = None \ \ noAnn (l@[p]) pan" apply (unfold noAnn_def) apply (rule allI) apply (rule impI) apply (simp only: set_append) apply (case_tac "pa \ set l") apply (erule_tac x="pa" in allE) apply (drule mp) apply assumption apply assumption apply simp done (*>*) (*<*) lemma noAnn_conv: "noAnn V aF = (\ p \ set V. aF p = None)" apply (simp add: noAnn_def) apply blast done (*>*) end