1
(*****************************************************************************)
2
(* Relational and clocked semantics of Pure Lisp *)
3
(*****************************************************************************)
8
["stringLib","finite_mapTheory","intLib"];
9
open sumTheory finite_mapTheory pred_setTheory optionTheory;
10
Globals.checking_const_names := false;
11
set_trace "Subgoal number" 1000;
14
(******************************************************************************
15
* Set default parsing to natural numbers rather than integers
16
******************************************************************************)
17
val _ = intLib.deprecate_int();
19
(*****************************************************************************)
20
(* Start new theory "PureLISP" *)
21
(*****************************************************************************)
22
val _ = new_theory "PureLISP";
24
(*****************************************************************************)
25
(* An atom is Nil or a number or a string *)
26
(*****************************************************************************)
29
`atom = Nil | Number of num | String of string`;
31
(*****************************************************************************)
32
(* An S-expression is an atom or a dotted pair (cons-cell) *)
33
(*****************************************************************************)
36
`sexpression = A of atom | Cons of sexpression => sexpression`;
38
(*****************************************************************************)
39
(* Printing utilities *)
40
(*****************************************************************************)
41
val int_of_term = numSyntax.int_of_term;
43
fun strip_quotes s = implode(tl(butlast(explode s)));
46
is_comb tm andalso is_comb(rator tm)
47
andalso is_const(rator(rator tm))
48
andalso (fst(dest_const(rator(rator tm)))) = "Cons";
51
is_comb tm andalso is_const(rator tm)
52
andalso fst(dest_const(rator tm)) = "A";
55
isAtom tm andalso rand tm = ``Nil``;
58
isCons tm andalso isNil(rand tm);
61
isCons tm andalso (isNil(rand tm) orelse isList(rand tm));
67
(Split(Cons e1 e2) = e1 :: Split e2)`;
69
(*****************************************************************************)
70
(* Some utility values and functions *)
71
(*****************************************************************************)
74
`Num n = A(Number n)`;
82
`isTrue s = ~(s = False)`;
86
`True = A(String "T")`;
90
`Car(Cons s1 s2) = s1`;
94
`Cdr(Cons s1 s2) = s2`;
99
(List (s::sl) = Cons s (List sl))`;
103
`(isList (A a) = (a = Nil))
105
(isList (Cons s1 s2) = isList s2)`;
110
``!sl1 sl2. (List sl1 = List sl2) = (sl1 = sl2)``,
112
THEN RW_TAC list_ss [List_def]
115
THEN RW_TAC list_ss [List_def],
117
THEN RW_TAC list_ss [List_def]
120
THEN RW_TAC list_ss [List_def],
121
METIS_TAC[List_def]]]);
126
``!sl. Split(List sl) = sl``,
128
THEN RW_TAC std_ss [Split_def,List_def]);
133
``!s. isList s ==> (List(Split s) = s)``,
135
THEN RW_TAC std_ss [Split_def,List_def,isList_def]);
139
`Eq ((A a1),(A a2)) = if a1 = a2 then True else False`;
149
`Add ((A(Number m)),(A(Number n))) = A(Number(m+n))`;
153
`Add1 (A(Number m)) = A(Number(m+1))`;
157
`Sub ((A(Number m)),(A(Number n))) = A(Number(m-n))`;
161
`Sub1 (A(Number m)) = A(Number(m-1))`;
165
`Mult ((A(Number m)),(A(Number n))) = A(Number(m*n))`;
170
if s = "car" then Car(EL 0 sl) else
171
if s = "cdr" then Cdr(EL 0 sl) else
172
if s = "atom" then Atom(EL 0 sl) else
173
if s = "eq" then Eq(EL 0 sl,EL 1 sl) else
174
if s = "cons" then Cons(EL 0 sl) (EL 1 sl) else
175
if s = "add" then Add(EL 0 sl,EL 1 sl) else
176
if s = "add1" then Add1(EL 0 sl) else
177
if s = "sub" then Sub(EL 0 sl,EL 1 sl) else
178
if s = "sub1" then Sub1(EL 0 sl) else
179
if s = "mult" then Mult(EL 0 sl,EL 1 sl) else
182
(*****************************************************************************)
183
(* Syntax of Pure Lisp *)
184
(*****************************************************************************)
187
`term = Con of sexpression
189
| App of func => term list
190
| Ite of (term # term)list;
192
func = FunCon of string
194
| Lambda of string list => term
195
| Label of string => func`;
197
(*****************************************************************************)
198
(* An environment (alist) is a finite function from names (strings) to *)
199
(* values of type ``:sexpression + func`` (so variables and *)
200
(* Label-defined functions share the same namespace). *)
201
(*****************************************************************************)
203
(*****************************************************************************)
204
(* VarBind a xl sl extends a by binding each string in xl to the *)
205
(* S-expression at the corresponding position in sl. If xl is shorter than *)
206
(* sl, then only the first n elements of sl are used, where n is the *)
207
(* length of x. If xl is longer than sl, than sl is padded with NILs. *)
209
(* Subtle point: with the semantics in which clock timeout returns NONE *)
210
(* having VarBind only partially specified is no problem, but *)
211
(* with the semantics in which timeout returns an S-expression it is *)
212
(* tricky to distinguish the arbitrary value returned when VarBind is *)
213
(* applied to lists of different lists from a real value. *)
214
(* We thus totalise VarBind as described above. *)
215
(*****************************************************************************)
218
`(VarBind a [] sl = (a : (string |-> sexpression + func)))
220
(VarBind a (x::xl) [] = (VarBind a xl []) |+ (x, INL(A Nil)))
222
(VarBind a (x::xl) (s::sl) = (VarBind a xl sl) |+ (x, INL s))`;
224
(*****************************************************************************)
225
(* FunBind a f fn extends a by binding fn to f *)
226
(*****************************************************************************)
229
`FunBind (a:string|->sexpression+func) f fn = a |+ (f, INR fn)`;
231
(*****************************************************************************)
232
(* Operational semantics of Pure Lisp using three inductive relations: *)
234
(* R_ap (fn,args,a) s - fn applied to args evaluates to s with alist a *)
235
(* R_ev (e,a) s - term e evaluates to S-expression s with alist a *)
236
(* R_evl (el,a) sl - term list el evaluates to S-expression list sl *)
238
(* The names R_evl_rules, R_evl_ind, R_evl_cases are the ones *)
239
(* automatically generated to name the theorems in the theory. *)
241
(*****************************************************************************)
242
val (R_ap_rules,R_ap_ind,R_ap_cases) =
245
R_ap (FunCon fc,args,a) (FunConSem fc args))
248
R_ap (OUTR(a ' fv),args,a) s ==> R_ap (FunVar fv,args,a) s)
251
R_ev (e,VarBind a xl args) s
252
==> R_ap (Lambda xl e,args,a) s)
255
R_ap (fn,args,FunBind a x fn) s ==> R_ap(Label x fn,args,a) s)
261
R_ev (Var x, a) (OUTL(a ' x)))
264
R_ev (Ite [], a) False)
267
R_ev (e1,a) False /\ R_ev (Ite el,a) s
268
==> R_ev (Ite ((e1,e2)::el),a) s)
271
R_ev (e1,a) s1 /\ isTrue s1 /\ R_ev (e2,a) s
273
R_ev (Ite ((e1,e2)::el),a) s)
276
R_evl (el,a) args /\ R_ap (fn,args,a) s
277
==> R_ev (App fn el,a) s)
283
R_ev (e,a) s /\ R_evl (el,a) sl
284
==> R_evl (e::el,a) (s::sl))`;
288
`EvalquoteR (fn,args) s = R_ap (fn,args,FEMPTY) s`;
291
computeLib.add_funs[FAPPLY_FUPDATE_THM];
292
computeLib.add_funs[FUPDATE_LIST_THM];
293
computeLib.add_funs[OUTL];
294
computeLib.add_funs[OUTR];
302
[(App (FunCon "eq") [Var "n"; Con (Num 0)],
306
[Var "n"; App (FunVar "fact") [App (FunCon "sub1") [Var "n"]]])]))`;
308
evalquote ``Fact`` ``[Num 6]``;
310
evalquote ``FunCon "car"`` ``[Cons x y]``;
311
evalquote ``FunCon "cdr"`` ``[Cons x y]``;
314
(*****************************************************************************)
315
(* Encode options in S-expressions *)
316
(*****************************************************************************)
320
`none = A(String "NONE")`;
324
`some s = Cons s (A Nil)`;
328
`(issome (Cons s0 s1) = (s1 = A Nil))
335
``(some s1 = some s2) = (s1 = s2)``,
336
RW_TAC std_ss [DB.theorem "sexpression_11",some_def]);
341
``(List(s1::sl1) = Cons s2 (List sl2)) = (s1 = s2) /\ (sl1 = sl2)``,
342
RW_TAC std_ss [DB.theorem "sexpression_11",some_def,List_def,ListListEq]);
347
``~(issome none) /\ ~(issome(A a)) /\ (issome s ==> ~(s = none))``,
350
THEN RW_TAC std_ss [issome_def]);
361
``!x. issome x = ?s. x = some s``,
363
THEN RW_TAC std_ss [issome_def,some_def]);
368
``~(some s = none) /\ ~(none = some s)``,
374
``((A a = none) = (a = String "NONE"))
376
((none = A a) = (a = String "NONE"))``,
393
`(apply_c n (fn,args,a) =
397
FunCon fc -> some(FunConSem fc args)
398
|| FunVar fv -> apply_c (n-1) (OUTR(a ' fv),args,a)
399
|| Lambda xl e -> eval_c (n-1) (e,VarBind a xl args)
400
|| Label x fn -> apply_c (n-1) (fn,args,FunBind a x fn))
407
|| Var v -> some(OUTL(a ' v))
408
|| Ite [] -> some False
409
|| Ite ((e1,e2)::eel) -> (let s = eval_c (n-1) (e1,a) in
412
else if the s = False
413
then eval_c (n-1) (Ite eel,a)
414
else eval_c (n-1) (e2,a))
415
|| App fn el -> let sl = evlis_c (n-1) (el,a) in
418
else apply_c (n-1) (fn,Split(the sl),a))
425
else let s = eval_c (n-1) (HD el,a) in
428
else let sl = evlis_c (n-1) (TL el, a) in
429
if sl = none then none else some(Cons (the s) (the sl)))`
433
then FST(OUTL x) else
434
if ISR x /\ ISL(OUTR x)
435
then FST(OUTL(OUTR x))
436
else FST(OUTR(OUTR x))`
437
THEN RW_TAC arith_ss []);
439
val EvalquoteEnc_def =
441
`EvalquoteEnc n (fn,args) = apply_c n (fn,args,FEMPTY)`;
443
(* Factorial function
445
computeLib.add_funs[FAPPLY_FUPDATE_THM];
446
computeLib.add_funs[FUPDATE_LIST_THM];
447
computeLib.add_funs[OUTL];
448
computeLib.add_funs[OUTR];
455
[(App (FunCon "eq") [Var "n"; Con (Num 0)],
459
[Var "n"; App (FunVar "fact") [App (FunCon "sub1") [Var "n"]]])]))`` ;
461
EVAL ``eval_c 63 (App ^fact_tm [Con(Num 1)],a)``;
463
EVAL ``eval_c 63 (App ^fact_tm [Con(Num 7)],a)``;
464
EVAL ``eval_c 64 (App ^fact_tm [Con(Num 7)],a)``;
466
EVAL ``EvalquoteEnc 62 (^fact_tm, [Num 7])``;
467
EVAL ``EvalquoteEnc 63 (^fact_tm, [Num 7])``;
469
EVAL ``EvalquoteEnc 10000 (APP Car [Cons x y])``;
475
``(!fn args a. issome(apply_c n (fn,args,a)) \/ (apply_c n (fn,args,a) = none))
477
(!e a. issome(eval_c n (e,a)) \/ (eval_c n (e,a) = none))
479
(!el a. issome(evlis_c n (el,a)) \/ (evlis_c n (el,a) = none))``,
482
[SIMP_RULE arith_ss [] (INST[``n:num``|->``SUC n``]apply_c_def),
483
SIMP_RULE arith_ss [] (INST[``n:num``|->``0``]apply_c_def),
484
issomesome,someNotEqnone,LET_DEF]
487
THEN RW_TAC std_ss [issomesome],
489
THEN RW_TAC std_ss [issomesome]
491
THEN RW_TAC std_ss [issomesome]
493
THEN RW_TAC std_ss [issomesome]]);
495
val apply_cCasesCor =
498
``(!fn n args a. issome(apply_c n (fn,args,a)) \/ (apply_c n (fn,args,a) = none))
500
(!e n a. issome(eval_c n (e,a)) \/ (eval_c n (e,a) = none))
502
(!el n a. issome(evlis_c n (el,a)) \/ (evlis_c n (el,a) = none))``,
503
METIS_TAC[apply_cCases]);
508
``(apply_c 0 (fn,args,a) = none)
510
(apply_c (SUC n) (FunCon fc,args,a) = some(FunConSem fc args))
512
(apply_c (SUC n) (FunVar fv,args,a) = apply_c n (OUTR(a ' fv),args,a))
514
(apply_c (SUC n) (Lambda xl e,args,a) = eval_c n (e,VarBind a xl args))
516
(apply_c (SUC n) (Label x fn,args,a) = apply_c n (fn,args,FunBind a x fn))
518
(eval_c 0 (e,a) = none)
520
(eval_c (SUC n) (Con s,a) = some s)
522
(eval_c (SUC n) (Var v,a) = some(OUTL(a ' v)))
524
(eval_c (SUC n) (Ite [],a) = some False)
526
(eval_c (SUC n) (Ite ((e1,e2)::eel),a) =
527
if issome(eval_c n (e1,a))
528
then (if the(eval_c n (e1,a)) = False
529
then eval_c n (Ite eel,a)
530
else eval_c n (e2,a))
533
(eval_c (SUC n) (App fn el,a) =
534
if issome(evlis_c n (el,a))
535
then apply_c n (fn,Split(the(evlis_c n (el,a))),a)
538
(evlis_c 0 (el,a) = none)
540
(evlis_c (SUC n) ([],a) = some(List[]))
542
(evlis_c (SUC n) (e::el,a) =
543
if issome(eval_c n (e,a))
544
then (if issome(evlis_c n (el,a))
545
then some(Cons (the(eval_c n (e,a))) (the(evlis_c n (el,a))))
549
[SIMP_RULE arith_ss [] (INST[``n:num``|->``SUC n``]apply_c_def),
550
SIMP_RULE arith_ss [] (INST[``n:num``|->``0``]apply_c_def)]
551
THEN FULL_SIMP_TAC std_ss [markerTheory.Abbrev_def]
552
THEN TRY(DISJ_CASES_TAC (Q.SPECL [`e1`,`a`] (el 2 (CONJUNCTS apply_cCases))))
553
THEN TRY(DISJ_CASES_TAC (Q.SPECL [`el`,`a`] (el 3 (CONJUNCTS apply_cCases))))
554
THEN TRY(DISJ_CASES_TAC (Q.SPECL [`e`,`a`] (el 2 (CONJUNCTS apply_cCases))))
555
THEN FULL_SIMP_TAC std_ss [issomenone,noneNONE]);
560
``!el n s. (evlis_c n (el,a) = some s) ==> isList s``,
562
THEN RW_TAC list_ss [apply_c,someNotEqnone,somesomeEq,isList_def,List_def]
564
THEN FULL_SIMP_TAC list_ss [apply_c,someNotEqnone,somesomeEq,isList_def,List_def]
565
THEN RW_TAC std_ss [isList_def]
566
THEN DISJ_CASES_TAC (Q.SPECL [`h`,`n'`,`a`] (el 2 (CONJUNCTS apply_cCasesCor)))
567
THEN DISJ_CASES_TAC (Q.SPECL [`el`,`n'`,`a`] (el 3 (CONJUNCTS apply_cCasesCor)))
568
THEN FULL_SIMP_TAC std_ss [issomenone,noneNONE,someNotEqnone,issomeExists,somesomeEq]
569
THEN RW_TAC std_ss [isList_def,thesome]
575
THEN RW_TAC arith_ss []
576
THEN `?m. n = SUC m` by intLib.COOPER_TAC
577
THEN RW_TAC std_ss [apply_c,LET_THM]
581
THEN RW_TAC std_ss []
582
THEN `?p. (n = SUC p) /\ m < p` by intLib.COOPER_TAC
583
THEN RW_TAC std_ss [apply_c,isTrue_def,LET_THM]
586
Q.EXISTS_TAC `SUC(m+m')`
587
THEN RW_TAC std_ss []
588
THEN `?p. (n = SUC p) /\ m < p /\ m' < p` by intLib.COOPER_TAC
589
THEN RW_TAC std_ss [apply_c,isTrue_def,LET_THM,issomesome]
591
[isTrue_def,False_def,DB.theorem "atom_distinct",apply_c,
592
SplitList,DB.theorem "sexpression_11",EVAL ``True = False``,
593
issomesome,thesome,somesomeEq,ListsomeEq]
595
val R_ap_apply_c_lemma =
597
("R_ap_apply_c_lemma",
600
==> (\fnargsa s. ?m. !n. m < n ==> (some s = apply_c n fnargsa)) fnargsa s)
604
==> (\ea s. ?m. !n. m < n ==> (some s = eval_c n ea)) ea s)
608
==> (\ela sl. ?m. !n. m < n ==> (some(List sl) = evlis_c n ela)) ela sl)``,
610
(IndDefRules.derive_mono_strong_induction [] (R_ap_rules,R_ap_ind))
611
THEN RW_TAC std_ss [LET_THM]
612
THEN TRY(TAC0 ORELSE TAC1 ORELSE TAC2))
618
``(!fnargsa s. R_ap fnargsa s ==> ?n. some s = apply_c n fnargsa)
620
(!ea s. R_ev ea s ==> ?n. some s = eval_c n ea)
622
(!ela sl. R_evl ela sl ==> ?n. some(List sl) = evlis_c n ela)``,
624
THEN IMP_RES_TAC R_ap_apply_c_lemma
625
THEN FULL_SIMP_TAC std_ss []
626
THEN `m < SUC m` by DECIDE_TAC
629
val apply_c_R_ap_lemma =
631
("apply_c_R_ap_lemma",
632
``(!fn args s a. (apply_c n (fn,args,a) = some s) ==> R_ap (fn,args,a) s)
634
(!e s a. (eval_c n (e,a) = some s) ==> R_ev (e,a) s)
636
(!el sl a. (evlis_c n (el,a) = some(List sl)) ==> R_evl (el,a) sl)``,
638
THEN RW_TAC std_ss [apply_c,R_ap_rules,someNotEqnone]
641
THEN FULL_SIMP_TAC std_ss [apply_c,R_ap_rules,somesomeEq]
642
THEN RW_TAC std_ss [apply_c,R_ap_rules],
644
THEN FULL_SIMP_TAC std_ss [apply_c,R_ap_rules,somesomeEq]
645
THEN RW_TAC std_ss [apply_c,R_ap_rules]
647
[DISJ_CASES_TAC (Q.SPECL [`l`,`a`] (el 3 (CONJUNCTS apply_cCases)))
648
THEN FULL_SIMP_TAC std_ss [apply_c,R_ap_rules,somesomeEq,issomeExists]
650
THEN METIS_TAC[someNotEqnone,thesome,isListevlis_c,ListSplit,R_ap_rules],
652
THEN RW_TAC std_ss [apply_c,R_ap_rules,somesomeEq]
653
THEN RW_TAC std_ss [apply_c,R_ap_rules,somesomeEq]
655
THEN Cases_on `eval_c n (q,a) = some False`
658
THEN FULL_SIMP_TAC std_ss [apply_c,issomesome,thesome]
659
THEN METIS_TAC[R_ap_rules],
660
FULL_SIMP_TAC std_ss [apply_c,issomesome,thesome]
661
THEN DISJ_CASES_TAC (Q.SPECL [`q`,`a`] (el 2 (CONJUNCTS apply_cCases)))
662
THEN FULL_SIMP_TAC std_ss [apply_c,R_ap_rules,somesomeEq,issomeExists]
663
THEN METIS_TAC[R_ap_rules,isTrue_def,thesome,somesomeEq]]],
665
THEN FULL_SIMP_TAC std_ss [apply_c,R_ap_rules]
666
THEN RW_TAC std_ss [apply_c,R_ap_rules]
667
THEN RW_TAC std_ss [apply_c,R_ap_rules]
669
[DISJ_CASES_TAC (Q.SPECL [`el`,`a`] (el 3 (CONJUNCTS apply_cCases)))
670
THEN FULL_SIMP_TAC std_ss [somesomeEq,issomeExists,ListListEq]
671
THEN RW_TAC std_ss [R_ap_rules],
672
DISJ_CASES_TAC (Q.SPECL [`h`,`a`] (el 2 (CONJUNCTS apply_cCases)))
673
THEN FULL_SIMP_TAC std_ss [somesomeEq,issomeExists,ListListEq,thesome,someNotEqnone]
674
THEN `sl = Split(Cons s' s)` by METIS_TAC[thesome,SplitList]
675
THEN RW_TAC std_ss [Split_def]
676
THEN METIS_TAC[ListSplit,R_ap_rules,isListevlis_c],
677
FULL_SIMP_TAC std_ss [someNotEqnone],
678
FULL_SIMP_TAC std_ss [someNotEqnone]]]);
683
``(!fnargsa s. (apply_c n fnargsa = some s) ==> R_ap fnargsa s)
685
(!ea s. (eval_c n ea = some s) ==> R_ev ea s)
687
(!ela sl. (evlis_c n ela = some(List sl)) ==> R_evl ela sl)``,
690
[Cases_on `fnargsa` THEN Cases_on `r`,
693
THEN METIS_TAC[apply_c_R_ap_lemma]);
695
val apply_c_R_ap_EQ =
698
``(!fnargsa s. R_ap fnargsa s = ?n. some s = apply_c n fnargsa)
700
(!ea s. R_ev ea s = ?n. some s = eval_c n ea)
702
(!ela sl. R_evl ela sl = ?n. some(List sl) = evlis_c n ela)``,
703
METIS_TAC[R_ap_apply_c,apply_c_R_ap]);
705
(*****************************************************************************)
706
(* Tool to compute s such that R_ap (fn,args,a) s *)
707
(*****************************************************************************)
708
fun apply fn_tm args_tm a =
710
(REWRITE_RULE[some_def](hd(CONJUNCTS apply_c_R_ap)))
711
(EVAL ``apply_c 1000000000 (^fn_tm,^args_tm,a)``);
713
(*****************************************************************************)
714
(* Add some library theorems to the evaluator compset to make computation on *)
715
(* finite functions work. *)
716
(*****************************************************************************)
717
computeLib.add_funs[FAPPLY_FUPDATE_THM];
718
computeLib.add_funs[FUPDATE_LIST_THM];
719
computeLib.add_funs[OUTL];
720
computeLib.add_funs[OUTR];
722
(*****************************************************************************)
723
(* Example: factorial function *)
724
(*****************************************************************************)
731
[(App (FunCon "eq") [Var "n"; Con (Num 0)],
736
App (FunVar "fact") [App (FunCon "sub1") [Var "n"]]])]))`;
738
(*****************************************************************************)
739
(* Evaluate 6!, 20!, 50! and 100! in the empty environment *)
740
(*****************************************************************************)
741
apply ``Fact`` ``[Num 6]`` ``FEMPTY``;
742
apply ``Fact`` ``[Num 20]`` ``FEMPTY``;
743
apply ``Fact`` ``[Num 50]`` ``FEMPTY``;
744
apply ``Fact`` ``[Num 100]`` ``FEMPTY``;
746
(*****************************************************************************)
747
(* Check (EQ (CAR(CONS X Y)) X) and (EQ (CDR(CONS X Y)) Y) by computation *)
748
(*****************************************************************************)
749
apply ``FunCon "car"`` ``[Cons x y]`` ``FEMPTY``;
750
apply ``FunCon "cdr"`` ``[Cons x y]`` ``FEMPTY``;