54 fun is_identity (Const (@{const_name "id"}, _)) = true |
54 fun is_identity (Const (@{const_name "id"}, _)) = true |
55 | is_identity _ = false |
55 | is_identity _ = false |
56 |
56 |
57 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty) |
57 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty) |
58 |
58 |
59 fun mk_fun_compose flag (trm1, trm2) = |
59 fun mk_fun_compose flag (trm1, trm2) = |
60 case flag of |
60 case flag of |
61 AbsF => Const (@{const_name "comp"}, dummyT) $ trm1 $ trm2 |
61 AbsF => Const (@{const_name "comp"}, dummyT) $ trm1 $ trm2 |
62 | RepF => Const (@{const_name "comp"}, dummyT) $ trm2 $ trm1 |
62 | RepF => Const (@{const_name "comp"}, dummyT) $ trm2 $ trm1 |
63 |
63 |
64 fun get_mapfun ctxt s = |
64 fun get_mapfun ctxt s = |
71 end |
71 end |
72 |
72 |
73 (* makes a Free out of a TVar *) |
73 (* makes a Free out of a TVar *) |
74 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT) |
74 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT) |
75 |
75 |
76 (* produces an aggregate map function for the |
76 (* produces an aggregate map function for the |
77 rty-part of a quotient definition; abstracts |
77 rty-part of a quotient definition; abstracts |
78 over all variables listed in vs (these variables |
78 over all variables listed in vs (these variables |
79 correspond to the type variables in rty) |
79 correspond to the type variables in rty) |
80 |
80 |
81 for example for: (?'a list * ?'b) |
81 for example for: (?'a list * ?'b) |
82 it produces: %a b. prod_map (map a) b |
82 it produces: %a b. prod_map (map a) b |
83 *) |
83 *) |
84 fun mk_mapfun ctxt vs rty = |
84 fun mk_mapfun ctxt vs rty = |
85 let |
85 let |
86 val vs' = map (mk_Free) vs |
86 val vs' = map (mk_Free) vs |
87 |
87 |
93 | _ => raise LIFT_MATCH "mk_mapfun (default)" |
93 | _ => raise LIFT_MATCH "mk_mapfun (default)" |
94 in |
94 in |
95 fold_rev Term.lambda vs' (mk_mapfun_aux rty) |
95 fold_rev Term.lambda vs' (mk_mapfun_aux rty) |
96 end |
96 end |
97 |
97 |
98 (* looks up the (varified) rty and qty for |
98 (* looks up the (varified) rty and qty for |
99 a quotient definition |
99 a quotient definition |
100 *) |
100 *) |
101 fun get_rty_qty ctxt s = |
101 fun get_rty_qty ctxt s = |
102 let |
102 let |
103 val thy = ProofContext.theory_of ctxt |
103 val thy = ProofContext.theory_of ctxt |
104 val exn = LIFT_MATCH ("No quotient type " ^ quote s ^ " found.") |
104 val exn = LIFT_MATCH ("No quotient type " ^ quote s ^ " found.") |
105 val qdata = (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn |
105 val qdata = (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn |
106 in |
106 in |
107 (#rtyp qdata, #qtyp qdata) |
107 (#rtyp qdata, #qtyp qdata) |
108 end |
108 end |
109 |
109 |
110 (* takes two type-environments and looks |
110 (* takes two type-environments and looks |
111 up in both of them the variable v, which |
111 up in both of them the variable v, which |
112 must be listed in the environment |
112 must be listed in the environment |
113 *) |
113 *) |
114 fun double_lookup rtyenv qtyenv v = |
114 fun double_lookup rtyenv qtyenv v = |
115 let |
115 let |
116 val v' = fst (dest_TVar v) |
116 val v' = fst (dest_TVar v) |
117 in |
117 in |
143 Syntax.check_term ctxt (absrep_const flag ctxt qty_str) |
143 Syntax.check_term ctxt (absrep_const flag ctxt qty_str) |
144 |
144 |
145 fun absrep_match_err ctxt ty_pat ty = |
145 fun absrep_match_err ctxt ty_pat ty = |
146 let |
146 let |
147 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat |
147 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat |
148 val ty_str = Syntax.string_of_typ ctxt ty |
148 val ty_str = Syntax.string_of_typ ctxt ty |
149 in |
149 in |
150 raise LIFT_MATCH (space_implode " " |
150 raise LIFT_MATCH (space_implode " " |
151 ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
151 ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
152 end |
152 end |
153 |
153 |
154 |
154 |
155 (** generation of an aggregate absrep function **) |
155 (** generation of an aggregate absrep function **) |
156 |
156 |
157 (* - In case of equal types we just return the identity. |
157 (* - In case of equal types we just return the identity. |
158 |
158 |
159 - In case of TFrees we also return the identity. |
159 - In case of TFrees we also return the identity. |
160 |
160 |
161 - In case of function types we recurse taking |
161 - In case of function types we recurse taking |
162 the polarity change into account. |
162 the polarity change into account. |
163 |
163 |
164 - If the type constructors are equal, we recurse for the |
164 - If the type constructors are equal, we recurse for the |
165 arguments and build the appropriate map function. |
165 arguments and build the appropriate map function. |
166 |
166 |
167 - If the type constructors are unequal, there must be an |
167 - If the type constructors are unequal, there must be an |
168 instance of quotient types: |
168 instance of quotient types: |
169 |
169 |
170 - we first look up the corresponding rty_pat and qty_pat |
170 - we first look up the corresponding rty_pat and qty_pat |
171 from the quotient definition; the arguments of qty_pat |
171 from the quotient definition; the arguments of qty_pat |
172 must be some distinct TVars |
172 must be some distinct TVars |
173 - we then match the rty_pat with rty and qty_pat with qty; |
173 - we then match the rty_pat with rty and qty_pat with qty; |
174 if matching fails the types do not correspond -> error |
174 if matching fails the types do not correspond -> error |
175 - the matching produces two environments; we look up the |
175 - the matching produces two environments; we look up the |
176 assignments for the qty_pat variables and recurse on the |
176 assignments for the qty_pat variables and recurse on the |
177 assignments |
177 assignments |
178 - we prefix the aggregate map function for the rty_pat, |
178 - we prefix the aggregate map function for the rty_pat, |
179 which is an abstraction over all type variables |
179 which is an abstraction over all type variables |
180 - finally we compose the result with the appropriate |
180 - finally we compose the result with the appropriate |
181 absrep function in case at least one argument produced |
181 absrep function in case at least one argument produced |
182 a non-identity function / |
182 a non-identity function / |
183 otherwise we just return the appropriate absrep |
183 otherwise we just return the appropriate absrep |
184 function |
184 function |
185 |
185 |
186 The composition is necessary for types like |
186 The composition is necessary for types like |
187 |
187 |
188 ('a list) list / ('a foo) foo |
188 ('a list) list / ('a foo) foo |
189 |
189 |
190 The matching is necessary for types like |
190 The matching is necessary for types like |
191 |
191 |
192 ('a * 'a) list / 'a bar |
192 ('a * 'a) list / 'a bar |
193 |
193 |
194 The test is necessary in order to eliminate superfluous |
194 The test is necessary in order to eliminate superfluous |
195 identity maps. |
195 identity maps. |
196 *) |
196 *) |
197 |
197 |
198 fun absrep_fun flag ctxt (rty, qty) = |
198 fun absrep_fun flag ctxt (rty, qty) = |
199 if rty = qty |
199 if rty = qty |
200 then mk_identity rty |
200 then mk_identity rty |
201 else |
201 else |
202 case (rty, qty) of |
202 case (rty, qty) of |
203 (Type ("fun", [ty1, ty2]), Type ("fun", [ty1', ty2'])) => |
203 (Type ("fun", [ty1, ty2]), Type ("fun", [ty1', ty2'])) => |
204 let |
204 let |
207 in |
207 in |
208 list_comb (get_mapfun ctxt "fun", [arg1, arg2]) |
208 list_comb (get_mapfun ctxt "fun", [arg1, arg2]) |
209 end |
209 end |
210 | (Type (s, tys), Type (s', tys')) => |
210 | (Type (s, tys), Type (s', tys')) => |
211 if s = s' |
211 if s = s' |
212 then |
212 then |
213 let |
213 let |
214 val args = map (absrep_fun flag ctxt) (tys ~~ tys') |
214 val args = map (absrep_fun flag ctxt) (tys ~~ tys') |
215 in |
215 in |
216 list_comb (get_mapfun ctxt s, args) |
216 list_comb (get_mapfun ctxt s, args) |
217 end |
217 end |
218 else |
218 else |
219 let |
219 let |
220 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
220 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
221 val rtyenv = match ctxt absrep_match_err rty_pat rty |
221 val rtyenv = match ctxt absrep_match_err rty_pat rty |
222 val qtyenv = match ctxt absrep_match_err qty_pat qty |
222 val qtyenv = match ctxt absrep_match_err qty_pat qty |
223 val args_aux = map (double_lookup rtyenv qtyenv) vs |
223 val args_aux = map (double_lookup rtyenv qtyenv) vs |
224 val args = map (absrep_fun flag ctxt) args_aux |
224 val args = map (absrep_fun flag ctxt) args_aux |
225 val map_fun = mk_mapfun ctxt vs rty_pat |
225 val map_fun = mk_mapfun ctxt vs rty_pat |
226 val result = list_comb (map_fun, args) |
226 val result = list_comb (map_fun, args) |
227 in |
227 in |
228 if forall is_identity args |
228 if forall is_identity args |
229 then absrep_const flag ctxt s' |
229 then absrep_const flag ctxt s' |
230 else mk_fun_compose flag (absrep_const flag ctxt s', result) |
230 else mk_fun_compose flag (absrep_const flag ctxt s', result) |
231 end |
231 end |
290 end |
290 end |
291 |
291 |
292 fun get_equiv_rel ctxt s = |
292 fun get_equiv_rel ctxt s = |
293 let |
293 let |
294 val thy = ProofContext.theory_of ctxt |
294 val thy = ProofContext.theory_of ctxt |
295 val exn = LIFT_MATCH ("get_quotdata (no quotient found for type " ^ s ^ ")") |
295 val exn = LIFT_MATCH ("get_quotdata (no quotient found for type " ^ s ^ ")") |
296 in |
296 in |
297 #equiv_rel (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn |
297 #equiv_rel (quotdata_lookup thy s) handle Quotient_Info.NotFound => raise exn |
298 end |
298 end |
299 |
299 |
300 fun equiv_match_err ctxt ty_pat ty = |
300 fun equiv_match_err ctxt ty_pat ty = |
301 let |
301 let |
302 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat |
302 val ty_pat_str = Syntax.string_of_typ ctxt ty_pat |
303 val ty_str = Syntax.string_of_typ ctxt ty |
303 val ty_str = Syntax.string_of_typ ctxt ty |
304 in |
304 in |
305 raise LIFT_MATCH (space_implode " " |
305 raise LIFT_MATCH (space_implode " " |
306 ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
306 ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"]) |
307 end |
307 end |
308 |
308 |
309 (* builds the aggregate equivalence relation |
309 (* builds the aggregate equivalence relation |
310 that will be the argument of Respects |
310 that will be the argument of Respects |
311 *) |
311 *) |
312 fun equiv_relation ctxt (rty, qty) = |
312 fun equiv_relation ctxt (rty, qty) = |
313 if rty = qty |
313 if rty = qty |
314 then HOLogic.eq_const rty |
314 then HOLogic.eq_const rty |
315 else |
315 else |
316 case (rty, qty) of |
316 case (rty, qty) of |
317 (Type (s, tys), Type (s', tys')) => |
317 (Type (s, tys), Type (s', tys')) => |
318 if s = s' |
318 if s = s' |
319 then |
319 then |
320 let |
320 let |
321 val args = map (equiv_relation ctxt) (tys ~~ tys') |
321 val args = map (equiv_relation ctxt) (tys ~~ tys') |
322 in |
322 in |
323 list_comb (get_relmap ctxt s, args) |
323 list_comb (get_relmap ctxt s, args) |
324 end |
324 end |
325 else |
325 else |
326 let |
326 let |
327 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
327 val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s' |
328 val rtyenv = match ctxt equiv_match_err rty_pat rty |
328 val rtyenv = match ctxt equiv_match_err rty_pat rty |
329 val qtyenv = match ctxt equiv_match_err qty_pat qty |
329 val qtyenv = match ctxt equiv_match_err qty_pat qty |
330 val args_aux = map (double_lookup rtyenv qtyenv) vs |
330 val args_aux = map (double_lookup rtyenv qtyenv) vs |
331 val args = map (equiv_relation ctxt) args_aux |
331 val args = map (equiv_relation ctxt) args_aux |
332 val rel_map = mk_relmap ctxt vs rty_pat |
332 val rel_map = mk_relmap ctxt vs rty_pat |
333 val result = list_comb (rel_map, args) |
333 val result = list_comb (rel_map, args) |
334 val eqv_rel = get_equiv_rel ctxt s' |
334 val eqv_rel = get_equiv_rel ctxt s' |
335 val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool}) |
335 val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool}) |
336 in |
336 in |
337 if forall is_eq args |
337 if forall is_eq args |
338 then eqv_rel' |
338 then eqv_rel' |
339 else mk_rel_compose (result, eqv_rel') |
339 else mk_rel_compose (result, eqv_rel') |
340 end |
340 end |
341 | _ => HOLogic.eq_const rty |
341 | _ => HOLogic.eq_const rty |
342 |
342 |
347 |
347 |
348 |
348 |
349 (*** Regularization ***) |
349 (*** Regularization ***) |
350 |
350 |
351 (* Regularizing an rtrm means: |
351 (* Regularizing an rtrm means: |
352 |
352 |
353 - Quantifiers over types that need lifting are replaced |
353 - Quantifiers over types that need lifting are replaced |
354 by bounded quantifiers, for example: |
354 by bounded quantifiers, for example: |
355 |
355 |
356 All P ----> All (Respects R) P |
356 All P ----> All (Respects R) P |
357 |
357 |
358 where the aggregate relation R is given by the rty and qty; |
358 where the aggregate relation R is given by the rty and qty; |
359 |
359 |
360 - Abstractions over types that need lifting are replaced |
360 - Abstractions over types that need lifting are replaced |
361 by bounded abstractions, for example: |
361 by bounded abstractions, for example: |
362 |
362 |
363 %x. P ----> Ball (Respects R) %x. P |
363 %x. P ----> Ball (Respects R) %x. P |
364 |
364 |
365 - Equalities over types that need lifting are replaced by |
365 - Equalities over types that need lifting are replaced by |
366 corresponding equivalence relations, for example: |
366 corresponding equivalence relations, for example: |
367 |
367 |
390 val mk_ball = Const (@{const_name Ball}, dummyT) |
390 val mk_ball = Const (@{const_name Ball}, dummyT) |
391 val mk_bex = Const (@{const_name Bex}, dummyT) |
391 val mk_bex = Const (@{const_name Bex}, dummyT) |
392 val mk_bex1_rel = Const (@{const_name Bex1_rel}, dummyT) |
392 val mk_bex1_rel = Const (@{const_name Bex1_rel}, dummyT) |
393 val mk_resp = Const (@{const_name Respects}, dummyT) |
393 val mk_resp = Const (@{const_name Respects}, dummyT) |
394 |
394 |
395 (* - applies f to the subterm of an abstraction, |
395 (* - applies f to the subterm of an abstraction, |
396 otherwise to the given term, |
396 otherwise to the given term, |
397 - used by regularize, therefore abstracted |
397 - used by regularize, therefore abstracted |
398 variables do not have to be treated specially |
398 variables do not have to be treated specially |
399 *) |
399 *) |
400 fun apply_subt f (trm1, trm2) = |
400 fun apply_subt f (trm1, trm2) = |
401 case (trm1, trm2) of |
401 case (trm1, trm2) of |
402 (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t')) |
402 (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t')) |
403 | _ => f (trm1, trm2) |
403 | _ => f (trm1, trm2) |
472 if ty = ty' then Const (@{const_name "Ex"}, ty) $ subtrm |
472 if ty = ty' then Const (@{const_name "Ex"}, ty) $ subtrm |
473 else mk_bex $ (mk_resp $ equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm |
473 else mk_bex $ (mk_resp $ equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm |
474 end |
474 end |
475 |
475 |
476 | (Const (@{const_name "Ex1"}, ty) $ (Abs (_, _, |
476 | (Const (@{const_name "Ex1"}, ty) $ (Abs (_, _, |
477 (Const (@{const_name "op &"}, _) $ (Const (@{const_name "op :"}, _) $ _ $ |
477 (Const (@{const_name "op &"}, _) $ (Const (@{const_name "op :"}, _) $ _ $ |
478 (Const (@{const_name "Respects"}, _) $ resrel)) $ (t $ _)))), |
478 (Const (@{const_name "Respects"}, _) $ resrel)) $ (t $ _)))), |
479 Const (@{const_name "Ex1"}, ty') $ t') => |
479 Const (@{const_name "Ex1"}, ty') $ t') => |
480 let |
480 let |
481 val t_ = incr_boundvars (~1) t |
481 val t_ = incr_boundvars (~1) t |
482 val subtrm = apply_subt (regularize_trm ctxt) (t_, t') |
482 val subtrm = apply_subt (regularize_trm ctxt) (t_, t') |
483 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
483 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
493 in |
493 in |
494 if ty = ty' then Const (@{const_name "Ex1"}, ty) $ subtrm |
494 if ty = ty' then Const (@{const_name "Ex1"}, ty) $ subtrm |
495 else mk_bex1_rel $ (equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm |
495 else mk_bex1_rel $ (equiv_relation ctxt (qnt_typ ty, qnt_typ ty')) $ subtrm |
496 end |
496 end |
497 |
497 |
498 | (Const (@{const_name "Ball"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, |
498 | (Const (@{const_name "Ball"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, |
499 Const (@{const_name "All"}, ty') $ t') => |
499 Const (@{const_name "All"}, ty') $ t') => |
500 let |
500 let |
501 val subtrm = apply_subt (regularize_trm ctxt) (t, t') |
501 val subtrm = apply_subt (regularize_trm ctxt) (t, t') |
502 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
502 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
503 in |
503 in |
504 if resrel <> needrel |
504 if resrel <> needrel |
505 then term_mismatch "regularize (Ball)" ctxt resrel needrel |
505 then term_mismatch "regularize (Ball)" ctxt resrel needrel |
506 else mk_ball $ (mk_resp $ resrel) $ subtrm |
506 else mk_ball $ (mk_resp $ resrel) $ subtrm |
507 end |
507 end |
508 |
508 |
509 | (Const (@{const_name "Bex"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, |
509 | (Const (@{const_name "Bex"}, ty) $ (Const (@{const_name "Respects"}, _) $ resrel) $ t, |
510 Const (@{const_name "Ex"}, ty') $ t') => |
510 Const (@{const_name "Ex"}, ty') $ t') => |
511 let |
511 let |
512 val subtrm = apply_subt (regularize_trm ctxt) (t, t') |
512 val subtrm = apply_subt (regularize_trm ctxt) (t, t') |
513 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
513 val needrel = equiv_relation_chk ctxt (qnt_typ ty, qnt_typ ty') |
514 in |
514 in |
525 if resrel <> needrel |
525 if resrel <> needrel |
526 then term_mismatch "regularize (Bex1_res)" ctxt resrel needrel |
526 then term_mismatch "regularize (Bex1_res)" ctxt resrel needrel |
527 else mk_bex1_rel $ resrel $ subtrm |
527 else mk_bex1_rel $ resrel $ subtrm |
528 end |
528 end |
529 |
529 |
530 | (* equalities need to be replaced by appropriate equivalence relations *) |
530 | (* equalities need to be replaced by appropriate equivalence relations *) |
531 (Const (@{const_name "op ="}, ty), Const (@{const_name "op ="}, ty')) => |
531 (Const (@{const_name "op ="}, ty), Const (@{const_name "op ="}, ty')) => |
532 if ty = ty' then rtrm |
532 if ty = ty' then rtrm |
533 else equiv_relation ctxt (domain_type ty, domain_type ty') |
533 else equiv_relation ctxt (domain_type ty, domain_type ty') |
534 |
534 |
535 | (* in this case we just check whether the given equivalence relation is correct *) |
535 | (* in this case we just check whether the given equivalence relation is correct *) |
536 (rel, Const (@{const_name "op ="}, ty')) => |
536 (rel, Const (@{const_name "op ="}, ty')) => |
537 let |
537 let |
538 val rel_ty = fastype_of rel |
538 val rel_ty = fastype_of rel |
539 val rel' = equiv_relation_chk ctxt (domain_type rel_ty, domain_type ty') |
539 val rel' = equiv_relation_chk ctxt (domain_type rel_ty, domain_type ty') |
540 in |
540 in |
541 if rel' aconv rel then rtrm |
541 if rel' aconv rel then rtrm |
542 else term_mismatch "regularise (relation mismatch)" ctxt rel rel' |
542 else term_mismatch "regularise (relation mismatch)" ctxt rel rel' |
543 end |
543 end |
544 |
544 |
545 | (_, Const _) => |
545 | (_, Const _) => |
546 let |
546 let |
555 handle Quotient_Info.NotFound => term_mismatch "regularize(constant notfound)" ctxt rtrm qtrm |
555 handle Quotient_Info.NotFound => term_mismatch "regularize(constant notfound)" ctxt rtrm qtrm |
556 in |
556 in |
557 if Pattern.matches thy (rtrm', rtrm) |
557 if Pattern.matches thy (rtrm', rtrm) |
558 then rtrm else term_mismatch "regularize(constant mismatch)" ctxt rtrm qtrm |
558 then rtrm else term_mismatch "regularize(constant mismatch)" ctxt rtrm qtrm |
559 end |
559 end |
560 end |
560 end |
561 |
561 |
562 | (((t1 as Const (@{const_name "split"}, _)) $ Abs (v1, ty, Abs(v1', ty', s1))), |
562 | (((t1 as Const (@{const_name "split"}, _)) $ Abs (v1, ty, Abs(v1', ty', s1))), |
563 ((t2 as Const (@{const_name "split"}, _)) $ Abs (v2, _ , Abs(v2', _ , s2)))) => |
563 ((t2 as Const (@{const_name "split"}, _)) $ Abs (v2, _ , Abs(v2', _ , s2)))) => |
564 regularize_trm ctxt (t1, t2) $ Abs (v1, ty, Abs (v1', ty', regularize_trm ctxt (s1, s2))) |
564 regularize_trm ctxt (t1, t2) $ Abs (v1, ty, Abs (v1', ty', regularize_trm ctxt (s1, s2))) |
565 |
565 |
569 |
569 |
570 | (t1 $ t2, t1' $ t2') => |
570 | (t1 $ t2, t1' $ t2') => |
571 regularize_trm ctxt (t1, t1') $ regularize_trm ctxt (t2, t2') |
571 regularize_trm ctxt (t1, t1') $ regularize_trm ctxt (t2, t2') |
572 |
572 |
573 | (Bound i, Bound i') => |
573 | (Bound i, Bound i') => |
574 if i = i' then rtrm |
574 if i = i' then rtrm |
575 else raise (LIFT_MATCH "regularize (bounds mismatch)") |
575 else raise (LIFT_MATCH "regularize (bounds mismatch)") |
576 |
576 |
577 | _ => |
577 | _ => |
578 let |
578 let |
579 val rtrm_str = Syntax.string_of_term ctxt rtrm |
579 val rtrm_str = Syntax.string_of_term ctxt rtrm |
580 val qtrm_str = Syntax.string_of_term ctxt qtrm |
580 val qtrm_str = Syntax.string_of_term ctxt qtrm |
581 in |
581 in |
582 raise (LIFT_MATCH ("regularize failed (default: " ^ rtrm_str ^ "," ^ qtrm_str ^ ")")) |
582 raise (LIFT_MATCH ("regularize failed (default: " ^ rtrm_str ^ "," ^ qtrm_str ^ ")")) |
583 end |
583 end |
584 |
584 |
585 fun regularize_trm_chk ctxt (rtrm, qtrm) = |
585 fun regularize_trm_chk ctxt (rtrm, qtrm) = |
586 regularize_trm ctxt (rtrm, qtrm) |
586 regularize_trm ctxt (rtrm, qtrm) |
587 |> Syntax.check_term ctxt |
587 |> Syntax.check_term ctxt |
588 |
588 |
589 |
589 |
590 |
590 |
591 (*** Rep/Abs Injection ***) |
591 (*** Rep/Abs Injection ***) |
593 (* |
593 (* |
594 Injection of Rep/Abs means: |
594 Injection of Rep/Abs means: |
595 |
595 |
596 For abstractions: |
596 For abstractions: |
597 |
597 |
598 * If the type of the abstraction needs lifting, then we add Rep/Abs |
598 * If the type of the abstraction needs lifting, then we add Rep/Abs |
599 around the abstraction; otherwise we leave it unchanged. |
599 around the abstraction; otherwise we leave it unchanged. |
600 |
600 |
601 For applications: |
601 For applications: |
602 |
602 |
603 * If the application involves a bounded quantifier, we recurse on |
603 * If the application involves a bounded quantifier, we recurse on |
604 the second argument. If the application is a bounded abstraction, |
604 the second argument. If the application is a bounded abstraction, |
605 we always put an Rep/Abs around it (since bounded abstractions |
605 we always put an Rep/Abs around it (since bounded abstractions |
606 are assumed to always need lifting). Otherwise we recurse on both |
606 are assumed to always need lifting). Otherwise we recurse on both |
607 arguments. |
607 arguments. |
608 |
608 |
609 For constants: |
609 For constants: |
610 |
610 |
611 * If the constant is (op =), we leave it always unchanged. |
611 * If the constant is (op =), we leave it always unchanged. |
612 Otherwise the type of the constant needs lifting, we put |
612 Otherwise the type of the constant needs lifting, we put |
613 and Rep/Abs around it. |
613 and Rep/Abs around it. |
614 |
614 |
615 For free variables: |
615 For free variables: |
616 |
616 |
617 * We put a Rep/Abs around it if the type needs lifting. |
617 * We put a Rep/Abs around it if the type needs lifting. |
618 |
618 |
619 Vars case cannot occur. |
619 Vars case cannot occur. |
620 *) |
620 *) |
621 |
621 |
622 fun mk_repabs ctxt (T, T') trm = |
622 fun mk_repabs ctxt (T, T') trm = |
623 absrep_fun RepF ctxt (T, T') $ (absrep_fun AbsF ctxt (T, T') $ trm) |
623 absrep_fun RepF ctxt (T, T') $ (absrep_fun AbsF ctxt (T, T') $ trm) |
624 |
624 |
625 fun inj_repabs_err ctxt msg rtrm qtrm = |
625 fun inj_repabs_err ctxt msg rtrm qtrm = |
626 let |
626 let |
627 val rtrm_str = Syntax.string_of_term ctxt rtrm |
627 val rtrm_str = Syntax.string_of_term ctxt rtrm |
628 val qtrm_str = Syntax.string_of_term ctxt qtrm |
628 val qtrm_str = Syntax.string_of_term ctxt qtrm |
629 in |
629 in |
630 raise LIFT_MATCH (space_implode " " [msg, quote rtrm_str, "and", quote qtrm_str]) |
630 raise LIFT_MATCH (space_implode " " [msg, quote rtrm_str, "and", quote qtrm_str]) |
631 end |
631 end |
632 |
632 |
633 |
633 |
660 in |
660 in |
661 if rty = qty then result |
661 if rty = qty then result |
662 else mk_repabs ctxt (rty, qty) result |
662 else mk_repabs ctxt (rty, qty) result |
663 end |
663 end |
664 |
664 |
665 | (t $ s, t' $ s') => |
665 | (t $ s, t' $ s') => |
666 (inj_repabs_trm ctxt (t, t')) $ (inj_repabs_trm ctxt (s, s')) |
666 (inj_repabs_trm ctxt (t, t')) $ (inj_repabs_trm ctxt (s, s')) |
667 |
667 |
668 | (Free (_, T), Free (_, T')) => |
668 | (Free (_, T), Free (_, T')) => |
669 if T = T' then rtrm |
669 if T = T' then rtrm |
670 else mk_repabs ctxt (T, T') rtrm |
670 else mk_repabs ctxt (T, T') rtrm |
671 |
671 |
672 | (_, Const (@{const_name "op ="}, _)) => rtrm |
672 | (_, Const (@{const_name "op ="}, _)) => rtrm |
673 |
673 |
674 | (_, Const (_, T')) => |
674 | (_, Const (_, T')) => |
675 let |
675 let |
676 val rty = fastype_of rtrm |
676 val rty = fastype_of rtrm |
677 in |
677 in |
678 if rty = T' then rtrm |
678 if rty = T' then rtrm |
679 else mk_repabs ctxt (rty, T') rtrm |
679 else mk_repabs ctxt (rty, T') rtrm |
680 end |
680 end |
681 |
681 |
682 | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm |
682 | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm |
683 |
683 |
684 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) = |
684 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) = |
685 inj_repabs_trm ctxt (rtrm, qtrm) |
685 inj_repabs_trm ctxt (rtrm, qtrm) |
686 |> Syntax.check_term ctxt |
686 |> Syntax.check_term ctxt |
687 |
687 |
688 |
688 |
689 |
689 |
690 (*** Wrapper for automatically transforming an rthm into a qthm ***) |
690 (*** Wrapper for automatically transforming an rthm into a qthm ***) |