1open HolKernel Parse boolLib bossLib;
2open optionTheory pairTheory pred_setTheory finite_mapTheory stringTheory;
3open integerTheory listTheory optionTheory rich_listTheory;
4open BasicProvers;
5open for_ndTheory for_nd_semTheory oracleSemTheory simple_traceTheory;
6open relationTheory;
7
8val _ = new_theory "for_osmall";
9
10val ect = BasicProvers.EVERY_CASE_TAC;
11val fct = BasicProvers.FULL_CASE_TAC;
12
13val some_no_choice = Q.prove (
14`!f. (some x. f x) = NONE ��� ��?x. f x`,
15 rw [some_def]);
16
17val some_SAT = Q.prove(
18`!P y. (some x. P x) = SOME y ��� P y`,
19rw[some_def,SELECT_THM]>>
20metis_tac[SELECT_AX])
21
22(* A small step semantics for the non-deterministic FOR language with I/O *)
23
24(* Add AddL and AddR to model making the choice one which sub-expression to
25 * evaluate before starting the evaluation. Thus preventing switching in the
26 * middle of evaluating one of them.
27 *)
28val _ = Datatype `
29small_e =
30  | Var string
31  | Num int
32  | Add small_e small_e
33  | AddL small_e small_e
34  | AddR small_e small_e
35  | Assign string small_e
36  | Getchar
37  | Putchar small_e`;
38
39(* Add a Handle statement that will stop breaks from propagating *)
40val _ = Datatype `
41small_t =
42  | Dec string small_t
43  | Exp small_e
44  | Break
45  | Seq small_t small_t
46  | If small_e small_t small_t
47  | For small_e small_e small_t
48  | Handle small_t`;
49
50val _ = Datatype `
51  lab = ND bool | W char | R char`;
52
53val e_to_small_e_def = Define `
54(e_to_small_e ((Num i):e) = ((Num i) : small_e)) ���
55(e_to_small_e (Var x) = Var x) ���
56(e_to_small_e (Add e1 e2) = Add (e_to_small_e e1) (e_to_small_e e2)) ���
57(e_to_small_e (Assign x e) = Assign x (e_to_small_e e)) ���
58(e_to_small_e Getchar = Getchar) ���
59(e_to_small_e (Putchar e) = Putchar (e_to_small_e e))`;
60
61val t_to_small_t_def = Define `
62(t_to_small_t ((Dec string t):t) = ((Dec string (t_to_small_t t)) : small_t)) ���
63(t_to_small_t (Exp e) = Exp (e_to_small_e e)) ���
64(t_to_small_t Break = Break) ���
65(t_to_small_t (Seq t1 t2) = Seq (t_to_small_t t1) (t_to_small_t t2)) ���
66(t_to_small_t (If e t1 t2) = If (e_to_small_e e) (t_to_small_t t1) (t_to_small_t t2)) ���
67(t_to_small_t (For e1 e2 t) = For (e_to_small_e e1) (e_to_small_e e2) (t_to_small_t t))`;
68
69val is_val_e_def = Define `
70(is_val_e (Num n) = T) ���
71(is_val_e _ = F)`;
72
73val (step_e_rules, step_e_ind, step_e_cases) = Hol_reln `
74(!s x n.
75  FLOOKUP s.store x = SOME n
76  ���
77  step_e (s, Var x) NONE (s, Num n)) ���
78(!s e1 e2 o'.
79  oracle_get s.non_det_o = (F, o')
80  ���
81  step_e (s, Add e1 e2)
82         (SOME (INR F))
83         (s with <| non_det_o := o'; io_trace := s.io_trace ++ [INR F] |>, AddL e1 e2)) ���
84(!s e1 e2 o'.
85  oracle_get s.non_det_o = (T, o')
86  ���
87  step_e (s, Add e1 e2) (SOME (INR T)) (s with <| non_det_o := o'; io_trace := s.io_trace ++ [INR T] |>, AddR e1 e2)) ���
88(!s n1 n2.
89  step_e (s, AddL (Num n1) (Num n2)) NONE (s, Num (n1 + n2))) ���
90(!s n1 n2.
91  step_e (s, AddR (Num n1) (Num n2)) NONE (s, Num (n1 + n2))) ���
92(!s s2 e1 e2 e3 l.
93  step_e (s, e1) l (s2, e3)
94  ���
95  step_e (s, AddL e1 e2) l (s2, AddL e3 e2)) ���
96(!s s2 i e1 e2 l.
97  step_e (s, e1) l (s2, e2)
98  ���
99  step_e (s, AddL (Num i) e1) l (s2, AddL (Num i) e2)) ���
100(!s s2 i e1 e2 l.
101  step_e (s, e1) l (s2, e2)
102  ���
103  step_e (s, AddR e1 (Num i)) l (s2, AddR e2 (Num i))) ���
104(!s s2 e1 e2 e3 l.
105  step_e (s, e2) l (s2, e3)
106  ���
107  step_e (s, AddR e1 e2) l (s2, AddR e1 e3)) ���
108(!s x n.
109  step_e (s, Assign x (Num n)) NONE (s with store := s.store |+ (x, n), Num n)) ���
110(!s s2 x e1 e2 l.
111  step_e (s, e1) l (s2, e2)
112  ���
113  step_e (s, Assign x e1) l (s2, Assign x e2)) ���
114(!s i input'.
115  getchar s.input = (i,input')
116  ���
117  step_e (s, Getchar)
118         (SOME (INL (Itag i)))
119         (s with <| input := input'; io_trace := s.io_trace ++ [INL (Itag i)] |>, Num i)) ���
120(!s s2 e1 e2 l.
121  step_e (s, e1) l (s2, e2)
122  ���
123  step_e (s, Putchar e1) l (s2, Putchar e2)) ���
124(!s i.
125  step_e (s, Putchar (Num i))
126         (SOME (INL (Otag i)))
127         (s with io_trace := s.io_trace ++ [INL (Otag i)], Num i))`;
128
129val is_val_t_def = Define `
130(is_val_t (Exp (e : small_e)) = is_val_e e) ���
131(is_val_t Break = T) ���
132(is_val_t _ = F)`;
133
134val (step_t_rules, step_t_ind, step_t_cases) = Hol_reln `
135(!s t x.
136  step_t (s, Dec x t) NONE (s with store := s.store |+ (x, 0), t)) ���
137(!s s2 e e2 l.
138  step_e (s, e) l (s2, e2)
139  ���
140  step_t (s, Exp e) l (s2, Exp e2)) ���
141(!s s2 t1 t2 t1' l.
142  step_t (s, t1) l (s2, t1')
143  ���
144  step_t (s, Seq t1 t2) l (s2, Seq t1' t2)) ���
145(!s t.
146  step_t (s, Seq Break t) NONE (s, Break)) ���
147(!s n t.
148  step_t (s, Seq (Exp (Num n)) t) NONE (s, t)) ���
149(!s s2 e t1 t2 e2 l.
150  step_e (s, e) l (s2,e2)
151  ���
152  step_t (s, If e t1 t2) l (s2, If e2 t1 t2)) ���
153(!s t1 t2.
154  step_t (s, If (Num 0) t1 t2) NONE (s, t2)) ���
155(!s n t1 t2.
156  n ��� 0
157  ���
158  step_t (s, If (Num n) t1 t2) NONE (s, t1)) ���
159(!s.
160  step_t (s, Handle Break) NONE (s, Exp (Num 0))) ���
161(!s t.
162  is_val_t t ���
163  t ��� Break
164  ���
165  step_t (s, Handle t) NONE (s, t)) ���
166(!s1 s2 t1 t2 l.
167  step_t (s1, t1) l (s2, t2)
168  ���
169  step_t (s1, Handle t1) l (s2, Handle t2)) ���
170(!s e1 e2 t.
171  step_t (s, For e1 e2 t) NONE (s, Handle (If e1 (Seq t (Seq (Exp e2) (For e1 e2 t))) (Exp (Num 0)))))`;
172
173val filter_map_def = Define `
174(filter_map f [] = []) ���
175(filter_map f (h::t) =
176  case f h of
177  | NONE => filter_map f t
178  | SOME x => x :: filter_map f t)`;
179
180val path_to_obs_def = Define `
181  path_to_obs p =
182    if ��finite p then
183      Diverge (lfilter_map I (labels p))
184    else if is_val_t (SND (last p)) then
185      Terminate (filter_map I (THE (toList (labels p))))
186    else
187      Crash`;
188
189val semantics_small_def = Define `
190  (semantics_small input prog =
191    { path_to_obs p | p,nd |
192      okpath step_t p ��� complete step_t p ��� first p = (init_st 0 nd input, t_to_small_t prog) })`;
193
194(* ----------- Connect to functional big step -------------- *)
195
196val for_small_sem_def = Define `
197  for_small_sem input =
198    <| step := (\st. some st'. ?l. step_t st l st');
199       is_result := (\st. is_val_t (SND st));
200       load := (\nd t. (init_st 0 nd input , t_to_small_t t));
201       unload := (\st. (FST st).io_trace) |>`;
202
203val for_eval_def = Define `
204  for_eval st env t =
205    case sem_t st t of
206      (Rval v, s) => (s, Val (SOME v))
207    | (Rbreak, s) => (s, Val NONE)
208    | (Rtimeout, s) => (s, Timeout)
209    | (Rfail, s) => (s, Error)`;
210
211val for_big_sem_def = Define `
212  for_big_sem input =
213    <| eval := for_eval;
214       init_st := (\nd. init_st 0 nd input);
215       init_env := ();
216       get_clock := (\x. x.clock);
217       set_clock := (\c st. st with clock := c);
218       get_oracle_events := (\st. st.io_trace) |>`;
219
220val (res_rel_t_rules, res_rel_t_ind, res_rel_t_cases) = Hol_reln `
221(!i s.
222  res_rel_t (Rval i, s) (s with clock := 0, Exp (Num i))) ���
223(!s t.
224  (~?l s' t'. step_t (s with clock := 0, t) l (s', t')) ���
225  ~is_val_t t
226  ���
227  res_rel_t (Rfail, s) (s with clock := 0, t)) ���
228(!s.
229  res_rel_t (Rbreak, s) (s with clock := 0, Break)) ���
230(!s t.
231  (?l s' t'. step_t (s, t) l (s', t')) ���
232  s.clock = 0
233  ���
234  res_rel_t (Rtimeout, s) (s, t))`;
235
236val (res_rel_e_rules, res_rel_e_ind, res_rel_e_cases) = Hol_reln `
237(!i s.
238  res_rel_e (Rval i, s) (s with clock:=0, Num i)) ���
239(!s e.
240  (~?s' e' l. step_e (s, e) l (s', e')) ���
241  ~is_val_e e
242  ���
243  res_rel_e (Rfail, s) (s with clock:=0, e))`
244
245val _ = set_trace "Goalstack.print_goal_at_top" 0;
246
247val step_t_strongind = (fetch "-" "step_t_strongind")
248val step_e_strongind = (fetch "-" "step_e_strongind")
249
250val conjs_def = Define` conjs A B ��� A ��� B`
251
252val etac = (fs[Once step_t_cases]>>fs[Once step_t_cases,Once step_e_cases,conjs_def])
253
254(* Determinism of small-step w.r.t. an oracle *)
255
256val step_e_determ = Q.prove(
257` ���se l1 se1.
258  step_e se l1 se1 ���
259  (���l2 se2.
260  step_e se l2 se2 ��� conjs (se1 = se2) (l1 = l2))`,
261  ho_match_mp_tac step_e_strongind>>rw[]>>fs[FORALL_PROD]
262  >- (rw[conjs_def]>>fs[Once step_e_cases]>>rfs[])
263  >- (rw[conjs_def]>>ntac 2(fs[Once step_e_cases]>>rfs[]))
264  >- (rw[conjs_def]>>ntac 2(fs[Once step_e_cases]>>rfs[]))
265  >- (rw[conjs_def]>>ntac 2(fs[Once step_e_cases]>>rfs[]))
266  >- (rw[conjs_def]>>ntac 2(fs[Once step_e_cases]>>rfs[]))
267  >>
268  TRY
269    (pop_assum mp_tac>>simp[Once step_e_cases]>>rw[]>>
270    fs[Once step_e_cases])
271  >>
272  fs[conjs_def])|>REWRITE_RULE[conjs_def]
273
274val step_t_determ = Q.prove(
275` ���st l1 st1.
276  step_t st l1 st1 ���
277  (���l2 st2.
278  step_t st l2 st2 ��� conjs (st1 = st2) (l1 = l2))`,
279  ho_match_mp_tac step_t_strongind >>rw[]
280  >- etac
281  >-
282    (fs[Once step_t_cases]>>
283    imp_res_tac step_e_determ>>
284    fs[conjs_def])
285  >-
286    (pop_assum mp_tac>>
287    simp[Once step_t_cases]>>fs[FORALL_PROD]>>rw[]>>
288    fs[Once step_t_cases,Once step_e_cases])
289  >- etac
290  >- etac
291  >-
292    (fs[Once step_t_cases]
293    >-
294      (imp_res_tac step_e_determ>>fs[conjs_def])
295    >> etac)
296  >- etac
297  >- etac
298  >- etac
299  >-
300    (fs[Once step_t_cases]>>rfs[conjs_def]>>
301    Cases_on`t`>>fs[is_val_t_def]>>
302    Cases_on`s'`>>fs[is_val_e_def]>>
303    fs[Once step_t_cases]>>
304    fs[Once step_e_cases])
305  >-
306    (pop_assum mp_tac>>
307    simp[Once step_t_cases]>>rw[]
308    >-
309      etac
310    >-
311      (Cases_on`t1`>>fs[is_val_t_def]>>Cases_on`s`>>fs[is_val_e_def]>>
312      fs[Once step_t_cases,Once step_e_cases])
313    >>
314      fs[FORALL_PROD]>>metis_tac[])
315  >>
316    fs[Once step_t_cases,conjs_def])|>REWRITE_RULE[conjs_def]
317
318val step_t_select_unique = Q.prove(
319`step_t (q,r) l st' ���
320 (@st'. ���l. step_t (q,r) l st') = st'`,
321 rw[]>>
322 metis_tac[step_t_determ])
323
324val some_to_SOME_step_e = Q.prove(
325`step_e A l B ���
326  (some st'. ���l. step_e A l st') = SOME B`,
327 rw[]>>fs[some_def]>>
328 metis_tac[step_e_determ]) |> GEN_ALL
329
330val some_to_SOME_step_t = Q.prove(
331`step_t A l B ���
332 (some st'. ���l. step_t A l st') =
333 SOME B`,
334 rw[]>>fs[some_def]>>metis_tac[step_t_determ]) |>GEN_ALL
335
336(* Contextual transitions of the small step semantics *)
337val check_trace_seq = Q.prove(
338`���tr.
339 check_trace (��st. some st'. ���l. step_t st l st') tr ���
340 check_trace (��st. some st'. ���l. step_t st l st') (MAP (��st,t. (st,Seq t p)) tr)`,
341 Induct>>rw[]>>
342 Cases_on`tr`>>fs[check_trace_def]>>
343 Cases_on`h`>>Cases_on`h'`>>
344 match_mp_tac some_to_SOME_step_t>>
345 fs[some_def]>>
346 simp[Once step_t_cases]>>
347 metis_tac[step_t_select_unique])
348
349val check_trace_assign = Q.prove(
350`���tr.
351 check_trace (��st. some st'. ?l. step_e st l st') tr ���
352 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e. (st,Assign s e)) tr)`,
353 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
354 Cases_on`h`>>Cases_on`h'`>>
355 match_mp_tac some_to_SOME_step_e>>
356 fs[some_def]>>
357 simp[Once step_e_cases]>>
358 metis_tac[step_e_determ])
359
360val check_trace_putchar = Q.prove(
361`���tr.
362 check_trace (��st. some st'. ?l. step_e st l st') tr ���
363 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e. (st,Putchar e)) tr)`,
364 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
365 Cases_on`h`>>Cases_on`h'`>>
366 match_mp_tac some_to_SOME_step_e>>
367 fs[some_def]>>
368 simp[Once step_e_cases]>>
369 metis_tac[step_e_determ])
370
371val check_trace_addl1 = Q.prove(
372`���tr.
373 check_trace (��st. some st'. ?l. step_e st l st') tr ���
374 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e. (st,AddL e e')) tr)`,
375 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
376 Cases_on`h`>>Cases_on`h'`>>
377 match_mp_tac some_to_SOME_step_e>>
378 fs[some_def]>>
379 simp[Once step_e_cases]>>
380 metis_tac[step_e_determ])
381
382val check_trace_addl2 = Q.prove(
383`���tr.
384 check_trace (��st. some st'. ?l. step_e st l st') tr ���
385 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e'. (st,AddL (Num i) e')) tr)`,
386 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
387 Cases_on`h`>>Cases_on`h'`>>
388 match_mp_tac some_to_SOME_step_e>>
389 fs[some_def]>>
390 simp[Once step_e_cases]>>
391 metis_tac[step_e_determ])
392
393val check_trace_addr1 = Q.prove(
394`���tr.
395 check_trace (��st. some st'. ?l. step_e st l st') tr ���
396 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e'. (st,AddR e e')) tr)`,
397 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
398 Cases_on`h`>>Cases_on`h'`>>
399 match_mp_tac some_to_SOME_step_e>>
400 fs[some_def]>>
401 simp[Once step_e_cases]>>
402 metis_tac[step_e_determ,is_val_e_def])
403
404val check_trace_addr2 = Q.prove(
405`���tr.
406 check_trace (��st. some st'. ?l. step_e st l st') tr ���
407 check_trace (��st. some st'. ?l. step_e st l st') (MAP (��st,e'. (st,AddR e' (Num i))) tr)`,
408 Induct>>rw[]>>Cases_on`tr`>>fs[check_trace_def]>>
409 Cases_on`h`>>Cases_on`h'`>>
410 match_mp_tac some_to_SOME_step_e>>
411 fs[some_def]>>
412 simp[Once step_e_cases]>>
413 metis_tac[step_e_determ,is_val_e_def])
414
415val check_trace_exp = Q.prove(
416`���tr.
417 check_trace (��st. some st'. ?l. step_e st l st') tr ���
418 check_trace (��st. some st'. ?l. step_t st l st') (MAP (��st,e'. (st,Exp e')) tr)`,
419 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
420 Cases_on`h`>>Cases_on`h'`>>
421 match_mp_tac some_to_SOME_step_t>>
422 fs[some_def]>>
423 simp[Once step_t_cases]>>
424 metis_tac[step_e_determ])
425
426val check_trace_if1 = Q.prove(
427`���tr.
428 check_trace (��st. some st'. ?l. step_e st l st') tr ���
429 check_trace (��st. some st'. ?l. step_t st l st') (MAP (��st,e'. (st,If e' a b)) tr)`,
430 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
431 Cases_on`h`>>Cases_on`h'`>>
432 match_mp_tac some_to_SOME_step_t>>
433 fs[some_def]>>
434 simp[Once step_t_cases]>>
435 metis_tac[step_e_determ])
436
437val check_trace_for1 = Q.prove(
438`���tr.
439 check_trace (��st. some st'. ?l. step_e st l st') tr ���
440 check_trace (��st. some st'. ?l. step_t st l st')
441   (MAP (��st,e'. (st,
442   Handle (If e' a b))) tr)`,
443 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
444 Cases_on`h`>>Cases_on`h'`>>
445 match_mp_tac some_to_SOME_step_t>>
446 fs[some_def]>>
447 simp[Once step_t_cases]>>
448 simp[Once step_t_cases]>>
449 metis_tac[step_e_determ])
450
451val check_trace_for2 = Q.prove(
452`���tr.
453 check_trace (��st. some st'. ?l. step_t st l st') tr ���
454 check_trace (��st. some st'. ?l. step_t st l st')
455   (MAP (��st,t'. (st,
456   Handle (Seq t' a))) tr)`,
457 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
458 Cases_on`h`>>Cases_on`h'`>>
459 match_mp_tac some_to_SOME_step_t>>
460 fs[some_def]>>
461 simp[Once step_t_cases]>>
462 simp[Once step_t_cases]>>
463 metis_tac[step_e_determ])
464
465val check_trace_for3 = Q.prove(
466`���tr.
467 check_trace (��st. some st'. ?l. step_e st l st') tr ���
468 check_trace (��st. some st'. ?l. step_t st l st')
469   (MAP (��st,e'. (st,
470   Handle (Seq (Exp e') a))) tr)`,
471 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
472 Cases_on`h`>>Cases_on`h'`>>
473 match_mp_tac some_to_SOME_step_t>>
474 fs[some_def]>>
475 ntac 3 (simp[Once step_t_cases])>>
476 metis_tac[step_e_determ])
477
478val check_trace_handle = Q.prove(
479`���tr.
480 check_trace (��st. some st'. ?l. step_t st l st') tr ���
481 check_trace (��st. some st'. ?l. step_t st l st')
482   (MAP (��st,t'. (st,
483   Handle t')) tr)`,
484 Induct>>rw[check_trace_def]>>Cases_on`tr`>>fs[check_trace_def]>>
485 Cases_on`h`>>Cases_on`h'`>>
486 match_mp_tac some_to_SOME_step_t>>
487 fs[some_def]>>
488 simp[Once step_t_cases]>>
489 Cases_on`st'`>>metis_tac[step_t_determ])
490
491(* Non-existence of contextual transitions in small-step *)
492val no_step_e_assign = Q.prove(
493`���e.
494 (���s' e' l. ��step_e (s,e) l (s',e')) ���
495 ��is_val_e e
496 ���
497 ���s' e' l. ��step_e (s,Assign v e) l (s',e')`,
498 Induct>>rw[is_val_e_def]>>
499 simp[Once step_e_cases])
500
501val no_step_e_putchar = Q.prove(
502`���e.
503 (���s' e' l. ��step_e (s,e) l (s',e')) ���
504 ��is_val_e e
505 ���
506 ���s' e' l. ��step_e (s,Putchar e) l (s',e')`,
507 Induct>>rw[is_val_e_def]>>
508 simp[Once step_e_cases])
509
510val no_step_e_addl1 = Q.prove(
511`���e.
512 (���s' e' l. ��step_e (s,e) l (s',e')) ���
513 ��is_val_e e
514 ���
515 ���s' e' l. ��step_e (s,AddL e e'') l (s',e')`,
516 Induct>>rw[is_val_e_def]>>simp[Once step_e_cases,is_val_e_def])
517
518val no_step_e_addl2 = Q.prove(
519`���e.
520 (���s' e' l. ��step_e (s,e) l (s',e')) ���
521 ��is_val_e e
522 ���
523 ���s' e' l. ��step_e (s,AddL (Num i) e) l (s',e')`,
524 Induct>>rw[is_val_e_def]>>rpt (simp[Once step_e_cases,is_val_e_def]))
525
526val no_step_e_addr1 = Q.prove(
527`���e.
528 (���s' e' l. ��step_e (s,e) l (s',e')) ���
529 ��is_val_e e
530 ���
531 ���s' e' l. ��step_e (s,AddR e'' e) l (s',e')`,
532 Induct>>rw[is_val_e_def]>>
533 rpt (simp[Once step_e_cases]))
534
535val no_step_e_addr2 = Q.prove(
536`���e.
537 (���s' e' l. ��step_e (s,e) l (s',e')) ���
538 ��is_val_e e
539 ���
540 ���s' e' l. ��step_e (s,AddR e (Num i)) l (s',e')`,
541 Induct>>rw[is_val_e_def]>>
542 rpt (simp[Once step_e_cases]))
543
544val no_step_t_exp = Q.prove(
545`���e.
546 (���s' e' l. ��step_e (s,e) l (s',e')) ���
547 ��is_val_e e
548 ���
549 ���s' t' l. ��step_t (s,Exp e) l (s',t')`,
550 Induct>>rw[is_val_e_def]>>
551 simp[Once step_t_cases])
552
553val no_step_t_seq = Q.prove(
554`���t.
555 (���s' t' l. ��step_t (s,t) l (s',t')) ���
556 ��is_val_t t
557 ���
558 ���s' t' l. ��step_t (s,Seq t p) l (s',t')`,
559 Induct>>rw[is_val_t_def]>>
560 simp[Once step_t_cases]>>
561 Cases_on`s'`>>fs[is_val_e_def])
562
563val no_step_t_if1 = Q.prove(
564`���e.
565 (���s' e' l. ��step_e (s,e) l (s',e')) ���
566 ��is_val_e e
567 ���
568 ���s' t' l. ��step_t (s,If e a b) l (s',t')`,
569 Induct>>rw[is_val_e_def]>>
570 simp[Once step_t_cases])
571
572val no_step_t_handle = Q.prove(
573`���t.
574 (���s' t' l. ��step_t (s,t) l (s',t')) ���
575 ��is_val_t t
576 ���
577 ���s' t' l. ��step_t (s,Handle t) l (s',t')`,
578 Induct>>rw[is_val_t_def]>>
579 simp[Once step_t_cases,is_val_t_def])
580
581val LAST_MAP = Q.prove(
582`���ls. ls ��� [] ��� LAST (MAP f ls) = f (LAST ls)`,
583 Induct>>fs[LAST_DEF]>>rw[])
584
585val HD_MAP = Q.prove(
586`���ls. ls ��� [] ��� HD(MAP f ls) = f (HD ls)`,
587 Induct>>rw[])
588
589val HD_APPEND = Q.prove(
590`ls ��� [] ��� HD (ls ++ ls') = HD ls`,
591Cases_on`ls`>>fs[])
592
593val LAST_APPEND = Q.prove(
594`ls' ��� [] ��� LAST (ls ++ ls') = LAST ls'`,
595Cases_on`ls'`>>fs[])
596
597val sem_e_not_timeout = Q.prove (
598`!st e r. sem_e st e ��� (Rtimeout, r)`,
599 Induct_on `e` >>
600 rw [sem_e_def, LET_THM, permute_pair_def, oracle_get_def, unpermute_pair_def, getchar_def] >>
601 ect >>
602 fs [] >>
603 metis_tac []);
604
605val sem_e_not_break = Q.prove(
606`!st e r. sem_e st e ��� (Rbreak,r)`,
607  Induct_on`e`>>srw_tac[][sem_e_def]>>
608  ect>>
609  fs[LET_THM,unpermute_pair_def,permute_pair_def,oracle_get_def] >>
610  qpat_x_assum `_ = (fst_e,snd_e)` mp_tac >> rw[] >>
611  rename1 `sem_e st' _ = (Rbreak, new_r)` >>
612  first_x_assum (qspecl_then [`st'`,`new_r`] assume_tac) >>
613  first_x_assum (qspecl_then [`st'`,`new_r`] assume_tac) >>
614  fs[]
615 );
616
617val LAST_HD_eq = Q.prove(`
618���ls ls'.
619 ls ��� [] ��� ls' ��� [] ���
620 LAST ls = HD ls' ���
621 BUTLASTN 1 ls ++ ls' =
622 ls ++ TL ls'`,
623 Induct>>fs[LAST_DEF,BUTLASTN_1]>>rw[]>>
624 Cases_on`ls'`>>fs[FRONT_DEF])
625
626val check_trace_append3 = Q.prove(`
627 check_trace f ls ���
628 f h = SOME (HD ls) ���
629 check_trace f (h :: ls)`,
630 rw[]>>imp_res_tac check_trace_append2>>
631 pop_assum(qspec_then`[h]`assume_tac)>>fs[]>>
632 rfs[check_trace_def])
633
634val check_trace_tl = Q.prove(`
635 check_trace f ls ��� ls ��� [] ���
636 check_trace f (TL ls)`,
637 Cases_on`ls`>>fs[check_trace_def]>>
638 Cases_on`t`>>fs[check_trace_def])
639
640(* Start connecting functional big step to small step traces *)
641local val rw = srw_tac[] val fs = fsrw_tac[] in
642val sem_e_big_small_lem = Q.prove(
643`!s e r.
644  sem_e s e = r
645  ���
646  ?tr.
647    tr ��� [] ���
648    check_trace (\st. some st'. ?l. step_e st l st') tr ���
649    HD tr = (s with clock:=0, e_to_small_e e) ���
650    res_rel_e r (LAST tr)`,
651 Induct_on`e`>>rw[]>>fs[sem_e_def,e_to_small_e_def]
652  >- (
653    fct>>fs[res_rel_e_cases]
654    >- (
655      qexists_tac`[(s' with clock:=0,Var s)]`>>fs[check_trace_def,is_val_e_def]>>
656      simp[Once step_e_cases]
657      )
658    >- (
659      qexists_tac`[(s' with clock:=0,Var s);(s' with clock:=0,Num x)]`>>
660      fs[check_trace_def,some_def]>>
661      ntac 2 (simp[Once step_e_cases])
662      )
663    )
664  >- (
665    fs[res_rel_e_cases]>>
666    qexists_tac`[s with clock:=0,Num i]`>>fs[check_trace_def]
667    )
668  >- (
669    fs[LET_THM,permute_pair_def,oracle_get_def]>>IF_CASES_TAC>>fs[]
670    >- (
671      qpat_abbrev_tac`st = s with <|io_trace:=B;non_det_o:=C|>`>>
672      first_x_assum(qspec_then`st`assume_tac)>>
673      Cases_on`sem_e st e'`>>Cases_on`q`>>
674      fs[sem_e_not_break,sem_e_not_timeout,unpermute_pair_def]
675      >- (
676        fct>>Cases_on`q`>>
677        fs[sem_e_not_break,sem_e_not_timeout]>>
678        last_x_assum(qspec_then`r` assume_tac)>>rfs[]>>
679        qpat_abbrev_tac`h =(A,B)`>>
680        qabbrev_tac`ls1 = (MAP (��st,e'. (st,AddR (e_to_small_e e) e')) tr)`>>
681        qabbrev_tac`ls2 = (MAP (��st,e'. (st,AddR e' (Num i))) tr')`>>
682        qabbrev_tac`ls = BUTLASTN 1 ls1 ++ ls2`>>
683        fs[res_rel_e_cases]>>
684        `LAST ls1 = HD ls2` by
685        (unabbrev_all_tac>>fs[LAST_MAP,HD_MAP])>>
686        `ls = ls1 ++ (TL ls2)` by
687        (unabbrev_all_tac>>
688        fs[LAST_HD_eq])>>
689        `check_trace (��st. some st'. ���l. step_e st l st') ls2` by
690        fs[Abbr`ls2`,check_trace_addr2]>>
691        `check_trace (��st. some st'. ���l. step_e st l st') ls` by (
692          fs[Abbr`ls`]>>Cases_on`ls2`>>fs[]>>Cases_on`t`>>fs[]
693          >- fs[check_trace_addr1,Abbr`ls1`] >>
694          match_mp_tac check_trace_append2>>rw[]
695          >- fs[check_trace_addr1,Abbr`ls1`]
696          >- (
697            fs[markerTheory.Abbrev_def]>>
698            `h''::t' = TL (LAST ls1::h''::t')` by fs[]>>
699            pop_assum SUBST_ALL_TAC>>
700            match_mp_tac check_trace_tl>>fs[check_trace_addr2]
701            ) >>
702          fs[check_trace_def]
703          )
704        >- (
705          qexists_tac`[h] ++ ls ++ [(r' with clock:=0,Num(i'+i))]`>>
706          rw[]>>
707          match_mp_tac check_trace_append3>>fs[check_trace_def]>>rw[]
708          >- (
709            match_mp_tac check_trace_append2>>
710            fs[check_trace_def]>>
711            fs[markerTheory.Abbrev_def,LAST_APPEND,LAST_MAP]>>
712            match_mp_tac some_to_SOME_step_e>>
713            simp[Once step_e_cases]
714            ) >>
715          match_mp_tac some_to_SOME_step_e>>
716          fs[HD_APPEND,Abbr`ls1`,HD_MAP,Abbr`h`,Abbr`st`]>>
717          simp[Once step_e_cases,oracle_get_def]
718          ) >>
719        qexists_tac`[h]++ls` >>rw[]
720        >- (
721          match_mp_tac check_trace_append3>>
722          fs[HD_APPEND,Abbr`ls1`,HD_MAP]>>
723          match_mp_tac some_to_SOME_step_e>>
724          fs[Abbr`h`,Abbr`st`]>>
725          simp[Once step_e_cases,oracle_get_def]
726          ) >>
727        fs[markerTheory.Abbrev_def,LAST_DEF,LAST_APPEND,LAST_MAP,
728           is_val_e_def,no_step_e_addr2]
729        )
730      >- (
731        qpat_abbrev_tac`h =(A,B)`>>
732        qexists_tac`[h]++(MAP (��st,e'. (st,AddR (e_to_small_e e) e')) tr)`>>
733        fs[HD_MAP,res_rel_e_cases,LAST_MAP,is_val_e_def,
734           LAST_APPEND,no_step_e_addr1]>>
735        match_mp_tac check_trace_append3>>fs[check_trace_addr1,HD_MAP]>>
736        match_mp_tac some_to_SOME_step_e>>
737        unabbrev_all_tac>>
738        simp[Once step_e_cases,oracle_get_def]
739        )
740      )
741    >- (
742      (*symmetric*)
743      qpat_abbrev_tac`st = s with <|io_trace:=B;non_det_o:=C|>`>>
744      last_x_assum(qspec_then`st`assume_tac)>>
745      Cases_on`sem_e st e`>>Cases_on`q`>>
746      fs[sem_e_not_break,sem_e_not_timeout,unpermute_pair_def]
747      >- (
748        fct>>Cases_on`q`>>
749        fs[sem_e_not_break,sem_e_not_timeout]>>
750        last_x_assum(qspec_then`r` assume_tac)>>rfs[]>>
751        qpat_abbrev_tac`h =(A,B)`>>
752        qabbrev_tac`ls1 = (MAP (��st,e. (st,AddL e (e_to_small_e e'))) tr)`>>
753        qabbrev_tac`ls2 = (MAP (��st,e'. (st,AddL (Num i) e')) tr')`>>
754        qabbrev_tac`ls = BUTLASTN 1 ls1 ++ ls2`>>
755        fs[res_rel_e_cases]>>
756        `LAST ls1 = HD ls2` by
757        (unabbrev_all_tac>>fs[LAST_MAP,HD_MAP])>>
758        `ls = ls1 ++ (TL ls2)` by
759        (unabbrev_all_tac>>
760        fs[LAST_HD_eq])>>
761        `check_trace (��st. some st'. ���l. step_e st l st') ls2` by
762        fs[Abbr`ls2`,check_trace_addl2]>>
763        `check_trace (��st. some st'. ���l. step_e st l st') ls` by (
764          fs[Abbr`ls`]>>Cases_on`ls2`>>fs[]>>Cases_on`t`>>fs[]
765          >- fs[check_trace_addl1,Abbr`ls1`] >>
766          match_mp_tac check_trace_append2>>rw[]
767          >- fs[check_trace_addl1,Abbr`ls1`]
768          >- (
769            fs[markerTheory.Abbrev_def]>>
770            `h''::t' = TL (LAST ls1::h''::t')` by fs[]>>
771            pop_assum SUBST_ALL_TAC>>
772            match_mp_tac check_trace_tl>>fs[check_trace_addr2]
773            ) >>
774          fs[check_trace_def]
775          )
776        >- (
777          qexists_tac`[h] ++ ls ++ [(r' with clock:=0,Num(i+i'))]`>>
778          rw[]>>
779          match_mp_tac check_trace_append3>>fs[check_trace_def]>>rw[]
780          >- (
781            match_mp_tac check_trace_append2>>
782            fs[check_trace_def]>>
783            fs[markerTheory.Abbrev_def,LAST_APPEND,LAST_MAP]>>
784            match_mp_tac some_to_SOME_step_e>>
785            simp[Once step_e_cases]
786            ) >>
787          match_mp_tac some_to_SOME_step_e>>
788          fs[HD_APPEND,Abbr`ls1`,HD_MAP,Abbr`h`,Abbr`st`]>>
789          simp[Once step_e_cases,oracle_get_def]
790          )
791        >- (
792          qexists_tac`[h]++ls` >>rw[]
793          >- (
794            match_mp_tac check_trace_append3>>
795            fs[HD_APPEND,Abbr`ls1`,HD_MAP]>>
796            match_mp_tac some_to_SOME_step_e>>
797            fs[Abbr`h`,Abbr`st`]>>
798            simp[Once step_e_cases,oracle_get_def]
799            ) >>
800          fs[markerTheory.Abbrev_def,LAST_DEF,LAST_APPEND,LAST_MAP,
801             is_val_e_def,no_step_e_addl2]
802          )
803        )
804      >- (
805        qpat_abbrev_tac`h =(A,B)`>>
806        qexists_tac`[h]++(MAP (��st,e. (st,AddL e (e_to_small_e e'))) tr)`>>
807        fs[HD_MAP,res_rel_e_cases,LAST_MAP,is_val_e_def,LAST_APPEND,
808           no_step_e_addl1]>>
809        match_mp_tac check_trace_append3>>fs[check_trace_addl1,HD_MAP]>>
810        match_mp_tac some_to_SOME_step_e>>
811        unabbrev_all_tac>>
812        simp[Once step_e_cases,oracle_get_def]
813        )
814      )
815    )
816  >- (
817    EVERY_CASE_TAC>>fs[res_rel_e_cases,sem_e_not_break,sem_e_not_timeout]>>
818    first_x_assum(qspec_then`s'` assume_tac)>>rfs[]
819    >- (
820      qexists_tac`(MAP (��st,e. (st,Assign s e)) tr)++
821        [r with <|store :=r.store |+ (s,i); clock:=0|>,Num i]`>>
822      fs[HD_MAP,HD_APPEND]>>
823      ho_match_mp_tac check_trace_append2>>
824      fs[check_trace_def,LAST_MAP,check_trace_assign]>>
825      ntac 2 (simp[Once step_e_cases])
826      ) >>
827      (
828        qexists_tac`(MAP (��st,e. (st,Assign s e)) tr)`>>
829        fs[HD_MAP,LAST_MAP,is_val_e_def,no_step_e_assign,check_trace_assign]
830      )
831    )
832  >- (
833    Cases_on`getchar s.input`>>fs[LET_THM,res_rel_e_cases]>>
834    qpat_abbrev_tac`t = (A,B)`>>
835    qpat_abbrev_tac`t' = (A,B)`>>
836    qexists_tac`[t;t']`>>unabbrev_all_tac>>fs[check_trace_def]>>
837    match_mp_tac some_to_SOME_step_e>>
838    simp[Once step_e_cases]
839    )
840  >- (
841    first_x_assum(qspec_then`s` assume_tac)>>fs[]>>
842    Cases_on`sem_e s e`>>Cases_on`q`>>fs[sem_e_not_break,sem_e_not_timeout]>>
843    qpat_abbrev_tac`t = (A,B)`>>
844    qpat_abbrev_tac`t' = (A,B)`
845    >- (
846      qexists_tac`MAP (��st,e. (st,Putchar e)) tr ++
847        [(r with <|io_trace := r.io_trace ++ [INL(Otag i)];clock:=0|>,Num i)]`>>
848      fs[HD_MAP,HD_APPEND,Abbr`t'`,res_rel_e_cases]>>
849      ho_match_mp_tac check_trace_append2>>
850      fs[check_trace_def,LAST_MAP,check_trace_putchar]>>
851      ntac 2 (simp[Once step_e_cases])
852      ) >>
853    qexists_tac`MAP (��st,e. (st,Putchar e)) tr`>>unabbrev_all_tac>>
854    fs[HD_MAP,res_rel_e_cases,LAST_MAP,is_val_e_def,check_trace_putchar,
855       no_step_e_putchar]
856    )
857)
858end
859
860val sem_t_for_no_break = Q.prove(
861 `���s s'. sem_t s (For e1 e2 t) ��� (Rbreak,s')`,
862 completeInduct_on`s.clock`>>fs[sem_t_def_with_stop]>>
863 rw[]>>fct>>Cases_on`q`>>
864 fs[sem_e_not_break,sem_e_not_timeout]>>
865 IF_CASES_TAC>>fs[]>>
866 fct>>Cases_on`q`>>fs[]>>
867 fct>>Cases_on`q`>>fs[sem_e_not_break,sem_e_not_timeout]>>
868 imp_res_tac sem_e_clock>>imp_res_tac sem_t_clock>>fs[]>>
869 IF_CASES_TAC>>fs[dec_clock_def]>>
870 simp[STOP_def]>>
871 simp[sem_t_def_with_stop]>>
872 fs[PULL_FORALL]>>
873 first_x_assum(qspec_then `r'' with clock := r''.clock-1` mp_tac)>>
874 fs[]>>
875 `r''.clock < 1 + r.clock ��� 0 < r.clock` by
876   DECIDE_TAC>>
877 fs[dec_clock_def])
878
879val step_e_clock = Q.prove(`
880  ���se l1 se'.
881  step_e se l1 se' ���
882  ���s e s' e'.
883  se = (s,e) ���
884  se' = (s',e') ���
885  (���c.
886  step_e (s with clock:=c,e) l1 (s' with clock:=c,e'))`,
887  ho_match_mp_tac step_e_strongind>>rw[]>>
888  simp[Once step_e_cases])
889
890val step_e_zero_clock = Q.prove(
891 `(���s e l. ��step_e (r,e') l (s,e))���
892 ���s e l. ��step_e (r with clock:=0,e') l (s,e)`,
893 rw[]>>CCONTR_TAC>>fs[]>>imp_res_tac step_e_clock>>fs[]>>
894 pop_assum(qspec_then`r.clock`assume_tac)>>fs[]>>
895 `r with clock:= r.clock = r` by fs[state_component_equality]>>
896 metis_tac[])
897
898val big_small_lem = Q.prove (
899`!s t r.
900  sem_t s t = r
901  ���
902  ?tr.
903    tr ��� [] ���
904    s.clock - (SND r).clock ��� LENGTH tr ���
905    check_trace (\st. some st'. ?l. step_t st l st') tr ���
906    HD tr = (s with clock := 0, (t_to_small_t t)) ���
907    res_rel_t r (LAST tr)`,
908 ho_match_mp_tac sem_t_ind >>
909 rw [sem_t_def_with_stop, t_to_small_t_def]
910 >-
911   (qabbrev_tac`r = sem_e s e`>>fs[markerTheory.Abbrev_def]>>
912   pop_assum (assume_tac o SYM)>>
913   imp_res_tac sem_e_big_small_lem>>
914   Cases_on`r`>>
915   qexists_tac`MAP (��st,e. (st,Exp e)) tr`>>
916   imp_res_tac sem_e_clock>>fs[HD_MAP,LAST_MAP]>>
917   CONJ_TAC>-
918     fs[check_trace_exp]
919   >>
920   fs[res_rel_t_cases,res_rel_e_cases,is_val_t_def]>>
921   imp_res_tac step_e_zero_clock>>
922   fs[Once step_t_cases])
923 >-
924   (qpat_abbrev_tac`A = (s with clock:=0,D)`>>
925   qexists_tac`A::tr`>>fs[Abbr`A`,check_trace_def]>>
926   CONJ_TAC >-
927     (Cases_on`tr`>>
928     simp[check_trace_def,optionTheory.some_def]>>
929     ntac 2 (simp[Once step_t_cases])>>
930     fs[])>>
931   fs[LAST_DEF])
932 >-
933   (qexists_tac`[s with clock:=0,Break]`>>
934   fs[res_rel_t_cases,check_trace_def])
935 >-
936   (EVERY_CASE_TAC>>fs[]
937   >-
938     (qpat_abbrev_tac`p = t_to_small_t t'`>>
939     qexists_tac`MAP (��st,t. (st,Seq t p)) tr ++ tr'`>>
940     fs[HD_MAP,HD_APPEND,LAST_APPEND]>>rw[] >>
941     match_mp_tac check_trace_append2>>
942     fs[check_trace_seq,LAST_MAP]>>
943     Cases_on`LAST tr`>>fs[]>>
944     match_mp_tac some_to_SOME_step_t>>
945     simp[Once step_t_cases]>>fs[Abbr`p`,res_rel_t_cases]>>
946     metis_tac[])
947   >-
948     (qpat_abbrev_tac `p = t_to_small_t t'`>>
949     qexists_tac`(MAP (��st,t. (st,Seq t p)) tr)++[r with clock:=0,Break]`>>
950     fs[HD_APPEND,HD_MAP, res_rel_t_cases]>>rw[] >>
951     match_mp_tac check_trace_append2>>
952     fs[check_trace_seq,LAST_MAP,check_trace_def]>>
953     fs[res_rel_t_cases]>>
954     match_mp_tac some_to_SOME_step_t>>
955     simp[Once step_t_cases]>>fs[Abbr`p`,res_rel_t_cases])
956   >-
957     (qpat_abbrev_tac `p = t_to_small_t t'`>>
958     qexists_tac`(MAP (��st,t. (st,Seq t p)) tr)`>>
959     fs[HD_APPEND,HD_MAP,check_trace_def,check_trace_seq]>>rw[]>>
960     fs[Once res_rel_t_cases,LAST_MAP]>>
961     rename1 `step_t _ _ (s',_)` >>
962     `step_t (r,Seq t'' p) l (s',Seq t''' p)` by
963       simp[Once step_t_cases]>>
964     metis_tac[])
965   >-
966     (qpat_abbrev_tac `p = t_to_small_t t'`>>
967     qexists_tac`(MAP (��st,t. (st,Seq t p)) tr)`>>
968     fs[HD_APPEND,HD_MAP,check_trace_def,check_trace_seq]>>rw[]>>
969     fs[Once res_rel_t_cases,LAST_MAP,is_val_t_def]>>
970     metis_tac[no_step_t_seq]))
971 >-
972   (EVERY_CASE_TAC>>fs[sem_e_not_break,sem_e_not_timeout]>>
973   imp_res_tac sem_e_big_small_lem>>
974   imp_res_tac sem_e_clock>>
975   qpat_abbrev_tac`p1 = t_to_small_t t1`>>
976   qpat_abbrev_tac`p2 = t_to_small_t t2`>>
977   TRY
978     (
979     qexists_tac`(MAP (��st,e. (st,(If e p1 p2))) tr') ++ tr`>>
980     fs[HD_MAP,HD_APPEND,LAST_MAP,LAST_APPEND]>>rw[] >>
981     match_mp_tac check_trace_append2>>fs[res_rel_e_cases]>>CONJ_TAC
982     >- metis_tac[check_trace_if1]
983     >>  match_mp_tac some_to_SOME_step_t>>fs[LAST_MAP]>>
984         simp[Once step_t_cases]>>
985         metis_tac[]
986     )
987   >>
988     qexists_tac`(MAP (��st,e. (st,(If e p1 p2))) tr)`>>rw[]>>
989     fs[HD_MAP,res_rel_t_cases,LAST_MAP,res_rel_e_cases,is_val_t_def,check_trace_if1,no_step_t_if1]>>
990     metis_tac[check_trace_if1,no_step_t_if1,step_e_zero_clock])
991  >- ( (*For*)
992    reverse (Cases_on`sem_e s e1`>>Cases_on`q`)>>
993    fs[sem_e_not_break,sem_e_not_timeout]>>
994    qpat_abbrev_tac`e1s = e_to_small_e e1`>>
995    qpat_abbrev_tac`e2s = e_to_small_e e2`>>
996    (*trace for e1*)
997    imp_res_tac sem_e_big_small_lem>>
998    imp_res_tac sem_e_clock>>
999    qpat_abbrev_tac`p = t_to_small_t t`>>
1000    qabbrev_tac `
1001      e1tr = (MAP (��st,e. (st,Handle
1002        (If e (Seq p (Seq (Exp e2s) (For e1s e2s p))) (Exp (Num 0))))) tr)`>>
1003    `check_trace (��st. some st'. ���l. step_t st l st') e1tr` by metis_tac[check_trace_for1]>>
1004    qabbrev_tac`ls = [s with clock:=0,For e1s e2s p]`>>
1005    `check_trace (��st. some st'. ���l. step_t st l st') (ls++e1tr)` by (
1006      match_mp_tac check_trace_append2>>unabbrev_all_tac>>
1007      fs[check_trace_def,HD_MAP]>>
1008      match_mp_tac some_to_SOME_step_t>>
1009      simp[Once step_t_cases]
1010      )
1011    >- (
1012      qexists_tac` ls ++ e1tr`>>
1013      unabbrev_all_tac>>fs[res_rel_t_cases,LAST_DEF,LAST_MAP,HD_APPEND]>>
1014      fs[LAST_APPEND,LAST_MAP,res_rel_e_cases,is_val_t_def]>>
1015      match_mp_tac no_step_t_handle>>fs[is_val_t_def]>>
1016      imp_res_tac step_e_zero_clock>>
1017      metis_tac[no_step_t_if1]
1018      ) >>
1019    IF_CASES_TAC>>fs[]
1020    >- ( (*run out of time*)
1021      fs[res_rel_t_cases,res_rel_e_cases]>>
1022      qexists_tac` (ls ++ e1tr) ++
1023        [(r with clock:=0,Handle(Exp (Num 0)));(r with clock:=0,Exp (Num 0))]`>>
1024      fs[LAST_APPEND,LAST_MAP]>>fs[]>>rw[]
1025      >- (
1026        match_mp_tac check_trace_append2>>rw[]
1027        >- (
1028          fs[check_trace_def]>>
1029          match_mp_tac some_to_SOME_step_t>>
1030          simp[Once step_t_cases,is_val_e_def,is_val_t_def]
1031          )
1032        >- (
1033          unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP]>>
1034          match_mp_tac some_to_SOME_step_t>>
1035          ntac 2 (simp[Once step_t_cases])
1036          )
1037        )
1038       >- (unabbrev_all_tac>>fs[HD_APPEND])
1039      ) >>
1040    reverse (Cases_on`sem_t r t`>>Cases_on`q`)>>fs[]>>
1041    qabbrev_tac`ttr = (MAP (��st,t. (st,Handle (Seq t (Seq (Exp e2s) (For e1s e2s p))) ))) tr'`>>
1042    `check_trace (��st. some st'. ���l. step_t st l st') ttr` by
1043      metis_tac[check_trace_for2]>>
1044    `check_trace (��st. some st'. ���l. step_t st l st') (ls++e1tr++ttr)` by (
1045      match_mp_tac check_trace_append2>>
1046      fs[]>> unabbrev_all_tac>>
1047      fs[LAST_MAP,res_rel_e_cases,HD_MAP,LAST_DEF]>>
1048      match_mp_tac some_to_SOME_step_t>>
1049      ntac 2 (simp[Once step_t_cases])
1050      )
1051    >- (
1052      qexists_tac`ls++e1tr++ttr`>>unabbrev_all_tac>>
1053      fs[LAST_APPEND,LAST_MAP,res_rel_t_cases]>>CONJ_TAC >>
1054      fs[is_val_t_def]>>match_mp_tac no_step_t_handle>>
1055      fs[is_val_t_def]>>match_mp_tac no_step_t_seq>>
1056      metis_tac[]
1057      )
1058    >- (
1059      qexists_tac`ls++e1tr++ttr`>>unabbrev_all_tac>>
1060      fs[LAST_APPEND,LAST_MAP,res_rel_t_cases] >>
1061      ntac 2 (simp[Once step_t_cases,is_val_t_def])>>
1062      metis_tac[]
1063      )
1064    >- (
1065      qexists_tac`
1066        ls++e1tr++ttr++
1067          [(r' with clock:= 0,Handle Break);(r' with clock:=0,Exp (Num 0))]`>>
1068      fs[LAST_APPEND,LAST_MAP,res_rel_t_cases]>>rw[]
1069      >- (unabbrev_all_tac>>fs[]>>DECIDE_TAC)
1070      >- (
1071        match_mp_tac check_trace_append2>>fs[check_trace_def]>>CONJ_TAC>>
1072        match_mp_tac some_to_SOME_step_t>>
1073        unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP,res_rel_t_cases]>>
1074        ntac 2 (simp[Once step_t_cases])
1075        )
1076      >- (unabbrev_all_tac>>fs[]>>DECIDE_TAC)
1077      ) >>
1078    (*continue executing*)
1079    reverse (Cases_on`sem_e r' e2`>>Cases_on`q`)>>
1080    fs[sem_e_not_break,sem_e_not_timeout]>>
1081    imp_res_tac sem_e_big_small_lem>>
1082    imp_res_tac sem_e_clock>>
1083    qabbrev_tac`
1084      e2tr = (MAP (��st,e. (st,Handle (Seq (Exp e) (For e1s e2s p)) ))) tr''`>>
1085    `check_trace (��st. some st'. ���l. step_t st l st') e2tr` by
1086      metis_tac[check_trace_for3]>>
1087    `check_trace (��st. some st'. ���l. step_t st l st')(ls++e1tr++ttr++e2tr)` by (
1088      match_mp_tac check_trace_append2>>fs[]>>
1089      match_mp_tac some_to_SOME_step_t>>
1090      unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP,HD_MAP,res_rel_t_cases]>>
1091      ntac 2 (simp[Once step_t_cases,res_rel_e_cases])
1092      )
1093    >- ( (* e2 fails *)
1094      qexists_tac`ls++e1tr++ttr++e2tr`>>fs[res_rel_e_cases]>>
1095      unabbrev_all_tac>>
1096      fs[LAST_APPEND,LAST_MAP,res_rel_t_cases,is_val_t_def]>>rw[] >>
1097      imp_res_tac step_e_zero_clock>>
1098      metis_tac[no_step_t_exp,no_step_t_handle,no_step_t_seq,is_val_t_def]
1099      ) >>
1100    (* e2 ok *)
1101    reverse (IF_CASES_TAC) >>fs[]
1102    >- (
1103      (*clock ended*)
1104      fs[res_rel_t_cases]>>
1105      qexists_tac`ls++e1tr++ttr++e2tr`>>fs[]>>reverse (rw[])
1106      >- (
1107        unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP,res_rel_e_cases]>>
1108        `r'' with clock:=0 = r''` by fs[state_component_equality]>>
1109        ntac 2 (simp[Once step_t_cases,is_val_t_def])>>
1110        metis_tac[]
1111        ) >>
1112      unabbrev_all_tac>>fs[]>>DECIDE_TAC
1113      ) >>
1114    (*clock ok*)
1115    simp[STOP_def]>>
1116    simp[Once sem_t_def_with_stop]>>
1117    fs[dec_clock_def]>>
1118    (*Need a handle wrapper around rest of trace*)
1119    qabbrev_tac`ftr = MAP (��st,t. (st, Handle t))tr''''` >>
1120    `check_trace (��st. some st'. ���l. step_t st l st') ftr` by
1121      metis_tac[check_trace_handle]>>
1122    `check_trace (��st. some st'. ���l. step_t st l st')
1123      (ls++e1tr++ttr++e2tr++ftr)` by (
1124        match_mp_tac check_trace_append2>>fs[]>>
1125        match_mp_tac some_to_SOME_step_t>>
1126        unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP,HD_MAP]>>
1127        fs[res_rel_e_cases]>>
1128        ntac 2 (simp[Once step_t_cases])
1129      ) >>
1130    fs[res_rel_t_cases]
1131    (*Case split on the rest of loop*)
1132    >- (
1133      qexists_tac`
1134        ls ++ e1tr ++ ttr ++ e2tr ++ ftr ++[s' with clock:=0,Exp (Num i''')]`>>
1135      fs[]>>rw[]
1136      >- (unabbrev_all_tac>>fs[]>>DECIDE_TAC)
1137      >- (
1138        match_mp_tac check_trace_append2>>fs[check_trace_def]>>
1139        match_mp_tac some_to_SOME_step_t>>unabbrev_all_tac>>
1140        fs[LAST_DEF,LAST_APPEND,LAST_MAP,res_rel_e_cases]>>
1141        simp[Once step_t_cases,is_val_t_def,is_val_e_def]
1142        )
1143      >- (unabbrev_all_tac>>fs[]>>DECIDE_TAC)
1144      >- (simp[Once sem_t_def_with_stop,LAST_APPEND,dec_clock_def])
1145      )
1146    >- (
1147      qexists_tac`ls ++ e1tr++ttr++e2tr++ftr`>>fs[]>> reverse (rw[])
1148      >- (
1149        ntac 4 (simp[Once sem_t_def_with_stop,LAST_APPEND,dec_clock_def])>>
1150        unabbrev_all_tac>>fs[LAST_APPEND,LAST_MAP,is_val_t_def]>>
1151        match_mp_tac no_step_t_handle>>
1152        metis_tac[]
1153        ) >>
1154      unabbrev_all_tac>>fs[]>>DECIDE_TAC
1155      )
1156    >- ( (*break never occurs*)
1157      qpat_x_assum `A = (RBreak,s')` mp_tac>>
1158      fct>>Cases_on`q`>>
1159      fs[sem_e_not_timeout,sem_e_not_break]>>
1160      IF_CASES_TAC>>fs[]>>
1161      fct>>Cases_on`q`>>
1162      fs[]>>
1163      fct>>Cases_on`q`>>
1164      fs[sem_e_not_timeout,sem_e_not_break]>>
1165      IF_CASES_TAC>>fs[]>>
1166      simp[STOP_def]>>
1167      metis_tac[sem_t_for_no_break]
1168      )
1169    >- (
1170      qexists_tac`ls ++ e1tr ++ ttr ++ e2tr ++ ftr`>>fs[]>> reverse (rw[]) >>
1171      unabbrev_all_tac
1172      >- (
1173        ntac 3 (
1174          simp[Once sem_t_def_with_stop,LAST_APPEND,dec_clock_def,LAST_MAP])>>
1175        simp[Once step_t_cases]>>metis_tac[]
1176        ) >>
1177      fs[] >> DECIDE_TAC
1178      )
1179    )
1180  )
1181
1182val big_timeout_0 = Q.prove (
1183`!st p r.
1184  sem_t st p = (Rtimeout,r)
1185  ���
1186  r.clock = 0`,
1187 ho_match_mp_tac sem_t_ind >>
1188 conj_tac >- (
1189   rw [sem_t_def_with_stop, sem_e_not_timeout]) >>
1190 conj_tac >- (
1191   rw [sem_t_def_with_stop, sem_e_not_timeout]) >>
1192 conj_tac >- (
1193   rw [sem_t_def_with_stop, sem_e_not_timeout] >>
1194   ect >> fs []) >>
1195 conj_tac >- (
1196   rw [sem_t_def_with_stop, sem_e_not_timeout] >>
1197   ect >> fs []) >>
1198 conj_tac >- (
1199   rw [sem_t_def_with_stop, sem_e_not_timeout] >>
1200   ect >> fs [sem_e_not_timeout])
1201 >- (
1202   rw [] >>
1203   pop_assum mp_tac >>
1204   simp [sem_t_def_with_stop] >>
1205   ect >>
1206   fs [sem_e_not_timeout, STOP_def] >>
1207   rw [] >>
1208   fs []));
1209
1210(* check traces are unique up to prefixing *)
1211val check_trace_determ = Q.prove(
1212`���tr h f.
1213 check_trace f (h::tr) ���
1214 ���tr'.
1215 LENGTH tr' ��� LENGTH tr ���
1216 check_trace f (h::tr') ���
1217 isPREFIX tr' tr`,
1218 Induct>>rw[]>>fs[check_clock_def,isPREFIX,LENGTH_NIL]>>
1219 Cases_on`tr'`>>fs[check_trace_def]>>
1220 metis_tac[])
1221
1222val check_trace_prefixes = Q.prove(
1223`���tr f.
1224 tr ��� [] ���
1225 check_trace f tr ���
1226 ���tr'.
1227 tr' ��� [] ��� HD tr' = HD tr ���
1228 check_trace f tr' ���
1229 isPREFIX tr tr' ��� isPREFIX tr' tr`,
1230 rw[]>>
1231 Cases_on`tr`>>Cases_on`tr'`>>fs[]>>
1232 Cases_on`LENGTH t' ��� LENGTH t`>>
1233 TRY(`LENGTH t ��� LENGTH t'` by DECIDE_TAC)>>
1234 metis_tac[check_trace_determ])
1235
1236val check_trace_TL = Q.prove(
1237`���tr tr'.
1238 (tr ��� [] ���
1239 check_trace (��st. some st'. ?l. step_t st l st') tr ���
1240 (���l t'. ��step_t (LAST tr) l t') ���
1241 check_trace (��st. some st'. ?l. step_t st l st') tr' ���
1242 isPREFIX tr tr') ���
1243 tr = tr'`,
1244 Induct>>fs[check_trace_def,LAST_DEF]>>rw[]>>Cases_on`tr'`>>fs[]
1245 >-
1246   (Cases_on`t`>>fs[check_trace_def,some_def]>>
1247   metis_tac[])
1248 >>
1249   Cases_on`tr`>>Cases_on`t`>>fs[check_trace_def]>>
1250   res_tac>>fs[])
1251
1252val prefix_append = Q.prove(
1253`���ls ls'.
1254  ls ��� ls' ���
1255  ���ls''. ls++ls'' = ls'`,
1256  metis_tac[rich_listTheory.IS_PREFIX_APPEND])
1257
1258val res_rel_t_io_trace = Q.prove(
1259 `res_rel_t (q,r) s ���
1260  r.io_trace = (FST s).io_trace`,
1261  simp[res_rel_t_cases]>>rw[]>>fs[])
1262
1263(*slow*)
1264val res_rel_t_clock = Q.prove(
1265 `res_rel_t (q,r) s ���
1266  step_t s l t ���
1267  q = Rtimeout ��� (FST s).clock = 0`,
1268  simp[res_rel_t_cases]>>rw[]
1269  >>
1270    fs[Once step_t_cases,Once step_e_cases]
1271  >>
1272   metis_tac[PAIR,FST])
1273
1274val step_e_io_mono = Q.prove(
1275`���s l s'.
1276  step_e s l s' ���
1277  (FST s).io_trace ��� (FST s').io_trace`,
1278  ho_match_mp_tac step_e_strongind>>fs[])
1279
1280val step_t_io_mono = Q.prove(
1281`���s l s'.
1282  step_t s l s' ���
1283  (FST s).io_trace ��� (FST s').io_trace`,
1284  ho_match_mp_tac step_t_strongind>>
1285  fs[]>>metis_tac[step_e_io_mono,FORALL_PROD,FST])
1286
1287val RTC_step_t_io_mono = Q.prove(
1288  `���x y. (��s1 s2. (some st'. ���l. step_t s1 l st') = SOME s2)^* x y ���
1289      (FST x).io_trace ��� (FST y).io_trace`,
1290  ho_match_mp_tac RTC_INDUCT >> rw[] >>
1291  last_x_assum mp_tac >>
1292  DEEP_INTRO_TAC some_intro >> rw[] >>
1293  metis_tac[step_t_io_mono,IS_PREFIX_TRANS])
1294
1295val check_trace_io_trace = Q.prove(
1296 `���tr ls.
1297  tr ��� [] ��� check_trace (��st. some st'. ���l. step_t st l st') (tr ++ ls) ���
1298  (FST(LAST tr)).io_trace ���
1299  (FST(LAST (tr++ls))).io_trace`,
1300  rw[] >>
1301  match_mp_tac RTC_step_t_io_mono >>
1302  simp[check_trace_thm] >>
1303  qexists_tac`LAST tr::ls` >>
1304  simp[] >>
1305  conj_tac >- ( Cases_on`ls`>>simp[] ) >>
1306  `LAST tr::ls = DROP (LENGTH tr - 1) (tr++ls)` suffices_by (
1307    disch_then SUBST1_TAC >>
1308    match_mp_tac check_trace_drop >> simp[] ) >>
1309  simp[DROP_APPEND1] >>
1310  Q.ISPECL_THEN[`1n`,`tr`]mp_tac (GSYM LASTN_DROP) >>
1311  `1 ��� LENGTH tr` by (
1312    Cases_on`tr`>>fs[] >> simp[] ) >>
1313  simp[] >>
1314  Q.ISPEC_THEN`tr`FULL_STRUCT_CASES_TAC SNOC_CASES >- fs[] >>
1315  REWRITE_TAC[arithmeticTheory.ONE,LASTN,LAST,SNOC])
1316
1317val sem_e_ignores_clock = Q.prove(
1318 `���s e c r s'.
1319  sem_e s e = (r,s') ���
1320  sem_e (s with clock:=c) e = (r,s' with clock:=c)`,
1321  ho_match_mp_tac sem_e_ind>>srw_tac[][sem_e_def]>>fs[LET_THM]
1322  >-
1323    (ect>>fs[])
1324  >- (
1325    fs[permute_pair_def,LET_THM,oracle_get_def,unpermute_pair_def]>>
1326    Cases_on`switch`>>fs[]>>
1327    qpat_x_assum`A=(r,s')` mp_tac>>
1328    fct>>Cases_on`q`>>res_tac>>
1329    fs[sem_e_not_break,sem_e_not_timeout]>>
1330    fct>>Cases_on`q`>>res_tac>>
1331    rw[]>>
1332    fs[sem_e_not_break,sem_e_not_timeout])
1333  >>
1334    Cases_on`sem_e s e`>>res_tac>>fs[]>>
1335    Cases_on`q`>>fs[state_component_equality])
1336
1337val sem_e_io_mono = Q.prove(
1338  `���s e c.
1339  (SND (sem_e s e)).io_trace ���
1340  (SND (sem_e (s with clock:= c) e)).io_trace`,
1341  rw[]>>Cases_on`sem_e s e`>>imp_res_tac sem_e_ignores_clock>>
1342  fs[])
1343
1344val sem_e_clock_inc = Q.prove(
1345  `���s e r.
1346  sem_e s e = r ���
1347  ���k. sem_e (s with clock:= s.clock+k) e =(FST r,(SND r)with clock:= (SND r).clock+k)`,
1348  metis_tac[sem_e_ignores_clock,sem_e_clock,FST,SND,PAIR])
1349
1350val sem_t_clock_inc = Q.prove(
1351  `���s t r.
1352  sem_t s t = r ��� FST r ��� Rtimeout ���
1353  ���k. sem_t (s with clock:= s.clock+k) t =(FST r,(SND r)with clock:= (SND r).clock+k)`,
1354  ho_match_mp_tac sem_t_ind>>rw[]>>fs[sem_e_clock]>>
1355  TRY(fs[sem_t_def_with_stop]>>NO_TAC)
1356  >-
1357    (fs[sem_t_def_with_stop]>>
1358    Cases_on`sem_e s e`>>
1359    imp_res_tac sem_e_ignores_clock>>
1360    fs[]>>metis_tac[sem_e_clock])
1361  >-
1362    (fs[sem_t_def_with_stop]>>Cases_on`sem_t s t`>>Cases_on`q`>>fs[])
1363  >-
1364    (fs[sem_t_def_with_stop]>>Cases_on`sem_e s e`>>Cases_on`q`>>fs[sem_e_res]>>
1365    imp_res_tac sem_e_clock_inc>>
1366    pop_assum(qspec_then`k` assume_tac)>>fs[]>>
1367    IF_CASES_TAC>>fs[])
1368  >>
1369    pop_assum mp_tac>>
1370    simp[sem_t_def_with_stop]>>
1371    Cases_on`sem_e s e1`>>Cases_on`q`>>fs[]>>
1372    imp_res_tac sem_e_clock_inc>>fs[]>>
1373    TRY(pop_assum(qspec_then`k` assume_tac))>>
1374    fs[DECIDE ``(A:num)+B = B+A``]>>
1375    IF_CASES_TAC>>fs[]>>
1376    Cases_on`sem_t r t`>>Cases_on`q`>>fs[]>>
1377    Cases_on`sem_e r' e2`>>Cases_on`q`>>fs[]>>
1378    TRY(metis_tac[sem_e_res])>>
1379    imp_res_tac sem_e_clock_inc>>fs[]>>
1380    TRY(pop_assum(qspec_then`k` assume_tac))>>
1381    fs[DECIDE ``(A:num)+B = B+A``]>>
1382    IF_CASES_TAC>>fs[]>>rw[]>>
1383    fs[dec_clock_def,STOP_def]>>
1384    `1 ��� r''.clock` by DECIDE_TAC>>
1385    metis_tac[arithmeticTheory.LESS_EQ_ADD_SUB])
1386
1387val check_trace_io_trace_simp = Q.prove(
1388  `tr ��� [] ���
1389  check_trace (��st.some st'. ���l. step_t st l st') tr ���
1390  (FST(HD tr)).io_trace ��� (FST (LAST tr)).io_trace`,
1391  Cases_on`tr`>>rw[]>>
1392  `FST h = FST(LAST [h])` by fs[]>>
1393  pop_assum SUBST1_TAC>>
1394  `h::t = [h]++t` by fs[]>>
1395  pop_assum SUBST1_TAC>>
1396  ho_match_mp_tac check_trace_io_trace>>
1397  rw[])
1398
1399val sem_t_sing_io_mono = Q.prove(
1400  `���s t res s'.
1401  sem_t s t = (res,s') ���
1402  s.io_trace ��� s'.io_trace`,
1403  rw[]>>imp_res_tac big_small_lem>>
1404  imp_res_tac check_trace_io_trace_simp>>
1405  fs[res_rel_t_cases]>>
1406  rfs[])
1407
1408val sem_e_sing_io_mono = Q.prove(
1409`���s e res s'.
1410  sem_e s e = (res,s') ���
1411  s.io_trace ��� s'.io_trace`,
1412  CCONTR_TAC>>fs[]>>
1413  `sem_t s (Exp e) = (res,s')` by
1414    fs[sem_t_def_with_stop]>>
1415  metis_tac[sem_t_sing_io_mono])
1416
1417(* Monotonicity of io_trace w.r.t. to clock *)
1418val sem_t_io_mono_lem = Q.prove(
1419 `���s t k.
1420  (SND (sem_t s t)).io_trace ���
1421  (SND (sem_t (s with clock:=s.clock+k) t)).io_trace`,
1422  ho_match_mp_tac sem_t_ind>>rw[]>>
1423  TRY(fs[sem_t_def_with_stop,sem_e_io_mono]>>NO_TAC)
1424  >-
1425    (fs[sem_t_def_with_stop]>>
1426    fct>>Cases_on`q`>>fs[]>>
1427    imp_res_tac sem_t_clock_inc>>fs[]>>
1428    fct>>Cases_on`q`>>fs[]>>
1429    first_x_assum(qspec_then`k` assume_tac)>>rfs[]>>
1430    Cases_on`sem_t r' t'`>>
1431    imp_res_tac sem_t_sing_io_mono>>
1432    fs[]>>
1433    metis_tac[IS_PREFIX_TRANS])
1434  >-
1435    (fs[sem_t_def_with_stop]>>
1436    fct>>Cases_on`q`>>fs[]>>TRY(metis_tac[sem_e_res])>>
1437    imp_res_tac sem_e_clock_inc>>fs[]>>
1438    IF_CASES_TAC>>fs[])
1439  >>
1440    simp[Once sem_t_def_with_stop]>>
1441    simp[Once sem_t_def_with_stop]>>
1442    fct>>Cases_on`q`>>fs[]>>TRY(metis_tac[sem_e_res])>>
1443    imp_res_tac sem_e_clock_inc>>
1444    pop_assum(qspec_then`k` assume_tac)>>
1445    fs[DECIDE ``(A:num)+B = B+A``]>>
1446    IF_CASES_TAC>>fs[]>>
1447    fct>>Cases_on`q`>>fs[]>>
1448    TRY(imp_res_tac sem_t_clock_inc>>fs[]>>
1449    pop_assum(qspec_then`k` assume_tac))>>rfs[]>>
1450    fs[DECIDE ``(A:num)+B = B+A``]
1451    >-
1452      (fct>>Cases_on`q`>>fs[]>>TRY(metis_tac[sem_e_res])>>
1453      imp_res_tac sem_e_clock_inc>>
1454      pop_assum(qspec_then`k` assume_tac)>>
1455      fs[DECIDE ``(A:num)+B = B+A``]>>
1456      IF_CASES_TAC>>fs[]
1457      >-
1458        (fs[dec_clock_def,STOP_def]>>
1459        `1 ��� r''.clock` by DECIDE_TAC>>
1460        metis_tac[arithmeticTheory.LESS_EQ_ADD_SUB])
1461      >>
1462      IF_CASES_TAC>>fs[]>>
1463      qpat_abbrev_tac`A = sem_t B C`>>
1464      Cases_on`A`>>fs[markerTheory.Abbrev_def]>>
1465      pop_assum (assume_tac o SYM)>>imp_res_tac sem_t_sing_io_mono>>
1466      fs[dec_clock_def])
1467    >>
1468      first_x_assum(qspec_then`k` assume_tac)>>
1469      fct>>Cases_on`q`>>fs[]>>
1470      fct>>Cases_on`q`>>fs[]>>TRY(metis_tac[sem_e_res])>>
1471      imp_res_tac sem_e_sing_io_mono
1472      >-
1473        (IF_CASES_TAC>>fs[dec_clock_def]>>
1474        TRY(qpat_abbrev_tac`A = sem_t B C`>>
1475        Cases_on`A`>>fs[markerTheory.Abbrev_def]>>
1476        pop_assum (assume_tac o SYM)>>imp_res_tac sem_t_sing_io_mono)>>
1477        fs[]>>metis_tac[IS_PREFIX_TRANS])
1478      >>
1479      metis_tac[IS_PREFIX_TRANS])
1480
1481val sem_t_io_mono = Q.prove (
1482`k1 ��� k2 ���
1483 (SND (sem_t (init_st 0 nd input with clock := k1) p)).io_trace ���
1484 (SND (sem_t (init_st 0 nd input with clock := k2) p)).io_trace`,
1485 qpat_abbrev_tac `st = init_st A B C`>>
1486 rw[]>>imp_res_tac arithmeticTheory.LESS_EQUAL_ADD >>
1487 Q.ISPECL_THEN [`st with clock:=k1`,`p`,`p'`] assume_tac sem_t_io_mono_lem>>
1488 fs[])
1489
1490val sem_equiv_lem = Q.store_thm ("sem_equiv_lem",
1491`���input prog r. ofbs_sem (for_big_sem input) prog r ��� osmall_sem (for_small_sem input) prog r`,
1492 gen_tac >>
1493 match_mp_tac osmall_fbs_equiv2 >>
1494 conj_tac >- (
1495   rw [for_small_sem_def] >>
1496   match_mp_tac step_t_io_mono>>
1497   Q.ISPEC_THEN `��st. ���l. step_t s1 l st` assume_tac some_SAT>>
1498   fs[ETA_AX])>>
1499 conj_tac >- (
1500   rw [for_big_sem_def] >>
1501   rw [eval_with_clock_def, for_eval_def] >>
1502   every_case_tac >>
1503   fs [] >>
1504   metis_tac [sem_t_io_mono, SND]) >>
1505 conj_tac >- (
1506   rw [for_big_sem_def, eval_with_clock_def, for_eval_def] >>
1507   ect >>
1508   fs [] >>
1509   metis_tac [big_timeout_0]) >>
1510 qexists_tac `I` >>
1511 conj_tac
1512 >- (
1513   rw [unbounded_def] >>
1514   qexists_tac `SUC x` >>
1515   simp []) >>
1516 rpt gen_tac >>
1517 simp [for_big_sem_def, for_eval_def, eval_with_clock_def] >>
1518 DISCH_TAC >>
1519 ect >>
1520 imp_res_tac big_small_lem >>
1521 fs [] >>
1522 qexists_tac `tr` >>
1523 fs [for_small_sem_def] >>
1524 rw [same_result_def] >>
1525 fs [res_rel_t_cases, is_val_t_def, is_val_e_def, some_no_choice, init_st_def] >>
1526 simp [] >>
1527 rw []
1528 >- (rw [Once step_t_cases] >>
1529     rw [Once step_e_cases])
1530 >- rw [Once step_t_cases]
1531 >- (rw [some_def] >>
1532     metis_tac [])
1533 >- metis_tac [PAIR]);
1534
1535val FST_SPLIT = Q.prove(
1536`FST x = y ��� ���z. x = (y,z)`,
1537Cases_on`x`>>fs[])
1538
1539val big_val_no_errors = Q.prove(
1540`!st p v s.
1541  sem_t st p = (Rval v,s)
1542  ���
1543  (���c.
1544    (FST (sem_t (st with clock:= c) p) ��� Rbreak)
1545  ��� (FST (sem_t (st with clock:=c) p) ��� Rfail))`,
1546  rw[]>>CCONTR_TAC>>fs[]>>imp_res_tac FST_SPLIT>>
1547  imp_res_tac big_small_lem>>
1548  `HD tr = HD tr'` by fs[]>>
1549  fs[res_rel_t_cases]>>
1550  `���l t'. ��step_t (LAST tr) l t'` by
1551    fs[Once step_t_cases,FORALL_PROD]>>
1552  `���l t'. ��step_t (LAST tr') l t'` by
1553    fs[Once step_t_cases,FORALL_PROD,Once step_e_cases]>>
1554  `isPREFIX tr tr' ��� isPREFIX tr' tr` by
1555    metis_tac[check_trace_prefixes]>>
1556  `tr = tr'` by metis_tac[check_trace_TL]>>
1557  fs[]>>
1558  qpat_assum`A=t` (SUBST_ALL_TAC o SYM)>>fs[is_val_t_def,is_val_e_def])
1559
1560(* we can prove an alternative characterisation of the semantics, now that we
1561   know sem_t's io_trace is a chain *)
1562
1563val over_all_def = Define`over_all f = GSPEC (��c. f c,T)`;
1564
1565val init_st_with_clock = Q.prove(
1566  `init_st a b c with clock := d = init_st d b c`,
1567  EVAL_TAC)
1568
1569val lprefix_chain_sem_t_io_trace_over_all_c = Q.store_thm("lprefix_chain_sem_t_io_trace_over_all_c",
1570  `prefix_chain (over_all (��c. (SND (sem_t (init_st c nd input) t)).io_trace))`,
1571  rw[lprefix_lubTheory.prefix_chain_def,over_all_def] >>
1572  qspecl_then[`c`,`c'`]strip_assume_tac arithmeticTheory.LESS_EQ_CASES >|[disj1_tac,disj2_tac] >>
1573  imp_res_tac sem_t_io_mono >> fs[init_st_with_clock])
1574
1575val image_intro = Q.prove(
1576  `{fromList (FILTER P (Q c)) | c | T} = IMAGE fromList (IMAGE (FILTER P) (over_all Q))`,
1577  rw[EXTENSION,over_all_def,PULL_EXISTS])
1578
1579val IMAGE_over_all = Q.store_thm("IMAGE_over_all",
1580  `IMAGE P (over_all f) = over_all (P o f)`,
1581  rw[EXTENSION,over_all_def,PULL_EXISTS])
1582
1583(* Pretty Printing *)
1584val BIGSUP_def = Define`BIGSUP f = build_lprefix_lub (over_all f)`
1585
1586val _ = Parse.add_rule{term_name="BIGSUP",fixity=Parse.Binder,pp_elements=[TOK"BIGSUP"],
1587                       block_style=(NoPhrasing,(PP.CONSISTENT,0)),paren_style=OnlyIfNecessary}
1588
1589val semantics_alt = save_thm("semantics_alt",
1590  semantics_def
1591    |> SIMP_RULE bool_ss [image_intro]
1592    |> SIMP_RULE bool_ss [lprefix_chain_sem_t_io_trace_over_all_c,lprefix_lubTheory.prefix_chain_FILTER,lprefix_lubTheory.prefix_chain_lprefix_chain,lprefix_lubTheory.build_prefix_lub_intro]
1593    |> SIMP_RULE bool_ss [IMAGE_over_all]
1594    |> SIMP_RULE bool_ss [prove(``f o g = ��c. f (g c)``,rw[FUN_EQ_THM])]
1595    |> SIMP_RULE bool_ss [GSYM BIGSUP_def])
1596
1597val oracle_upd_def = Define`
1598  oracle_upd s (b,a) =
1599  s with <|non_det_o := a; io_trace:=s.io_trace ++[INR b]|>`
1600
1601val _ = save_thm ("step_e_rules_oracle_upd",step_e_rules|>REWRITE_RULE[GSYM oracle_upd_def])
1602
1603val _ = export_theory ();
1604