26 |
28 |
27 fun stringize [] = "" |
29 fun stringize [] = "" |
28 | stringize [i] = Int.toString i |
30 | stringize [i] = Int.toString i |
29 | stringize (h::t) = (Int.toString h^", "^stringize t); |
31 | stringize (h::t) = (Int.toString h^", "^stringize t); |
30 |
32 |
31 |
33 fun front_last [] = raise TFL_ERR {func="front_last", mesg="empty list"} |
32 fun TFL_ERR{func,mesg} = U.ERR{module = "Tfl", func = func, mesg = mesg}; |
34 | front_last [x] = ([],x) |
|
35 | front_last (h::t) = |
|
36 let val (pref,x) = front_last t |
|
37 in |
|
38 (h::pref,x) |
|
39 end; |
|
40 |
33 |
41 |
34 |
42 |
35 (*--------------------------------------------------------------------------- |
43 (*--------------------------------------------------------------------------- |
36 handling of user-supplied congruence rules: lcp*) |
44 handling of user-supplied congruence rules: lcp*) |
37 |
45 |
286 quote (string_of_cterm (Thry.typecheck thy pat))} |
293 quote (string_of_cterm (Thry.typecheck thy pat))} |
287 else check rst |
294 else check rst |
288 in check (FV_multiset pat) |
295 in check (FV_multiset pat) |
289 end; |
296 end; |
290 |
297 |
|
298 fun dest_atom (Free p) = p |
|
299 | dest_atom (Const p) = p |
|
300 | dest_atom _ = raise TFL_ERR {func="dest_atom", |
|
301 mesg="function name not an identifier"}; |
|
302 |
|
303 |
291 local fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
304 local fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
292 fun single [Free(a,_)] = |
305 fun single [_$_] = |
293 mk_functional_err (a ^ " has not been declared as a constant") |
|
294 | single [_$_] = |
|
295 mk_functional_err "recdef does not allow currying" |
306 mk_functional_err "recdef does not allow currying" |
296 | single [Const arg] = arg |
307 | single [f] = f |
297 | single [_] = mk_functional_err "recdef: bad function name" |
|
298 | single fs = mk_functional_err (Int.toString (length fs) ^ |
308 | single fs = mk_functional_err (Int.toString (length fs) ^ |
299 " distinct function names!") |
309 " distinct function names!") |
300 in |
310 in |
301 fun mk_functional thy clauses = |
311 fun mk_functional thy clauses = |
302 let val (L,R) = ListPair.unzip (map HOLogic.dest_eq clauses) |
312 let val (L,R) = ListPair.unzip (map HOLogic.dest_eq clauses) |
303 handle _ => raise TFL_ERR |
313 handle _ => raise TFL_ERR |
304 {func = "mk_functional", |
314 {func = "mk_functional", |
305 mesg = "recursion equations must use the = relation"} |
315 mesg = "recursion equations must use the = relation"} |
306 val (funcs,pats) = ListPair.unzip (map (fn (t$u) =>(t,u)) L) |
316 val (funcs,pats) = ListPair.unzip (map (fn (t$u) =>(t,u)) L) |
307 val (fname, ftype) = single (gen_distinct (op aconv) funcs) |
317 val atom = single (gen_distinct (op aconv) funcs) |
|
318 val (fname,ftype) = dest_atom atom |
308 val dummy = map (no_repeat_vars thy) pats |
319 val dummy = map (no_repeat_vars thy) pats |
309 val rows = ListPair.zip (map (fn x => ([],[x])) pats, |
320 val rows = ListPair.zip (map (fn x => ([]:term list,[x])) pats, |
310 map GIVEN (enumerate R)) |
321 map GIVEN (enumerate R)) |
311 val names = foldr add_term_names (R,[]) |
322 val names = foldr add_term_names (R,[]) |
312 val atype = type_of(hd pats) |
323 val atype = type_of(hd pats) |
313 and aname = variant names "a" |
324 and aname = variant names "a" |
314 val a = Free(aname,atype) |
325 val a = Free(aname,atype) |
325 val dummy = case (originals\\finals) |
336 val dummy = case (originals\\finals) |
326 of [] => () |
337 of [] => () |
327 | L => mk_functional_err("The following rows (counting from zero)\ |
338 | L => mk_functional_err("The following rows (counting from zero)\ |
328 \ are inaccessible: "^stringize L) |
339 \ are inaccessible: "^stringize L) |
329 in {functional = Abs(Sign.base_name fname, ftype, |
340 in {functional = Abs(Sign.base_name fname, ftype, |
330 abstract_over (Const(fname,ftype), |
341 abstract_over (atom, |
331 absfree(aname, atype, case_tm))), |
342 absfree(aname,atype, case_tm))), |
332 pats = patts2} |
343 pats = patts2} |
333 end end; |
344 end end; |
334 |
345 |
335 |
346 |
336 (*---------------------------------------------------------------------------- |
347 (*---------------------------------------------------------------------------- |
437 |
448 |
438 |
449 |
439 (*--------------------------------------------------------------------------- |
450 (*--------------------------------------------------------------------------- |
440 * Perform the extraction without making the definition. Definition and |
451 * Perform the extraction without making the definition. Definition and |
441 * extraction commute for the non-nested case. (Deferred recdefs) |
452 * extraction commute for the non-nested case. (Deferred recdefs) |
442 *---------------------------------------------------------------------------*) |
453 * |
|
454 * The purpose of wfrec_eqns is merely to instantiate the recursion theorem |
|
455 * and extract termination conditions: no definition is made. |
|
456 *---------------------------------------------------------------------------*) |
|
457 |
443 fun wfrec_eqns thy fid tflCongs eqns = |
458 fun wfrec_eqns thy fid tflCongs eqns = |
444 let val {functional as Abs(Name, Ty, _), pats} = mk_functional thy eqns |
459 let val {lhs,rhs} = S.dest_eq (hd eqns) |
|
460 val (f,args) = S.strip_comb lhs |
|
461 val (fname,fty) = dest_atom f |
|
462 val (SV,a) = front_last args (* SV = schematic variables *) |
|
463 val g = list_comb(f,SV) |
|
464 val h = Free(fname,type_of g) |
|
465 val eqns1 = map (subst_free[(g,h)]) eqns |
|
466 val {functional as Abs(Name, Ty, _), pats} = mk_functional thy eqns1 |
445 val given_pats = givens pats |
467 val given_pats = givens pats |
446 val f = #1 (S.strip_comb(#lhs(S.dest_eq (hd eqns)))) |
|
447 (* val f = Free(Name,Ty) *) |
468 (* val f = Free(Name,Ty) *) |
448 val Type("fun", [f_dty, f_rty]) = Ty |
469 val Type("fun", [f_dty, f_rty]) = Ty |
449 val dummy = if Name<>fid then |
470 val dummy = if Name<>fid then |
450 raise TFL_ERR{func = "lazyR_def", |
471 raise TFL_ERR{func = "wfrec_eqns", |
451 mesg = "Expected a definition of " ^ |
472 mesg = "Expected a definition of " ^ |
452 quote fid ^ " but found one of " ^ |
473 quote fid ^ " but found one of " ^ |
453 quote Name} |
474 quote Name} |
454 else () |
475 else () |
455 val SV = S.free_vars_lr functional (* schema variables *) |
|
456 val (case_rewrites,context_congs) = extraction_thms thy |
476 val (case_rewrites,context_congs) = extraction_thms thy |
457 val tych = Thry.typecheck thy |
477 val tych = Thry.typecheck thy |
458 val WFREC_THM0 = R.ISPEC (tych functional) Thms.WFREC_COROLLARY |
478 val WFREC_THM0 = R.ISPEC (tych functional) Thms.WFREC_COROLLARY |
459 val Const("All",_) $ Abs(Rname,Rtype,_) = concl WFREC_THM0 |
479 val Const("All",_) $ Abs(Rname,Rtype,_) = concl WFREC_THM0 |
460 val R = Free (variant (foldr add_term_names (eqns,[])) Rname, |
480 val R = Free (variant (foldr add_term_names (eqns,[])) Rname, |
461 Rtype) |
481 Rtype) |
462 val WFREC_THM = R.ISPECL [tych R, tych f] WFREC_THM0 |
482 val WFREC_THM = R.ISPECL [tych R, tych g] WFREC_THM0 |
463 val ([proto_def, WFR],_) = S.strip_imp(concl WFREC_THM) |
483 val ([proto_def, WFR],_) = S.strip_imp(concl WFREC_THM) |
464 val dummy = |
484 val dummy = |
465 if !trace then |
485 if !trace then |
466 writeln ("ORIGINAL PROTO_DEF: " ^ |
486 writeln ("ORIGINAL PROTO_DEF: " ^ |
467 Sign.string_of_term (Theory.sign_of thy) proto_def) |
487 Sign.string_of_term (Theory.sign_of thy) proto_def) |
470 val corollary' = R.UNDISCH(R.UNDISCH WFREC_THM) |
490 val corollary' = R.UNDISCH(R.UNDISCH WFREC_THM) |
471 val corollaries = map (fn pat => R.SPEC (tych pat) corollary') given_pats |
491 val corollaries = map (fn pat => R.SPEC (tych pat) corollary') given_pats |
472 val corollaries' = map (rewrite_rule case_rewrites) corollaries |
492 val corollaries' = map (rewrite_rule case_rewrites) corollaries |
473 fun extract X = R.CONTEXT_REWRITE_RULE |
493 fun extract X = R.CONTEXT_REWRITE_RULE |
474 (f, R1::SV, cut_apply, tflCongs@context_congs) X |
494 (f, R1::SV, cut_apply, tflCongs@context_congs) X |
475 in {proto_def = (*Use == rather than = for definitions*) |
495 in {proto_def = proto_def, |
|
496 (*LCP: want this?? |
|
497 (*Use == rather than = for definitions*) |
476 mk_const_def (Theory.sign_of thy) |
498 mk_const_def (Theory.sign_of thy) |
477 (Name, Ty, S.rhs proto_def), |
499 (Name, Ty, S.rhs proto_def), *) |
478 SV=SV, |
500 SV=SV, |
479 WFR=WFR, |
501 WFR=WFR, |
480 pats=pats, |
502 pats=pats, |
481 extracta = map extract corollaries'} |
503 extracta = map extract corollaries'} |
482 end; |
504 end; |
486 * Define the constant after extracting the termination conditions. The |
508 * Define the constant after extracting the termination conditions. The |
487 * wellfounded relation used in the definition is computed by using the |
509 * wellfounded relation used in the definition is computed by using the |
488 * choice operator on the extracted conditions (plus the condition that |
510 * choice operator on the extracted conditions (plus the condition that |
489 * such a relation must be wellfounded). |
511 * such a relation must be wellfounded). |
490 *---------------------------------------------------------------------------*) |
512 *---------------------------------------------------------------------------*) |
|
513 |
491 fun lazyR_def thy fid tflCongs eqns = |
514 fun lazyR_def thy fid tflCongs eqns = |
492 let val {proto_def,WFR,pats,extracta,SV} = |
515 let val {proto_def,WFR,pats,extracta,SV} = |
493 wfrec_eqns thy fid (congs tflCongs) eqns |
516 wfrec_eqns thy fid (congs tflCongs) eqns |
494 val R1 = S.rand WFR |
517 val R1 = S.rand WFR |
495 val f = #1 (Logic.dest_equals proto_def) |
518 val f = #lhs(S.dest_eq proto_def) |
|
519 (*LCP: want this? val f = #1 (Logic.dest_equals proto_def) *) |
496 val (extractants,TCl) = ListPair.unzip extracta |
520 val (extractants,TCl) = ListPair.unzip extracta |
497 val dummy = if !trace |
521 val dummy = if !trace |
498 then (writeln "Extractants = "; |
522 then (writeln "Extractants = "; |
499 prths extractants; |
523 prths extractants; |
500 ()) |
524 ()) |
506 val proto_def' = subst_free[(R1,R')] proto_def |
530 val proto_def' = subst_free[(R1,R')] proto_def |
507 val dummy = if !trace then writeln ("proto_def' = " ^ |
531 val dummy = if !trace then writeln ("proto_def' = " ^ |
508 Sign.string_of_term |
532 Sign.string_of_term |
509 (Theory.sign_of thy) proto_def') |
533 (Theory.sign_of thy) proto_def') |
510 else () |
534 else () |
|
535 val {lhs,rhs} = S.dest_eq proto_def' |
|
536 val (c,args) = S.strip_comb lhs |
|
537 val (Name,Ty) = dest_atom c |
|
538 val defn = mk_const_def (Theory.sign_of thy) |
|
539 (Name, Ty, S.list_mk_abs (args,rhs)) |
|
540 (*LCP: want this?? |
511 val theory = |
541 val theory = |
512 thy |
542 thy |
513 |> PureThy.add_defs_i |
543 |> PureThy.add_defs_i |
514 [Thm.no_attributes (fid ^ "_def", proto_def')]; |
544 [Thm.no_attributes (fid ^ "_def", proto_def')]; |
515 val def = get_axiom theory (fid ^ "_def") RS meta_eq_to_obj_eq |
545 val def = get_axiom theory (fid ^ "_def") RS meta_eq_to_obj_eq |
|
546 *) |
|
547 val theory = |
|
548 thy |
|
549 |> PureThy.add_defs_i |
|
550 [Thm.no_attributes (fid ^ "_def", defn)] |
|
551 val def = freezeT (get_axiom theory (fid ^ "_def")) |
516 val dummy = if !trace then writeln ("DEF = " ^ string_of_thm def) |
552 val dummy = if !trace then writeln ("DEF = " ^ string_of_thm def) |
517 else () |
553 else () |
518 val fconst = #lhs(S.dest_eq(concl def)) |
554 (* val fconst = #lhs(S.dest_eq(concl def)) *) |
519 val tych = Thry.typecheck theory |
555 val tych = Thry.typecheck theory |
520 val full_rqt_prop = map (Dcterm.mk_prop o tych) full_rqt |
556 val full_rqt_prop = map (Dcterm.mk_prop o tych) full_rqt |
521 (*lcp: a lot of object-logic inference to remove*) |
557 (*lcp: a lot of object-logic inference to remove*) |
522 val baz = R.DISCH_ALL |
558 val baz = R.DISCH_ALL |
523 (U.itlist R.DISCH full_rqt_prop |
559 (U.itlist R.DISCH full_rqt_prop |
524 (R.LIST_CONJ extractants)) |
560 (R.LIST_CONJ extractants)) |
525 val dum = if !trace then writeln ("baz = " ^ string_of_thm baz) |
561 val dum = if !trace then writeln ("baz = " ^ string_of_thm baz) |
526 else () |
562 else () |
527 val f_free = Free (fid, fastype_of f) (*'cos f is a Const*) |
563 val f_free = Free (fid, fastype_of f) (*'cos f is a Const*) |
528 val def' = R.MP (R.SPEC (tych fconst) |
564 val SV' = map tych SV; |
529 (R.SPEC (tych R') |
565 val SVrefls = map reflexive SV' |
530 (R.GENL[tych R1, tych f_free] baz))) |
566 val def0 = (U.rev_itlist (fn x => fn th => R.rbeta(combination th x)) |
531 def |
567 SVrefls def) |
|
568 RS meta_eq_to_obj_eq |
|
569 val def' = R.MP (R.SPEC (tych R') (R.GEN (tych R1) baz)) def0 |
532 val body_th = R.LIST_CONJ (map R.ASSUME full_rqt_prop) |
570 val body_th = R.LIST_CONJ (map R.ASSUME full_rqt_prop) |
533 val bar = R.MP (R.ISPECL[tych R'abs, tych R1] Thms.SELECT_AX) |
571 val bar = R.MP (R.ISPECL[tych R'abs, tych R1] Thms.SELECT_AX) |
534 body_th |
572 body_th |
535 in {theory = theory, R=R1, SV=SV, |
573 in {theory = theory, R=R1, SV=SV, |
536 rules = U.rev_itlist (U.C R.MP) (R.CONJUNCTS bar) def', |
574 rules = U.rev_itlist (U.C R.MP) (R.CONJUNCTS bar) def', |
886 * 1. if |- tc = T, then eliminate it with eqT; otherwise, |
924 * 1. if |- tc = T, then eliminate it with eqT; otherwise, |
887 * 2. apply the terminator to tc'. If |- tc' = T then eliminate; else |
925 * 2. apply the terminator to tc'. If |- tc' = T then eliminate; else |
888 * 3. replace tc by tc' in both the rules and the induction theorem. |
926 * 3. replace tc by tc' in both the rules and the induction theorem. |
889 *---------------------------------------------------------------------*) |
927 *---------------------------------------------------------------------*) |
890 |
928 |
891 fun print_thms s L = |
929 fun print_thms s L = |
892 if !trace then writeln (cat_lines (s :: map string_of_thm L)) |
930 if !trace then writeln (cat_lines (s :: map string_of_thm L)) |
893 else (); |
931 else (); |
894 |
932 |
895 fun print_cterms s L = |
933 fun print_cterms s L = |
896 if !trace then writeln (cat_lines (s :: map string_of_cterm L)) |
934 if !trace then writeln (cat_lines (s :: map string_of_cterm L)) |
897 else ();; |
935 else ();; |
898 |
936 |
899 fun simplify_tc tc (r,ind) = |
937 fun simplify_tc tc (r,ind) = |
900 let val tc1 = tych tc |
938 let val tc1 = tych tc |
901 val _ = print_cterms "TC before simplification: " [tc1] |
939 val _ = print_cterms "TC before simplification: " [tc1] |
902 val tc_eq = simplifier tc1 |
940 val tc_eq = simplifier tc1 |