File: env_permScript.sml

package info (click to toggle)
ott 0.34%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,440 kB
  • sloc: ml: 25,103; makefile: 1,374; awk: 736; lisp: 183; sh: 14; sed: 4
file content (579 lines) | stat: -rw-r--r-- 28,867 bytes parent folder | download | duplicates (3)
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
open bossLib HolKernel boolLib listTheory optionTheory rich_listTheory sortingTheory;
open ottTheory ottLib caml_typedefTheory;
open utilTheory basicTheory shiftTheory environmentTheory;

val OPTION_MAP_ID = Q.prove (
`!Op. OPTION_MAP (\x. x) Op = Op`,
Cases THEN SRW_TAC [] []);

val _ = new_theory "env_perm";

val idx_bound_append_thm = Q.store_thm ("idx_bound_append_thm",
`!E1 E2 idx. idx_bound (E1++E2) idx = idx_bound E1 idx \/ idx_bound E2 (idx - num_tv E1)`,
Induct THEN SRW_TAC [] [idx_bound_def, num_tv_def] THEN Cases_on `h` THEN
SRW_TAC [] [idx_bound_def, num_tv_def] THEN Cases_on `idx` THEN
SRW_TAC [ARITH_ss] [idx_bound_def, num_tv_def, arithmeticTheory.ADD1]);

val idx_env_thm = Q.store_thm ("idx_env_thm",
`!E idx. value_env E \/ type_env E \/ store_env E ==> ~(idx_bound E idx)`,
Induct THEN SRW_TAC [] [value_env_def, type_env_def, store_env_def, idx_bound_def] THEN
Cases_on `h` THEN FULL_SIMP_TAC list_ss [value_env_def, type_env_def, store_env_def, idx_bound_def]);

val type_env_lookup_lem = Q.store_thm ("type_env_lookup_lem",
`!E. type_env E ==>
            (!x. lookup E (name_l x) = NONE) /\
            (!x. lookup E (name_vn x) = NONE) /\
            (!x. lookup E name_tv = NONE)`,
Induct THEN SRW_TAC [] [lookup_def, type_env_def, domEB_def] THEN Cases_on `h` THEN
FULL_SIMP_TAC list_ss [type_env_def, domEB_def, name_distinct]);

val type_env_num_tv_thm = Q.prove (
`!E. type_env E ==> (num_tv E = 0)`,
Induct THEN SRW_TAC [] [num_tv_def, type_env_def] THEN Cases_on `h` THEN
FULL_SIMP_TAC list_ss [num_tv_def, type_env_def]);

val lookup_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 EB name. type_env E2 /\ store_env E3 /\
          (lookup (E1++E2++E3++E4) name = SOME EB) ==> (lookup (E1++E3++E2++E4) name = SOME EB)`,
SRW_TAC [] [lookup_append_thm] THEN
Cases_on `lookup E1 name` THEN FULL_SIMP_TAC list_ss [option_case_def] THEN
Cases_on `lookup E2 name` THEN FULL_SIMP_TAC list_ss [option_case_def] THEN
Cases_on `lookup E3 name` THEN FULL_SIMP_TAC list_ss [option_case_def, num_tv_append_thm] THEN
IMP_RES_TAC type_env_num_tv_thm THEN IMP_RES_TAC value_env_num_tv_thm THEN FULL_SIMP_TAC list_ss [] THEN
Cases_on `name` THEN IMP_RES_TAC store_env_lookup_lem THEN FULL_SIMP_TAC list_ss [] THEN
METIS_TAC [NOT_SOME_NONE, type_env_lookup_lem]);

val idx_bound_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 idx. type_env E2 /\ store_env E3 /\ idx_bound (E1 ++ E2 ++ E3 ++ E4) idx ==>
                   idx_bound (E1 ++ E3 ++ E2 ++ E4) idx`,
SRW_TAC [ARITH_ss] [idx_bound_append_thm, idx_env_thm, num_tv_append_thm] THEN
METIS_TAC [idx_env_thm]);

local

val lem1 = Q.prove (
`!E1 E2 E3 t. tkind (E1++E3) t /\ Eok (E1++E2++E3) /\ store_env E1 /\ type_env E2 ==> tkind (E1++E2++E3) t`,
Induct THEN SRW_TAC [] [] THENL
[IMP_RES_TAC tkind_weak_thm THEN IMP_RES_TAC type_env_num_tv_thm THEN FULL_SIMP_TAC list_ss [shiftt_add_thm],
 Cases_on `h` THEN FULL_SIMP_TAC list_ss [store_env_def] THEN
    MATCH_MP_TAC ((SIMP_RULE list_ss [num_tv_def, shiftt_add_thm] o Q.SPEC `[EB_l n t']`) tkind_weak_thm) THEN
    `tkind (E1 ++ E3) t` by METIS_TAC [value_env_ok_str_thm, APPEND, APPEND_ASSOC, store_env_def] THEN
    METIS_TAC [ok_ok_thm, APPEND]]);

