304 end; |
304 end; |
305 |
305 |
306 local fun paired1{lhs,rhs} = (lhs,rhs) |
306 local fun paired1{lhs,rhs} = (lhs,rhs) |
307 and paired2{Rator,Rand} = (Rator,Rand) |
307 and paired2{Rator,Rand} = (Rator,Rand) |
308 fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
308 fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
|
309 fun single [f] = f |
|
310 | single fs = mk_functional_err (Int.toString (length fs) ^ |
|
311 " distinct function names!") |
309 in |
312 in |
310 fun mk_functional thy eqs = |
313 fun mk_functional thy eqs = |
311 let val clauses = S.strip_conj eqs |
314 let val clauses = S.strip_conj eqs |
312 val (L,R) = U.unzip (map (paired1 o S.dest_eq o U.snd o S.strip_forall) |
315 val (L,R) = U.unzip (map (paired1 o S.dest_eq o U.snd o S.strip_forall) |
313 clauses) |
316 clauses) |
314 val (funcs,pats) = U.unzip(map (paired2 o S.dest_comb) L) |
317 val (funcs,pats) = U.unzip(map (paired2 o S.dest_comb) L) |
315 val [f] = U.mk_set (S.aconv) funcs |
318 val f = single (U.mk_set (S.aconv) funcs) |
316 handle _ => mk_functional_err "function name not unique" |
319 val fvar = if (S.is_var f) then f else S.mk_var(S.dest_const f) |
317 val _ = map (no_repeat_vars thy) pats |
320 val _ = map (no_repeat_vars thy) pats |
318 val rows = U.zip (map (fn x => ([],[x])) pats) (map GIVEN (enumerate R)) |
321 val rows = U.zip (map (fn x => ([],[x])) pats) (map GIVEN (enumerate R)) |
319 val fvs = S.free_varsl R |
322 val fvs = S.free_varsl R |
320 val a = S.variant fvs (S.mk_var{Name="a", Ty = S.type_of(hd pats)}) |
323 val a = S.variant fvs (S.mk_var{Name="a", Ty = S.type_of(hd pats)}) |
321 val FV = a::fvs |
324 val FV = a::fvs |
332 fun int_eq i1 (i2:int) = (i1=i2) |
335 fun int_eq i1 (i2:int) = (i1=i2) |
333 val _ = case (U.set_diff int_eq originals finals) |
336 val _ = case (U.set_diff int_eq originals finals) |
334 of [] => () |
337 of [] => () |
335 | L => mk_functional_err("The following rows (counting from zero)\ |
338 | L => mk_functional_err("The following rows (counting from zero)\ |
336 \ are inaccessible: "^stringize L) |
339 \ are inaccessible: "^stringize L) |
337 in {functional = S.list_mk_abs ([f,a], case_tm), |
340 val case_tm' = S.subst [f |-> fvar] case_tm |
|
341 in {functional = S.list_mk_abs ([fvar,a], case_tm'), |
338 pats = patts2} |
342 pats = patts2} |
339 end end; |
343 end end; |
340 |
344 |
341 |
345 |
342 (*---------------------------------------------------------------------------- |
346 (*---------------------------------------------------------------------------- |
344 * PRINCIPLES OF DEFINITION |
348 * PRINCIPLES OF DEFINITION |
345 * |
349 * |
346 *---------------------------------------------------------------------------*) |
350 *---------------------------------------------------------------------------*) |
347 |
351 |
348 |
352 |
349 (*---------------------------------------------------------------------------- |
353 (*--------------------------------------------------------------------------- |
350 * This basic principle of definition takes a functional M and a relation R |
354 * R is already assumed to be type-copacetic with M |
351 * and specializes the following theorem |
355 *---------------------------------------------------------------------------*) |
352 * |
356 local val f_eq_wfrec_R_M = |
353 * |- !M R f. (f = WFREC R M) ==> WF R ==> !x. f x = M (f%R,x) x |
357 #ant(S.dest_imp(#2(S.strip_forall (concl Thms.WFREC_COROLLARY)))) |
354 * |
358 val {lhs=f, rhs} = S.dest_eq f_eq_wfrec_R_M |
355 * to them (getting "th1", say). Then we make the definition "f = WFREC R M" |
359 val fname = #Name(S.dest_var f) |
356 * and instantiate "th1" to the constant "f" (getting th2). Then we use the |
360 val (wfrec,_) = S.strip_comb rhs |
357 * definition to delete the first antecedent to th2. Hence the result in |
361 in |
358 * the "corollary" field is |
362 fun wfrec_definition0 thy R functional = |
359 * |
363 let val {Bvar,...} = S.dest_abs functional |
360 * |- WF R ==> !x. f x = M (f%R,x) x |
364 val {Name, Ty} = S.dest_var Bvar |
361 * |
365 val def_name = U.concat Name "_def" |
362 *---------------------------------------------------------------------------*) |
366 val (_,ty_theta) = Thry.match_term thy f (S.mk_var{Name=fname,Ty=Ty}) |
363 |
367 val wfrec' = S.inst ty_theta wfrec |
364 fun prim_wfrec_definition thy {R, functional} = |
368 val wfrec_R_M' = S.list_mk_comb(wfrec',[R,functional]) |
365 let val tych = Thry.typecheck thy |
369 val def_term = S.mk_eq{lhs=Bvar, rhs=wfrec_R_M'} |
366 val {Bvar,...} = S.dest_abs functional |
370 in |
367 val {Name,...} = S.dest_var Bvar (* Intended name of definition *) |
371 Thry.make_definition thy def_name def_term |
368 val cor1 = R.ISPEC (tych functional) Thms.WFREC_COROLLARY |
372 end |
369 val cor2 = R.ISPEC (tych R) cor1 |
373 end; |
370 val f_eq_WFREC_R_M = (#ant o S.dest_imp o #Body |
374 |
371 o S.dest_forall o concl) cor2 |
|
372 val {lhs,rhs} = S.dest_eq f_eq_WFREC_R_M |
|
373 val {Ty, ...} = S.dest_var lhs |
|
374 val def_term = S.mk_eq{lhs = S.mk_var{Name=Name,Ty=Ty}, rhs=rhs} |
|
375 val (def_thm,thy1) = Thry.make_definition thy |
|
376 (U.concat Name "_def") def_term |
|
377 val (_,[f,_]) = (S.strip_comb o concl) def_thm |
|
378 val cor3 = R.ISPEC (Thry.typecheck thy1 f) cor2 |
|
379 in |
|
380 {theory = thy1, def=def_thm, corollary=R.MP cor3 def_thm} |
|
381 end; |
|
382 |
375 |
383 |
376 |
384 (*--------------------------------------------------------------------------- |
377 (*--------------------------------------------------------------------------- |
385 * This structure keeps track of congruence rules that aren't derived |
378 * This structure keeps track of congruence rules that aren't derived |
386 * from a datatype definition. |
379 * from a datatype definition. |
420 fun not_omitted (GIVEN(tm,_)) = tm |
413 fun not_omitted (GIVEN(tm,_)) = tm |
421 | not_omitted (OMITTED _) = raise TFL_ERR{func="not_omitted",mesg=""} |
414 | not_omitted (OMITTED _) = raise TFL_ERR{func="not_omitted",mesg=""} |
422 val givens = U.mapfilter not_omitted; |
415 val givens = U.mapfilter not_omitted; |
423 |
416 |
424 |
417 |
425 (*-------------------------------------------------------------------------- |
418 fun post_definition (theory, (def, pats)) = |
426 * This is a wrapper for "prim_wfrec_definition": it builds a functional, |
419 let val tych = Thry.typecheck theory |
427 * calls "prim_wfrec_definition", then specializes the result. This gives a |
420 val f = #lhs(S.dest_eq(concl def)) |
428 * list of rewrite rules where the right hand sides are quite ugly, so we |
421 val corollary = R.MATCH_MP Thms.WFREC_COROLLARY def |
429 * simplify to get rid of the case statements. In essence, this function |
|
430 * performs pre- and post-processing for patterns. As well, after |
|
431 * simplification, termination conditions are extracted. |
|
432 *-------------------------------------------------------------------------*) |
|
433 |
|
434 fun gen_wfrec_definition thy {R, eqs} = |
|
435 let val {functional,pats} = mk_functional thy eqs |
|
436 val given_pats = givens pats |
422 val given_pats = givens pats |
437 val {def,corollary,theory} = prim_wfrec_definition thy |
|
438 {R=R, functional=functional} |
|
439 val tych = Thry.typecheck theory |
|
440 val {lhs=f,...} = S.dest_eq(concl def) |
|
441 val WFR = #ant(S.dest_imp(concl corollary)) |
423 val WFR = #ant(S.dest_imp(concl corollary)) |
|
424 val R = #Rand(S.dest_comb WFR) |
442 val corollary' = R.UNDISCH corollary (* put WF R on assums *) |
425 val corollary' = R.UNDISCH corollary (* put WF R on assums *) |
443 val corollaries = map (U.C R.SPEC corollary' o tych) given_pats |
426 val corollaries = map (U.C R.SPEC corollary' o tych) given_pats |
444 val (case_rewrites,context_congs) = extraction_thms thy |
427 val (case_rewrites,context_congs) = extraction_thms theory |
445 val corollaries' = map(R.simplify case_rewrites) corollaries |
428 val corollaries' = map(R.simplify case_rewrites) corollaries |
446 fun xtract th = R.CONTEXT_REWRITE_RULE(f,R) |
429 fun xtract th = R.CONTEXT_REWRITE_RULE(f,R) |
447 {thms = [(R.ISPECL o map tych)[f,R] Thms.CUT_LEMMA], |
430 {thms = [(R.ISPECL o map tych)[f,R] Thms.CUT_LEMMA], |
448 congs = context_congs, |
431 congs = context_congs, |
449 th = th} |
432 th = th} |
519 val def' = R.MP (R.SPEC (tych fconst) |
501 val def' = R.MP (R.SPEC (tych fconst) |
520 (R.SPEC (tych R') (R.GENL[tych R1, tych f] baz))) |
502 (R.SPEC (tych R') (R.GENL[tych R1, tych f] baz))) |
521 def |
503 def |
522 val body_th = R.LIST_CONJ (map (R.ASSUME o tych) full_rqt) |
504 val body_th = R.LIST_CONJ (map (R.ASSUME o tych) full_rqt) |
523 val bar = R.MP (R.BETA_RULE(R.ISPECL[tych R'abs, tych R1] Thms.SELECT_AX)) |
505 val bar = R.MP (R.BETA_RULE(R.ISPECL[tych R'abs, tych R1] Thms.SELECT_AX)) |
524 body_th |
506 body_th |
525 in {theory = theory, R=R1, |
507 in {theory = theory, R=R1, |
526 rules = U.rev_itlist (U.C R.MP) (R.CONJUNCTS bar) def', |
508 rules = U.rev_itlist (U.C R.MP) (R.CONJUNCTS bar) def', |
527 full_pats_TCs = merge (map pat_of pats) (U.zip (givens pats) TCl), |
509 full_pats_TCs = merge (map pat_of pats) (U.zip (givens pats) TCl), |
528 patterns = pats} |
510 patterns = pats} |
529 end; |
511 end; |
903 in |
885 in |
904 {induction = ind2, rules = R.LIST_CONJ rules2, nested_tcs = extras} |
886 {induction = ind2, rules = R.LIST_CONJ rules2, nested_tcs = extras} |
905 end; |
887 end; |
906 |
888 |
907 |
889 |
908 (*--------------------------------------------------------------------------- |
|
909 * Extract termination goals so that they can be put it into a goalstack, or |
|
910 * have a tactic directly applied to them. |
|
911 *--------------------------------------------------------------------------*) |
|
912 local exception IS_NEG |
|
913 fun strip_imp tm = if S.is_neg tm then raise IS_NEG else S.strip_imp tm |
|
914 in |
|
915 fun termination_goals rules = |
|
916 U.itlist (fn th => fn A => |
|
917 let val tcl = (#1 o S.strip_imp o #2 o S.strip_forall o concl) th |
|
918 in tcl@A |
|
919 end handle _ => A) (R.CONJUNCTS rules) (hyp rules) |
|
920 end; |
|
921 |
|
922 end; (* TFL *) |
890 end; (* TFL *) |