theory Prompt_monad_extras imports Prompt_monad begin lemma All_bind_dom: "bind_dom (oc, f)" by (induction oc) (auto intro: bind.domintros; blast intro: bind.domintros)+ termination bind using All_bind_dom by auto lemma bind_induct[case_names Done Read_mem Read_reg Write_memv Excl_res Write_ea Barrier Footprint Write_reg Escape Fail Error Exception Internal]: fixes m :: "('a, 'e) outcome" and f :: "'a \ ('b, 'e) outcome" assumes "\a f. P (Done a) f" and "\rk addr sz k f. (\v m' opt. (m', opt) = k v \ P m' f) \ P (Read_mem (rk, addr, sz) k) f" and "\reg k f. (\v m' opt. (m', opt) = k v \ P m' f) \ P (Read_reg reg k) f" and "\val k f. (\v m' opt. (m', opt) = k v \ P m' f) \ P (Write_memv val k) f" and "\k f. (\v m' opt. (m', opt) = k v \ P m' f) \ P (Excl_res k) f" and "\wk addr sz m opt f. P m f \ P (Write_ea (wk, addr, sz) (m, opt)) f" and "\bk m opt f. P m f \ P (Barrier bk (m, opt)) f" and "\m opt f. P m f \ P (Footprint (m, opt)) f" and "\reg val m opt f. P m f \ P (Write_reg (reg, val) (m, opt)) f" and "\descr f. P (Escape descr) f" and "\descr f. P (Fail descr) f" and "\descr f. P (Error descr) f" and "\e f. P (Exception e) f" and "\i m opt f. P m f \ P (Internal i (m, opt)) f" shows "P m f" by (rule bind.induct[split_format (complete), OF assms]; blast) datatype event = (* Request to read memory *) Read_mem read_kind address_lifted nat memory_value (* Write is imminent, at address lifted, of size nat *) | Write_ea write_kind address_lifted nat (* Request the result of store-exclusive *) | Excl_res bool (* Request to write memory at last signalled address. Memory value should be 8 times the size given in ea signal *) | Write_memv memory_value bool (* Request a memory barrier *) | Barrier " barrier_kind " (* Tell the system to dynamically recalculate dependency footprint *) | Footprint (* Request to read register *) | Read_reg reg_name register_value (* Request to write register *) | Write_reg reg_name register_value | Internal " ( string option * (unit \ string)option) " inductive_set T :: "(('a, 'e)outcome \ event \ ('a, 'e)outcome) set" where Read_mem: "\opt. k v = (m, opt) \ ((outcome.Read_mem (rk, addr, sz) k), Read_mem rk addr sz v, m) \ T" | Write_ea: "\opt. k = (m, opt) \ ((outcome.Write_ea (rk, addr, sz) k), Write_ea rk addr sz, m) \ T" | Excl_res: "\opt. k r = (m, opt) \ ((outcome.Excl_res k), Excl_res r, m) \ T" | Write_memv: "\opt. k r = (m, opt) \ ((outcome.Write_memv v k), Write_memv v r, m) \ T" | Barrier: "\opt. k = (m, opt) \ ((outcome.Barrier bk k), Barrier bk, m) \ T" | Footprint: "\opt. k = (m, opt) \ ((outcome.Footprint k), Footprint, m) \ T" | Read_reg: "\opt. k v = (m, opt) \ ((outcome.Read_reg r k), Read_reg r v, m) \ T" | Write_reg: "\opt. k = (m, opt) \ ((outcome.Write_reg (r, v) k), Write_reg r v, m) \ T" | Internal: "\opt. k = (m, opt) \ ((outcome.Internal descr k), Internal descr, m) \ T" inductive_set Traces :: "(('a, 'r)outcome \ event list \ ('a, 'r)outcome) set" where Nil: "(s, [], s) \ Traces" | Step: "\(s, e, s'') \ T; (s'', t, s') \ Traces\ \ (s, e # t, s') \ Traces" declare Traces.intros[intro] declare T.intros[intro] declare prod.splits[split] (* lemma fst_case_bind[simp]: "fst (case k of (o1, x) \ (bind o1 f, x)) = bind (fst k) f" by (cases k) auto *) lemmas Traces_ConsI = T.intros[THEN Step, rotated] inductive_cases Traces_NilE[elim]: "(s, [], s') \ Traces" inductive_cases Traces_ConsE[elim]: "(s, e # t, s') \ Traces" abbreviation Run :: "('a, 'r)outcome \ event list \ 'a \ bool" where "Run s t a \ (s, t, Done a) \ Traces" lemma Run_appendI: assumes "(s, t1, s') \ Traces" and "Run s' t2 a" shows "Run s (t1 @ t2) a" proof (use assms in \induction t1 arbitrary: s\) case (Cons e t1) then show ?case by (elim Traces_ConsE) auto qed auto lemma bind_DoneE: assumes "bind m f = outcome.Done a" obtains a' where "m = outcome.Done a'" and "f a' = outcome.Done a" using assms by (auto elim: bind.elims) lemma bind_T_cases: assumes "(bind m f, e, s') \ T" obtains (Done) a where "m = Done a" | (Bind) m' where "s' = bind m' f" and "(m, e, m') \ T" proof cases assume D: "\a. m \ Done a" show thesis using assms proof cases case (Read_mem k v rk addr sz) then obtain k' where "m = outcome.Read_mem (rk, addr, sz) k'" using D by (cases m) auto then show ?thesis using Read_mem by (intro Bind[of "fst (k' v)"]) auto next case (Write_ea k rk addr sz) then obtain k' where "m = outcome.Write_ea (rk, addr, sz) k'" using D by (cases m) auto then show ?thesis using Write_ea by (intro Bind[of "fst k'"]) auto next case (Excl_res k r) then obtain k' where "m = outcome.Excl_res k'" using D by (cases m) auto then show ?thesis using Excl_res by (intro Bind[of "fst (k' r)"]) auto next case (Write_memv k r v) then obtain k' where "m = outcome.Write_memv v k'" using D by (cases m) auto then show ?thesis using Write_memv by (intro Bind[of "fst (k' r)"]) auto next case (Barrier k bk) then obtain k' where "m = outcome.Barrier bk k'" using D by (cases m) auto then show ?thesis using Barrier by (intro Bind[of "fst k'"]) auto next case (Footprint k) then obtain k' where "m = outcome.Footprint k'" using D by (cases m) auto then show ?thesis using Footprint by (intro Bind[of "fst k'"]) auto next case (Read_reg k v r) then obtain k' where "m = outcome.Read_reg r k'" using D by (cases m) auto then show ?thesis using Read_reg by (intro Bind[of "fst (k' v)"]) (auto split: prod.splits) next case (Write_reg k r v) then obtain k' where "m = outcome.Write_reg (r, v) k'" using D by (cases m) auto then show ?thesis using Write_reg by (intro Bind[of "fst k'"]) auto next case (Internal k descr) then obtain k' where "m = outcome.Internal descr k'" using D by (cases m) auto then show ?thesis using Internal by (intro Bind[of "fst k'"]) auto qed qed auto lemma Run_bindE: fixes m :: "('b, 'r) outcome" and a :: 'a assumes "Run (bind m f) t a" obtains tm am tf where "t = tm @ tf" and "Run m tm am" and "Run (f am) tf a" proof (use assms in \induction "bind m f" t "Done a :: ('a,'r) outcome" arbitrary: m rule: Traces.induct\) case Nil obtain am where "m = Done am" and "f am = Done a" using Nil(1) by (elim bind_DoneE) then show ?case by (intro Nil(2)) auto next case (Step e s'' t m) show thesis using Step(1) proof (cases rule: bind_T_cases) case (Done am) then show ?thesis using Step(1,2) by (intro Step(4)[of "[]" "e # t" am]) auto next case (Bind m') show ?thesis proof (rule Step(3)[OF Bind(1)]) fix tm tf am assume "t = tm @ tf" and "Run m' tm am" and "Run (f am) tf a" then show thesis using Bind by (intro Step(4)[of "e # tm" tf am]) auto qed qed qed lemma Run_DoneE: assumes "Run (Done a) t a'" obtains "t = []" and "a' = a" using assms by (auto elim: Traces.cases T.cases) lemma Run_Done_iff_Nil[simp]: "Run (Done a) t a' \ t = [] \ a' = a" by (auto elim: Run_DoneE) lemma Run_BarrierE[elim!]: assumes "Run (outcome.Barrier bk k) t a" obtains t' where "t = Barrier bk # t'" and "Run (fst k) t' a" using assms by cases (auto elim: T.cases) lemma bind_cong[fundef_cong]: assumes m: "m1 = m2" and f: "\t a. Run m2 t a \ f1 a = f2 a" shows "bind m1 f1 = bind m2 f2" proof (unfold m, use f in \induction m2 f1 arbitrary: f2 rule: bind_induct\) case (Read_mem rk addr sz k f) have "bind m' f = bind m' f2" if k: "k v = (m', opt)" for v m' opt using k by (auto intro!: Read_mem.IH[of _ opt v] Read_mem.prems) then show ?case by auto next case (Read_reg reg k f) have "bind m' f = bind m' f2" if k: "k v = (m', opt)" for v m' opt using k by (auto intro!: Read_reg.IH[of _ opt v] Read_reg.prems) then show ?case by auto next case (Write_memv val k f) have "bind m' f = bind m' f2" if k: "k v = (m', opt)" for v m' opt using k by (auto intro!: Write_memv.IH[of _ opt v] Write_memv.prems) then show ?case by auto next case (Excl_res k f) have "bind m' f = bind m' f2" if k: "k v = (m', opt)" for v m' opt using k by (auto intro!: Excl_res.IH[of _ opt v] Excl_res.prems) then show ?case by auto next case (Write_ea wk addr sz m opt f) show ?case by (auto intro!: Write_ea) next case (Barrier bk m opt f) show ?case by (auto intro!: Barrier) next case (Footprint m opt f) show ?case by (auto intro!: Footprint) next case (Write_reg reg val m opt f) show ?case by (auto intro!: Write_reg) next case (Internal i m opt f) show ?case by (auto intro!: Internal) qed auto end