val lem2 = Q.prove (
`Eok (E2 ++ EB_l n t::E3 ++ E4) ==> ~MEM (name_l n) (MAP domEB E2)`,
Induct_on `E2` THEN SRW_TAC [] [] THEN `Eok (E2 ++ EB_l n t::E3 ++ E4)` by METIS_TAC [APPEND, ok_ok_thm] THEN
FULL_SIMP_TAC list_ss [] THEN Cases_on `h` THEN FULL_SIMP_TAC list_ss [Eok_def] THEN
FULL_SIMP_TAC list_ss [domEB_def] THEN SRW_TAC [] []);

in

val ok_store_type_perm_thm = Q.prove (
`(!E1 E2 E3 E4. Eok (E1++E2++E3++E4) /\ type_env E2 /\ store_env E3 ==>
                  Eok (E1++E3++E2++E4)) /\
 (!E1 tc E2 E3 E4 k. (typeconstr_kind (E1++E2++E3++E4) tc = SOME k) /\ type_env E2 /\
                       store_env E3 ==>
                      (typeconstr_kind (E1++E3++E2++E4) tc = SOME k)) /\
 (!E1 ts E2 E3 E4. tsok (E1++E2++E3++E4) ts /\ type_env E2 /\ store_env E3 ==>
                     tsok (E1++E3++E2++E4) ts) /\
 (!E1 tpo ts E2 E3 E4. ntsok (E1++E2++E3++E4) tpo ts /\ type_env E2 /\ store_env E3 ==>
                         ntsok (E1++E3++E2++E4) tpo ts) /\
 (!E1 t E2 E3 E4. tkind (E1++E2++E3++E4) t /\ type_env E2 /\ store_env E3 ==>
                    tkind (E1++E3++E2++E4) t)`,
HO_MATCH_MP_TAC Eok_ind THEN SRW_TAC [] [Eok_def, COND_EXPAND_EQ] THEN
FULL_SIMP_TAC list_ss [Eok_def, type_env_def, store_env_def, EVERY_MEM] THEN SRW_TAC [] [] THENL
[ALL_TAC,
 METIS_TAC [lookup_store_type_perm_thm],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [lookup_store_type_perm_thm],
 METIS_TAC [lookup_store_type_perm_thm],
 METIS_TAC [lookup_store_type_perm_thm],
 Cases_on `lookup (E1 ++ E2 ++ E3 ++ E4) (name_tcn typeconstr_name)` THEN
       FULL_SIMP_TAC list_ss [option_case_def] THEN IMP_RES_TAC lookup_store_type_perm_thm THEN SRW_TAC [] [],
 METIS_TAC [idx_bound_store_type_perm_thm]]
THEN
Induct_on `E3` THEN SRW_TAC [] [] THEN Cases_on `h` THEN FULL_SIMP_TAC list_ss [store_env_def] THEN
`Eok (EB_l n t::E3 ++ E4)` by METIS_TAC [ok_ok_thm, APPEND, APPEND_ASSOC] THEN
FULL_SIMP_TAC list_ss [Eok_def] THEN
`Eok (E2++E3++E4)` by METIS_TAC [value_env_ok_str_thm, store_env_def, APPEND, APPEND_ASSOC] THEN
SRW_TAC [] [lem1] THEN METIS_TAC [lem2]);

end;


val teq_store_type_perm_thm = Q.prove (
`!E t t'. JTeq E t t' ==> !E1 E2 E3 E4. (E = E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
          JTeq (E1++E3++E2++E4) t t'`,
INDUCT_TAC JTeq_ind []
[([``"JTeq_refl"``], METIS_TAC [ok_store_type_perm_thm, ok_ok_thm, JTeq_rules]),
 ([``"JTeq_sym"``, ``"JTeq_trans"``], METIS_TAC [JTeq_rules]),
 ([``"JTeq_expand"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN NTAC 3 DISJ2_TAC THEN DISJ1_TAC THEN
      FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN 
      METIS_TAC [lookup_store_type_perm_thm, ok_store_type_perm_thm]),
 ([``"JTeq_arrow"``], METIS_TAC [JTeq_rules]),
 ([``"JTeq_tuple"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN
      METIS_TAC []),
 ([``"JTeq_constr"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN
      METIS_TAC [ok_store_type_perm_thm])]);



val uprim_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 up t. JTuprim (E1++E2++E3++E4) up t /\ store_env E3 /\ type_env E2 ==>
                    JTuprim (E1++E3++E2++E4) up t`,
SRW_TAC [] [JTuprim_cases, ok_store_type_perm_thm]);

val bprim_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 bp t. JTbprim (E1++E2++E3++E4) bp t /\ store_env E3 /\ type_env E2 ==>
                    JTbprim (E1++E3++E2++E4) bp t`,
SRW_TAC [] [JTbprim_cases, ok_store_type_perm_thm]);

val inst_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 t ts. JTinst (E1++E2++E3++E4) t ts /\ store_env E3 /\ type_env E2 ==>
                    JTinst (E1++E3++E2++E4) t ts`,
SRW_TAC [] [JTinst_cases, EVERY_MEM] THEN METIS_TAC [ok_store_type_perm_thm]);

val inst_named_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 t tpo ts. JTinst_named (E1++E2++E3++E4) t tpo ts /\ store_env E3 /\ type_env E2 ==>
                        JTinst_named (E1++E3++E2++E4) t tpo ts`,
SRW_TAC [] [JTinst_named_cases, EVERY_MEM] THEN METIS_TAC [ok_store_type_perm_thm]);

val vn_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 vn t. JTvalue_name (E1++E2++E3++E4) vn t /\ store_env E3 /\ type_env E2 ==>
                    JTvalue_name (E1++E3++E2++E4) vn t`,
SRW_TAC [] [JTvalue_name_cases] THEN Q.EXISTS_TAC `ts` THEN
SRW_TAC [] [lookup_store_type_perm_thm, inst_store_type_perm_thm]);

val constr_c_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t. JTconstr_c (E1++E2++E3++E4) c t /\ store_env E3 /\ type_env E2 ==>
                   JTconstr_c (E1++E3++E2++E4) c t`,
SRW_TAC [] [JTconstr_c_cases, ok_store_type_perm_thm, lookup_store_type_perm_thm, EVERY_MEM]);

