1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
|
theory Sail2_prompt_monad_lemmas
imports
Sail2_prompt_monad
Sail2_values_lemmas
begin
notation bind (infixr "\<bind>" 54)
abbreviation seq :: "('rv,unit,'e)monad \<Rightarrow> ('rv,'b,'e)monad \<Rightarrow>('rv,'b,'e)monad" (infixr "\<then>" 54) where
"m \<then> n \<equiv> m \<bind> (\<lambda>_. n)"
lemma All_bind_dom: "bind_dom (m, f)"
by (induction m) (auto intro: bind.domintros)
termination bind using All_bind_dom by auto
lemmas bind_induct[case_names Done Read_mem Write_memv Read_reg Excl_res Write_ea Barrier Write_reg Fail Exception] = bind.induct
lemma bind_return[simp]: "bind (return a) f = f a"
by (auto simp: return_def)
lemma bind_return_right[simp]: "bind x return = x" by (induction x) (auto simp: return_def)
lemma bind_assoc[simp]: "bind (bind m f) g = bind m (\<lambda>x. bind (f x) g)"
by (induction m f arbitrary: g rule: bind.induct) auto
lemma bind_assert_True[simp]: "bind (assert_exp True msg) f = f ()"
by (auto simp: assert_exp_def)
lemma All_try_catch_dom: "try_catch_dom (m, h)"
by (induction m) (auto intro: try_catch.domintros)
termination try_catch using All_try_catch_dom by auto
lemmas try_catch_induct[case_names Done Read_mem Write_memv Read_reg Excl_res Write_ea Barrier Write_reg Fail Exception] = try_catch.induct
inductive_set T :: "(('rv, 'a, 'e) monad \<times> 'rv event \<times> ('rv, 'a, 'e) monad) set" where
Read_mem: "((Read_mem rk addr sz k), E_read_mem rk addr sz v, k v) \<in> T"
| Read_memt: "((Read_memt rk addr sz k), E_read_memt rk addr sz v, k v) \<in> T"
| Write_ea: "((Write_ea wk addr sz k), E_write_ea wk addr sz, k) \<in> T"
| Excl_res: "((Excl_res k), E_excl_res r, k r) \<in> T"
| Write_mem: "((Write_mem wk addr sz v k), E_write_mem wk addr sz v r, k r) \<in> T"
| Write_memt: "((Write_memt wk addr sz v t k), E_write_memt wk addr sz v t r, k r) \<in> T"
| Footprint: "((Footprint k), E_footprint, k) \<in> T"
| Barrier: "((Barrier bk k), E_barrier bk, k) \<in> T"
| Read_reg: "((Read_reg r k), E_read_reg r v, k v) \<in> T"
| Write_reg: "((Write_reg r v k), E_write_reg r v, k) \<in> T"
| Choose: "((Choose descr k), E_choose descr v, k v) \<in> T"
| Print: "((Print msg k), E_print msg, k) \<in> T"
lemma emitEvent_iff_T: "emitEvent m e = Some m' \<longleftrightarrow> (m, e, m') \<in> T"
by (cases e) (auto simp: emitEvent_def elim: T.cases intro: T.intros split: monad.splits)
inductive_set Traces :: "(('rv, 'a, 'e) monad \<times> 'rv event list \<times> ('rv, 'a, 'e) monad) set" where
Nil: "(s, [], s) \<in> Traces"
| Step: "\<lbrakk>(s, e, s'') \<in> T; (s'', t, s') \<in> Traces\<rbrakk> \<Longrightarrow> (s, e # t, s') \<in> Traces"
declare Traces.intros[intro]
declare T.intros[intro]
declare prod.splits[split]
lemmas Traces_ConsI = T.intros[THEN Step, rotated]
inductive_cases Traces_NilE[elim]: "(s, [], s') \<in> Traces"
inductive_cases Traces_ConsE[elim]: "(s, e # t, s') \<in> Traces"
lemma runTrace_iff_Traces: "runTrace t m = Some m' \<longleftrightarrow> (m, t, m') \<in> Traces"
by (induction t m rule: runTrace.induct; fastforce simp: bind_eq_Some_conv emitEvent_iff_T)
lemma hasTrace_iff_Traces_final: "hasTrace t m \<longleftrightarrow> (\<exists>m'. (m, t, m') \<in> Traces \<and> final m')"
by (auto simp: hasTrace_def runTrace_iff_Traces[symmetric] split: option.splits)
lemma Traces_cases:
fixes m :: "('rv, 'a, 'e) monad"
assumes Run: "(m, t, m') \<in> Traces"
obtains (Nil) a where "m = m'" and "t = []"
| (Read_mem) rk addr s k t' v where "m = Read_mem rk addr s k" and "t = E_read_mem rk addr s v # t'" and "(k v, t', m') \<in> Traces"
| (Read_memt) rk addr s k t' v tag where "m = Read_memt rk addr s k" and "t = E_read_memt rk addr s (v, tag) # t'" and "(k (v, tag), t', m') \<in> Traces"
| (Write_mem) wk addr sz val k v t' where "m = Write_mem wk addr sz val k" and "t = E_write_mem wk addr sz val v # t'" and "(k v, t', m') \<in> Traces"
| (Write_memt) wk addr sz val tag k t' v where "m = Write_memt wk addr sz val tag k" and "t = E_write_memt wk addr sz val tag v # t'" and "(k v, t', m') \<in> Traces"
| (Barrier) bk k t' v where "m = Barrier bk k" and "t = E_barrier bk # t'" and "(k, t', m') \<in> Traces"
| (Read_reg) reg k t' v where "m = Read_reg reg k" and "t = E_read_reg reg v # t'" and "(k v, t', m') \<in> Traces"
| (Excl_res) k t' v where "m = Excl_res k" and "t = E_excl_res v # t'" and "(k v, t', m') \<in> Traces"
| (Write_ea) wk addr s k t' where "m = Write_ea wk addr s k" and "t = E_write_ea wk addr s # t'" and "(k, t', m') \<in> Traces"
| (Footprint) k t' where "m = Footprint k" and "t = E_footprint # t'" and "(k, t', m') \<in> Traces"
| (Write_reg) reg v k t' where "m = Write_reg reg v k" and "t = E_write_reg reg v # t'" and "(k, t', m') \<in> Traces"
| (Choose) descr v k t' where "m = Choose descr k" and "t = E_choose descr v # t'" and "(k v, t', m') \<in> Traces"
| (Print) msg k t' where "m = Print msg k" and "t = E_print msg # t'" and "(k, t', m') \<in> Traces"
proof (use Run in \<open>cases m t m' set: Traces\<close>)
case Nil
then show ?thesis by (auto intro: that(1))
next
case (Step e m'' t')
note t = \<open>t = e # t'\<close>
note m' = \<open>(m'', t', m') \<in> Traces\<close>
from \<open>(m, e, m'') \<in> T\<close> and t and m'
show ?thesis proof (cases m e m'' rule: T.cases)
case (Read_memt rk addr sz k v)
then show ?thesis using t m' by (cases v; elim that; blast)
qed (elim that; blast)+
qed
abbreviation Run :: "('rv, 'a, 'e) monad \<Rightarrow> 'rv event list \<Rightarrow> 'a \<Rightarrow> bool"
where "Run s t a \<equiv> (s, t, Done a) \<in> Traces"
lemma final_cases:
assumes "final m"
obtains (Done) a where "m = Done a" | (Fail) f where "m = Fail f" | (Ex) e where "m = Exception e"
using assms by (cases m) (auto simp: final_def)
lemma hasTraces_elim:
assumes "hasTrace t m"
obtains m' where "(m, t, m') \<in> Traces" and "final m'"
using assms
unfolding hasTrace_iff_Traces_final
by blast
lemma hasTrace_cases:
assumes "hasTrace t m"
obtains (Run) a where "Run m t a"
| (Fail) f where "(m, t, Fail f) \<in> Traces"
| (Ex) e where "(m, t, Exception e) \<in> Traces"
using assms by (elim hasTraces_elim final_cases) auto
lemma Traces_appendI:
assumes "(s, t1, s') \<in> Traces"
and "(s', t2, s'') \<in> Traces"
shows "(s, t1 @ t2, s'') \<in> Traces"
proof (use assms in \<open>induction t1 arbitrary: s\<close>)
case (Cons e t1)
then show ?case by (elim Traces_ConsE) auto
qed auto
lemma bind_DoneE:
assumes "bind m f = Done a"
obtains a' where "m = Done a'" and "f a' = Done a"
using assms by (auto elim: bind.elims)
lemma bind_T_cases:
assumes "(bind m f, e, s') \<in> T"
obtains (Done) a where "m = Done a" and "(f a, e, s') \<in> T"
| (Bind) m' where "s' = bind m' f" and "(m, e, m') \<in> T"
using assms by (cases; fastforce elim: bind.elims)
lemma Traces_bindI:
fixes m :: "('r, 'a, 'e) monad"
assumes "Run m t1 a1"
and "(f a1, t2, m') \<in> Traces"
shows "(m \<bind> f, t1 @ t2, m') \<in> Traces"
proof (use assms in \<open>induction m t1 "Done a1 :: ('r, 'a, 'e) monad" rule: Traces.induct\<close>)
case (Step s e s'' t)
then show ?case by (elim T.cases) auto
qed auto
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' \<longleftrightarrow> t = [] \<and> a' = a"
by (auto elim: Run_DoneE)
lemma Run_Nil_iff_Done: "Run m [] a \<longleftrightarrow> m = Done a"
by auto
lemma Traces_Nil_iff: "(m, [], m') \<in> Traces \<longleftrightarrow> m' = m"
by auto
lemma bind_Traces_cases:
assumes "(m \<bind> f, t, m') \<in> Traces"
obtains (Left) m'' where "(m, t, m'') \<in> Traces" and "m' = m'' \<bind> f"
| (Bind) tm am tf where "t = tm @ tf" and "Run m tm am" and "(f am, tf, m') \<in> Traces"
proof (use assms in \<open>induction "bind m f" t m' arbitrary: m rule: Traces.induct\<close>)
case Nil
then show ?case by (auto simp: Traces_Nil_iff)
next
case (Step e s'' t s')
note IH = Step(3)
note Left' = Step(4)
note Bind' = Step(5)
show thesis
proof (use \<open>(m \<bind> f, e, s'') \<in> T\<close> in \<open>cases rule: bind_T_cases\<close>)
case (Done a)
then show ?thesis using \<open>(s'', t, s') \<in> Traces\<close> Step(5)[of "[]" "e # t" a] by auto
next
case (Bind m')
show ?thesis
proof (rule IH)
show "s'' = m' \<bind> f" using Bind by blast
next
fix m''
assume "(m', t, m'') \<in> Traces" and "s' = m'' \<bind> f"
then show thesis using \<open>(m, e, m') \<in> T\<close> Left'[of m''] by auto
next
fix tm tf am
assume "t = tm @ tf" and "Run m' tm am" and "(f am, tf, s') \<in> Traces"
then show thesis using \<open>(m, e, m') \<in> T\<close> Bind'[of "e # tm" tf am] by auto
qed
qed
qed
lemma final_bind_cases:
assumes "final (m \<bind> f)"
obtains (Done) a where "m = Done a" and "final (f a)"
| (Fail) msg where "m = Fail msg"
| (Ex) e where "m = Exception e"
using assms by (cases m) (auto simp: final_def)
lemma hasFailure_iff_Traces_Fail: "hasFailure t m \<longleftrightarrow> (\<exists>msg. (m, t, Fail msg) \<in> Traces)"
by (auto simp: hasFailure_def runTrace_iff_Traces[symmetric] split: option.splits monad.splits)
lemma hasException_iff_Traces_Exception: "hasException t m \<longleftrightarrow> (\<exists>e. (m, t, Exception e) \<in> Traces)"
by (auto simp: hasException_def runTrace_iff_Traces[symmetric] split: option.splits monad.splits)
lemma hasTrace_bind_cases:
assumes "hasTrace t (m \<bind> f)"
obtains (Bind) tm am tf where "t = tm @ tf" and "Run m tm am" and "hasTrace tf (f am)"
| (Fail) "hasFailure t m"
| (Ex) "hasException t m"
proof -
from assms obtain m' where t: "(m \<bind> f, t, m') \<in> Traces" and m': "final m'"
by (auto simp: hasTrace_iff_Traces_final)
note [simp] = hasTrace_iff_Traces_final hasFailure_iff_Traces_Fail hasException_iff_Traces_Exception
from t show thesis
proof (cases rule: bind_Traces_cases)
case (Left m'')
then show ?thesis
using m' Fail Ex Bind[of t "[]"]
by (fastforce elim!: final_bind_cases)
next
case (Bind tm am tf)
then show ?thesis
using m' that
by fastforce
qed
qed
lemma try_catch_T_cases:
assumes "(try_catch m h, e, m') \<in> T"
obtains (NoEx) m'' where "(m, e, m'') \<in> T" and "m' = try_catch m'' h"
| (Ex) ex where "m = Exception ex" and "(h ex, e, m') \<in> T"
using assms
by (cases m) (auto elim!: T.cases)
lemma try_catch_Traces_cases:
assumes "(try_catch m h, t, mtc) \<in> Traces"
obtains (NoEx) m' where "(m, t, m') \<in> Traces" and "mtc = try_catch m' h"
| (Ex) tm ex th where "(m, tm, Exception ex) \<in> Traces" and "(h ex, th, mtc) \<in> Traces" and "t = tm @ th"
proof (use assms in \<open>induction "try_catch m h" t mtc arbitrary: m rule: Traces.induct\<close>)
case Nil
then show ?case by auto
next
case (Step e mtc' t mtc)
note e = \<open>(try_catch m h, e, mtc') \<in> T\<close>
note t = \<open>(mtc', t, mtc) \<in> Traces\<close>
note IH = Step(3)
note NoEx_ConsE = Step(4)
note Ex_ConsE = Step(5)
show ?case
proof (use e in \<open>cases rule: try_catch_T_cases\<close>)
case (NoEx m1)
show ?thesis
proof (rule IH)
show "mtc' = try_catch m1 h" using NoEx by auto
next
fix m'
assume "(m1, t, m') \<in> Traces" and "mtc = try_catch m' h"
then show ?thesis
using NoEx NoEx_ConsE[of m']
by auto
next
fix tm ex th
assume "(m1, tm, Exception ex) \<in> Traces" and "(h ex, th, mtc) \<in> Traces" and "t = tm @ th"
then show ?thesis
using NoEx Ex_ConsE[of "e # tm" ex th]
by auto
qed
next
case (Ex ex)
then show ?thesis
using t Ex_ConsE[of "[]" ex "e # t"]
by auto
qed
qed
lemma Done_Traces_iff[simp]: "(Done a, t, m') \<in> Traces \<longleftrightarrow> t = [] \<and> m' = Done a"
by (auto elim: Traces_cases)
lemma Fail_Traces_iff[simp]: "(Fail msg, t, m') \<in> Traces \<longleftrightarrow> t = [] \<and> m' = Fail msg"
by (auto elim: Traces_cases)
lemma Exception_Traces_iff[simp]: "(Exception e, t, m') \<in> Traces \<longleftrightarrow> t = [] \<and> m' = Exception e"
by (auto elim: Traces_cases)
lemma Read_reg_TracesE:
assumes "(Read_reg r k, t, m') \<in> Traces"
obtains (Nil) "t = []" and "m' = Read_reg r k"
| (Cons) v t' where "t = E_read_reg r v # t'" and "(k v, t', m') \<in> Traces"
using assms
by (auto elim: Traces_cases)
lemma Write_reg_TracesE:
assumes "(Write_reg r v k, t, m') \<in> Traces"
obtains (Nil) "t = []" and "m' = Write_reg r v k"
| (Cons) t' where "t = E_write_reg r v # t'" and "(k, t', m') \<in> Traces"
using assms
by (auto elim: Traces_cases)
lemma Write_ea_TracesE:
assumes "(Write_ea wk addr sz k, t, m') \<in> Traces"
obtains (Nil) "t = []" and "m' = Write_ea wk addr sz k"
| (Cons) t' where "t = E_write_ea wk addr sz # t'" and "(k, t', m') \<in> Traces"
using assms
by (auto elim: Traces_cases)
lemma Write_memt_TracesE:
assumes "(Write_memt wk addr sz v tag k, t, m') \<in> Traces"
obtains (Nil) "t = []" and "m' = Write_memt wk addr sz v tag k"
| (Cons) t' r where "t = E_write_memt wk addr sz v tag r # t'" and "(k r, t', m') \<in> Traces"
using assms
by (auto elim: Traces_cases)
lemma Run_bindE:
fixes m :: "('rv, 'b, 'e) monad" 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 \<open>induction "bind m f" t "Done a :: ('rv, 'a, 'e) monad" arbitrary: m rule: Traces.induct\<close>)
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_bindE_ignore_trace:
assumes "Run (m \<bind> f) t a"
obtains tm tf am where "Run m tm am" and "Run (f am) tf a"
using assms by (elim Run_bindE)
lemma Run_letE:
assumes "Run (let x = y in f x) t a"
obtains "Run (f y) t a"
using assms by auto
lemma Run_ifE:
assumes "Run (if b then f else g) t a"
obtains "b" and "Run f t a" | "\<not>b" and "Run g t a"
using assms by (auto split: if_splits)
lemma Run_returnE:
assumes "Run (return x) t a"
obtains "t = []" and "a = x"
using assms by (auto simp: return_def)
lemma Run_early_returnE:
assumes "Run (early_return x) t a"
shows P
using assms by (auto simp: early_return_def throw_def elim: Traces_cases)
lemma bind_cong[fundef_cong]:
assumes m: "m1 = m2"
and f: "\<And>t a. Run m2 t a \<Longrightarrow> f1 a = f2 a"
shows "bind m1 f1 = bind m2 f2"
unfolding m using f
by (induction m2 f1 arbitrary: f2 rule: bind.induct; unfold bind.simps; blast)
lemma liftR_read_reg[simp]: "liftR (read_reg reg) = read_reg reg" by (auto simp: read_reg_def liftR_def split: option.splits)
lemma try_catch_return[simp]: "try_catch (return x) h = return x" by (auto simp: return_def)
lemma try_catch_choose_bool[simp]: "try_catch (choose_bool descr) h = choose_bool descr" by (auto simp: choose_bool_def)
lemma liftR_choose_bool[simp]: "liftR (choose_bool descr) = choose_bool descr" by (auto simp: choose_bool_def liftR_def)
lemma liftR_return[simp]: "liftR (return x) = return x" by (auto simp: liftR_def)
lemma liftR_undefined_bool[simp]: "liftR (undefined_bool ()) = undefined_bool ()" by (auto simp: undefined_bool_def)
lemma assert_exp_True_return[simp]: "assert_exp True msg = return ()" by (auto simp: assert_exp_def return_def)
end
|