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
|
Require Import Sail.State_monad.
(*Require Import Sail.Values_lemmas.*)
Require Export Setoid.
Require Export Morphisms Equivalence.
(* Basic results for reasoning about definitions which use the state monad.
Note that rewriting results are put into both a rewriting hint database and
a normal automation one. The former can be used with autorewrite and friends,
but the latter can be used with the rewriting under congruence tactics, such as
statecong in Sail.State_lemmas, and PrePostE_rewrite in Hoare. *)
(* Ensure that pointwise equality on states is the preferred notion of
equivalence for the state monad. *)
Local Open Scope equiv_scope.
Instance monadS_equivalence {Regs A E} :
Equivalence (pointwise_relation (sequential_state Regs) (@eq (list (result A E * sequential_state Regs)))) | 9.
split; apply _.
Qed.
Global Instance refl_eq_subrelation {A : Type} {R : A -> A -> Prop} `{Reflexive A R} : subrelation eq R.
intros x y EQ. subst. reflexivity.
Qed.
Hint Extern 4 (_ === _) => reflexivity : core.
Hint Extern 4 (_ === _) => symmetry : core.
Lemma bindS_ext_cong (*[fundef_cong]:*) {Regs A B E}
{m1 m2 : monadS Regs A E} {f1 f2 : A -> monadS Regs B E} s :
m1 s = m2 s ->
(forall a s', List.In (Value a, s') (m2 s) -> f1 a s' = f2 a s') ->
bindS m1 f1 s = bindS m2 f2 s.
intros.
unfold bindS.
rewrite H.
rewrite !List.flat_map_concat_map.
f_equal.
apply List.map_ext_in.
intros [[a|a] s'] H_in; auto.
Qed.
(* Weaker than the Isabelle version, but avoids talking about individual states *)
Lemma bindS_cong (*[fundef_cong]:*) Regs A B E m1 m2 (f1 f2 : A -> monadS Regs B E) :
m1 === m2 ->
(forall a, f1 a === f2 a) ->
bindS m1 f1 === bindS m2 f2.
intros M F s.
apply bindS_ext_cong; intros; auto.
apply F.
Qed.
Add Parametric Morphism {Regs A B E : Type} : (@bindS Regs A B E)
with signature equiv ==> equiv ==> equiv as bindS_morphism.
auto using bindS_cong.
Qed.
Lemma bindS_returnS_left Regs A B E {x : A} {f : A -> monadS Regs B E} :
bindS (returnS x) f === f x.
intro s.
unfold returnS, bindS.
simpl.
auto using List.app_nil_r.
Qed.
Hint Rewrite bindS_returnS_left : state.
Hint Resolve bindS_returnS_left : state.
Lemma bindS_returnS_right Regs A E {m : monadS Regs A E} :
bindS m returnS === m.
intro s.
unfold returnS, bindS.
induction (m s) as [|[[a|a] s'] t]; auto;
simpl;
rewrite IHt;
reflexivity.
Qed.
Hint Rewrite bindS_returnS_right : state.
Hint Resolve bindS_returnS_right : state.
Lemma bindS_readS {Regs A E} {f} {m : A -> monadS Regs A E} {s} :
bindS (readS f) m s = m (f s) s.
unfold readS, bindS.
simpl.
rewrite List.app_nil_r.
reflexivity.
Qed.
Lemma bindS_updateS {Regs A E} {f : sequential_state Regs -> sequential_state Regs} {m : unit -> monadS Regs A E} {s} :
bindS (updateS f) m s = m tt (f s).
unfold updateS, bindS.
simpl.
auto using List.app_nil_r.
Qed.
Lemma bindS_assertS_true Regs A E msg {f : unit -> monadS Regs A E} :
bindS (assert_expS true msg) f === f tt.
intro s.
unfold assert_expS, bindS.
simpl.
auto using List.app_nil_r.
Qed.
Hint Rewrite bindS_assertS_true : state.
Hint Resolve bindS_assertS_true : state.
Lemma bindS_chooseS_returnS (*[simp]:*) Regs A B E {xs : list A} {f : A -> B} :
bindS (Regs := Regs) (E := E) (chooseS xs) (fun x => returnS (f x)) === chooseS (List.map f xs).
intro s.
unfold chooseS, bindS, returnS.
induction xs; auto.
simpl. rewrite IHxs.
reflexivity.
Qed.
Hint Rewrite bindS_chooseS_returnS : state.
Hint Resolve bindS_chooseS_returnS : state.
Lemma result_cases : forall (A E : Type) (P : result A E -> Prop),
(forall a, P (Value a)) ->
(forall e, P (Ex (Throw e))) ->
(forall msg, P (Ex (Failure msg))) ->
forall r, P r.
intros.
destruct r; auto.
destruct e; auto.
Qed.
Lemma result_state_cases {A E S} {P : result A E * S -> Prop} :
(forall a s, P (Value a, s)) ->
(forall e s, P (Ex (Throw e), s)) ->
(forall msg s, P (Ex (Failure msg), s)) ->
forall rs, P rs.
intros.
destruct rs as [[a|[e|msg]] s]; auto.
Qed.
(* TODO: needs sets, not lists
Lemma monadS_ext_eqI {Regs A E} {m m' : monadS Regs A E} s :
(forall a s', List.In (Value a, s') (m s) <-> List.In (Value a, s') (m' s)) ->
(forall e s', List.In (Ex (Throw e), s') (m s) <-> List.In (Ex (Throw e), s') (m' s)) ->
(forall msg s', List.In (Ex (Failure msg), s') (m s) <-> List.In (Ex (Failure msg), s') (m' s)) ->
m s = m' s.
proof (intro set_eqI)
fix x
show "x \<in> m s \<longleftrightarrow> x \<in> m' s" using assms by (cases x rule: result_state_cases) auto
qed
lemma monadS_eqI:
fixes m m' :: "('regs, 'a, 'e) monadS"
assumes "\<And>s a s'. (Value a, s') \<in> m s \<longleftrightarrow> (Value a, s') \<in> m' s"
and "\<And>s e s'. (Ex (Throw e), s') \<in> m s \<longleftrightarrow> (Ex (Throw e), s') \<in> m' s"
and "\<And>s msg s'. (Ex (Failure msg), s') \<in> m s \<longleftrightarrow> (Ex (Failure msg), s') \<in> m' s"
shows "m = m'"
using assms by (intro ext monadS_ext_eqI)
*)
Lemma bindS_cases {Regs A B E} {m} {f : A -> monadS Regs B E} {r s s'} :
List.In (r, s') (bindS m f s) ->
(exists a a' s'', r = Value a /\ List.In (Value a', s'') (m s) /\ List.In (Value a, s') (f a' s'')) \/
(exists e, r = Ex e /\ List.In (Ex e, s') (m s)) \/
(exists e a s'', r = Ex e /\ List.In (Value a, s'') (m s) /\ List.In (Ex e, s') (f a s'')).
unfold bindS.
intro IN.
apply List.in_flat_map in IN.
destruct IN as [[r' s''] [INr' INr]].
destruct r' as [a'|e'].
* destruct r as [a|e].
+ left. eauto 10.
+ right; right. eauto 10.
* right; left. simpl in INr. destruct INr as [|[]]. inversion H. subst. eauto 10.
Qed.
Lemma bindS_intro_Value {Regs A B E} {m} {f : A -> monadS Regs B E} {s a s' a' s''} :
List.In (Value a', s'') (m s) -> List.In (Value a, s') (f a' s'') -> List.In (Value a, s') (bindS m f s).
intros; unfold bindS.
apply List.in_flat_map.
eauto.
Qed.
Lemma bindS_intro_Ex_left {Regs A B E} {m} {f : A -> monadS Regs B E} {s e s'} :
List.In (Ex e, s') (m s) -> List.In (Ex e, s') (bindS m f s).
intros; unfold bindS.
apply List.in_flat_map.
exists (Ex e, s').
auto with datatypes.
Qed.
Lemma bindS_intro_Ex_right {Regs A B E} {m} {f : A -> monadS Regs B E} {s e s' a s''} :
List.In (Ex e, s') (f a s'') -> List.In (Value a, s'') (m s) -> List.In (Ex e, s') (bindS m f s).
intros; unfold bindS.
apply List.in_flat_map.
eauto.
Qed.
Hint Resolve bindS_intro_Value bindS_intro_Ex_left bindS_intro_Ex_right : bindS_intros.
Lemma bindS_assoc Regs A B C E {m} {f : A -> monadS Regs B E} {g : B -> monadS Regs C E} :
bindS (bindS m f) g === bindS m (fun x => bindS (f x) g).
intro s.
unfold bindS.
induction (m s) as [ | [[a | e] t]].
* reflexivity.
* simpl. rewrite <- IHl.
rewrite !List.flat_map_concat_map.
rewrite List.map_app.
rewrite List.concat_app.
reflexivity.
* simpl. rewrite IHl. reflexivity.
Qed.
Hint Rewrite bindS_assoc : state.
Hint Resolve bindS_assoc : state.
Lemma bindS_failS Regs A B E {msg} {f : A -> monadS Regs B E} :
bindS (failS msg) f = failS msg.
reflexivity.
Qed.
Hint Rewrite bindS_failS : state.
Hint Resolve bindS_failS : state.
Lemma bindS_throwS Regs A B E {e} {f : A -> monadS Regs B E} :
bindS (throwS e) f = throwS e.
reflexivity.
Qed.
Hint Rewrite bindS_throwS : state.
Hint Resolve bindS_throwS : state.
(*declare seqS_def[simp]*)
Lemma seqS_def Regs A E m (m' : monadS Regs A E) :
m >>$ m' = m >>$= (fun _ => m').
reflexivity.
Qed.
Hint Rewrite seqS_def : state.
Hint Resolve seqS_def : state.
Lemma Value_bindS_elim {Regs A B E} {a m} {f : A -> monadS Regs B E} {s s'} :
List.In (Value a, s') (bindS m f s) ->
exists s'' a', List.In (Value a', s'') (m s) /\ List.In (Value a, s') (f a' s'').
intro H.
apply bindS_cases in H.
destruct H as [(a0 & a' & s'' & [= <-] & [*]) | [(e & [= ] & _) | (_ & _ & _ & [= ] & _)]].
eauto.
Qed.
Lemma Ex_bindS_elim {Regs A B E} {e m s s'} {f : A -> monadS Regs B E} :
List.In (Ex e, s') (bindS m f s) ->
List.In (Ex e, s') (m s) \/
exists s'' a', List.In (Value a', s'') (m s) /\ List.In (Ex e, s') (f a' s'').
intro H.
apply bindS_cases in H.
destruct H as [(? & ? & ? & [= ] & _) | [(? & [= <-] & X) | (? & ? & ? & [= <-] & X)]];
eauto.
Qed.
Lemma try_catchS_returnS Regs A E1 E2 {a} {h : E1 -> monadS Regs A E2}:
try_catchS (returnS a) h = returnS a.
reflexivity.
Qed.
Hint Rewrite try_catchS_returnS : state.
Hint Resolve try_catchS_returnS : state.
Lemma try_catchS_failS Regs A E1 E2 {msg} {h : E1 -> monadS Regs A E2}:
try_catchS (failS msg) h = failS msg.
reflexivity.
Qed.
Hint Rewrite try_catchS_failS : state.
Hint Resolve try_catchS_failS : state.
Lemma try_catchS_throwS Regs A E1 E2 {e} {h : E1 -> monadS Regs A E2}:
try_catchS (throwS e) h === h e.
intro s.
unfold try_catchS, throwS.
simpl.
auto using List.app_nil_r.
Qed.
Hint Rewrite try_catchS_throwS : state.
Hint Resolve try_catchS_throwS : state.
Lemma try_catchS_cong (*[cong]:*) {Regs A E1 E2 m1 m2} {h1 h2 : E1 -> monadS Regs A E2} :
m1 === m2 ->
(forall e, h1 e === h2 e) ->
try_catchS m1 h1 === try_catchS m2 h2.
intros H1 H2 s.
unfold try_catchS.
rewrite H1.
rewrite !List.flat_map_concat_map.
f_equal.
apply List.map_ext_in.
intros [[a|[e|msg]] s'] H_in; auto. apply H2.
Qed.
Add Parametric Morphism {Regs A E1 E2 : Type} : (@try_catchS Regs A E1 E2)
with signature equiv ==> equiv ==> equiv as try_catchS_morphism.
intros. auto using try_catchS_cong.
Qed.
Add Parametric Morphism {Regs A E : Type} : (@catch_early_returnS Regs A E)
with signature equiv ==> equiv as catch_early_returnS_morphism.
intros.
unfold catch_early_returnS.
rewrite H.
reflexivity.
Qed.
Lemma try_catchS_cases {Regs A E1 E2 m} {h : E1 -> monadS Regs A E2} {r s s'} :
List.In (r, s') (try_catchS m h s) ->
(exists a, r = Value a /\ List.In (Value a, s') (m s)) \/
(exists msg, r = Ex (Failure msg) /\ List.In (Ex (Failure msg), s') (m s)) \/
(exists e s'', List.In (Ex (Throw e), s'') (m s) /\ List.In (r, s') (h e s'')).
unfold try_catchS.
intro IN.
apply List.in_flat_map in IN.
destruct IN as [[r' s''] [INr' INr]].
destruct r' as [a'|[e'|msg]].
* left. simpl in INr. destruct INr as [[= <- <-] | []]. eauto 10.
* simpl in INr. destruct INr as [[= <- <-] | []]. eauto 10.
* eauto 10.
Qed.
Lemma try_catchS_intros {Regs A E1 E2} {m} {h : E1 -> monadS Regs A E2} :
(forall s a s', List.In (Value a, s') (m s) -> List.In (Value a, s') (try_catchS m h s)) /\
(forall s msg s', List.In (Ex (Failure msg), s') (m s) -> List.In (Ex (Failure msg), s') (try_catchS m h s)) /\
(forall s e s'' r s', List.In (Ex (Throw e), s'') (m s) -> List.In (r, s') (h e s'') -> List.In (r, s') (try_catchS m h s)).
repeat split; unfold try_catchS; intros;
apply List.in_flat_map.
* eexists; split; [ apply H | ]. simpl. auto.
* eexists; split; [ apply H | ]. simpl. auto.
* eexists; split; [ apply H | ]. simpl. auto.
Qed.
Lemma no_Ex_basic_builtins (*[simp]:*) {Regs E} {s s' : sequential_state Regs} {e : ex E} :
(forall A (a:A), ~ List.In (Ex e, s') (returnS a s)) /\
(forall A (f : _ -> A), ~ List.In (Ex e, s') (readS f s)) /\
(forall f, ~ List.In (Ex e, s') (updateS f s)) /\
(forall A (xs : list A), ~ List.In (Ex e, s') (chooseS xs s)).
repeat split; intros;
unfold returnS, readS, updateS, chooseS; simpl;
try intuition congruence.
* intro H.
apply List.in_map_iff in H.
destruct H as [x [X _]].
congruence.
Qed.
Import List.ListNotations.
Definition ignore_throw_aux {A E1 E2 S} (rs : result A E1 * S) : list (result A E2 * S) :=
match rs with
| (Value a, s') => [(Value a, s')]
| (Ex (Throw e), s') => []
| (Ex (Failure msg), s') => [(Ex (Failure msg), s')]
end.
Definition ignore_throw {A E1 E2 S} (m : S -> list (result A E1 * S)) s : list (result A E2 * S) :=
List.flat_map ignore_throw_aux (m s).
Lemma ignore_throw_cong {Regs A E1 E2} {m1 m2 : monadS Regs A E1} :
m1 === m2 ->
ignore_throw (E2 := E2) m1 === ignore_throw m2.
intros H s.
unfold ignore_throw.
rewrite H.
reflexivity.
Qed.
Lemma ignore_throw_aux_member_simps (*[simp]:*) {A E1 E2 S} {s' : S} {ms} :
(forall a:A, List.In (Value a, s') (ignore_throw_aux (E1 := E1) (E2 := E2) ms) <-> ms = (Value a, s')) /\
(forall e, ~ List.In (Ex (E := E2) (Throw e), s') (ignore_throw_aux ms)) /\
(forall msg, List.In (Ex (E := E2) (Failure msg), s') (ignore_throw_aux ms) <-> ms = (Ex (Failure msg), s')).
destruct ms as [[a' | [e' | msg']] s]; simpl;
intuition congruence.
Qed.
Lemma ignore_throw_member_simps (*[simp]:*) {A E1 E2 S} {s s' : S} {m} :
(forall {a:A}, List.In (Value (E := E2) a, s') (ignore_throw m s) <-> List.In (Value (E := E1) a, s') (m s)) /\
(forall {a:A}, List.In (Value (E := E2) a, s') (ignore_throw m s) <-> List.In (Value a, s') (m s)) /\
(forall e, ~ List.In (Ex (E := E2) (Throw e), s') (ignore_throw m s)) /\
(forall {msg}, List.In (Ex (E := E2) (Failure msg), s') (ignore_throw m s) <-> List.In (Ex (Failure msg), s') (m s)).
unfold ignore_throw.
repeat apply conj; intros; try apply conj;
rewrite ?List.in_flat_map;
solve
[ intros [x [H1 H2]]; apply ignore_throw_aux_member_simps in H2; congruence
| intro H; eexists; split; [ apply H | apply ignore_throw_aux_member_simps; reflexivity] ].
Qed.
Lemma ignore_throw_cases {A E S} {m : S -> list (result A E * S)} {r s s'} :
ignore_throw m s = m s ->
List.In (r, s') (m s) ->
(exists a, r = Value a) \/
(exists msg, r = Ex (Failure msg)).
destruct r as [a | [e | msg]]; eauto.
* intros H1 H2. rewrite <- H1 in H2.
apply ignore_throw_member_simps in H2.
destruct H2.
Qed.
(* *** *)
Lemma flat_map_app {A B} {f : A -> list B} {l1 l2} :
List.flat_map f (l1 ++ l2) = (List.flat_map f l1 ++ List.flat_map f l2)%list.
rewrite !List.flat_map_concat_map.
rewrite List.map_app, List.concat_app.
reflexivity.
Qed.
Lemma ignore_throw_bindS (*[simp]:*) Regs A B E E2 {m} {f : A -> monadS Regs B E} :
ignore_throw (E2 := E2) (bindS m f) === bindS (ignore_throw m) (fun s => ignore_throw (f s)).
intro s.
unfold bindS, ignore_throw.
induction (m s) as [ | [[a | [e | msg]] t]].
* reflexivity.
* simpl. rewrite <- IHl. rewrite flat_map_app. reflexivity.
* simpl. rewrite <- IHl. reflexivity.
* simpl. apply IHl.
Qed.
Hint Rewrite ignore_throw_bindS : ignore_throw.
Hint Resolve ignore_throw_bindS : ignore_throw.
Lemma try_catchS_bindS_no_throw {Regs A B E1 E2} {m1 : monadS Regs A E1} {m2 : monadS Regs A E2} {f : A -> monadS Regs B _} {h} :
ignore_throw m1 === m1 ->
ignore_throw m1 === m2 ->
try_catchS (bindS m1 f) h === bindS m2 (fun a => try_catchS (f a) h).
intros Ignore1 Ignore2.
transitivity ((ignore_throw m1 >>$= (fun a => try_catchS (f a) h))).
* intro s.
unfold bindS, try_catchS, ignore_throw.
specialize (Ignore1 s). revert Ignore1. unfold ignore_throw.
induction (m1 s) as [ | [[a | [e | msg]] t]]; auto.
+ intro Ig. simpl. rewrite flat_map_app. rewrite IHl. auto. injection Ig. auto.
+ intro Ig. simpl. rewrite IHl. reflexivity. injection Ig. auto.
+ intro Ig. exfalso. clear -Ig.
assert (List.In (Ex (Throw msg), t) (List.flat_map ignore_throw_aux l)).
simpl in Ig. rewrite Ig. simpl. auto.
apply List.in_flat_map in H.
destruct H as [x [H1 H2]].
apply ignore_throw_aux_member_simps in H2.
assumption.
* apply bindS_cong; auto.
Qed.
Lemma concat_map_singleton {A B} {f : A -> B} {a : list A} :
List.concat (List.map (fun x => [f x]%list) a) = List.map f a.
induction a; simpl; try rewrite IHa; auto with datatypes.
Qed.
(*lemma no_throw_basic_builtins[simp]:*)
Lemma no_throw_basic_builtins_1 Regs A E E2 {a : A} :
ignore_throw (E1 := E2) (returnS a) = @returnS Regs A E a.
reflexivity. Qed.
Lemma no_throw_basic_builtins_2 Regs A E E2 {f : sequential_state Regs -> A} :
ignore_throw (E1 := E) (E2 := E2) (readS f) = readS f.
reflexivity. Qed.
Lemma no_throw_basic_builtins_3 Regs E E2 {f : sequential_state Regs -> sequential_state Regs} :
ignore_throw (E1 := E) (E2 := E2) (updateS f) = updateS f.
reflexivity. Qed.
Lemma no_throw_basic_builtins_4 Regs A E1 E2 {xs : list A} :
ignore_throw (E1 := E1) (chooseS xs) === @chooseS Regs A E2 xs.
intro s.
unfold ignore_throw, chooseS.
rewrite List.flat_map_concat_map, List.map_map. simpl.
rewrite concat_map_singleton.
reflexivity.
Qed.
Lemma no_throw_basic_builtins_5 Regs E1 E2 :
ignore_throw (E1 := E1) (choose_boolS tt) = @choose_boolS Regs E2 tt.
reflexivity. Qed.
Lemma no_throw_basic_builtins_6 Regs A E1 E2 msg :
ignore_throw (E1 := E1) (failS msg) = @failS Regs A E2 msg.
reflexivity. Qed.
Lemma no_throw_basic_builtins_7 Regs A E1 E2 msg x :
ignore_throw (E1 := E1) (maybe_failS msg x) = @maybe_failS Regs A E2 msg x.
destruct x; reflexivity. Qed.
Hint Rewrite no_throw_basic_builtins_1 no_throw_basic_builtins_2
no_throw_basic_builtins_3 no_throw_basic_builtins_4
no_throw_basic_builtins_5 no_throw_basic_builtins_6
no_throw_basic_builtins_7 : ignore_throw.
Hint Resolve no_throw_basic_builtins_1 no_throw_basic_builtins_2
no_throw_basic_builtins_3 no_throw_basic_builtins_4
no_throw_basic_builtins_5 no_throw_basic_builtins_6
no_throw_basic_builtins_7 : ignore_throw.
Lemma ignore_throw_option_case_distrib_1 Regs B C E1 E2 (c : sequential_state Regs -> option B) s (n : monadS Regs C E1) (f : B -> monadS Regs C E1) :
ignore_throw (E2 := E2) (match c s with None => n | Some b => f b end) s =
match c s with None => ignore_throw n s | Some b => ignore_throw (f b) s end.
destruct (c s); auto.
Qed.
Lemma ignore_throw_option_case_distrib_2 Regs B C E1 E2 (c : option B) (n : monadS Regs C E1) (f : B -> monadS Regs C E1) :
ignore_throw (E2 := E2) (match c with None => n | Some b => f b end) =
match c with None => ignore_throw n | Some b => ignore_throw (f b) end.
destruct c; auto.
Qed.
Lemma ignore_throw_let_distrib Regs A B E1 E2 (y : A) (f : A -> monadS Regs B E1) :
ignore_throw (E2 := E2) (let x := y in f x) = (let x := y in ignore_throw (f x)).
reflexivity.
Qed.
Lemma no_throw_mem_builtins_1 Regs E1 E2 rk a sz :
ignore_throw (E2 := E2) (@read_memt_bytesS Regs E1 rk a sz) === read_memt_bytesS rk a sz.
unfold read_memt_bytesS. autorewrite with ignore_throw.
apply bindS_cong; auto. intros. autorewrite with ignore_throw. reflexivity.
Qed.
Hint Rewrite no_throw_mem_builtins_1 : ignore_throw.
Hint Resolve no_throw_mem_builtins_1 : ignore_throw.
Lemma no_throw_mem_builtins_2 Regs E1 E2 rk a sz :
ignore_throw (E2 := E2) (@read_mem_bytesS Regs E1 rk a sz) === read_mem_bytesS rk a sz.
unfold read_mem_bytesS. autorewrite with ignore_throw.
apply bindS_cong; intros; autorewrite with ignore_throw; auto.
destruct a0; reflexivity.
Qed.
Hint Rewrite no_throw_mem_builtins_2 : ignore_throw.
Hint Resolve no_throw_mem_builtins_2 : ignore_throw.
Lemma no_throw_mem_builtins_3 Regs A E1 E2 a :
ignore_throw (E2 := E2) (@read_tagS Regs A E1 a) === read_tagS a.
reflexivity. Qed.
Hint Rewrite no_throw_mem_builtins_3 : ignore_throw.
Hint Resolve no_throw_mem_builtins_3 : ignore_throw.
Lemma no_throw_mem_builtins_4 Regs A V E1 E2 rk a sz H :
ignore_throw (E2 := E2) (@read_memtS Regs E1 A V rk a sz H) === read_memtS rk a sz.
unfold read_memtS. autorewrite with ignore_throw.
apply bindS_cong; intros; autorewrite with ignore_throw.
reflexivity. destruct a0; simpl. autorewrite with ignore_throw.
reflexivity.
Qed.
Hint Rewrite no_throw_mem_builtins_4 : ignore_throw.
Hint Resolve no_throw_mem_builtins_4 : ignore_throw.
Lemma no_throw_mem_builtins_5 Regs A V E1 E2 rk a sz H :
ignore_throw (E2 := E2) (@read_memS Regs E1 A V rk a sz H) === read_memS rk a sz.
unfold read_memS. autorewrite with ignore_throw.
apply bindS_cong; intros; autorewrite with ignore_throw; auto.
destruct a0; auto.
Qed.
Hint Rewrite no_throw_mem_builtins_5 : ignore_throw.
Hint Resolve no_throw_mem_builtins_5 : ignore_throw.
Lemma no_throw_mem_builtins_6 Regs E1 E2 wk addr sz v t :
ignore_throw (E2 := E2) (@write_memt_bytesS Regs E1 wk addr sz v t) === write_memt_bytesS wk addr sz v t.
unfold write_memt_bytesS. unfold seqS. autorewrite with ignore_throw.
reflexivity.
Qed.
Hint Rewrite no_throw_mem_builtins_6 : ignore_throw.
Hint Resolve no_throw_mem_builtins_6 : ignore_throw.
Lemma no_throw_mem_builtins_7 Regs E1 E2 wk addr sz v :
ignore_throw (E2 := E2) (@write_mem_bytesS Regs E1 wk addr sz v) === write_mem_bytesS wk addr sz v.
unfold write_mem_bytesS. autorewrite with ignore_throw. reflexivity.
Qed.
Hint Rewrite no_throw_mem_builtins_7 : ignore_throw.
Hint Resolve no_throw_mem_builtins_7 : ignore_throw.
Lemma no_throw_mem_builtins_8 Regs E1 E2 A B wk addr sz v t :
ignore_throw (E2 := E2) (@write_memtS Regs E1 A B wk addr sz v t) === write_memtS wk addr sz v t.
unfold write_memtS. rewrite ignore_throw_option_case_distrib_2.
destruct (Sail.Values.mem_bytes_of_bits v); autorewrite with ignore_throw; auto.
Qed.
Hint Rewrite no_throw_mem_builtins_8 : ignore_throw.
Hint Resolve no_throw_mem_builtins_8 : ignore_throw.
Lemma no_throw_mem_builtins_9 Regs E1 E2 A B wk addr sz v :
ignore_throw (E2 := E2) (@write_memS Regs E1 A B wk addr sz v) === write_memS wk addr sz v.
unfold write_memS. autorewrite with ignore_throw; auto.
Qed.
Hint Rewrite no_throw_mem_builtins_9 : ignore_throw.
Hint Resolve no_throw_mem_builtins_9 : ignore_throw.
Lemma no_throw_mem_builtins_10 Regs E1 E2 :
ignore_throw (E2 := E2) (@excl_resultS Regs E1 tt) === excl_resultS tt.
reflexivity. Qed.
Hint Rewrite no_throw_mem_builtins_10 : ignore_throw.
Hint Resolve no_throw_mem_builtins_10 : ignore_throw.
Lemma no_throw_mem_builtins_11 Regs E1 E2 :
ignore_throw (E2 := E2) (@undefined_boolS Regs E1 tt) === undefined_boolS tt.
reflexivity. Qed.
Hint Rewrite no_throw_mem_builtins_11 : ignore_throw.
Hint Resolve no_throw_mem_builtins_11 : ignore_throw.
Lemma no_throw_read_regvalS Regs RV E1 E2 r reg_name :
ignore_throw (E2 := E2) (@read_regvalS Regs RV E1 r reg_name) === read_regvalS r reg_name.
destruct r; simpl. autorewrite with ignore_throw.
apply bindS_cong; intros; auto. rewrite ignore_throw_option_case_distrib_2.
autorewrite with ignore_throw. reflexivity.
Qed.
Hint Rewrite no_throw_read_regvalS : ignore_throw.
Hint Resolve no_throw_read_regvalS : ignore_throw.
Lemma no_throw_write_regvalS Regs RV E1 E2 r reg_name v :
ignore_throw (E2 := E2) (@write_regvalS Regs RV E1 r reg_name v) === write_regvalS r reg_name v.
destruct r; simpl. autorewrite with ignore_throw.
apply bindS_cong; intros; auto. rewrite ignore_throw_option_case_distrib_2.
autorewrite with ignore_throw. reflexivity.
Qed.
Hint Rewrite no_throw_write_regvalS : ignore_throw.
Hint Resolve no_throw_write_regvalS : ignore_throw.
|