-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathL2Defs.thy
658 lines (586 loc) · 27 KB
/
L2Defs.thy
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
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
(*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*)
theory L2Defs
imports CorresXF L1Defs L1Peephole MonadMono
begin
type_synonym ('s, 'a, 'e) L2_monad = "('s, 'e + 'a) nondet_monad"
definition "L2_unknown (name :: string list) \<equiv> liftE (select UNIV) :: ('s, 'a, 'e) L2_monad"
definition "L2_seq (A :: ('s, 'a, 'e) L2_monad) (B :: 'a \<Rightarrow> ('s, 'b, 'e) L2_monad) \<equiv> (A >>=E B) :: ('s, 'b, 'e) L2_monad"
definition "L2_modify m \<equiv> liftE (modify m) :: ('s, unit, 'e) L2_monad"
definition "L2_gets f (names :: string list) \<equiv> liftE (gets f) :: ('s, 'a, 'e) L2_monad"
definition "L2_condition c (A :: ('s, 'a, 'e) L2_monad) (B :: ('s, 'a, 'e) L2_monad) \<equiv> condition c A B"
definition "L2_catch (A :: ('s, 'a, 'e) L2_monad) (B :: 'e \<Rightarrow> ('s, 'a, 'ee) L2_monad) \<equiv> (A <handle2> B)"
definition "L2_while c (A :: 'a \<Rightarrow> ('s, 'a, 'e) L2_monad) i (name :: string list) \<equiv> whileLoopE c A i :: ('s, 'a, 'e) L2_monad"
definition "L2_throw x (name :: string list) \<equiv> throwError x :: ('s, 'a, 'e) L2_monad"
definition "L2_spec r \<equiv> liftE (spec r >>= (\<lambda>_. select UNIV)) :: ('s, 'a, 'e) L2_monad"
definition "L2_guard c \<equiv> (liftE (guard c)) :: ('s, unit, 'e) L2_monad"
definition "L2_fail \<equiv> fail :: ('s, 'a, 'e) L2_monad"
definition "L2_call x \<equiv> x <handle2> (\<lambda>_. fail) :: ('s, 'a, 'e) L2_monad"
definition "L2_recguard n b \<equiv> (condition (\<lambda>s. (n :: nat) = 0) fail b) :: ('s, 'a, 'e) L2_monad"
abbreviation "L2_skip \<equiv> L2_gets (\<lambda>_. ()) []"
(*
* Temporary constructions, used internally but not emitted.
*
* "L2_folded_gets" is like "L2_gets", but the peephole optimiser will
* try to eliminate the call to where it is used, eliminating it where
* possible. It is used for automatically generated "L2_gets" calls
* which the user really doesn't need to know about.
*
* The various "call" defintions are to help generate proofs for the
* different ways of making function calls, which are hard to unify.
*)
definition "L2_folded_gets f names \<equiv> L2_gets f names :: ('s, 'a, 'e) L2_monad"
definition "L2_voidcall x \<equiv> L2_seq (L2_call x) (\<lambda>ret. L2_skip) :: ('s, unit, 'e) L2_monad"
definition "L2_modifycall x m \<equiv> L2_seq (L2_call x) (\<lambda>ret. L2_modify (m ret)) :: ('s, unit, 'e) L2_monad"
definition "L2_returncall x f \<equiv> L2_seq (L2_call x) (\<lambda>ret. L2_folded_gets (f ret) [''retval'']) :: ('s, 'a, 'e) L2_monad"
lemma L2_folded_gets_bind:
"L2_seq (L2_folded_gets (\<lambda>_. x) name) f = f x"
apply (rule ext)
apply (monad_eq simp: L2_folded_gets_def L2_seq_def L2_gets_def)
done
(* FIXME: we can merge these *)
lemmas L2_remove_scaffolding_1 =
L2_folded_gets_bind [THEN eq_reflection]
L2_returncall_def
L2_modifycall_def
L2_voidcall_def
lemmas L2_remove_scaffolding_2 =
L2_remove_scaffolding_1
L2_folded_gets_def
abbreviation (input) "L2_guarded_while G C B i n \<equiv> L2_seq (L2_guard (G i))
(\<lambda>_. L2_while C (\<lambda>i. L2_seq (B i) (\<lambda>r. L2_seq (L2_guard (G r)) (\<lambda>_. L2_gets (\<lambda>_. r) n))) i n)"
lemmas L2_defs = L2_unknown_def L2_seq_def
L2_modify_def L2_gets_def L2_condition_def L2_catch_def L2_while_def
L2_throw_def L2_spec_def L2_guard_def L2_fail_def L2_folded_gets_def
L2_voidcall_def L2_modifycall_def L2_returncall_def L2_recguard_def
(* Alternate definitions. *)
lemma L2_defs':
"L2_unknown n \<equiv> unknownE"
"L2_seq A' B' \<equiv> A' >>=E B'"
"L2_modify m \<equiv> modifyE m"
"L2_gets f n \<equiv> getsE f"
"L2_condition c L R \<equiv> condition c L R"
"L2_catch A B \<equiv> (A <handle2> B)"
"L2_while c' B'' i n \<equiv> whileLoopE c' B'' i"
"L2_throw x n \<equiv> throwError x"
"L2_spec r \<equiv> (specE r >>=E (\<lambda>_. selectE UNIV))"
"L2_guard c \<equiv> guardE c"
"L2_fail \<equiv> fail"
by (auto simp: monad_defs L2_defs bind_liftE_distrib)
definition
L2corres :: "('s \<Rightarrow> 't) \<Rightarrow> ('s \<Rightarrow> 'r) \<Rightarrow> ('s \<Rightarrow> 'e) \<Rightarrow> ('s \<Rightarrow> bool)
\<Rightarrow> ('t, 'e + 'r) nondet_monad \<Rightarrow> ('s, unit + unit) nondet_monad \<Rightarrow> bool"
where
"L2corres st ret_xf ex_xf P A C
\<equiv> corresXF st (\<lambda>_. ret_xf) (\<lambda>_. ex_xf) P A C"
(* Wrapper for calling un-translated functions. *)
definition
"L2_call_L1 arg_xf gs ret_xf l1body
= do cur_gs \<leftarrow> get;
s \<leftarrow> select {s. gs s = cur_gs \<and> arg_xf s};
(rv, s') \<leftarrow> select_f (l1body s);
put (gs s');
case rv of Inl _ \<Rightarrow> fail
| Inr _ \<Rightarrow> return (Inr (ret_xf s') :: (unit + _))
od"
lemma L2corres_L2_call_L1:
"L2corres gs ret_xf ex_xf arg_xf
(L2_call_L1 arg_xf gs ret_xf f) f"
apply (clarsimp simp: L2corres_def corresXF_def L2_call_L1_def
split: sum.split)
apply (clarsimp simp: snd_bind in_monad exec_get select_def)
apply (clarsimp simp: select_f_def snd_bind put_def split: sum.split_asm)
apply (fastforce simp: return_def)
done
lemma L2corres_L2_call_simpl:
"l1_f \<equiv> simpl_f \<Longrightarrow>
L2corres gs ret_xf ex_xf arg_xf
(L2_call_L1 arg_xf gs ret_xf simpl_f) l1_f"
by (simp add: L2corres_L2_call_L1)
(* shouldn't be needed
lemma empty_set_exists: "(\<forall>a. a \<noteq> {}) = False"
apply blast
done
*)
lemma L2corres_modify_global:
"\<lbrakk> \<And>s. P s \<Longrightarrow> M (st s) = st (M' s) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_modify M) (L1_modify M')"
apply (clarsimp simp: L2corres_def L2_defs L1_defs)
apply (fold modifyE_def)
apply (auto intro: corresXF_modify_global)
done
lemma L2corres_modify_unknown:
"\<lbrakk> \<And>s. P s \<Longrightarrow> st s = st (M s) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_unknown name) (L1_modify M)"
apply (clarsimp simp: L2corres_def L2_defs L1_defs)
apply (fold selectE_def modifyE_def)
apply (auto intro: corresXF_select_modify)
done
lemma L2corres_spec_unknown:
"\<lbrakk> \<And>s a. st s = st (M (a::('a \<Rightarrow> ('a::{type}))) s) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_unknown name) (L1_init M)"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma L2corres_modify_gets:
"\<lbrakk> \<And>s. P s \<Longrightarrow> st s = st (M s); \<And>s. P s \<Longrightarrow> ret (M s) = f (st s) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_gets (\<lambda>s. f s) n) (L1_modify M)"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma L2corres_gets_skip:
"L2corres st ret ex P L2_skip L1_skip"
by (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
lemma L2corres_guard:
"\<lbrakk> \<And>s. P s \<Longrightarrow> G' s = G (st s) \<rbrakk> \<Longrightarrow> L2corres st return_xf exception_xf P (L2_guard G) (L1_guard G')"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma L2corres_fail:
"L2corres st return_xf exception_xf P L2_fail X"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma spec_alt_def: "spec r = (\<lambda>s. (Pair () ` {s'. (s, s') \<in> r}, \<not> (\<exists>s'. (s, s') \<in> r)))"
apply (clarsimp simp: spec_def)
done
lemma L2corres_spec:
"\<lbrakk> \<And>s s'. ((s, s') \<in> A') = ((st s, st s') \<in> A); surj st \<rbrakk>
\<Longrightarrow> L2corres st return_xf exception_xf P (L2_spec A) (L1_spec A')"
apply (clarsimp simp: L2corres_def L2_defs L1_spec_def corresXF_def
liftE_def spec_alt_def return_def bind_def select_def)
apply (clarsimp simp: image_def)
apply (smt (verit) UNIV_I mem_Collect_eq)
done
lemma L2corres_seq:
"\<lbrakk> L2corres st return_xf exception_xf P A A';
\<And>x. L2corres st return_xf' exception_xf (P' x) (B x) B';
\<lbrace>R\<rbrace> A' \<lbrace>\<lambda>_ s. P' (return_xf s) s\<rbrace>, \<lbrace>\<lambda>_. \<top>\<rbrace>;
\<And>s. R s \<Longrightarrow> P s \<rbrakk> \<Longrightarrow>
L2corres st return_xf' exception_xf R (L2_seq A B) (L1_seq A' B')"
apply (unfold L2corres_def L2_seq_def L1_seq_def)
apply (rule corresXF_guard_imp)
apply (rule corresXF_join, assumption+)
done
lemma L2corres_catch:
"\<lbrakk> L2corres st V E P L L';
\<And>x. L2corres st V E' (P' x) (R x) R';
\<lbrace>Q\<rbrace> L' \<lbrace>\<lambda>_ _. True\<rbrace>, \<lbrace>\<lambda>_ s. P' (E s) s\<rbrace>; \<And>s. Q s \<Longrightarrow> P s \<rbrakk> \<Longrightarrow>
L2corres st V E' Q (L2_catch L R) (L1_catch L' R')"
apply (clarsimp simp: L2corres_def L2_catch_def L1_catch_def)
apply (unfold handleE_def)
apply (erule corresXF_except)
apply assumption
apply assumption
apply simp
done
lemma L2corres_throw:
"\<lbrakk> \<And>s. P s \<Longrightarrow> E s = A \<rbrakk> \<Longrightarrow> L2corres st V E P (L2_throw A n) (L1_throw)"
apply (clarsimp simp: L2corres_def L2_throw_def L1_throw_def)
apply (clarsimp simp: throwError_def return_def)
apply (clarsimp simp: corresXF_def)
done
lemma L2corres_cond:
"\<lbrakk> L2corres st return_xf exception_xf P A A';
L2corres st return_xf exception_xf P' B B';
\<And>s. R s \<Longrightarrow> P s;
\<And>s. R s \<Longrightarrow> P' s;
\<And>s. R s \<Longrightarrow> c' s = c (st s) \<rbrakk> \<Longrightarrow>
L2corres st return_xf exception_xf R (L2_condition c A B) (L1_condition c' A' B')"
apply (unfold L2corres_def L2_condition_def L1_condition_def)
apply (rule corresXF_cond)
apply (erule corresXF_guard_imp, fastforce)
apply (erule corresXF_guard_imp, fastforce)
apply (clarsimp)
done
lemma L2corres_inject_return:
"\<lbrakk> L2corres st V E P L R; \<lbrace>P'\<rbrace> R \<lbrace>\<lambda>_ s. W (V s) = V' s\<rbrace>, \<lbrace> \<lambda>_. \<top> \<rbrace>; \<And>s. P' s \<Longrightarrow> P s\<rbrakk> \<Longrightarrow>
L2corres st V' E P' (L2_seq L (\<lambda>x. L2_gets (\<lambda>_. W x) n)) R"
apply (clarsimp simp: L2corres_def)
apply (drule corresXF_guard_imp [where P=P'], simp)
apply (unfold L2_seq_def L2_gets_def)
apply (fold getsE_def)
apply (rule corresXF_guard_imp)
apply (erule corresXF_append_gets_abs)
apply (erule hoare_weaken_preE)
apply simp
apply simp
done
lemma L2corres_skip:
"L2corres st return_xf exception_xf P L2_skip L1_skip"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma L2corres_while:
assumes body_corres: "\<And>x. L2corres st ret ex (P' x) (A x) B"
and inv_holds: "\<lbrace>\<lambda>s. P (ret s) s \<rbrace> B \<lbrace>\<lambda>_ s. P (ret s) s \<rbrace>, \<lbrace>\<lambda>_ _. True\<rbrace>"
and cond_match: "\<And>s. P (ret s) s \<Longrightarrow> c' s = c (ret s) (st s)"
and pred_imply: "\<And>s x. P x s \<Longrightarrow> P' x s"
and pred_extract: "\<And>s. P x s \<Longrightarrow> ret s = x"
and pred_imply2: "\<And>s. Q x s \<Longrightarrow> P x s"
shows "L2corres st ret ex (Q x) (L2_while c A x n) (L1_while c' B)"
apply (clarsimp simp: L2corres_def L2_while_def L1_while_def)
apply (rule corresXF_guard_imp)
apply (rule corresXF_while [
where P="\<lambda>r s. P (ret s) s" and C'=c and C="\<lambda>_. c'" and A=A and B="\<lambda>_. B"
and ret="\<lambda>r s. ret s" and ex="\<lambda>r s. ex s" and st=st and y=x and x="()" and P'="\<lambda>r s. Q x s"])
apply (rule corresXF_guard_imp)
apply (rule body_corres [unfolded L2corres_def])
apply (clarsimp simp: pred_imply)
apply (clarsimp simp: cond_match)
apply (rule hoare_chainE [OF inv_holds], (clarsimp simp: pred_imply2)+)[1]
apply (metis pred_extract pred_imply2)
apply (metis pred_extract pred_imply2)
apply simp
done
lemma corresXF_E:
fixes st :: "'state \<Rightarrow> 'state2"
shows "\<lbrakk> corresXF st ret_xf ex_xf P A C; P s;
\<lbrakk> \<not> snd (A (st s)); \<not> snd (C s) \<rbrakk> \<Longrightarrow> (r, t) \<in> fst (C s);
\<lbrakk> \<not> snd (A (st s)); \<not> snd (C s);
\<exists>x. r = Inl x \<and> (Inl (ex_xf x t), st t) \<in> fst (A (st s)) \<rbrakk> \<Longrightarrow> R;
\<lbrakk> \<not> snd (A (st s)); \<not> snd (C s);
\<exists>x. r = Inr x \<and> (Inr (ret_xf x t), st t) \<in> fst (A (st s)) \<rbrakk> \<Longrightarrow> R;
\<lbrakk> snd (A (st s)) \<rbrakk> \<Longrightarrow> R
\<rbrakk> \<Longrightarrow> R"
apply atomize_elim
apply (unfold corresXF_def)
apply clarsimp
apply (erule allE, erule impE, fastforce)
apply clarsimp
apply (drule (1) bspec)
apply (clarsimp split: sum.splits)
done
declare Ball_def [monad_eq]
declare Bex_def [monad_eq]
lemma corresXF_measure_call:
"\<lbrakk> monad_mono C; \<And>m. corresXF st rx ex P (A m) (C m) \<rbrakk>
\<Longrightarrow> corresXF st rx ex P (measure_call A) (measure_call C)"
apply (unfold measure_call_def corresXF_def)
apply (clarsimp split: prod.splits sum.splits)
apply (fastforce dest: monad_mono_incl)
done
lemma L2corres_returncall:
"\<lbrakk> monad_mono dest_fn;
\<And>m. L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>t s. st (return_xf t (scope_teardown s t)) = st t;
\<And>s. st (scope_setup s) = st s;
\<And>t s. P s \<Longrightarrow> ret (return_xf t (scope_teardown s t)) = F (ret' t) (st t) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_returncall (measure_call Z) F) (L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)"
unfolding L1_call_def L2_returncall_def L2_call_def L2corres_def L2_defs
apply (drule_tac A = Z and C = dest_fn in corresXF_measure_call, assumption)
apply (rule corresXF_I)
apply monad_eq
apply (erule allE)
apply (erule_tac s="scope_setup s'" in corresXF_E)
apply simp
apply blast
apply clarsimp
apply clarsimp
apply blast
apply clarsimp
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (metis (lifting, mono_tags) corresXF_exec_fail)
apply (metis (lifting, mono_tags) corresXF_exec_except sum.distinct(2))
done
lemma L2corres_recursive_returncall:
"\<lbrakk> L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>t s. st (return_xf t (scope_teardown s t)) = st t;
\<And>s. st (scope_setup s) = st s;
\<And>t s. P s \<Longrightarrow> ret (return_xf t (scope_teardown s t)) = F (ret' t) (st t) \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_returncall (Z m) F)
(L1_call scope_setup (dest_fn m) scope_teardown return_xf)"
apply atomize
unfolding L1_call_def L2_returncall_def L2_call_def L2_defs L2corres_def
apply (rule corresXF_I)
apply monad_eq
apply (erule_tac s="scope_setup s'" in corresXF_E)
apply simp
apply assumption
apply simp
apply monad_eq
apply blast
apply simp
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (simp add: corresXF_def)
apply clarsimp
apply (drule (1) corresXF_exec_except)
apply force
apply clarsimp
apply clarsimp
apply force
done
lemma handleE_fail:
"(A <handle> (\<lambda>_. fail)) = (liftE (A <catch> (\<lambda>_. fail)))"
apply (monad_eq)
apply force
done
lemma handleE'_fail:
"(A <handle2> (\<lambda>_. fail)) = (liftE (A <catch> (\<lambda>_. fail)))"
apply (monad_eq)
apply force
done
lemma L2corres_modifycall:
"\<lbrakk> monad_mono dest_fn;
\<And>m. L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. P r \<Longrightarrow> F (ret' s) (st s) = st (return_xf s (scope_teardown r s));
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_modifycall (measure_call Z) F)
(L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)"
apply (clarsimp simp: L1_call_def L2_call_def L2_defs L2corres_def)
apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail)
apply (drule_tac A = Z and C = dest_fn in corresXF_measure_call, assumption)
apply (rule corresXF_I)
apply monad_eq
apply (erule allE)
apply (drule (1) corresXF_exec_normal)
apply clarsimp
apply clarsimp
apply clarsimp
apply metis
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (fastforce dest!: corresXF_exec_fail)
apply (fastforce dest!: corresXF_exec_except)
done
lemma L2corres_recursive_modifycall:
"\<lbrakk> L2corres st ret' ex' P' (Z m) (dest_fn (m :: nat));
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. P r \<Longrightarrow> F (ret' s) (st s) = st (return_xf s (scope_teardown r s));
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_modifycall (Z m) F)
(L1_call scope_setup (dest_fn m) scope_teardown return_xf)"
apply atomize
apply (clarsimp simp: L1_call_def L2_call_def L2_defs L2corres_def)
apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail)
apply (rule corresXF_I)
apply monad_eq
apply (erule_tac s="scope_setup s'" in corresXF_E)
apply simp
apply assumption
apply simp
apply metis
apply simp
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (simp add: corresXF_def)
apply (fastforce dest!: corresXF_exec_except)
done
lemma L2corres_voidcall:
"\<lbrakk> monad_mono dest_fn;
\<And>m. L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. st (return_xf s (scope_teardown r s)) = st s;
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_voidcall (measure_call Z))
(L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)"
apply (unfold L2_voidcall_def)
apply (frule corresXF_measure_call)
apply (subst (asm) L2corres_def, assumption)
apply (rule_tac t = "L2_skip" and s = "L2_modify (\<lambda>s. s)" in subst)
apply (monad_eq simp: L2_defs)
apply (fold L2_modifycall_def L2corres_def)
apply (fastforce elim!: L2corres_modifycall)
done
lemma L2corres_recursive_voidcall:
"\<lbrakk> L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. st (return_xf s (scope_teardown r s)) = st s;
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_voidcall (Z m))
(L1_call scope_setup (dest_fn m) scope_teardown return_xf)"
apply (unfold L2_voidcall_def)
apply (subgoal_tac "L2_skip = L2_modify (\<lambda>s. s)")
apply (erule ssubst)
apply (fold L2_modifycall_def)
apply (erule L2corres_recursive_modifycall, simp_all)[1]
apply (monad_eq simp: L2_defs)
done
lemma L2corres_call:
"\<lbrakk> monad_mono dest_fn;
\<And>m. L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. st (return_xf s (scope_teardown r s)) = st s;
\<And>s r. ret (return_xf s (scope_teardown r s)) = ret' s;
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_call (measure_call Z))
(L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)"
apply (clarsimp simp: L2corres_def L2_call_def L1_call_def L2_defs)
apply (drule corresXF_measure_call, assumption)
apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail)
apply (rule corresXF_I)
apply monad_eq
apply (fastforce dest!: corresXF_exec_normal)
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (fastforce dest!: corresXF_exec_fail)
apply (fastforce dest!: corresXF_exec_except)
done
lemma L2corres_recursive_call:
"\<lbrakk> L2corres st ret' ex' P' (Z m) (dest_fn m);
\<And>s. P s \<Longrightarrow> P' (scope_setup s);
\<And>s r. st (return_xf s (scope_teardown r s)) = st s;
\<And>s r. ret (return_xf s (scope_teardown r s)) = ret' s;
\<And>s. st (scope_setup s) = st s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_call (Z m)) (L1_call scope_setup (dest_fn m) scope_teardown return_xf)"
apply (clarsimp simp: L2corres_def L2_call_def L1_call_def L2_defs)
apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail)
apply (rule corresXF_I)
apply monad_eq
apply (fastforce dest!: corresXF_exec_normal)
apply monad_eq
apply monad_eq
apply (rule conjI)
apply (fastforce dest!: corresXF_exec_fail)
apply (fastforce dest!: corresXF_exec_except)
done
lemma L2corres_recguard:
"\<lbrakk> L2corres st ret ex P' B B';
\<And>s. P s \<Longrightarrow> P' s \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_recguard x B) (L1_recguard x B')"
apply (clarsimp simp: L2_recguard_def L1_defs)
apply (rule L2corres_cond [unfolded L2_condition_def L1_condition_def])
apply (rule L2corres_fail [unfolded L2_fail_def L1_fail_def])
apply assumption
apply assumption
apply simp
apply simp
done
lemma L2_gets_bind: "\<lbrakk> \<And>s s'. V s = V s' \<rbrakk> \<Longrightarrow> L2_seq (L2_gets V n) f = f (V undefined)"
apply (rule ext)
apply (clarsimp simp: L2_seq_def L2_gets_def gets_def get_def return_def bindE_def)
apply (clarsimp simp: liftE_def2 bind_def lift_def)
apply metis
done
(* TODO: remove internal var if it is not user-visible *)
lemma L2corres_folded_gets:
"\<lbrakk> \<And>a. L2corres st ret ex (P and (\<lambda>s. a = c (st s))) (X a) Y \<rbrakk> \<Longrightarrow>
L2corres st ret ex P (L2_seq (L2_folded_gets c name) X) Y"
apply atomize
apply (clarsimp simp: L2_seq_def L2_folded_gets_def L2_gets_def bindE_def bind_def gets_def liftE_def return_def)
apply (clarsimp simp: split_def image_def lift_def get_def pred_conj_def)
apply (clarsimp simp: L2corres_def corresXF_def)
done
lemma L2corres_guard_imp:
"\<lbrakk> L2corres st ret_state ex_state Q M M'; \<And>s. P s \<Longrightarrow> Q s \<rbrakk> \<Longrightarrow> L2corres st ret_state ex_state P M M'"
apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs)
done
lemma L2_recguard_cong [fundef_cong, cong]:
"\<lbrakk> n = n'; n \<noteq> 0 \<Longrightarrow> b = b' \<rbrakk> \<Longrightarrow> L2_recguard n b = L2_recguard n' b'"
apply (clarsimp simp: L2_recguard_def)
done
lemma L2_call_cong [fundef_cong, cong]:
"f = f' \<Longrightarrow> L2_call f = L2_call f'"
by simp
lemma L2corres_recguard_0:
"L2corres sr ret ex P (L2_recguard 0 X) Y"
apply (clarsimp simp: L2_recguard_def)
apply (rule L2corres_fail [unfolded L2_fail_def])
done
lemma L2_call_liftE [simp]:
"L2_call (liftE x) \<equiv> liftE x"
by (monad_eq simp: L2_defs L2_call_def liftE_left liftE_liftE)
lemma L2_recguard_0 [simp]: "L2_recguard 0 x = fail"
apply (clarsimp simp: L2_recguard_def)
done
lemma L2_call_fail [simp]: "L2_call fail = fail"
apply (monad_eq simp: L2_call_def)
done
lemma L2_call_L2_gets [simp]: "L2_call (L2_gets x n) = L2_gets x n"
apply (monad_eq simp: L2_call_def L2_gets_def)
done
(*
* Rules for adjusting case_prod statements after transformations.
*
* c.f. fix_L2_while_loop_splits_conv
*)
lemma L2_split_fixup_1:
"(L2_seq A (\<lambda>x. case y of (a, b) \<Rightarrow> B a b x)) =
(case y of (a, b) \<Rightarrow> L2_seq A (\<lambda>x. B a b x))"
by (auto simp: split_def)
lemma L2_split_fixup_2:
"(L2_seq (case y of (a, b) \<Rightarrow> B a b) A) =
(case y of (a, b) \<Rightarrow> L2_seq (B a b) A)"
by (auto simp: split_def)
lemma L2_split_fixup_3:
"(case (x, y) of (a, b) \<Rightarrow> P a b) = P x y"
by (auto simp: split_def)
lemma L2_split_fixup_4:
"case_prod (\<lambda>a (b :: 'a \<times> 'b). P a ) = case_prod (\<lambda>a. case_prod (\<lambda>(x :: 'a) (y :: 'b). P a ))"
by (auto simp: split_def)
lemma L2_split_fixup_f:
"(f (case y of (a, b) \<Rightarrow> G a b) =
(case y of (a, b) \<Rightarrow> f (G a b)))"
by (auto simp: split_def)
lemma L2_split_fixup_g:
"case_prod (\<lambda>a (b :: 'a \<times> 'b). P a b) = case_prod (\<lambda>a. case_prod (\<lambda>(x :: 'a) (y :: 'b). P a (x, y)))"
by (auto simp: split_def)
lemmas L2_split_fixups =
L2_split_fixup_1
L2_split_fixup_2
L2_split_fixup_3
L2_split_fixup_4
L2_split_fixup_f [where f=L2_guard]
L2_split_fixup_f [where f=L2_gets]
L2_split_fixup_f [where f=L2_modify]
L2_split_fixup_g [where P="\<lambda>a b. L2_gets (P a b) n" for P n]
L2_split_fixup_g [where P="\<lambda>a b. L2_guard (P a b)" for P]
L2_split_fixup_g [where P="\<lambda>a b. L2_modify (P a b)" for P]
L2_split_fixup_g [where P="\<lambda>a b. L2_spec (P a b)" for P]
L2_split_fixup_g [where P="\<lambda>a b. L2_throw (P a b) n" for P n]
L2_split_fixup_g [where P="\<lambda>a b. L2_seq (L a b) (R a b)" for L R]
L2_split_fixup_g [where P="\<lambda>a b. L2_while (C a b) (B a b) (I a b) n" for C B I n]
L2_split_fixup_g [where P="\<lambda>a b. L2_unknown n" for n]
L2_split_fixup_g [where P="\<lambda>a b. L2_catch (L a b) (R a b)" for L R]
L2_split_fixup_g [where P="\<lambda>a b. L2_condition (C a b) (L a b) (R a b)" for C L R]
L2_split_fixup_g [where P="\<lambda>a b. L2_call (M a b)" for M]
lemmas L2_split_fixups_congs =
prod.case_cong
(* Peephole simplification rules for L2 programs (including HeapLift and WordAbstract). *)
named_theorems L2opt
(* L2 monad_mono rules *)
lemma L2_seq_monad_mono_step:
"\<lbrakk> monad_mono_step f m; \<And>x. monad_mono_step (\<lambda>m. g m x) m \<rbrakk>
\<Longrightarrow> monad_mono_step (\<lambda>m. L2_seq (f m) (g m)) m"
by (simp add: L2_seq_def monad_mono_step_bindE)
lemma L2_condition_monad_mono_step:
"\<lbrakk> monad_mono_step f m; monad_mono_step g m \<rbrakk>
\<Longrightarrow> monad_mono_step (\<lambda>m. L2_condition C (f m) (g m)) m"
by (simp add: L2_condition_def monad_mono_step_condition)
lemma L2_catch_monad_mono_step:
"\<lbrakk> monad_mono_step f m; \<And>x. monad_mono_step (\<lambda>m. g m x) m \<rbrakk>
\<Longrightarrow> monad_mono_step (\<lambda>m. L2_catch (f m) (g m)) m"
by (simp add: L2_catch_def monad_mono_step_handleE')
lemma L2_while_monad_mono_step:
"(\<And>x. monad_mono_step (\<lambda>m. B m x) m) \<Longrightarrow> monad_mono_step (\<lambda>m. L2_while C (B m) i n) m"
by (simp add: L2_while_def monad_mono_step_whileLoopE)
lemma L2_recguard_monad_mono_step:
"monad_mono_step f m \<Longrightarrow> monad_mono_step (\<lambda>m. L2_recguard m (f m)) m"
by (simp add: L2_recguard_def monad_mono_step_def condition_def fail_def)
lemma L2_reccall_monad_mono_step:
"monad_mono_step f m \<Longrightarrow> monad_mono_step (\<lambda>m. L2_call (f m)) m"
apply (simp add: L2_call_def)
apply (force intro: monad_mono_step_bindE monad_mono_step_const monad_mono_step_handleE')
done
lemmas L2_monad_mono_step_rules =
monad_mono_step_const
L2_while_monad_mono_step
L2_recguard_monad_mono_step
L2_catch_monad_mono_step
L2_seq_monad_mono_step
L2_condition_monad_mono_step
L2_reccall_monad_mono_step
monad_mono_step_recguard_dec_Suc
(* Base case *)
lemma monad_mono_step_L2_recguard_0:
"monad_mono_step (\<lambda>m. L2_recguard m (x m)) 0"
by (monad_eq simp: monad_mono_step_def L2_recguard_def)
end