val const_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t. JTconst (E1++E2++E3++E4) c t /\ store_env E3 /\ type_env E2 ==>
                   JTconst (E1++E3++E2++E4) c t`,
SRW_TAC [] [JTconst_cases, ok_store_type_perm_thm, constr_c_store_type_perm_thm]);

val constr_p_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t t'. JTconstr_p (E1++E2++E3++E4) c t t' /\ store_env E3 /\ type_env E2 ==>
                      JTconstr_p (E1++E3++E2++E4) c t t'`,
SRW_TAC [] [JTconstr_p_cases, ok_store_type_perm_thm] THEN
METIS_TAC [lookup_store_type_perm_thm, inst_named_store_type_perm_thm]);

val field_store_type_perm_thm = Q.prove (
`!E1 E2 E3 E4 fn t t'. JTfield (E1++E2++E3++E4) fn t t' /\ store_env E3 /\ type_env E2 ==>
                       JTfield (E1++E3++E2++E4) fn t t'`,
SRW_TAC [] [JTfield_cases] THEN
METIS_TAC [lookup_store_type_perm_thm, inst_named_store_type_perm_thm]);

val inst_any_store_type_perm_thm = Q.prove (
`!E t t'. JTinst_any E t t' ==> !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
          JTinst_any (E1++E3++E2++E4) t t'`,
RULE_INDUCT_TAC JTinst_any_ind [JTinst_any_fun, EVERY_MEM]
[] THEN
METIS_TAC [ok_store_type_perm_thm]);

