header {* \isaheader{Extended Jinja Virtual Machine} *} theory JBC_Semantics = Form: (* changes the preprocessor for the simplifier, such that internally generated lemmas are augmented with proof objects *) setup {* [Simplifier.change_simpset_of op setmksimps (setmp proofs 2 (mksimps mksimps_pairs))] *} section {* States and Program Syntax *} record env = cs::"heap list" lv::"var \ val option" types jbc_state = "pos \ jvm_state \ env" types jbc_prog = "jvm_prog \ (pos ~~> expr)" subsection {* Auxiliary functions *} constdefs incA::"pos \ pos" "incA \ \(C,M,n). (C,M,n+1)" constdefs cmd::"jbc_prog \ pos \ instr option" "cmd \ \(P,A) (C,M,pc). case class P C of None \ None | Some c \ (case (map_of (snd (snd c)) M) of None \ None | Some m \ (let is=fst (snd (snd (snd (snd m)))) in (if pc < length is then Some (is!pc) else None)))" consts domMC::"(cname \ mname \ jvm_method) \ pos list" recdef domMC "measure (\x.0)" "domMC (C,M,(mxs,mxl,bd,et)) = map (\n. (C,M,n)) (upt 0 (length bd))" consts domCC::"jvm_method cdecl \ pos list" recdef domCC "measure (\(C,cd). length (snd (snd cd)))" "domCC (C,(C',fs,[])) = []" "domCC (C,(C',fs,(M,Ts,T,m)#ms)) = domMC (C,M,m) @ (domCC (C,(C',fs,ms)))" constdefs domC::"jbc_prog \ pos list" "domC \ \ concat (map domCC (fst \))" constdefs anF::"jbc_prog \ pos \ expr option" "anF \ \(P,An) p. An ? p" consts hasAn::"jbc_prog \ pos \ bool" defs hasAn_def [simp]: "hasAn \ p \ (case anF \ p of None \ False | Some a \ True)" constdefs aF::"jbc_prog \ pos \ expr" "aF \ p \ (case anF \ p of None \ TT | Some A \ A)" constdefs domA :: "jbc_prog \ pos list" "domA \ (\ \.[p\ domC \. hasAn \ p])" consts invokes::"instr option \ pos \ bool" recdef invokes "{}" --"invokes (ins,(C,M,p)) checks whether ins calls method M." "invokes (Some (Invoke Mn n),(C,M,pc)) = (Mn=M)" "invokes (instr,p) = False" constdefs callers::"jbc_prog \ pos \ pos list" "callers \ p \ [cp \ (domC \). invokes ((cmd \ cp),p)]" constdefs classnames ::"jvm_prog \ cname list" "classnames P \ map fst P" constdefs has_method::"jvm_prog \ cname \ mname \ bool" "has_method P C M \ (C,M) mem (methodnames P)" subsection {* Operational Semantics *} constdefs Start :: cname "Start \ ''Start''" main ::mname "main \ ''main''" constdefs ipc::"jbc_prog \ pos" "ipc P \ (Start,main,0)" section {* Transition Relation *} consts effS::"jbc_prog \ (jbc_state \ jbc_state) set" --{* Note: In case of an uncaught exception this semantics halts, whereas the JVM Semantics halts and empties the framestack. *} inductive "effS \" intros expt: "\ P = fst \; p = (C,M,pc); i = instrs_of P C M ! pc; \ = (None,h,(stk,loc,p)#frs); has_method P C M; exec_instr i P h stk loc C M pc frs = (Some xa,h',bla); find_handler P xa h ((stk,loc,p)#frs) = \'; \' = (None,h,([Addr xa],loc',p')#frs'); e' = e\cs:=drop (length frs - length frs') (cs e)\ \ \ ((p,\,e),(p',\',e')) \ effS \" nrml: "\ P = fst \; p = (C,M,pc); i = instrs_of P C M ! pc; \ = (None,h,(stk,loc,p)#frs); has_method P C M; exec_instr i P h stk loc C M pc frs = (None,h',fr'#frs'); \' = (None,h',fr' # frs'); p' = snd (snd fr'); e' = e\cs:=if \M n. i = Invoke M n then h#(cs e) else if i = Return then tl (cs e) else cs e\ \ \ ((p,\,e),(p',\',e')) \ effS \" constdefs initS ::"jbc_prog \ jbc_state set" "initS \ \ { (p,\,e) . p = ipc \ \ \ = start_state (fst \) (fst (ipc \)) (fst (snd (ipc \))) \ cs e = [] }" consts Reachables::"jbc_prog \ jbc_state set" inductive "Reachables \" intros init: "\ s \ initS \ \ \ s \ Reachables \" step: "\ s \ Reachables \; (s,s') \ effS \ \ \ s' \ Reachables \" section {* Auxiliary Lemmas *} lemma sees_field_class: "P \ Cl sees F:T in Cl' \ is_class P Cl" (*<*) apply (simp add: is_class_def) apply (drule has_visible_field) apply (simp only: has_field_def) apply (erule conjE | erule exE)+ apply (erule Fields.elims) apply fastsimp apply fastsimp done (*>*) lemma domCC_split: "domCC (C,(S,fs,ms@ms')) = domCC (C,(S,fs,ms)) @ domCC (C,(S,fs,ms'))" (*<*) apply (induct ms) apply (simp add: split_paired_all domCC.simps)+ done (*>*) lemma cmd_domC: "\p \ instr. cmd \ p = Some instr \ p\ set (domC \)" (*<*) apply (simp add: domC_def cmd_def domCC.simps split_def split_paired_all fst_conv snd_conv split add: split_if_asm) apply (rule_tac x="(a,ac,ad,ba)" in bexI) apply (drule map_of_SomeD) apply (simp add: domCC.simps in_set_conv_decomp) apply (erule exE)+ apply (simp add: domCC_split) apply (subgoal_tac "(upt 0 (length ai)) = (upt 0 b)@(upt b (length ai))") prefer 2 apply (subgoal_tac "\c. length ai = b + c") prefer 2 apply (rule_tac x="length ai - b" in exI) apply arith apply (erule exE) apply simp apply (rule upt_add_eq_append) apply simp apply (simp add: upt_conv_Cons) apply (rule_tac x="domCC (a, ac, ad, ys) @ map (\n. (a, aa, n)) (upt 0 b)" in exI) apply fastsimp apply (rule map_of_SomeD) apply (simp add: class_def) done (*>*) lemma domC_cmd: "p\ set (domC \) \ cmd \ p = None" (*<*) apply (rule classical) apply simp apply (erule exE) apply (drule cmd_domC) apply simp done (*>*) lemma domCC_split_parts: "(C,M,pc) \ set (domCC (C',S,Fs,Ms)) \ \ Ms' Ms'' Ts T mxs mxl is et. Ms = Ms' @ (M,Ts,T,(mxs,mxl,is,et)) # Ms'' \ (C,M,pc) \ set (domMC (C',M,mxs,mxl,is,et))" (*<*) apply (induct Ms) apply simp apply (simp add: split_paired_all domCC.simps) apply (erule disjE) apply (erule imageE) apply (rule_tac x="[]" in exI) apply (rule_tac x="Ms" in exI) apply fastsimp apply simp apply (erule exE | erule conjE)+ apply (rule_tac x="(a,aa,ab,ac,ad,ae,b)#Ms'" in exI) apply fastsimp done (*>*) lemma domCC_map: "domCC (C,C',fs,ms) = concat (map (\ (M,Ts,T,m). domMC (C,M,m)) ms)" (*<*) apply (induct ms) apply simp apply (simp add: split_paired_all) done (*>*) lemma domMC_props: "\ m. (C,M,pc) \ set (domMC (C',M',m)) \ C = C' \ M = M' \ pc < length (fst (snd (snd m)))" (*<*) apply (subgoal_tac "\ mxs mxr is et. m = (mxs,mxr,is,et)") prefer 2 apply (simp add: split_paired_all) apply (erule exE)+ apply (simp only: domMC.simps) apply (simp add: set_map) apply (erule imageE) apply simp done (*>*) lemma domA_simp: "domA = (\\. [pc\domC \. anF \ pc \ None])" (*<*) apply (rule ext) apply (simp add: domA_def) done (*>*) lemma effS_Reachables: "s \ Reachables \ = (\ s0. s0 \ initS \ \ (s0,s) \ (effS \)\<^sup>*)" (*<*) apply (rule iffI) -- {* if *} apply (erule Reachables.induct) apply (rule_tac x="s" in exI) apply simp apply (erule exE | erule conjE)+ apply (rule_tac x="s0" in exI) apply (rule conjI) apply assumption apply (rule_tac b="s" in rtrancl_into_rtrancl) apply assumption apply assumption --{* only if *} apply (erule exE | erule conjE)+ apply (erule rev_mp) apply (erule rtrancl.induct) apply (rule impI) apply (rule Reachables.init) apply assumption apply (rule impI) apply (rule Reachables.step) apply simp apply simp done (*>*) lemma check_inv: assumes wt:"wf_jvm_prog\<^isub>k P" assumes initial:"\ = start_state P C M \ (P \ C sees M:[]\T = m in C)" assumes reachable:"P \ \ -jvm\ \'" shows "check P \'" (*<*) proof - from wt have wf_P:"\ \. wf_jvm_prog\<^sub>\ P " by (simp add: jvm_kildall_correct wf_jvm_prog_def) from initial reachable show ?thesis proof - from wf_P obtain \ where wf_P': "wf_jvm_prog\<^sub>\ P" .. from this have state_ok: "P,\ \ \' \" proof (rule typesafe) from initial show "P \ C sees M: []\T = m in C" .. from initial reachable show "P \ start_state P C M -jvm\ \'" by simp qed from wf_P' this have "exec_d P \' \ TypeError" proof (rule no_type_error) qed from this show "check P \'" apply (simp add: exec_d_def split add: split_if_asm) done qed qed (*>*) end