1 (* Title: TFL/tfl |
1 (* Title: TFL/tfl |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Konrad Slind, Cambridge University Computer Laboratory |
3 Author: Konrad Slind, Cambridge University Computer Laboratory |
4 Copyright 1997 University of Cambridge |
4 Copyright 1997 University of Cambridge |
5 |
5 |
6 Main TFL functor |
6 Main module |
7 *) |
7 *) |
8 |
8 |
9 functor TFL(structure Rules : Rules_sig |
9 structure Prim : TFL_sig = |
10 structure Thry : Thry_sig |
|
11 structure Thms : Thms_sig) : TFL_sig = |
|
12 struct |
10 struct |
13 |
|
14 (* Declarations *) |
|
15 structure Thms = Thms; |
|
16 structure Rules = Rules; |
|
17 structure Thry = Thry; |
|
18 structure USyntax = Thry.USyntax; |
|
19 |
|
20 |
11 |
21 (* Abbreviations *) |
12 (* Abbreviations *) |
22 structure R = Rules; |
13 structure R = Rules; |
23 structure S = USyntax; |
14 structure S = USyntax; |
24 structure U = S.Utils; |
15 structure U = S.Utils; |
25 |
|
26 nonfix mem -->; |
|
27 val --> = S.-->; |
|
28 |
|
29 infixr 3 -->; |
|
30 |
16 |
31 val concl = #2 o R.dest_thm; |
17 val concl = #2 o R.dest_thm; |
32 val hyp = #1 o R.dest_thm; |
18 val hyp = #1 o R.dest_thm; |
33 |
19 |
34 val list_mk_type = U.end_itlist (curry(op -->)); |
20 val list_mk_type = U.end_itlist (curry(op -->)); |
81 let fun pfail s = raise TFL_ERR{func = "partition.part", mesg = s} |
67 let fun pfail s = raise TFL_ERR{func = "partition.part", mesg = s} |
82 fun part {constrs = [], rows = [], A} = rev A |
68 fun part {constrs = [], rows = [], A} = rev A |
83 | part {constrs = [], rows = _::_, A} = pfail"extra cases in defn" |
69 | part {constrs = [], rows = _::_, A} = pfail"extra cases in defn" |
84 | part {constrs = _::_, rows = [], A} = pfail"cases missing in defn" |
70 | part {constrs = _::_, rows = [], A} = pfail"cases missing in defn" |
85 | part {constrs = c::crst, rows, A} = |
71 | part {constrs = c::crst, rows, A} = |
86 let val {Name,Ty} = S.dest_const c |
72 let val (Name,Ty) = dest_Const c |
87 val (L,_) = S.strip_type Ty |
73 val L = binder_types Ty |
88 val (in_group, not_in_group) = |
74 val (in_group, not_in_group) = |
89 U.itlist (fn (row as (p::rst, rhs)) => |
75 U.itlist (fn (row as (p::rst, rhs)) => |
90 fn (in_group,not_in_group) => |
76 fn (in_group,not_in_group) => |
91 let val (pc,args) = S.strip_comb p |
77 let val (pc,args) = S.strip_comb p |
92 in if (#Name(S.dest_const pc) = Name) |
78 in if (#1(dest_Const pc) = Name) |
93 then ((args@rst, rhs)::in_group, not_in_group) |
79 then ((args@rst, rhs)::in_group, not_in_group) |
94 else (in_group, row::not_in_group) |
80 else (in_group, row::not_in_group) |
95 end) rows ([],[]) |
81 end) rows ([],[]) |
96 val col_types = U.take type_of (length L, #1(hd in_group)) |
82 val col_types = U.take type_of (length L, #1(hd in_group)) |
97 in |
83 in |
110 * clause in a function definition. |
96 * clause in a function definition. |
111 *---------------------------------------------------------------------------*) |
97 *---------------------------------------------------------------------------*) |
112 datatype pattern = GIVEN of term * int |
98 datatype pattern = GIVEN of term * int |
113 | OMITTED of term * int |
99 | OMITTED of term * int |
114 |
100 |
115 fun psubst theta (GIVEN (tm,i)) = GIVEN(subst_free theta tm, i) |
101 fun pattern_map f (GIVEN (tm,i)) = GIVEN(f tm, i) |
116 | psubst theta (OMITTED (tm,i)) = OMITTED(subst_free theta tm, i); |
102 | pattern_map f (OMITTED (tm,i)) = OMITTED(f tm, i); |
|
103 |
|
104 fun pattern_subst theta = pattern_map (subst_free theta); |
117 |
105 |
118 fun dest_pattern (GIVEN (tm,i)) = ((GIVEN,i),tm) |
106 fun dest_pattern (GIVEN (tm,i)) = ((GIVEN,i),tm) |
119 | dest_pattern (OMITTED (tm,i)) = ((OMITTED,i),tm); |
107 | dest_pattern (OMITTED (tm,i)) = ((OMITTED,i),tm); |
120 |
108 |
121 val pat_of = #2 o dest_pattern; |
109 val pat_of = #2 o dest_pattern; |
123 |
111 |
124 (*--------------------------------------------------------------------------- |
112 (*--------------------------------------------------------------------------- |
125 * Produce an instance of a constructor, plus genvars for its arguments. |
113 * Produce an instance of a constructor, plus genvars for its arguments. |
126 *---------------------------------------------------------------------------*) |
114 *---------------------------------------------------------------------------*) |
127 fun fresh_constr ty_match colty gv c = |
115 fun fresh_constr ty_match colty gv c = |
128 let val {Ty,...} = S.dest_const c |
116 let val (_,Ty) = dest_Const c |
129 val (L,ty) = S.strip_type Ty |
117 val L = binder_types Ty |
|
118 and ty = body_type Ty |
130 val ty_theta = ty_match ty colty |
119 val ty_theta = ty_match ty colty |
131 val c' = S.inst ty_theta c |
120 val c' = S.inst ty_theta c |
132 val gvars = map (S.inst ty_theta o gv) L |
121 val gvars = map (S.inst ty_theta o gv) L |
133 in (c', gvars) |
122 in (c', gvars) |
134 end; |
123 end; |
140 *---------------------------------------------------------------------------*) |
129 *---------------------------------------------------------------------------*) |
141 fun mk_group Name rows = |
130 fun mk_group Name rows = |
142 U.itlist (fn (row as ((prefix, p::rst), rhs)) => |
131 U.itlist (fn (row as ((prefix, p::rst), rhs)) => |
143 fn (in_group,not_in_group) => |
132 fn (in_group,not_in_group) => |
144 let val (pc,args) = S.strip_comb p |
133 let val (pc,args) = S.strip_comb p |
145 in if ((#Name(S.dest_const pc) = Name) handle _ => false) |
134 in if ((#1(dest_Const pc) = Name) handle _ => false) |
146 then (((prefix,args@rst), rhs)::in_group, not_in_group) |
135 then (((prefix,args@rst), rhs)::in_group, not_in_group) |
147 else (in_group, row::not_in_group) end) |
136 else (in_group, row::not_in_group) end) |
148 rows ([],[]); |
137 rows ([],[]); |
149 |
138 |
150 (*--------------------------------------------------------------------------- |
139 (*--------------------------------------------------------------------------- |
155 (constructors, colty, res_ty, rows as (((prefix,_),_)::_)) = |
144 (constructors, colty, res_ty, rows as (((prefix,_),_)::_)) = |
156 let val fresh = fresh_constr ty_match colty gv |
145 let val fresh = fresh_constr ty_match colty gv |
157 fun part {constrs = [], rows, A} = rev A |
146 fun part {constrs = [], rows, A} = rev A |
158 | part {constrs = c::crst, rows, A} = |
147 | part {constrs = c::crst, rows, A} = |
159 let val (c',gvars) = fresh c |
148 let val (c',gvars) = fresh c |
160 val {Name,Ty} = S.dest_const c' |
149 val (Name,Ty) = dest_Const c' |
161 val (in_group, not_in_group) = mk_group Name rows |
150 val (in_group, not_in_group) = mk_group Name rows |
162 val in_group' = |
151 val in_group' = |
163 if (null in_group) (* Constructor not given *) |
152 if (null in_group) (* Constructor not given *) |
164 then [((prefix, #2(fresh c)), OMITTED (S.ARB res_ty, ~1))] |
153 then [((prefix, #2(fresh c)), OMITTED (S.ARB res_ty, ~1))] |
165 else in_group |
154 else in_group |
176 (*--------------------------------------------------------------------------- |
165 (*--------------------------------------------------------------------------- |
177 * Misc. routines used in mk_case |
166 * Misc. routines used in mk_case |
178 *---------------------------------------------------------------------------*) |
167 *---------------------------------------------------------------------------*) |
179 |
168 |
180 fun mk_pat (c,l) = |
169 fun mk_pat (c,l) = |
181 let val L = length(#1(S.strip_type(type_of c))) |
170 let val L = length (binder_types (type_of c)) |
182 fun build (prefix,tag,plist) = |
171 fun build (prefix,tag,plist) = |
183 let val args = take (L,plist) |
172 let val args = take (L,plist) |
184 and plist' = drop(L,plist) |
173 and plist' = drop(L,plist) |
185 in (prefix,tag,list_comb(c,args)::plist') end |
174 in (prefix,tag,list_comb(c,args)::plist') end |
186 in map build l end; |
175 in map build l end; |
209 | expand constructors ty (row as ((prefix, p::rst), rhs)) = |
198 | expand constructors ty (row as ((prefix, p::rst), rhs)) = |
210 if (is_Free p) |
199 if (is_Free p) |
211 then let val fresh = fresh_constr ty_match ty fresh_var |
200 then let val fresh = fresh_constr ty_match ty fresh_var |
212 fun expnd (c,gvs) = |
201 fun expnd (c,gvs) = |
213 let val capp = list_comb(c,gvs) |
202 let val capp = list_comb(c,gvs) |
214 in ((prefix, capp::rst), psubst[(p,capp)] rhs) |
203 in ((prefix, capp::rst), pattern_subst[(p,capp)] rhs) |
215 end |
204 end |
216 in map expnd (map fresh constructors) end |
205 in map expnd (map fresh constructors) end |
217 else [row] |
206 else [row] |
218 fun mk{rows=[],...} = mk_case_fail"no rows" |
207 fun mk{rows=[],...} = mk_case_fail"no rows" |
219 | mk{path=[], rows = ((prefix, []), rhs)::_} = (* Done *) |
208 | mk{path=[], rows = ((prefix, []), rhs)::_} = (* Done *) |
227 | mk{path = u::rstp, rows as ((_, p::_), _)::_} = |
216 | mk{path = u::rstp, rows as ((_, p::_), _)::_} = |
228 let val (pat_rectangle,rights) = ListPair.unzip rows |
217 let val (pat_rectangle,rights) = ListPair.unzip rows |
229 val col0 = map(hd o #2) pat_rectangle |
218 val col0 = map(hd o #2) pat_rectangle |
230 in |
219 in |
231 if (forall is_Free col0) |
220 if (forall is_Free col0) |
232 then let val rights' = map (fn(v,e) => psubst[(v,u)] e) |
221 then let val rights' = map (fn(v,e) => pattern_subst[(v,u)] e) |
233 (ListPair.zip (col0, rights)) |
222 (ListPair.zip (col0, rights)) |
234 val pat_rectangle' = map v_to_prefix pat_rectangle |
223 val pat_rectangle' = map v_to_prefix pat_rectangle |
235 val (pref_patl,tm) = mk{path = rstp, |
224 val (pref_patl,tm) = mk{path = rstp, |
236 rows = ListPair.zip (pat_rectangle', |
225 rows = ListPair.zip (pat_rectangle', |
237 rights')} |
226 rights')} |
241 let val pty as Type (ty_name,_) = type_of p |
230 let val pty as Type (ty_name,_) = type_of p |
242 in |
231 in |
243 case (ty_info ty_name) |
232 case (ty_info ty_name) |
244 of None => mk_case_fail("Not a known datatype: "^ty_name) |
233 of None => mk_case_fail("Not a known datatype: "^ty_name) |
245 | Some{case_const,constructors} => |
234 | Some{case_const,constructors} => |
246 let val case_const_name = #Name(S.dest_const case_const) |
235 let val case_const_name = #1(dest_Const case_const) |
247 val nrows = List_.concat (map (expand constructors pty) rows) |
236 val nrows = List_.concat (map (expand constructors pty) rows) |
248 val subproblems = divide(constructors, pty, range_ty, nrows) |
237 val subproblems = divide(constructors, pty, range_ty, nrows) |
249 val groups = map #group subproblems |
238 val groups = map #group subproblems |
250 and new_formals = map #new_formals subproblems |
239 and new_formals = map #new_formals subproblems |
251 and constructors' = map #constructor subproblems |
240 and constructors' = map #constructor subproblems |
254 val rec_calls = map mk news |
243 val rec_calls = map mk news |
255 val (pat_rect,dtrees) = ListPair.unzip rec_calls |
244 val (pat_rect,dtrees) = ListPair.unzip rec_calls |
256 val case_functions = map S.list_mk_abs |
245 val case_functions = map S.list_mk_abs |
257 (ListPair.zip (new_formals, dtrees)) |
246 (ListPair.zip (new_formals, dtrees)) |
258 val types = map type_of (case_functions@[u]) @ [range_ty] |
247 val types = map type_of (case_functions@[u]) @ [range_ty] |
259 val case_const' = S.mk_const{Name = case_const_name, |
248 val case_const' = Const(case_const_name, list_mk_type types) |
260 Ty = list_mk_type types} |
|
261 val tree = list_comb(case_const', case_functions@[u]) |
249 val tree = list_comb(case_const', case_functions@[u]) |
262 val pat_rect1 = List_.concat |
250 val pat_rect1 = List_.concat |
263 (ListPair.map mk_pat (constructors', pat_rect)) |
251 (ListPair.map mk_pat (constructors', pat_rect)) |
264 in (pat_rect1,tree) |
252 in (pat_rect1,tree) |
265 end |
253 end |
286 quote (string_of_cterm (Thry.typecheck thy pat))} |
274 quote (string_of_cterm (Thry.typecheck thy pat))} |
287 else check rst |
275 else check rst |
288 in check (FV_multiset pat) |
276 in check (FV_multiset pat) |
289 end; |
277 end; |
290 |
278 |
291 local fun paired1{lhs,rhs} = (lhs,rhs) |
279 local fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
292 and paired2{Rator,Rand} = (Rator,Rand) |
|
293 fun mk_functional_err s = raise TFL_ERR{func = "mk_functional", mesg=s} |
|
294 fun single [f] = f |
280 fun single [f] = f |
295 | single fs = mk_functional_err (Int.toString (length fs) ^ |
281 | single fs = mk_functional_err (Int.toString (length fs) ^ |
296 " distinct function names!") |
282 " distinct function names!") |
297 in |
283 in |
298 fun mk_functional thy eqs = |
284 fun mk_functional thy clauses = |
299 let val clauses = S.strip_conj eqs |
285 let val (L,R) = ListPair.unzip |
300 val (L,R) = ListPair.unzip |
286 (map (fn (Const("op =",_) $ t $ u) => (t,u)) clauses) |
301 (map (paired1 o S.dest_eq o #2 o S.strip_forall) |
287 val (funcs,pats) = ListPair.unzip (map (fn (t$u) =>(t,u)) L) |
302 clauses) |
288 val f = single (gen_distinct (op aconv) funcs) |
303 val (funcs,pats) = ListPair.unzip(map (paired2 o S.dest_comb) L) |
289 (**??why change the Const to a Free??????????????**) |
304 val f = single (U.mk_set (S.aconv) funcs) |
290 val fvar = if (is_Free f) then f else Free(dest_Const f) |
305 val fvar = if (is_Free f) then f else S.mk_var(S.dest_const f) |
|
306 val dummy = map (no_repeat_vars thy) pats |
291 val dummy = map (no_repeat_vars thy) pats |
307 val rows = ListPair.zip (map (fn x => ([],[x])) pats, |
292 val rows = ListPair.zip (map (fn x => ([],[x])) pats, |
308 map GIVEN (enumerate R)) |
293 map GIVEN (enumerate R)) |
309 val fvs = S.free_varsl R |
294 val fvs = S.free_varsl R |
310 val a = S.variant fvs (S.mk_var{Name="a", Ty = type_of(hd pats)}) |
295 val a = S.variant fvs (Free("a",type_of(hd pats))) |
311 val FV = a::fvs |
296 val FV = a::fvs |
312 val ty_info = Thry.match_info thy |
297 val ty_info = Thry.match_info thy |
313 val ty_match = Thry.match_type thy |
298 val ty_match = Thry.match_type thy |
314 val range_ty = type_of (hd R) |
299 val range_ty = type_of (hd R) |
315 val (patts, case_tm) = mk_case ty_info ty_match FV range_ty |
300 val (patts, case_tm) = mk_case ty_info ty_match FV range_ty |
316 {path=[a], rows=rows} |
301 {path=[a], rows=rows} |
317 val patts1 = map (fn (_,(tag,i),[pat]) => tag (pat,i)) patts handle _ |
302 val patts1 = map (fn (_,(tag,i),[pat]) => tag (pat,i)) patts |
318 => mk_functional_err "error in pattern-match translation" |
303 handle _ => mk_functional_err "error in pattern-match translation" |
319 val patts2 = U.sort(fn p1=>fn p2=> row_of_pat p1 < row_of_pat p2) patts1 |
304 val patts2 = U.sort(fn p1=>fn p2=> row_of_pat p1 < row_of_pat p2) patts1 |
320 val finals = map row_of_pat patts2 |
305 val finals = map row_of_pat patts2 |
321 val originals = map (row_of_pat o #2) rows |
306 val originals = map (row_of_pat o #2) rows |
322 fun int_eq i1 (i2:int) = (i1=i2) |
307 val dummy = case (originals\\finals) |
323 val dummy = case (U.set_diff int_eq originals finals) |
|
324 of [] => () |
308 of [] => () |
325 | L => mk_functional_err("The following rows (counting from zero)\ |
309 | L => mk_functional_err("The following rows (counting from zero)\ |
326 \ are inaccessible: "^stringize L) |
310 \ are inaccessible: "^stringize L) |
327 val case_tm' = subst_free [(f,fvar)] case_tm |
311 val case_tm' = subst_free [(f,fvar)] case_tm |
328 in {functional = S.list_mk_abs ([fvar,a], case_tm'), |
312 in {functional = S.list_mk_abs ([fvar,a], case_tm'), |
350 #ant(S.dest_imp(#2(S.strip_forall (concl Thms.WFREC_COROLLARY)))) |
334 #ant(S.dest_imp(#2(S.strip_forall (concl Thms.WFREC_COROLLARY)))) |
351 val {lhs=f, rhs} = S.dest_eq f_eq_wfrec_R_M |
335 val {lhs=f, rhs} = S.dest_eq f_eq_wfrec_R_M |
352 val (fname,_) = dest_Free f |
336 val (fname,_) = dest_Free f |
353 val (wfrec,_) = S.strip_comb rhs |
337 val (wfrec,_) = S.strip_comb rhs |
354 in |
338 in |
355 fun wfrec_definition0 thy fid R functional = |
339 fun wfrec_definition0 thy fid R (functional as Abs(Name, Ty, _)) = |
356 let val {Bvar,...} = S.dest_abs functional |
340 let val def_name = if Name<>fid then |
357 val (Name, Ty) = dest_Free Bvar |
|
358 val def_name = if Name<>fid then |
|
359 raise TFL_ERR{func = "wfrec_definition0", |
341 raise TFL_ERR{func = "wfrec_definition0", |
360 mesg = "Expected a definition of " ^ |
342 mesg = "Expected a definition of " ^ |
361 quote fid ^ " but found one of " ^ |
343 quote fid ^ " but found one of " ^ |
362 quote Name} |
344 quote Name} |
363 else Name ^ "_def" |
345 else Name ^ "_def" |
364 val wfrec_R_M = map_term_types poly_tvars |
346 val wfrec_R_M = map_term_types poly_tvars |
365 (wfrec $ R $ (map_term_types poly_tvars functional)) |
347 (wfrec $ map_term_types poly_tvars R) |
|
348 $ functional |
366 val (_, def_term, _) = |
349 val (_, def_term, _) = |
367 Sign.infer_types (sign_of thy) (K None) (K None) [] false |
350 Sign.infer_types (sign_of thy) (K None) (K None) [] false |
368 ([HOLogic.mk_eq(Bvar, wfrec_R_M)], |
351 ([HOLogic.mk_eq(Const(Name,Ty), wfrec_R_M)], |
369 HOLogic.boolT) |
352 HOLogic.boolT) |
370 |
353 |
371 in |
354 in |
372 Thry.make_definition thy def_name def_term |
355 Thry.make_definition thy def_name def_term |
373 end |
356 end |
399 * cases. This routine is used to prepare input for mk_induction. |
382 * cases. This routine is used to prepare input for mk_induction. |
400 *---------------------------------------------------------------------------*) |
383 *---------------------------------------------------------------------------*) |
401 fun merge full_pats TCs = |
384 fun merge full_pats TCs = |
402 let fun insert (p,TCs) = |
385 let fun insert (p,TCs) = |
403 let fun insrt ((x as (h,[]))::rst) = |
386 let fun insrt ((x as (h,[]))::rst) = |
404 if (S.aconv p h) then (p,TCs)::rst else x::insrt rst |
387 if (p aconv h) then (p,TCs)::rst else x::insrt rst |
405 | insrt (x::rst) = x::insrt rst |
388 | insrt (x::rst) = x::insrt rst |
406 | insrt[] = raise TFL_ERR{func="merge.insert",mesg="pat not found"} |
389 | insrt[] = raise TFL_ERR{func="merge.insert", |
|
390 mesg="pattern not found"} |
407 in insrt end |
391 in insrt end |
408 fun pass ([],ptcl_final) = ptcl_final |
392 fun pass ([],ptcl_final) = ptcl_final |
409 | pass (ptcs::tcl, ptcl) = pass(tcl, insert ptcs ptcl) |
393 | pass (ptcs::tcl, ptcl) = pass(tcl, insert ptcs ptcl) |
410 in |
394 in |
411 pass (TCs, map (fn p => (p,[])) full_pats) |
395 pass (TCs, map (fn p => (p,[])) full_pats) |
412 end; |
396 end; |
413 |
397 |
414 fun not_omitted (GIVEN(tm,_)) = tm |
398 |
415 | not_omitted (OMITTED _) = raise TFL_ERR{func="not_omitted",mesg=""} |
399 (*Replace all TFrees by TVars [CURRENTLY UNUSED]*) |
416 val givens = U.mapfilter not_omitted; |
400 val tvars_of_tfrees = |
417 |
401 map_term_types (map_type_tfree (fn (a,sort) => TVar ((a, 0), sort))); |
|
402 |
|
403 fun givens [] = [] |
|
404 | givens (GIVEN(tm,_)::pats) = tm :: givens pats |
|
405 | givens (OMITTED _::pats) = givens pats; |
418 |
406 |
419 fun post_definition (theory, (def, pats)) = |
407 fun post_definition (theory, (def, pats)) = |
420 let val tych = Thry.typecheck theory |
408 let val tych = Thry.typecheck theory |
421 val f = #lhs(S.dest_eq(concl def)) |
409 val f = #lhs(S.dest_eq(concl def)) |
422 val corollary = R.MATCH_MP Thms.WFREC_COROLLARY def |
410 val corollary = R.MATCH_MP Thms.WFREC_COROLLARY def |
423 val given_pats = givens pats |
411 val given_pats = givens pats |
424 val WFR = #ant(S.dest_imp(concl corollary)) |
412 val WFR = #ant(S.dest_imp(concl corollary)) |
425 val R = #Rand(S.dest_comb WFR) |
413 val R = #Rand(S.dest_comb WFR) |
426 val corollary' = R.UNDISCH corollary (* put WF R on assums *) |
414 val corollary' = R.UNDISCH corollary (* put WF R on assums *) |
427 val corollaries = map (U.C R.SPEC corollary' o tych) given_pats |
415 val corollaries = map (fn pat => R.SPEC (tych pat) corollary') |
|
416 given_pats |
428 val (case_rewrites,context_congs) = extraction_thms theory |
417 val (case_rewrites,context_congs) = extraction_thms theory |
429 val corollaries' = map(R.simplify case_rewrites) corollaries |
418 val corollaries' = map(R.simplify case_rewrites) corollaries |
430 fun xtract th = R.CONTEXT_REWRITE_RULE(f,R) |
419 fun xtract th = R.CONTEXT_REWRITE_RULE(f,R) |
431 {cut_lemma = R.ISPECL (map tych [f,R]) Thms.CUT_LEMMA, |
420 {cut_lemma = R.ISPECL (map tych [f,R]) Thms.CUT_LEMMA, |
432 congs = context_congs, |
421 congs = context_congs, |
455 val {Bvar = x, ...} = S.dest_abs Body |
445 val {Bvar = x, ...} = S.dest_abs Body |
456 val (Name, Type("fun", [f_dty, f_rty])) = dest_Free f |
446 val (Name, Type("fun", [f_dty, f_rty])) = dest_Free f |
457 val (case_rewrites,context_congs) = extraction_thms thy |
447 val (case_rewrites,context_congs) = extraction_thms thy |
458 val tych = Thry.typecheck thy |
448 val tych = Thry.typecheck thy |
459 val WFREC_THM0 = R.ISPEC (tych functional) Thms.WFREC_COROLLARY |
449 val WFREC_THM0 = R.ISPEC (tych functional) Thms.WFREC_COROLLARY |
460 val R = S.variant(S.free_vars eqns) |
450 val R = S.variant(foldr add_term_frees (eqns,[])) |
461 (#Bvar(S.dest_forall(concl WFREC_THM0))) |
451 (#Bvar(S.dest_forall(concl WFREC_THM0))) |
462 val WFREC_THM = R.ISPECL [tych R, tych f] WFREC_THM0 |
452 val WFREC_THM = R.ISPECL [tych R, tych f] WFREC_THM0 |
463 val ([proto_def, WFR],_) = S.strip_imp(concl WFREC_THM) |
453 val ([proto_def, WFR],_) = S.strip_imp(concl WFREC_THM) |
464 val R1 = S.rand WFR |
454 val R1 = S.rand WFR |
465 val corollary' = R.UNDISCH(R.UNDISCH WFREC_THM) |
455 val corollary' = R.UNDISCH(R.UNDISCH WFREC_THM) |
614 end; |
604 end; |
615 |
605 |
616 |
606 |
617 fun complete_cases thy = |
607 fun complete_cases thy = |
618 let val tych = Thry.typecheck thy |
608 let val tych = Thry.typecheck thy |
619 fun pmk_var n ty = S.mk_var{Name = n,Ty = ty} |
|
620 val ty_info = Thry.induct_info thy |
609 val ty_info = Thry.induct_info thy |
621 in fn pats => |
610 in fn pats => |
622 let val FV0 = S.free_varsl pats |
611 let val FV0 = S.free_varsl pats |
623 val a = S.variant FV0 (pmk_var "a" (type_of(hd pats))) |
612 val T = type_of (hd pats) |
624 val v = S.variant (a::FV0) (pmk_var "v" (type_of a)) |
613 val a = S.variant FV0 (Free ("a", T)) |
|
614 val v = S.variant (a::FV0) (Free ("v", T)) |
625 val FV = a::v::FV0 |
615 val FV = a::v::FV0 |
626 val a_eq_v = HOLogic.mk_eq(a,v) |
616 val a_eq_v = HOLogic.mk_eq(a,v) |
627 val ex_th0 = R.EXISTS (tych (S.mk_exists{Bvar=v,Body=a_eq_v}), tych a) |
617 val ex_th0 = R.EXISTS (tych (S.mk_exists{Bvar=v,Body=a_eq_v}), tych a) |
628 (R.REFL (tych a)) |
618 (R.REFL (tych a)) |
629 val th0 = R.ASSUME (tych a_eq_v) |
619 val th0 = R.ASSUME (tych a_eq_v) |
659 val P_y = if (nested tm) then R_y_pat ==> P^y else P^y |
649 val P_y = if (nested tm) then R_y_pat ==> P^y else P^y |
660 in case cntxt |
650 in case cntxt |
661 of [] => (P_y, (tm,[])) |
651 of [] => (P_y, (tm,[])) |
662 | _ => let |
652 | _ => let |
663 val imp = S.list_mk_conj cntxt ==> P_y |
653 val imp = S.list_mk_conj cntxt ==> P_y |
664 val lvs = U.set_diff S.aconv (S.free_vars_lr imp) globals |
654 val lvs = gen_rems (op aconv) (S.free_vars_lr imp, globals) |
665 val locals = #2(U.pluck (S.aconv P) lvs) handle _ => lvs |
655 val locals = #2(U.pluck (S.aconv P) lvs) handle _ => lvs |
666 in (S.list_mk_forall(locals,imp), (tm,locals)) end |
656 in (S.list_mk_forall(locals,imp), (tm,locals)) end |
667 end |
657 end |
668 in case TCs |
658 in case TCs |
669 of [] => (S.list_mk_forall(globals, P^pat), []) |
659 of [] => (S.list_mk_forall(globals, P^pat), []) |
748 val Sinduction = R.UNDISCH (R.ISPEC (tych R) Thms.WF_INDUCTION_THM) |
738 val Sinduction = R.UNDISCH (R.ISPEC (tych R) Thms.WF_INDUCTION_THM) |
749 val (pats,TCsl) = ListPair.unzip pat_TCs_list |
739 val (pats,TCsl) = ListPair.unzip pat_TCs_list |
750 val case_thm = complete_cases thy pats |
740 val case_thm = complete_cases thy pats |
751 val domain = (type_of o hd) pats |
741 val domain = (type_of o hd) pats |
752 val P = S.variant (S.all_varsl (pats @ List_.concat TCsl)) |
742 val P = S.variant (S.all_varsl (pats @ List_.concat TCsl)) |
753 (S.mk_var{Name="P", Ty=domain --> HOLogic.boolT}) |
743 (Free("P",domain --> HOLogic.boolT)) |
754 val Sinduct = R.SPEC (tych P) Sinduction |
744 val Sinduct = R.SPEC (tych P) Sinduction |
755 val Sinduct_assumf = S.rand ((#ant o S.dest_imp o concl) Sinduct) |
745 val Sinduct_assumf = S.rand ((#ant o S.dest_imp o concl) Sinduct) |
756 val Rassums_TCl' = map (build_ih f P) pat_TCs_list |
746 val Rassums_TCl' = map (build_ih f P) pat_TCs_list |
757 val (Rassums,TCl') = ListPair.unzip Rassums_TCl' |
747 val (Rassums,TCl') = ListPair.unzip Rassums_TCl' |
758 val Rinduct_assum = R.ASSUME (tych (S.list_mk_conj Rassums)) |
748 val Rinduct_assum = R.ASSUME (tych (S.list_mk_conj Rassums)) |
759 val cases = map (S.beta_conv o combize Sinduct_assumf) pats |
749 val cases = map (S.beta_conv o combize Sinduct_assumf) pats |
760 val tasks = U.zip3 cases TCl' (R.CONJUNCTS Rinduct_assum) |
750 val tasks = U.zip3 cases TCl' (R.CONJUNCTS Rinduct_assum) |
761 val proved_cases = map (prove_case f thy) tasks |
751 val proved_cases = map (prove_case f thy) tasks |
762 val v = S.variant (S.free_varsl (map concl proved_cases)) |
752 val v = S.variant (S.free_varsl (map concl proved_cases)) |
763 (S.mk_var{Name="v", Ty=domain}) |
753 (Free("v",domain)) |
764 val vtyped = tych v |
754 val vtyped = tych v |
765 val substs = map (R.SYM o R.ASSUME o tych o (curry HOLogic.mk_eq v)) pats |
755 val substs = map (R.SYM o R.ASSUME o tych o (curry HOLogic.mk_eq v)) pats |
766 val proved_cases1 = ListPair.map (fn (th,th') => R.SUBS[th]th') |
756 val proved_cases1 = ListPair.map (fn (th,th') => R.SUBS[th]th') |
767 (substs, proved_cases) |
757 (substs, proved_cases) |
768 val abs_cases = map (LEFT_ABS_VSTRUCT tych) proved_cases1 |
758 val abs_cases = map (LEFT_ABS_VSTRUCT tych) proved_cases1 |
873 *-------------------------------------------------------------------*) |
864 *-------------------------------------------------------------------*) |
874 fun strip_imp tm = if S.is_neg tm then ([],tm) else S.strip_imp tm |
865 fun strip_imp tm = if S.is_neg tm then ([],tm) else S.strip_imp tm |
875 fun loop ([],extras,R,ind) = (rev R, ind, extras) |
866 fun loop ([],extras,R,ind) = (rev R, ind, extras) |
876 | loop ((r,ftcs)::rst, nthms, R, ind) = |
867 | loop ((r,ftcs)::rst, nthms, R, ind) = |
877 let val tcs = #1(strip_imp (concl r)) |
868 let val tcs = #1(strip_imp (concl r)) |
878 val extra_tcs = U.set_diff S.aconv ftcs tcs |
869 val extra_tcs = gen_rems (op aconv) (ftcs, tcs) |
879 val extra_tc_thms = map simplify_nested_tc extra_tcs |
870 val extra_tc_thms = map simplify_nested_tc extra_tcs |
880 val (r1,ind1) = U.rev_itlist simplify_tc tcs (r,ind) |
871 val (r1,ind1) = U.rev_itlist simplify_tc tcs (r,ind) |
881 val r2 = R.FILTER_DISCH_ALL(not o S.is_WFR) r1 |
872 val r2 = R.FILTER_DISCH_ALL(not o S.is_WFR) r1 |
882 in loop(rst, nthms@extra_tc_thms, r2::R, ind1) |
873 in loop(rst, nthms@extra_tc_thms, r2::R, ind1) |
883 end |
874 end |