-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathholKernelScript.sml
1376 lines (1200 loc) · 40.7 KB
/
holKernelScript.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
Define the overloading version of the Candle kernel as shallowly
embedded functions in HOL using a monadic style in order to
conveniently pass around state and propagate exceptions.
*)
open preamble mlstringTheory holSyntaxExtraTheory
holSyntaxCyclicityTheory
ml_monadBaseTheory ml_monadBaseLib
val _ = new_theory "holKernel";
val _ = ParseExtras.temp_loose_equality();
val _ = patternMatchesLib.ENABLE_PMATCH_CASES();
val _ = monadsyntax.temp_add_monadsyntax()
Overload monad_bind[local] = ``st_ex_bind``
Overload monad_unitbind[local] = ``\x y. st_ex_bind x (\z. y)``
Overload monad_ignore_bind[local] = ``\x y. st_ex_bind x (\z. y)``
Overload return[local] = ``st_ex_return``
val _ = hide "state";
(* we reuse the datatypes of types and terms from the inference system *)
val type_size_def = holSyntaxTheory.type_size_def
(*
type thm = Sequent of (term list * term)
*)
Datatype:
thm = Sequent (term list) term
End
(*
We define a record that holds the state, i.e.
let the_type_constants = ref ["bool",0; "fun",2]x
let the_term_constants =
ref [("=", mk_fun_ty aty (mk_fun_ty aty bool_ty))]
let the_axioms = ref ([]:thm list)
The context is the global theory context tracked by the inference system, and
subsumes the above references. But we use them instead for efficiency (and to
be close to HOL Light).
*)
Datatype:
hol_refs = <| the_type_constants : (mlstring # num) list ;
the_term_constants : (mlstring # type) list ;
the_axioms : thm list ;
the_context : update list |>
End
(* the state-exception monad *)
Datatype:
hol_exn = Fail mlstring | Clash term
End
Type M = ``: (hol_refs, 'a, hol_exn) M``
(* deref/ref functions *)
val _ = define_monad_access_funs ``:hol_refs``;
(* failwith *)
val _ = define_monad_exception_functions ``:hol_exn`` ``:hol_refs``;
Overload failwith[local] = ``raise_Fail``
Overload raise_clash[local] = ``raise_Clash``
Overload handle_clash[local] = ``handle_Clash``
(* others *)
Definition try_def:
try f x msg = (f x otherwise failwith msg)
End
(* define failing lookup function *)
Definition assoc_def:
assoc s l =
dtcase l of
[] => failwith (strlit "not in list")
| ((x:'a,y:'b)::xs) => if s = x then do return y od else assoc s xs
End
Definition map_def:
map f l =
dtcase l of
[] => return []
| (h::t) => do h <- f h ;
t <- map f t ;
return (h::t) od
End
(*
Definition app_def:
app f l =
case l of
[] => return ()
| (h::t) => do f h ; app f t od
End
Definition first_def:
first p l =
case l of
[] => NONE
| (h::t) => if p h then SOME h else first p t
End
*)
Definition forall_def:
forall p l =
dtcase l of
[] => return T
| (h::t) => do ok <- p h ;
if ok then forall p t else return F od
End
Definition subset_def:
subset l1 l2 = EVERY (\t. MEM t l2) l1
End
(*
let types() = !the_type_constants
*)
Definition types_def:
types () = get_the_type_constants
End
(*
let get_type_arity s = assoc s (!the_type_constants)
*)
Definition get_type_arity_def:
get_type_arity s =
do l <- get_the_type_constants ; assoc s l od
End
(*
let new_type(name,arity) =
if can get_type_arity name then
failwith ("new_type: type "^name^" has already been declared")
else the_type_constants := (name,arity)::(!the_type_constants)
*)
Definition add_def_def:
add_def d = do defs <- get_the_context ;
set_the_context (d::defs) od
End
Definition add_type_def:
add_type (name,arity) =
do ok <- can get_type_arity name ;
if ok then failwith ((strlit"new_type: ") ^ name ^ (strlit" has already been declared"))
else do ts <- get_the_type_constants ;
set_the_type_constants ((name,arity)::ts) od od
End
Definition new_type_def:
new_type (name,arity) =
do add_type (name,arity);
add_def (NewType name arity) od
End
(*
let mk_type(tyop,args) =
let arity = try get_type_arity tyop with Failure _ ->
failwith ("mk_type: type "^tyop^" has not been defined") in
if arity = length args then
Tyapp(tyop,args)
else failwith ("mk_type: wrong number of arguments to "^tyop)
*)
Definition mk_type_def:
mk_type (tyop,args) =
do arity <- try get_type_arity tyop
((strlit"mk_type: type ") ^ tyop ^ (strlit" has not been defined"));
if arity = LENGTH args then
return (Tyapp tyop args)
else failwith ((strlit"mk_type: wrong number of arguments to ") ^ tyop)
od
End
(*
let mk_vartype v = Tyvar(v)
*)
Definition mk_vartype_def:
mk_vartype v = Tyvar v
End
(*
let dest_type =
function
(Tyapp (s,ty)) -> s,ty
| (Tyvar _) -> failwith "dest_type: type variable not a constructor"
*)
Definition dest_type_def:
dest_type t =
dtcase t of
Tyapp s ty => do return (s,ty) od
| Tyvar _ => do failwith (strlit"dest_type: type variable not a constructor") od
End
(*
let dest_vartype =
function
(Tyapp(_,_)) -> failwith "dest_vartype: type constructor not a variable"
| (Tyvar s) -> s
*)
Definition dest_vartype_def:
dest_vartype t =
dtcase t of
Tyapp _ _ => do failwith (strlit "dest_vartype: type constructor not a variable") od
| Tyvar s => do return s od
End
(*
let is_type = can dest_type
*)
Definition is_type_def:
is_type t = dtcase t of Tyapp s ty => T | _ => F
End
(*
let is_vartype = can dest_vartype
We optimise this by making it perform the pattern match directly.
*)
Definition is_vartype_def:
is_vartype t = dtcase t of Tyvar _ => T | _ => F
End
(*
let rec tyvars =
function
(Tyapp(_,args)) -> itlist (union o tyvars) args []
| (Tyvar v as tv) -> [tv]
*)
Definition tyvars_def:
tyvars x =
dtcase x of (Tyapp _ args) => itlist union (MAP tyvars args) []
| (Tyvar tv) => [tv]
Termination
WF_REL_TAC `measure (type_size)` THEN Induct_on `args`
THEN FULL_SIMP_TAC (srw_ss()) [type_size_def]
THEN REPEAT STRIP_TAC THEN FULL_SIMP_TAC std_ss [] THEN RES_TAC
THEN REPEAT (POP_ASSUM (MP_TAC o SPEC_ALL)) THEN REPEAT STRIP_TAC
THEN DECIDE_TAC
End
(*
let rec type_subst i ty =
match ty with
Tyapp(tycon,args) ->
let args' = qmap (type_subst i) args in
if args' == args then ty else Tyapp(tycon,args')
| _ -> rev_assocd ty i ty
*)
Definition rev_assocd_def:
rev_assocd a l d =
dtcase l of
[] => d
| ((x,y)::l) => if y = a then x else rev_assocd a l d
End
Definition type_subst_def:
type_subst i ty =
dtcase ty of
Tyapp tycon args =>
let args' = MAP (type_subst i) args in
if args' = args then ty else Tyapp tycon args'
| _ => rev_assocd ty i ty
Termination
WF_REL_TAC `measure (type_size o SND)` THEN Induct_on `args`
THEN FULL_SIMP_TAC (srw_ss()) [type_size_def]
THEN REPEAT STRIP_TAC THEN FULL_SIMP_TAC std_ss [] THEN RES_TAC
THEN REPEAT (POP_ASSUM (MP_TAC o SPEC_ALL)) THEN REPEAT STRIP_TAC
THEN DECIDE_TAC
End
(*
let bool_ty = mk_type("bool",[]);;
let mk_fun_ty ty1 ty2 = mk_type("fun",[ty1; ty2]);;
let aty = mk_vartype "A";;
let bty = mk_vartype "B";;
*)
Definition mk_fun_ty_def:
mk_fun_ty ty1 ty2 = mk_type(strlit"fun",[ty1; ty2])
End
Overload bool_ty[local] = ``mk_type(strlit"bool",[])``
Overload aty[local] = ``mk_vartype (strlit "A")``
Overload bty[local] = ``mk_vartype (strlit "B")``
(*
let constants() = !the_term_constants
*)
Definition constants_def:
constants () = get_the_term_constants
End
(*
let get_const_type s = assoc s (!the_term_constants)
*)
Definition get_const_type_def:
get_const_type s =
do l <- get_the_term_constants ; assoc s l od
End
(*
let rec type_of tm =
match tm with
Var(_,ty) -> ty
| Const(_,ty) -> ty
| Comb(s,_) -> hd(tl(snd(dest_type(type_of s))))
| Abs(Var(_,ty),t) -> mk_fun_ty ty (type_of t)
*)
Definition type_of_def:
type_of tm =
dtcase tm of
Var _ ty => return ty
| Const _ ty => return ty
| Comb s _ => do ty <- type_of s ;
x <- dest_type ty ;
dtcase x of (_,_::ty1::_) => return ty1
| _ => failwith (strlit "match")
od
| Abs (Var _ ty) t => do x <- type_of t; mk_fun_ty ty x od
| _ => failwith (strlit "match")
End
(*
let aconv =
let rec alphavars env tm1 tm2 =
match env with
[] -> tm1 = tm2
| (t1,t2)::oenv ->
(t1 = tm1 & t2 = tm2) or
(t1 <> tm1 & t2 <> tm2 & alphavars oenv tm1 tm2) in
let rec raconv env tm1 tm2 =
(tm1 == tm2 & env = []) or
match (tm1,tm2) with
Var(_,_),Var(_,_) -> alphavars env tm1 tm2
| Const(_,_),Const(_,_) -> tm1 = tm2
| Comb(s1,t1),Comb(s2,t2) -> raconv env s1 s2 & raconv env t1 t2
| Abs(Var(_,ty1) as x1,t1),Abs(Var(_,ty2) as x2,t2) ->
ty1 = ty2 & raconv ((x1,x2)::env) t1 t2
| _ -> false in
fun tm1 tm2 -> raconv [] tm1 tm2
*)
Definition alphavars_def:
alphavars env tm1 tm2 =
dtcase env of
[] => (tm1 = tm2)
| (t1,t2)::oenv =>
((t1 = tm1) /\ (t2 = tm2)) \/
((t1 <> tm1) /\ (t2 <> tm2) /\ alphavars oenv tm1 tm2)
End
Definition raconv_def:
raconv env tm1 tm2 =
dtcase (tm1,tm2) of
(Var _ _, Var _ _) => alphavars env tm1 tm2
| (Const _ _, Const _ _) => (tm1 = tm2)
| (Comb s1 t1, Comb s2 t2) => raconv env s1 s2 /\ raconv env t1 t2
| (Abs v1 t1, Abs v2 t2) =>
(dtcase (v1,v2) of
(Var n1 ty1, Var n2 ty2) => (ty1 = ty2) /\
raconv ((v1,v2)::env) t1 t2
| _ => F)
| _ => F
End
Definition aconv_def:
aconv tm1 tm2 = raconv [] tm1 tm2
End
(*
let is_var = function (Var(_,_)) -> true | _ -> false
let is_const = function (Const(_,_)) -> true | _ -> false
let is_abs = function (Abs(_,_)) -> true | _ -> false
let is_comb = function (Comb(_,_)) -> true | _ -> false
*)
Definition is_var_def:
is_var x = dtcase x of (Var _ _) => T | _ => F
End
Definition is_const_def:
is_const x = dtcase x of (Const _ _) => T | _ => F
End
Definition is_abs_def:
is_abs x = dtcase x of (Abs _ _) => T | _ => F
End
Definition is_comb_def:
is_comb x = dtcase x of (Comb _ _) => T | _ => F
End
(*
let mk_var(v,ty) = Var(v,ty)
*)
Definition mk_var_def:
mk_var(v,ty) = Var v ty
End
(*
let mk_const(name,theta) =
let uty = try get_const_type name with Failure _ ->
failwith "mk_const: not a constant name" in
Const(name,type_subst theta uty)
*)
Definition mk_const_def:
mk_const(name,theta) =
do uty <- try get_const_type name
(strlit "mk_const: not a constant name") ;
return (Const name (type_subst theta uty))
od
End
(*
let mk_abs(bvar,bod) =
match bvar with
Var(_,_) -> Abs(bvar,bod)
| _ -> failwith "mk_abs: not a variable"
*)
Definition mk_abs_def:
mk_abs(bvar,bod) =
dtcase bvar of
Var n ty => return (Abs bvar bod)
| _ => failwith (strlit "mk_abs: not a variable")
End
(*
let mk_comb(f,a) =
match type_of f with
Tyapp("fun",[ty;_]) when ty = type_of a -> Comb(f,a)
| _ -> failwith "mk_comb: types do not agree"
*)
Definition mk_comb_def:
mk_comb(f,a) =
do tyf <- type_of f ;
tya <- type_of a ;
dtcase tyf of
Tyapp (strlit "fun") [ty;_] => if tya = ty then return (Comb f a) else
failwith (strlit "mk_comb: types do not agree")
| _ => failwith (strlit "mk_comb: types do not agree")
od
End
(*
let dest_var =
function (Var(s,ty)) -> s,ty | _ -> failwith "dest_var: not a variable"
let dest_const =
function (Const(s,ty)) -> s,ty | _ -> failwith "dest_const: not a constant"
let dest_comb =
function (Comb(f,x)) -> f,x | _ -> failwith "dest_comb: not a combination"
let dest_abs =
function (Abs(v,b)) -> v,b | _ -> failwith "dest_abs: not an abstraction"
*)
Definition dest_var_def:
dest_var tm = dtcase tm of Var s ty => return (s,ty)
| _ => failwith (strlit "dest_var: not a variable")
End
Definition dest_const_def:
dest_const tm = dtcase tm of Const s ty => return (s,ty)
| _ => failwith (strlit "dest_const: not a constant")
End
Definition dest_comb_def:
dest_comb tm = dtcase tm of Comb f x => return (f,x)
| _ => failwith (strlit "dest_comb: not a combination")
End
Definition dest_abs_def:
dest_abs tm = dtcase tm of Abs v b => return (v,b)
| _ => failwith (strlit "dest_abs: not an abstraction")
End
(*
let rec frees tm =
match tm with
Var(_,_) -> [tm]
| Const(_,_) -> []
| Abs(bv,bod) -> subtract (frees bod) [bv]
| Comb(s,t) -> union (frees s) (frees t)
*)
(*
let freesl tml = itlist (union o frees) tml []
*)
Definition freesl_def:
freesl tml = itlist (union o frees) tml []
End
(*
let rec freesin acc tm =
match tm with
Var(_,_) -> mem tm acc
| Const(_,_) -> true
| Abs(bv,bod) -> freesin (bv::acc) bod
| Comb(s,t) -> freesin acc s & freesin acc t
*)
Definition freesin_def:
freesin acc tm =
dtcase tm of
Var _ _ => MEM tm acc
| Const _ _ => T
| Abs bv bod => freesin (bv::acc) bod
| Comb s t => freesin acc s /\ freesin acc t
End
(*
let rec vfree_in v tm =
match tm with
Abs(bv,bod) -> v <> bv & vfree_in v bod
| Comb(s,t) -> vfree_in v s or vfree_in v t
| _ -> tm = v
*)
(*
let rec type_vars_in_term tm =
match tm with
Var(_,ty) -> tyvars ty
| Const(_,ty) -> tyvars ty
| Comb(s,t) -> union (type_vars_in_term s) (type_vars_in_term t)
| Abs(Var(_,ty),t) -> union (tyvars ty) (type_vars_in_term t)
The Abs case is modified slightly.
*)
Definition type_vars_in_term_def:
type_vars_in_term tm =
dtcase tm of
Var _ ty => tyvars ty
| Const _ ty => tyvars ty
| Comb s t => union (type_vars_in_term s) (type_vars_in_term t)
| Abs v t => union (type_vars_in_term v) (type_vars_in_term t)
End
(*
let rec variant avoid v =
if not(exists (vfree_in v) avoid) then v else
match v with
Var(s,ty) -> variant avoid (Var(s^"'",ty))
| _ -> failwith "variant: not a variable"
This function requires a non-trivial terminiation proof. We make
this a non-failing function to make it pure.
*)
Triviality EXISTS_IMP:
!xs p. EXISTS p xs ==> ?x. MEM x xs /\ p x
Proof
Induct THEN SIMP_TAC (srw_ss()) [EXISTS_DEF] THEN METIS_TAC []
QED
Triviality MEM_subtract:
!y z x. MEM x (subtract y z) = (MEM x y /\ ~MEM x z)
Proof
FULL_SIMP_TAC std_ss [subtract_def,MEM_FILTER] THEN METIS_TAC []
QED
Triviality vfree_in_IMP:
!(t:term) x v. vfree_in (Var v ty) x ==> MEM (Var v ty) (frees x)
Proof
HO_MATCH_MP_TAC (SIMP_RULE std_ss [] (vfree_in_ind))
THEN REPEAT STRIP_TAC THEN Cases_on `x` THEN POP_ASSUM MP_TAC
THEN ONCE_REWRITE_TAC [vfree_in_def,frees_def]
THEN FULL_SIMP_TAC (srw_ss()) []
THEN FULL_SIMP_TAC (srw_ss()) [MEM_union,MEM_subtract]
THEN REPEAT STRIP_TAC THEN RES_TAC THEN ASM_SIMP_TAC std_ss []
QED
(*
let vsubst =
let rec vsubst ilist tm =
match tm with
Var(_,_) -> rev_assocd tm ilist tm
| Const(_,_) -> tm
| Comb(s,t) -> let s' = vsubst ilist s and t' = vsubst ilist t in
if s' == s & t' == t then tm else Comb(s',t')
| Abs(v,s) -> let ilist' = filter (fun (t,x) -> x <> v) ilist in
if ilist' = [] then tm else
let s' = vsubst ilist' s in
if s' == s then tm else
if exists (fun (t,x) -> vfree_in v t & vfree_in x s) ilist'
then let v' = variant [s'] v in
Abs(v',vsubst ((v',v)::ilist') s)
else Abs(v,s') in
fun theta ->
if theta = [] then (fun tm -> tm) else
if forall (fun (t,x) -> type_of t = snd(dest_var x)) theta
then vsubst theta else failwith "vsubst: Bad substitution list"
*)
Definition vsubst_aux_def:
vsubst_aux ilist tm =
dtcase tm of
Var _ _ => rev_assocd tm ilist tm
| Const _ _ => tm
| Comb s t => let s' = vsubst_aux ilist s in
let t' = vsubst_aux ilist t in
Comb s' t'
| Abs v s => if ~is_var v then tm else
let ilist' = FILTER (\(t,x). x <> v) ilist in
if ilist' = [] then tm else
let s' = vsubst_aux ilist' s in
(* if s' = s then tm else --- commented out becuase it doesn't
seem to fit Harrison's formalisation *)
if EXISTS (\(t,x). vfree_in v t /\ vfree_in x s) ilist'
then let v' = variant [s'] v in
Abs v' (vsubst_aux ((v',v)::ilist') s)
else Abs v s'
End
Definition vsubst_def:
vsubst theta tm =
if theta = [] then return tm else
do ok <- forall (\(t,x). do ty <- type_of t ;
vty <- dest_var x ;
return (ty = SND vty) od) theta ;
if ok
then return (vsubst_aux theta tm)
else failwith (strlit "vsubst: Bad substitution list") od
End
(*
let inst =
let rec inst env tyin tm =
match tm with
Var(n,ty) -> let ty' = type_subst tyin ty in
let tm' = if ty' == ty then tm else Var(n,ty') in
if rev_assocd tm' env tm = tm then tm'
else raise (Clash tm')
| Const(c,ty) -> let ty' = type_subst tyin ty in
if ty' == ty then tm else Const(c,ty')
| Comb(f,x) -> let f' = inst env tyin f and x' = inst env tyin x in
if f' == f & x' == x then tm else Comb(f',x')
| Abs(y,t) -> let y' = inst [] tyin y in
let env' = (y,y')::env in
try let t' = inst env' tyin t in
if y' == y & t' == t then tm else Abs(y',t')
with (Clash(w') as ex) ->
if w' <> y' then raise ex else
let ifrees = map (inst [] tyin) (frees t) in
let y'' = variant ifrees y' in
let z = Var(fst(dest_var y''),snd(dest_var y)) in
inst env tyin (Abs(z,vsubst[z,y] t)) in
fun tyin -> if tyin = [] then fun tm -> tm else inst [] tyin
*)
Definition my_term_size_def:
(my_term_size (Var _ _) = 1:num) /\
(my_term_size (Const _ _) = 1) /\
(my_term_size (Comb s1 s2) = 1 + my_term_size s1 + my_term_size s2) /\
(my_term_size (Abs s1 s2) = 1 + my_term_size s1 + my_term_size s2)
End
Triviality my_term_size_variant:
!avoid t. my_term_size (variant avoid t) = my_term_size t
Proof
HO_MATCH_MP_TAC (variant_ind) THEN REPEAT STRIP_TAC
THEN ONCE_REWRITE_TAC [variant_def]
THEN Cases_on `t` THEN FULL_SIMP_TAC (srw_ss()) []
THEN SRW_TAC [] [] THEN RES_TAC
THEN FULL_SIMP_TAC std_ss [my_term_size_def]
QED
Triviality is_var_variant:
!avoid t. is_var (variant avoid t) = is_var t
Proof
HO_MATCH_MP_TAC (variant_ind) THEN REPEAT STRIP_TAC
THEN ONCE_REWRITE_TAC [variant_def]
THEN Cases_on `t` THEN FULL_SIMP_TAC (srw_ss()) []
THEN SRW_TAC [] [] THEN RES_TAC
THEN FULL_SIMP_TAC (srw_ss()) [my_term_size_def,fetch "-" "is_var_def"]
QED
val my_term_size_vsubst_aux = Q.prove(
`!t xs. EVERY (\x. is_var (FST x)) xs ==>
(my_term_size (vsubst_aux xs t) = my_term_size t)`,
Induct THEN1
(FULL_SIMP_TAC (srw_ss()) [my_term_size_def,Once (fetch "-" "vsubst_aux_def")]
THEN Induct_on `xs` THEN1 (EVAL_TAC THEN SRW_TAC [] [my_term_size_def])
THEN Cases
THEN ASM_SIMP_TAC (srw_ss()) [EVERY_DEF,Once (fetch "-" "rev_assocd_def")]
THEN FULL_SIMP_TAC (srw_ss()) []
THEN Cases THEN SRW_TAC [] [] THEN Cases_on `q`
THEN FULL_SIMP_TAC (srw_ss()) [fetch "-" "is_var_def",my_term_size_def])
THEN ASM_SIMP_TAC (srw_ss()) [my_term_size_def,
Once (fetch "-" "vsubst_aux_def"),LET_DEF]
THEN reverse (SRW_TAC [] [my_term_size_def])
THEN1 (Q.PAT_X_ASSUM `!bbbb. xx ==> bbb` MATCH_MP_TAC
THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM,FILTER,MEM_FILTER])
THEN Cases_on `is_var t` THEN FULL_SIMP_TAC std_ss [my_term_size_variant]
THEN Q.PAT_X_ASSUM `!bbbb. xx ==> bbb` MATCH_MP_TAC
THEN FULL_SIMP_TAC (srw_ss()) [EVERY_MEM,FILTER,MEM_FILTER,is_var_variant])
|> Q.SPECL [`t`,`[(Var v ty,x)]`]
|> SIMP_RULE (srw_ss()) [EVERY_DEF,fetch "-" "is_var_def"]
Triviality ZERO_LT_term_size:
!t. 0 < my_term_size t
Proof
Cases THEN EVAL_TAC THEN DECIDE_TAC
QED
Definition inst_aux_def:
(inst_aux (env:(term # term) list) tyin tm) =
dtcase tm of
Var n ty => let ty' = type_subst tyin ty in
let tm' = if ty' = ty then tm else Var n ty' in
if rev_assocd tm' env tm = tm then return tm'
else raise_clash tm'
| Const c ty => let ty' = type_subst tyin ty in
if ty' = ty then return tm else return (Const c ty')
| Comb f x => do f' <- inst_aux env tyin f ;
x' <- inst_aux env tyin x ;
if (f = f') /\ (x = x') then return tm
else return (Comb f' x') od
| Abs y t => do (y':term) <- inst_aux [] tyin y ;
env' <- return ((y,y')::env) ;
handle_clash
(do t' <- inst_aux env' tyin t ;
if (y = y') /\ (t = t')
then return tm
else return (Abs y' t') od)
(\w'.
if w' <> y' then raise_clash w' else
do temp <- inst_aux [] tyin t ;
y' <- return (variant (frees temp) y') ;
(v1,ty') <- dest_var y' ;
(v2,ty) <- dest_var y ;
t' <- inst_aux ((Var v1 ty,Var v1 ty')::env) tyin
(vsubst_aux [(Var v1 ty,y)] t) ;
return (Abs y' t') od)
od
Termination
WF_REL_TAC `measure (\(env,tyin,tm). my_term_size tm)`
THEN SIMP_TAC (srw_ss()) [my_term_size_def]
THEN REPEAT STRIP_TAC
THEN FULL_SIMP_TAC std_ss [my_term_size_vsubst_aux]
THEN DECIDE_TAC
End
Definition inst_def:
inst tyin tm = if tyin = [] then return tm else inst_aux [] tyin tm
End
(*
let rator tm =
match tm with
Comb(l,r) -> l
| _ -> failwith "rator: Not a combination";;
let rand tm =
match tm with
Comb(l,r) -> r
| _ -> failwith "rand: Not a combination";;
*)
Definition rator_def:
rator tm =
dtcase tm of
Comb l r => return l
| _ => failwith (strlit "rator: Not a combination")
End
Definition rand_def:
rand tm =
dtcase tm of
Comb l r => return r
| _ => failwith (strlit "rand: Not a combination")
End
(*
let mk_eq =
let eq = mk_const("=",[]) in
fun (l,r) ->
try let ty = type_of l in
let eq_tm = inst [ty,aty] eq in
mk_comb(mk_comb(eq_tm,l),r)
with Failure _ -> failwith "mk_eq";;
*)
Definition mk_eq_def:
mk_eq (l,r) =
try (\(l,r).
do ty <- type_of l ;
eq <- mk_const(strlit"=",[]) ;
eq_tm <- inst [(ty,aty)] eq ;
t <- mk_comb(eq_tm,l) ;
t <- mk_comb(t,r) ;
return t
od) (l,r) (strlit "mk_eq")
End
(*
let dest_eq tm =
match tm with
Comb(Comb(Const("=",_),l),r) -> l,r
| _ -> failwith "dest_eq";;
let is_eq tm =
match tm with
Comb(Comb(Const("=",_),_),_) -> true
| _ -> false;;
*)
Definition dest_eq_def:
dest_eq tm =
dtcase tm of
Comb (Comb (Const (strlit "=") _) l) r => return (l,r)
| _ => failwith (strlit "dest_eq")
End
Definition is_eq_def:
is_eq tm =
dtcase tm of
Comb (Comb (Const (strlit "=") _) l) r => T
| _ => F
End
(*
let dest_thm (Sequent(asl,c)) = (asl,c)
let hyp (Sequent(asl,c)) = asl
let concl (Sequent(asl,c)) = c
*)
Definition dest_thm_def:
dest_thm (Sequent asl c) = (asl,c)
End
Definition hyp_def:
hyp (Sequent asl c) = asl
End
Definition concl_def:
concl (Sequent asl c) = c
End
(*
let REFL tm =
Sequent([],mk_eq(tm,tm))
*)
Definition REFL_def:
REFL tm = do eq <- mk_eq(tm,tm); return (Sequent [] eq) od
End
(*
let TRANS (Sequent(asl1,c1)) (Sequent(asl2,c2)) =
match (c1,c2) with
Comb(Comb(Const("=",_),l),m1),Comb(Comb(Const("=",_),m2),r)
when aconv m1 m2 -> Sequent(term_union asl1 asl2,mk_eq(l,r))
| _ -> failwith "TRANS"
*)
val _ = PmatchHeuristics.with_classic_heuristic Define `
TRANS (Sequent asl1 c1) (Sequent asl2 c2) =
dtcase (c1,c2) of
(Comb (Comb (Const (strlit "=") _) l) m1, Comb (Comb (Const (strlit "=") _) m2) r) =>
if aconv m1 m2 then do eq <- mk_eq(l,r);
return (Sequent (term_union asl1 asl2) eq) od
else failwith (strlit "TRANS")
| _ => failwith (strlit "TRANS")`
(* some in-kernel but derivable rules (TRANS is also in this category) *)
Definition SYM_def:
SYM (Sequent asl eq) =
dtcase eq of
Comb (Comb (Const (strlit "=") t) l) r =>
return (Sequent asl (Comb (Comb (Const (strlit "=") t) r) l))
| _ => failwith (strlit "SYM")
End
Definition PROVE_HYP_def:
PROVE_HYP (Sequent asl1 c1) (Sequent asl2 c2) =
return (Sequent (term_union asl2 (term_remove c2 asl1)) c1)
End
Definition list_to_hypset_def:
(list_to_hypset [] a = a) ∧
(list_to_hypset (h::hs) a =
list_to_hypset hs (term_union [h] a))
End
Definition ALPHA_THM_def:
ALPHA_THM (Sequent h c) (h',c') =
if aconv c c' then
let h' = list_to_hypset h' [] in
if EVERY (λx. EXISTS (aconv x) h') h then
do
bty <- bool_ty;
tys <- map type_of h';
if EVERY (λty. ty = bty) tys then
return (Sequent h' c')
else failwith (strlit "ALPHA_THM")
od
else failwith (strlit "ALPHA_THM")
else failwith (strlit "ALPHA_THM")
End
(* -- *)
(*
let MK_COMB (Sequent(asl1,c1),Sequent(asl2,c2)) =
match (c1,c2) with
Comb(Comb(Const("=",_),l1),r1),Comb(Comb(Const("=",_),l2),r2)
-> Sequent(term_union asl1 asl2,mk_eq(mk_comb(l1,l2),mk_comb(r1,r2)))
| _ -> failwith "MK_COMB"
*)
val _ = PmatchHeuristics.with_classic_heuristic Define `
MK_COMB (Sequent asl1 c1,Sequent asl2 c2) =
dtcase (c1,c2) of
(Comb (Comb (Const (strlit "=") _) l1) r1, Comb (Comb (Const (strlit "=") _) l2) r2) =>
do x1 <- mk_comb(l1,l2) ;
x2 <- mk_comb(r1,r2) ;
eq <- mk_eq(x1,x2) ;
return (Sequent(term_union asl1 asl2) eq) od
| _ => failwith (strlit "MK_COMB")`
(*
let ABS v (Sequent(asl,c)) =
match c with
Comb(Comb(Const("=",_),l),r) ->
if exists (vfree_in v) asl
then failwith "ABS: variable is free in assumptions"
else Sequent(asl,mk_eq(mk_abs(v,l),mk_abs(v,r)))
| _ -> failwith "ABS: not an equation"
*)
Definition ABS_def:
ABS v (Sequent asl c) =
dtcase c of
Comb (Comb (Const (strlit "=") _) l) r =>
if EXISTS (vfree_in v) asl
then failwith (strlit "ABS: variable is free in assumptions")
else do a1 <- mk_abs(v,l) ;
a2 <- mk_abs(v,r) ;
eq <- mk_eq(a1,a2) ;
return (Sequent asl eq) od
| _ => failwith (strlit "ABS: not an equation")
End
(*
let BETA tm =
match tm with
Comb(Abs(v,bod),arg) when arg = v -> Sequent([],mk_eq(tm,bod))
| _ -> failwith "BETA: not a trivial beta-redex"
*)
Definition BETA_def:
BETA tm =
dtcase tm of
Comb (Abs v bod) arg =>
if arg = v then do eq <- mk_eq(tm,bod) ; return (Sequent [] eq) od
else failwith (strlit "BETA: not a trivial beta-redex")
| _ => failwith (strlit "BETA: not a trivial beta-redex")
End
(*
let ASSUME tm =
if type_of tm = bool_ty then Sequent([tm],tm)
else failwith "ASSUME: not a proposition"
*)
Definition ASSUME_def:
ASSUME tm =
do ty <- type_of tm ;
bty <- bool_ty ;