val pat_store_type_perm_thm = Q.prove (
`!S E p t E'. JTpat S E p t E' ==> !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
              JTpat S (E1++E3++E2++E4) p t E'`,
RULE_INDUCT_TAC JTpat_ind [JTpat_fun, EVERY_MEM]
[([``"JTpat_var"``, ``"JTpat_any"``, ``"JTpat_tuple"``, ``"JTpat_cons"``],
  METIS_TAC [ok_store_type_perm_thm]),
 ([``"JTpat_typed"``], SRW_TAC [] [] THEN METIS_TAC [inst_any_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTpat_constant"``],
  METIS_TAC [const_store_type_perm_thm]),
 ([``"JTpat_construct"``, ``"JTpat_construct_any"``],
  METIS_TAC [constr_p_store_type_perm_thm]),
 ([``"JTpat_record"``],
  METIS_TAC [field_store_type_perm_thm]),
 ([``"JTpat_or"``],
  METIS_TAC [])]);

val store_type_perm_thm = Q.prove (
`(!S E e t. JTe S E e t ==> !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
            JTe S (E1++E3++E2++E4) e t) /\
 (!S E pm t t'. JTpat_matching S E pm t t' ==>
                !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
                JTpat_matching S (E1++E3++E2++E4) pm t t') /\
 (!S E lb E'. JTlet_binding S E lb E' ==> !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
              JTlet_binding S (E1++E3++E2++E4) lb E') /\
 (!S E lrbs E'. JTletrec_binding S E lrbs E' ==>
                !E1 E2 E3 E4. (E=E1++E2++E3++E4) /\ store_env E3 /\ type_env E2 ==>
                JTletrec_binding S (E1++E3++E2++E4) lrbs E')`,
RULE_INDUCT_TAC JTe_ind [JTe_fun, EVERY_MEM]
[([``"JTe_uprim"``, ``"JTe_bprim"``, ``"JTe_ident"``, ``"JTe_constant"``],
  METIS_TAC [uprim_store_type_perm_thm, bprim_store_type_perm_thm, vn_store_type_perm_thm,
             const_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTe_typed"``], SRW_TAC [] [] THEN METIS_TAC [inst_any_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTe_tuple"``, ``"JTe_apply"``, ``"JTe_match"``, ``"JTe_cons"``, ``"JTe_and"``, ``"JTe_or"``,
   ``"JTe_while"``, ``"JTe_function"``, ``"JTe_assert"``],
  METIS_TAC [teq_store_type_perm_thm]),
 ([``"JTe_construct"``],
  METIS_TAC [constr_p_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTe_record_constr"``],
  SRW_TAC [] [] THEN
  MAP_EVERY Q.EXISTS_TAC [`field_name'_list`, `t'_list`, `field_name_e_t_list`] THEN
  METIS_TAC [field_store_type_perm_thm, lookup_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTe_record_with"``, ``"JTe_record_proj"``],
  METIS_TAC [field_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTe_for"``],
  METIS_TAC [APPEND, teq_store_type_perm_thm]),
 ([``"JTe_let_mono"``],
  METIS_TAC [APPEND_ASSOC]),
 ([``"JTe_let_poly"``],
  SRW_TAC [] [] THEN DISJ2_TAC THEN Q.EXISTS_TAC `x_t_list` THEN METIS_TAC [APPEND, APPEND_ASSOC]),
 ([``"JTe_letrec"``],
  METIS_TAC [APPEND, APPEND_ASSOC]),
 ([``"JTe_assertfalse"``],
  SRW_TAC [] [JTconst_cases] THEN METIS_TAC [ok_store_type_perm_thm]),
 ([``"JTe_location"``],
  METIS_TAC [lookup_store_type_perm_thm, ok_store_type_perm_thm, teq_store_type_perm_thm]),
 ([``"JTpat_matching_pm"``], 
  SRW_TAC [] [] THEN Q.EXISTS_TAC `pattern_e_E_list` THEN SRW_TAC [] [] THEN 
         METIS_TAC [pat_store_type_perm_thm]),
 ([``"JTlet_binding_poly"``],
  METIS_TAC [pat_store_type_perm_thm, APPEND_ASSOC]),
 ([``"JTletrec_binding_equal_function"``],
  SRW_TAC [] [] THEN Q.EXISTS_TAC `value_name_pattern_matching_t_t'_list` THEN SRW_TAC [] [])]);

val type_def_store_type_perm_thm = Q.prove (
`!E td E'. JTtype_definition E td E' ==> !E1 E2 E3 E4. (E = E1++E2++E3++E4) /\ type_env E2 /\ store_env E3 ==>
           JTtype_definition (E1++E3++E2++E4) td E'`,
RULE_INDUCT_TAC JTtype_definition_ind [JTtype_definition_rules] [] THEN
SRW_TAC [] [] THEN IMP_RES_TAC JTtype_definition_rules THEN FULL_SIMP_TAC (srw_ss()) [] THEN
`Eok ((E''' ++ E'' ++ E' ++ E1) ++ E2 ++ E3 ++ E4) ==>
 Eok ((E''' ++ E'' ++ E' ++ E1) ++ E3 ++ E2 ++ E4)` by METIS_TAC [ok_store_type_perm_thm] THEN
 FULL_SIMP_TAC (srw_ss()) []);


val def_store_type_perm_thm = Q.prove (
`!E d E'. JTdefinition E d E' ==> !E1 E2 E3 E4. (E = E1++E2++E3++E4) /\ type_env E2 /\ store_env E3 ==>
          JTdefinition (E1++E3++E2++E4) d E'`,
RULE_INDUCT_TAC JTdefinition_ind [JTdefinition_fun]
[([``"JTdefinition_let_poly"``, ``"JTdefinition_let_mono"``, ``"JTdefinition_letrec"``],
  SRW_TAC [] [] THEN METIS_TAC [store_type_perm_thm, APPEND, APPEND_ASSOC]),
 ([``"JTdefinition_typedef"``],
  METIS_TAC [type_def_store_type_perm_thm]),
 ([``"JTdefinition_exndef"``],
  SRW_TAC [] [JTconstr_decl_cases] THEN METIS_TAC [ok_store_type_perm_thm])]);

val defs_store_type_perm_thm = Q.store_thm ("defs_store_type_perm_thm",
`!E ds E'. JTdefinitions E ds E' ==> !E1 E2 E3 E4. (E = E1++E2++E3++E4) /\ type_env E2 /\ store_env E3 ==>
           JTdefinitions (E1++E3++E2++E4) ds E'`,
RULE_INDUCT_TAC JTdefinitions_ind [JTdefinitions_fun]
[([``"JTdefinitions_empty"``], METIS_TAC [ok_store_type_perm_thm]),
 ([``"JTdefinitions_item"``], METIS_TAC [def_store_type_perm_thm, APPEND_ASSOC])]);

local

val lem1 = Q.prove (
`!x E. value_env (x::E) = (?n ts. x = EB_vn n ts) /\ value_env E`,
Cases THEN SRW_TAC [] [value_env_def]);

val lem2 = Q.prove (
`!E1 E2. PERM E1 E2 ==> ALL_DISTINCT (MAP domEB E1) /\ value_env E1 ==> PERM E1 E2 /\ 
                        !name. (lookup E1 name = lookup E2 name)`,
HO_MATCH_MP_TAC PERM_IND THEN
SRW_TAC [] [PERM_REFL, PERM_MONO, PERM_SWAP_AT_FRONT, PERM_TRANS, lem1] THENL
[SRW_TAC [] [lookup_def],
 SRW_TAC [] [lookup_def, shiftEB_add_thm, OPTION_MAP_ID, domEB_def] THEN FULL_SIMP_TAC (srw_ss()) [domEB_def],
 METIS_TAC [PERM_ALL_DISTINCT, PERM_MAP, PERM_TRANS, value_env_perm_thm],
 METIS_TAC [PERM_ALL_DISTINCT, PERM_MAP, PERM_TRANS, value_env_perm_thm]]);

in

val lookup_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 EB name. value_env E2 /\ PERM E2 E3 /\ (ALL_DISTINCT (MAP domEB E2) \/ !n. ~(name = name_vn n)) /\
          (lookup (E1++E2++E4) name = SOME EB) ==> (lookup (E1++E3++E4) name = SOME EB)`,
SRW_TAC [] [lookup_append_thm] THEN IMP_RES_TAC value_env_perm_thm THEN 
Cases_on `lookup E1 name` THEN FULL_SIMP_TAC (srw_ss()) [] THEN
Cases_on `lookup E2 name` THEN FULL_SIMP_TAC (srw_ss()) [] THEN
Cases_on `lookup E3 name` THEN FULL_SIMP_TAC (srw_ss()) [num_tv_append_thm] THEN
IMP_RES_TAC value_env_num_tv_thm THEN FULL_SIMP_TAC (srw_ss()) [] THEN IMP_RES_TAC value_env_lookup_lem THENL
[METIS_TAC [NOT_SOME_NONE, lem2, PERM_SYM, SOME_11],
 METIS_TAC [NOT_SOME_NONE, lem2, PERM_SYM, SOME_11],
 METIS_TAC [NOT_SOME_NONE, lem2, PERM_SYM, SOME_11],
 Cases_on `name` THEN FULL_SIMP_TAC (srw_ss()) [],
 Cases_on `name` THEN FULL_SIMP_TAC (srw_ss()) [],
 Cases_on `name` THEN FULL_SIMP_TAC (srw_ss()) []]);

end;


val idx_bound_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 idx. value_env E2 /\ PERM E2 E3 /\ idx_bound (E1 ++ E2 ++ E4) idx ==>
                   idx_bound (E1 ++ E3 ++ E4) idx`,
SRW_TAC [ARITH_ss] [idx_bound_append_thm, idx_env_thm, num_tv_append_thm] THEN
METIS_TAC [idx_env_thm, value_env_perm_thm, value_env_num_tv_thm]);

local

val lem1 = Q.prove (
`!E1 E2 E3 t. tkind (E1++E3) t /\ Eok (E1++E2++E3) /\ store_env E1 /\ type_env E2 ==> tkind (E1++E2++E3) t`,
Induct THEN SRW_TAC [] [] THENL
[IMP_RES_TAC tkind_weak_thm THEN IMP_RES_TAC type_env_num_tv_thm THEN FULL_SIMP_TAC list_ss [shiftt_add_thm],
 Cases_on `h` THEN FULL_SIMP_TAC list_ss [store_env_def] THEN
    MATCH_MP_TAC ((SIMP_RULE list_ss [num_tv_def, shiftt_add_thm] o Q.SPEC `[EB_l n t']`) tkind_weak_thm) THEN
    `tkind (E1 ++ E3) t` by METIS_TAC [value_env_ok_str_thm, APPEND, APPEND_ASSOC, store_env_def] THEN
    METIS_TAC [ok_ok_thm, APPEND]]);

val lem2 = Q.prove (
`Eok (E2 ++ EB_l n t::E3 ++ E4) ==> ~MEM (name_l n) (MAP domEB E2)`,
Induct_on `E2` THEN SRW_TAC [] [] THEN `Eok (E2 ++ EB_l n t::E3 ++ E4)` by METIS_TAC [APPEND, ok_ok_thm] THEN
FULL_SIMP_TAC list_ss [] THEN Cases_on `h` THEN FULL_SIMP_TAC list_ss [Eok_def] THEN
FULL_SIMP_TAC list_ss [domEB_def] THEN SRW_TAC [] []);

val lem3 = Q.prove (
`!x E. value_env (x::E) = (?n ts. x = EB_vn n ts) /\ value_env E`,
Cases THEN SRW_TAC [] [value_env_def]);

val lem4 = Q.prove (
`!E. value_env E ==> ~MEM EB_tv E`,
Induct THEN SRW_TAC [] [lem3]);

val lem5 = Q.prove (
`tsok (E2 ++ E4) ts /\ value_env E2 /\ value_env E3 /\ Eok (E3 ++ E4) ==> tsok (E3++E4) ts`,
METIS_TAC [value_env_ok_str_thm, APPEND, lem4, weak_ok_thm]);

val lem6 = Q.prove (
`!E2 E3. PERM E2 E3 ==> Eok (E2 ++ E4) /\ value_env E2 ==> 
         PERM E2 E3 /\ Eok (E3 ++ E4)`,
HO_MATCH_MP_TAC PERM_IND THEN SRW_TAC [] [lem3] THEN FULL_SIMP_TAC (srw_ss()) [Eok_def] THENL
[METIS_TAC [ok_ok_thm],
 METIS_TAC [ok_ok_thm, lem5, value_env_perm_thm],
 IMP_RES_TAC ok_ok_thm THEN FULL_SIMP_TAC (srw_ss()) [Eok_def] THEN IMP_RES_TAC ok_ok_thm THEN
     FULL_SIMP_TAC (srw_ss()) [Eok_def] THEN METIS_TAC [PERM_SWAP_AT_FRONT],
 IMP_RES_TAC ok_ok_thm THEN FULL_SIMP_TAC (srw_ss()) [Eok_def] THEN IMP_RES_TAC ok_ok_thm THEN
     SIMP_TAC pure_ss [GSYM APPEND] THEN MATCH_MP_TAC (GEN_ALL lem5) THEN
     FULL_SIMP_TAC (srw_ss()) [Eok_def, lem3] THEN Q.EXISTS_TAC `E2` THEN
     SRW_TAC [] [] THEN1 METIS_TAC [value_env_perm_thm] THEN
     METIS_TAC [value_env_ok_str_thm, APPEND, lem4, weak_ok_thm, value_env_perm_thm, lem3],
 METIS_TAC [value_env_perm_thm, PERM_TRANS],
 METIS_TAC [value_env_perm_thm]]);

in

val ok_value_perm_thm = Q.prove (
`(!E1 E2 E3 E4. Eok (E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 ==>
                  Eok (E1++E3++E4)) /\
 (!E1 tc E2 E3 E4 k. (typeconstr_kind (E1++E2++E4) tc = SOME k) /\ value_env E2 /\
                       PERM E2 E3 ==>
                      (typeconstr_kind (E1++E3++E4) tc = SOME k)) /\
 (!E1 ts E2 E3 E4. tsok (E1++E2++E4) ts /\ value_env E2 /\ PERM E2 E3 ==>
                     tsok (E1++E3++E4) ts) /\
 (!E1 tpo ts E2 E3 E4. ntsok (E1++E2++E4) tpo ts /\ value_env E2 /\ PERM E2 E3 ==>
                         ntsok (E1++E3++E4) tpo ts) /\
 (!E1 t E2 E3 E4. tkind (E1++E2++E4) t /\ value_env E2 /\ PERM E2 E3 ==>
                    tkind (E1++E3++E4) t)`,
HO_MATCH_MP_TAC Eok_ind THEN SRW_TAC [] [Eok_def, COND_EXPAND_EQ] THEN
FULL_SIMP_TAC list_ss [Eok_def, value_env_def, EVERY_MEM] THEN SRW_TAC [] [] THEN
IMP_RES_TAC value_env_perm_thm THEN IMP_RES_TAC value_env_lookup_lem THEN 
FULL_SIMP_TAC (srw_ss()) [GSYM lookup_dom_thm] THENL
[METIS_TAC [lem6],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [lookup_value_perm_thm, name_distinct],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [lookup_value_perm_thm, name_distinct],
 METIS_TAC [],
 METIS_TAC [lookup_value_perm_thm, name_distinct],
 METIS_TAC [],
 METIS_TAC [lookup_value_perm_thm, name_distinct],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 Cases_on `lookup (E1 ++ E2 ++ E4) (name_tcn typeconstr_name)` THEN FULL_SIMP_TAC (srw_ss()) [] THEN
      `lookup (E1 ++ E3 ++ E4) (name_tcn typeconstr_name) = SOME x` 
             by METIS_TAC [lookup_value_perm_thm, name_distinct] THEN
      SRW_TAC [] [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [idx_bound_value_perm_thm],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC [],
 METIS_TAC []]);

end;

val teq_value_perm_thm = Q.prove (
`!E t t'. JTeq E t t' ==> !E1 E2 E3 E4. (E = E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 ==>
          JTeq (E1++E3++E4) t t'`,
INDUCT_TAC JTeq_ind []
[([``"JTeq_refl"``], METIS_TAC [ok_value_perm_thm, ok_ok_thm, JTeq_rules]),
 ([``"JTeq_sym"``, ``"JTeq_trans"``], METIS_TAC [JTeq_rules]),
 ([``"JTeq_expand"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN NTAC 3 DISJ2_TAC THEN DISJ1_TAC THEN
      FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN 
      METIS_TAC [lookup_value_perm_thm, ok_value_perm_thm, name_distinct]),
 ([``"JTeq_arrow"``], METIS_TAC [JTeq_rules]),
 ([``"JTeq_tuple"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN
      METIS_TAC []),
 ([``"JTeq_constr"``], 
  SRW_TAC [] [] THEN ONCE_REWRITE_TAC [JTeq_cases] THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM] THEN
      METIS_TAC [ok_value_perm_thm])]);


val uprim_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 up t. JTuprim (E1++E2++E4) up t /\ value_env E2 /\ PERM E2 E3 ==>
                    JTuprim (E1++E3++E4) up t`,
SRW_TAC [] [JTuprim_cases] THEN METIS_TAC [ok_value_perm_thm]);

val bprim_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 bp t. JTbprim (E1++E2++E4) bp t /\ value_env E2 /\ PERM E2 E3 ==>
                    JTbprim (E1++E3++E4) bp t`,
SRW_TAC [] [JTbprim_cases] THEN METIS_TAC [ok_value_perm_thm]);

val inst_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 t ts. JTinst (E1++E2++E4) t ts /\ value_env E2 /\ PERM E2 E3==>
                    JTinst (E1++E3++E4) t ts`,
SRW_TAC [] [JTinst_cases, EVERY_MEM] THEN METIS_TAC [ok_value_perm_thm]);

val inst_named_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 t tpo ts. JTinst_named (E1++E2++E4) t tpo ts /\ value_env E2 /\ PERM E2 E3 ==>
                        JTinst_named (E1++E3++E4) t tpo ts`,
SRW_TAC [] [JTinst_named_cases, EVERY_MEM] THEN METIS_TAC [ok_value_perm_thm]);

val vn_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 vn t. JTvalue_name (E1++E2++E4) vn t /\ value_env E2 /\ PERM E2 E3 /\ 
                    ALL_DISTINCT (MAP domEB E2) ==>
                    JTvalue_name (E1++E3++E4) vn t`,
SRW_TAC [] [JTvalue_name_cases] THEN Q.EXISTS_TAC `ts` THEN
SRW_TAC [] [] THEN METIS_TAC [lookup_value_perm_thm, inst_value_perm_thm]);

val constr_c_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t. JTconstr_c (E1++E2++E4) c t /\ value_env E2 /\ PERM E2 E3 ==>
                   JTconstr_c (E1++E3++E4) c t`,
SRW_TAC [] [JTconstr_c_cases, EVERY_MEM] THEN 
METIS_TAC [ok_value_perm_thm, lookup_value_perm_thm, name_distinct]);

val const_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t. JTconst (E1++E2++E4) c t /\ value_env E2 /\ PERM E2 E3 ==>
                   JTconst (E1++E3++E4) c t`,
SRW_TAC [] [JTconst_cases] THEN METIS_TAC [ok_value_perm_thm, constr_c_value_perm_thm]);

val constr_p_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 c t t'. JTconstr_p (E1++E2++E4) c t t' /\ value_env E2 /\ PERM E2 E3 ==>
                      JTconstr_p (E1++E3++E4) c t t'`,
SRW_TAC [] [JTconstr_p_cases] THEN
METIS_TAC [ok_value_perm_thm, lookup_value_perm_thm, inst_named_value_perm_thm, name_distinct]);

val field_value_perm_thm = Q.prove (
`!E1 E2 E3 E4 fn t t'. JTfield (E1++E2++E4) fn t t' /\ value_env E2 /\ PERM E2 E3 ==>
                       JTfield (E1++E3++E4) fn t t'`,
SRW_TAC [] [JTfield_cases] THEN
METIS_TAC [ok_value_perm_thm, lookup_value_perm_thm, inst_named_value_perm_thm, name_distinct]);

val inst_any_value_perm_thm = Q.prove (
`!E t t'. JTinst_any E t t' ==> !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 ==>
          JTinst_any (E1++E3++E4) t t'`,
RULE_INDUCT_TAC JTinst_any_ind [JTinst_any_fun, EVERY_MEM] [] THEN
METIS_TAC [ok_value_perm_thm]);

val pat_value_perm_thm = Q.prove (
`!S E p t E'. JTpat S E p t E' ==> !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 ==>
              JTpat S (E1++E3++E4) p t E'`,
RULE_INDUCT_TAC JTpat_ind [JTpat_fun, EVERY_MEM]
[([``"JTpat_var"``, ``"JTpat_any"``, ``"JTpat_tuple"``, ``"JTpat_cons"``],
  METIS_TAC [ok_value_perm_thm]),
 ([``"JTpat_typed"``], SRW_TAC [] [] THEN METIS_TAC [inst_any_value_perm_thm, teq_value_perm_thm]),
 ([``"JTpat_constant"``],
  METIS_TAC [const_value_perm_thm]),
 ([``"JTpat_construct"``, ``"JTpat_construct_any"``],
  METIS_TAC [constr_p_value_perm_thm]),
 ([``"JTpat_record"``],
  METIS_TAC [field_value_perm_thm]),
 ([``"JTpat_or"``],
  METIS_TAC [])]);

val value_perm_thm = Q.store_thm ("value_perm_thm",
`(!S E e t. JTe S E e t ==> !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\ 
                                          ALL_DISTINCT (MAP domEB E2) ==>
            JTe S (E1++E3++E4) e t) /\
 (!S E pm t t'. JTpat_matching S E pm t t' ==>
                !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\ ALL_DISTINCT (MAP domEB E2) ==>
                JTpat_matching S (E1++E3++E4) pm t t') /\
 (!S E lb E'. JTlet_binding S E lb E' ==> !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\
                                                        ALL_DISTINCT (MAP domEB E2) ==>
              JTlet_binding S (E1++E3++E4) lb E') /\
 (!S E lrbs E'. JTletrec_binding S E lrbs E' ==>
                !E1 E2 E3 E4. (E=E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\ ALL_DISTINCT (MAP domEB E2) ==>
                JTletrec_binding S (E1++E3++E4) lrbs E')`,
RULE_INDUCT_TAC JTe_ind [JTe_fun, EVERY_MEM]
[([``"JTe_uprim"``, ``"JTe_bprim"``, ``"JTe_ident"``, ``"JTe_constant"``],
  METIS_TAC [uprim_value_perm_thm, bprim_value_perm_thm, vn_value_perm_thm, const_value_perm_thm,
             teq_value_perm_thm]),
 ([``"JTe_typed"``], SRW_TAC [] [] THEN METIS_TAC [inst_any_value_perm_thm, teq_value_perm_thm]),
 ([``"JTe_tuple"``, ``"JTe_apply"``, ``"JTe_match"``, ``"JTe_cons"``, ``"JTe_and"``, ``"JTe_or"``, 
   ``"JTe_while"``, ``"JTe_function"``, ``"JTe_assert"``],
  METIS_TAC [teq_value_perm_thm]),
 ([``"JTe_construct"``],
  METIS_TAC [constr_p_value_perm_thm, teq_value_perm_thm]),
 ([``"JTe_record_constr"``],
  SRW_TAC [] [] THEN
  MAP_EVERY Q.EXISTS_TAC [`field_name'_list`, `t'_list`, `field_name_e_t_list`] THEN SRW_TAC [] [] THEN
  METIS_TAC [field_value_perm_thm, lookup_value_perm_thm, teq_value_perm_thm]),
 ([``"JTe_record_with"``, ``"JTe_record_proj"``],
  METIS_TAC [field_value_perm_thm, teq_value_perm_thm]),
 ([``"JTe_for"``],
  METIS_TAC [APPEND, teq_value_perm_thm]),
 ([``"JTe_let_mono"``],
  METIS_TAC [APPEND_ASSOC]),
 ([``"JTe_let_poly"``],
  SRW_TAC [] [] THEN DISJ2_TAC THEN Q.EXISTS_TAC `x_t_list` THEN METIS_TAC [APPEND, APPEND_ASSOC]),
 ([``"JTe_letrec"``],
  METIS_TAC [APPEND, APPEND_ASSOC]),
 ([``"JTe_assertfalse"``],
  SRW_TAC [] [JTconst_cases] THEN METIS_TAC [ok_value_perm_thm]),
 ([``"JTe_location"``],
  METIS_TAC [lookup_value_perm_thm, ok_value_perm_thm, teq_value_perm_thm]),
 ([``"JTlet_binding_poly"``],
  METIS_TAC [pat_value_perm_thm, APPEND_ASSOC]),
 ([``"JTpat_matching_pm"``],
  SRW_TAC [] [] THEN Q.EXISTS_TAC `pattern_e_E_list` THEN SRW_TAC [] [] THEN METIS_TAC [pat_value_perm_thm]),
 ([``"JTletrec_binding_equal_function"``],
  SRW_TAC [] [] THEN Q.EXISTS_TAC `value_name_pattern_matching_t_t'_list` THEN SRW_TAC [] [])]);

val type_def_value_perm_thm = Q.prove (
`!E td E'. JTtype_definition E td E' ==> !E1 E2 E3 E4. (E = E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 ==>
           JTtype_definition (E1++E3++E4) td E'`,
RULE_INDUCT_TAC JTtype_definition_ind [JTtype_definition_rules] [] THEN
SRW_TAC [] [] THEN IMP_RES_TAC JTtype_definition_rules THEN FULL_SIMP_TAC (srw_ss()) [] THEN
`Eok ((E''' ++ E'' ++ E' ++ E1) ++ E2 ++ E4) ==>
 Eok ((E''' ++ E'' ++ E' ++ E1) ++ E3 ++ E4)` by METIS_TAC [ok_value_perm_thm] THEN
 FULL_SIMP_TAC (srw_ss()) []);

val def_value_perm_thm = Q.prove (
`!E d E'. JTdefinition E d E' ==> !E1 E2 E3 E4. (E = E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\
          ALL_DISTINCT (MAP domEB E2) ==>
          JTdefinition (E1++E3++E4) d E'`,
RULE_INDUCT_TAC JTdefinition_ind [JTdefinition_fun]
[([``"JTdefinition_let_poly"``, ``"JTdefinition_let_mono"``, ``"JTdefinition_letrec"``],
  SRW_TAC [] [] THEN METIS_TAC [value_perm_thm, APPEND, APPEND_ASSOC]),
 ([``"JTdefinition_typedef"``],
  METIS_TAC [type_def_value_perm_thm]),
 ([``"JTdefinition_exndef"``],
  SRW_TAC [] [JTconstr_decl_cases] THEN METIS_TAC [ok_value_perm_thm])]);

val defs_value_perm_thm = Q.store_thm ("defs_value_perm_thm",
`!E ds E'. JTdefinitions E ds E' ==> !E1 E2 E3 E4. (E = E1++E2++E4) /\ value_env E2 /\ PERM E2 E3 /\
           ALL_DISTINCT (MAP domEB E2) ==>
           JTdefinitions (E1++E3++E4) ds E'`,
RULE_INDUCT_TAC JTdefinitions_ind [JTdefinitions_fun]
[([``"JTdefinitions_empty"``], METIS_TAC [ok_value_perm_thm]),
 ([``"JTdefinitions_item"``], 
  SRW_TAC [] [] THEN Q.EXISTS_TAC `E'` THEN SRW_TAC [] [] THEN METIS_TAC [def_value_perm_thm, APPEND_ASSOC])]);

val _ = export_theory();