42 fp_nesting_maps: thm list, |
42 fp_nesting_maps: thm list, |
43 fp_nesting_map_ident0s: thm list, |
43 fp_nesting_map_ident0s: thm list, |
44 fp_nesting_map_comps: thm list, |
44 fp_nesting_map_comps: thm list, |
45 ctr_specs: corec_ctr_spec list} |
45 ctr_specs: corec_ctr_spec list} |
46 |
46 |
|
47 val abstract_over_list: term list -> term -> term |
47 val abs_tuple_balanced: term list -> term -> term |
48 val abs_tuple_balanced: term list -> term -> term |
|
49 |
|
50 val mk_conjs: term list -> term |
|
51 val mk_disjs: term list -> term |
|
52 val mk_dnf: term list list -> term |
|
53 val conjuncts_s: term -> term list |
|
54 val s_not: term -> term |
|
55 val s_not_conj: term list -> term list |
|
56 val s_conjs: term list -> term |
|
57 val s_disjs: term list -> term |
|
58 val s_dnf: term list list -> term list |
48 |
59 |
49 val fold_rev_let_if_case: Proof.context -> (term list -> term -> 'a -> 'a) -> typ list -> |
60 val fold_rev_let_if_case: Proof.context -> (term list -> term -> 'a -> 'a) -> typ list -> |
50 term -> 'a -> 'a |
61 term -> 'a -> 'a |
51 val massage_let_if_case: Proof.context -> (term -> bool) -> (typ list -> term -> term) -> |
62 val massage_let_if_case: Proof.context -> (term -> bool) -> (typ list -> term -> term) -> |
52 (typ list -> term -> unit) -> typ list -> term -> term |
63 (typ list -> term -> unit) -> typ list -> term -> term |
159 fp_nesting_map_comps: thm list, |
170 fp_nesting_map_comps: thm list, |
160 ctr_specs: corec_ctr_spec list}; |
171 ctr_specs: corec_ctr_spec list}; |
161 |
172 |
162 exception NO_MAP of term; |
173 exception NO_MAP of term; |
163 |
174 |
|
175 fun abstract_over_list rev_vs = |
|
176 let |
|
177 val vs = rev rev_vs; |
|
178 |
|
179 fun abs n (t $ u) = abs n t $ abs n u |
|
180 | abs n (Abs (s, T, t)) = Abs (s, T, abs (n + 1) t) |
|
181 | abs n t = |
|
182 let val j = find_index (curry (op =) t) vs in |
|
183 if j < 0 then t else Bound (n + j) |
|
184 end; |
|
185 in |
|
186 abs 0 |
|
187 end; |
|
188 |
164 val abs_tuple_balanced = HOLogic.tupled_lambda o mk_tuple_balanced; |
189 val abs_tuple_balanced = HOLogic.tupled_lambda o mk_tuple_balanced; |
|
190 |
|
191 fun curried_type (Type (@{type_name fun}, [Type (@{type_name prod}, Ts), T])) = |
|
192 Ts ---> T; |
165 |
193 |
166 fun sort_list_duplicates xs = map snd (sort (int_ord o apply2 fst) xs); |
194 fun sort_list_duplicates xs = map snd (sort (int_ord o apply2 fst) xs); |
167 |
195 |
168 val mk_conjs = try (foldr1 HOLogic.mk_conj) #> the_default @{const True}; |
196 val mk_conjs = try (foldr1 HOLogic.mk_conj) #> the_default @{const True}; |
169 val mk_disjs = try (foldr1 HOLogic.mk_disj) #> the_default @{const False}; |
197 val mk_disjs = try (foldr1 HOLogic.mk_disj) #> the_default @{const False}; |
305 if Term.is_dummy_pattern t then Const (@{const_name undefined}, fastype_of t) else t) |
333 if Term.is_dummy_pattern t then Const (@{const_name undefined}, fastype_of t) else t) |
306 end; |
334 end; |
307 |
335 |
308 fun massage_let_if_case_corec ctxt has_call massage_leaf bound_Ts t0 = |
336 fun massage_let_if_case_corec ctxt has_call massage_leaf bound_Ts t0 = |
309 massage_let_if_case ctxt has_call massage_leaf (K (unexpected_corec_call ctxt [t0])) bound_Ts t0; |
337 massage_let_if_case ctxt has_call massage_leaf (K (unexpected_corec_call ctxt [t0])) bound_Ts t0; |
310 |
|
311 fun curried_type (Type (@{type_name fun}, [Type (@{type_name prod}, Ts), T])) = Ts ---> T; |
|
312 |
338 |
313 fun massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts U T t0 = |
339 fun massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts U T t0 = |
314 let |
340 let |
315 fun check_no_call t = if has_call t then unexpected_corec_call ctxt [t0] t else (); |
341 fun check_no_call t = if has_call t then unexpected_corec_call ctxt [t0] t else (); |
316 |
342 |
560 is_some gfp_sugar_thms, lthy) |
586 is_some gfp_sugar_thms, lthy) |
561 end; |
587 end; |
562 |
588 |
563 val undef_const = Const (@{const_name undefined}, dummyT); |
589 val undef_const = Const (@{const_name undefined}, dummyT); |
564 |
590 |
565 fun abstract vs = |
|
566 let |
|
567 fun abs n (t $ u) = abs n t $ abs n u |
|
568 | abs n (Abs (s, T, t)) = Abs (s, T, abs (n + 1) t) |
|
569 | abs n t = |
|
570 let val j = find_index (curry (op =) t) vs in |
|
571 if j < 0 then t else Bound (n + j) |
|
572 end; |
|
573 in abs 0 end; |
|
574 |
|
575 type coeqn_data_disc = |
591 type coeqn_data_disc = |
576 {fun_name: string, |
592 {fun_name: string, |
577 fun_T: typ, |
593 fun_T: typ, |
578 fun_args: term list, |
594 fun_args: term list, |
579 ctr: term, |
595 ctr: term, |
685 [prem] => is_catch_all_prem prem |
701 [prem] => is_catch_all_prem prem |
686 | _ => |
702 | _ => |
687 if exists is_catch_all_prem prems0 then error_at ctxt [concl] "Superfluous premises" |
703 if exists is_catch_all_prem prems0 then error_at ctxt [concl] "Superfluous premises" |
688 else false); |
704 else false); |
689 val matchedss = AList.lookup (op =) matchedsss fun_name |> the_default []; |
705 val matchedss = AList.lookup (op =) matchedsss fun_name |> the_default []; |
690 val prems = map (abstract (List.rev fun_args)) prems0; |
706 val prems = map (abstract_over_list fun_args) prems0; |
691 val actual_prems = |
707 val actual_prems = |
692 (if catch_all orelse sequential then maps s_not_conj matchedss else []) @ |
708 (if catch_all orelse sequential then maps s_not_conj matchedss else []) @ |
693 (if catch_all then [] else prems); |
709 (if catch_all then [] else prems); |
694 |
710 |
695 val matchedsss' = AList.delete (op =) fun_name matchedsss |
711 val matchedsss' = AList.delete (op =) fun_name matchedsss |
696 |> cons (fun_name, if sequential then matchedss @ [prems] else matchedss @ [actual_prems]); |
712 |> cons (fun_name, if sequential then matchedss @ [prems] else matchedss @ [actual_prems]); |
697 |
713 |
698 val user_eqn = |
714 val user_eqn = |
699 (actual_prems, concl) |
715 (actual_prems, concl) |
700 |>> map HOLogic.mk_Trueprop ||> HOLogic.mk_Trueprop o abstract (List.rev fun_args) |
716 |>> map HOLogic.mk_Trueprop ||> HOLogic.mk_Trueprop o abstract_over_list fun_args |
701 |> curry Logic.list_all (map dest_Free fun_args) o Logic.list_implies; |
717 |> curry Logic.list_all (map dest_Free fun_args) o Logic.list_implies; |
702 |
718 |
703 val _ = check_extra_frees ctxt fun_args fun_names user_eqn; |
719 val _ = check_extra_frees ctxt fun_args fun_names user_eqn; |
704 in |
720 in |
705 (Disc {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, ctr_no = ctr_no, |
721 (Disc {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, ctr_no = ctr_no, |
753 val (eqn_data_disc_opt, matchedsss') = |
769 val (eqn_data_disc_opt, matchedsss') = |
754 if null (tl basic_ctr_specs) andalso not (null sels) then |
770 if null (tl basic_ctr_specs) andalso not (null sels) then |
755 (NONE, matchedsss) |
771 (NONE, matchedsss) |
756 else |
772 else |
757 apfst SOME (dissect_coeqn_disc ctxt fun_names sequentials basic_ctr_specss eqn_pos |
773 apfst SOME (dissect_coeqn_disc ctxt fun_names sequentials basic_ctr_specss eqn_pos |
758 (SOME (abstract (List.rev fun_args) rhs)) code_rhs_opt prems disc_concl matchedsss); |
774 (SOME (abstract_over_list fun_args rhs)) code_rhs_opt prems disc_concl matchedsss); |
759 |
775 |
760 val sel_concls = sels ~~ ctr_args |
776 val sel_concls = sels ~~ ctr_args |
761 |> map (fn (sel, ctr_arg) => HOLogic.mk_eq (betapply (sel, lhs), ctr_arg)) |
777 |> map (fn (sel, ctr_arg) => HOLogic.mk_eq (betapply (sel, lhs), ctr_arg)) |
762 handle ListPair.UnequalLengths => |
778 handle ListPair.UnequalLengths => |
763 error_at ctxt [rhs] "Partially applied constructor in right-hand side"; |
779 error_at ctxt [rhs] "Partially applied constructor in right-hand side"; |
764 |
780 |
765 val eqns_data_sel = |
781 val eqns_data_sel = |
766 map (dissect_coeqn_sel ctxt fun_names basic_ctr_specss eqn_pos |
782 map (dissect_coeqn_sel ctxt fun_names basic_ctr_specss eqn_pos |
767 (SOME (abstract (List.rev fun_args) rhs)) code_rhs_opt eqn0 (SOME ctr)) sel_concls; |
783 (SOME (abstract_over_list fun_args rhs)) code_rhs_opt eqn0 (SOME ctr)) |
|
784 sel_concls; |
768 in |
785 in |
769 (the_list eqn_data_disc_opt @ eqns_data_sel, matchedsss') |
786 (the_list eqn_data_disc_opt @ eqns_data_sel, matchedsss') |
770 end; |
787 end; |
771 |
788 |
772 fun dissect_coeqn_code ctxt has_call fun_names basic_ctr_specss eqn_pos eqn0 concl matchedsss = |
789 fun dissect_coeqn_code ctxt has_call fun_names basic_ctr_specss eqn_pos eqn0 concl matchedsss = |
796 val _ = null bads orelse unexpected_corec_call ctxt [eqn0] rhs; |
813 val _ = null bads orelse unexpected_corec_call ctxt [eqn0] rhs; |
797 |
814 |
798 val sequentials = replicate (length fun_names) false; |
815 val sequentials = replicate (length fun_names) false; |
799 in |
816 in |
800 @{fold_map 2} (dissect_coeqn_ctr ctxt fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
817 @{fold_map 2} (dissect_coeqn_ctr ctxt fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
801 (SOME (abstract (List.rev fun_args) rhs))) |
818 (SOME (abstract_over_list fun_args rhs))) |
802 ctr_premss ctr_concls matchedsss |
819 ctr_premss ctr_concls matchedsss |
803 end; |
820 end; |
804 |
821 |
805 fun dissect_coeqn ctxt has_call fun_names sequentials |
822 fun dissect_coeqn ctxt has_call fun_names sequentials |
806 (basic_ctr_specss : basic_corec_ctr_spec list list) (eqn_pos, eqn0) of_spec_opt matchedsss = |
823 (basic_ctr_specss : basic_corec_ctr_spec list list) (eqn_pos, eqn0) of_spec_opt matchedsss = |
918 if is_Free t andalso has_call t then Inr_const T U2 $ HOLogic.unit else t; |
935 if is_Free t andalso has_call t then Inr_const T U2 $ HOLogic.unit else t; |
919 in |
936 in |
920 rewrite bound_Ts t0 |
937 rewrite bound_Ts t0 |
921 end; |
938 end; |
922 |
939 |
923 fun massage_noncall bound_Ts U T t = |
940 fun massage_noncall U T t = |
924 build_map ctxt [] (uncurry Inl_const o dest_sumT o snd) (T, U) $ t; |
941 build_map ctxt [] (uncurry Inl_const o dest_sumT o snd) (T, U) $ t; |
925 |
942 |
926 val bound_Ts = List.rev (map fastype_of fun_args); |
943 val bound_Ts = List.rev (map fastype_of fun_args); |
927 in |
944 in |
928 fn t => |
945 fn t => |
929 rhs_term |
946 rhs_term |
930 |> massage_nested_corec_call ctxt has_call massage_call massage_noncall bound_Ts |
947 |> massage_nested_corec_call ctxt has_call massage_call (K massage_noncall) bound_Ts |
931 (range_type (fastype_of t)) (fastype_of1 (bound_Ts, rhs_term)) |
948 (range_type (fastype_of t)) (fastype_of1 (bound_Ts, rhs_term)) |
932 |> abs_tuple_balanced fun_args |
949 |> abs_tuple_balanced fun_args |
933 end); |
950 end); |
934 |
951 |
935 fun build_corec_args_sel ctxt has_call (all_sel_eqns : coeqn_data_sel list) |
952 fun build_corec_args_sel ctxt has_call (all_sel_eqns : coeqn_data_sel list) |
1269 val k = 1 + ctr_no; |
1286 val k = 1 + ctr_no; |
1270 val m = length prems; |
1287 val m = length prems; |
1271 val goal = |
1288 val goal = |
1272 applied_fun_of fun_name fun_T fun_args |
1289 applied_fun_of fun_name fun_T fun_args |
1273 |> curry betapply sel |
1290 |> curry betapply sel |
1274 |> rpair (abstract (List.rev fun_args) rhs_term) |
1291 |> rpair (abstract_over_list fun_args rhs_term) |
1275 |> HOLogic.mk_Trueprop o HOLogic.mk_eq |
1292 |> HOLogic.mk_Trueprop o HOLogic.mk_eq |
1276 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1293 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1277 |> curry Logic.list_all (map dest_Free fun_args); |
1294 |> curry Logic.list_all (map dest_Free fun_args); |
1278 val (distincts, _, _, split_sels, split_sel_asms) = case_thms_of_term lthy rhs_term; |
1295 val (distincts, _, _, split_sels, split_sel_asms) = case_thms_of_term lthy rhs_term; |
1279 in |
1296 in |
1312 (case ctr_rhs_opt of |
1329 (case ctr_rhs_opt of |
1313 SOME rhs => rhs |
1330 SOME rhs => rhs |
1314 | NONE => |
1331 | NONE => |
1315 filter (curry (op =) ctr o #ctr) sel_eqns |
1332 filter (curry (op =) ctr o #ctr) sel_eqns |
1316 |> fst o finds (op = o apsnd #sel) sels |
1333 |> fst o finds (op = o apsnd #sel) sels |
1317 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) #-> abstract) |
1334 |> map (snd #> (fn [x] => (#fun_args x, #rhs_term x)) |
|
1335 #-> abstract_over_list) |
1318 |> curry Term.list_comb ctr) |
1336 |> curry Term.list_comb ctr) |
1319 |> curry mk_Trueprop_eq (applied_fun_of fun_name fun_T fun_args) |
1337 |> curry mk_Trueprop_eq (applied_fun_of fun_name fun_T fun_args) |
1320 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1338 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1321 |> curry Logic.list_all (map dest_Free fun_args); |
1339 |> curry Logic.list_all (map dest_Free fun_args); |
1322 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1340 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1371 val prems = find_first (curry (op =) ctr o #ctr) disc_eqns |
1389 val prems = find_first (curry (op =) ctr o #ctr) disc_eqns |
1372 |> Option.map #prems |> the_default []; |
1390 |> Option.map #prems |> the_default []; |
1373 val t = |
1391 val t = |
1374 filter (curry (op =) ctr o #ctr) sel_eqns |
1392 filter (curry (op =) ctr o #ctr) sel_eqns |
1375 |> fst o finds (op = o apsnd #sel) sels |
1393 |> fst o finds (op = o apsnd #sel) sels |
1376 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) |
1394 |> map (snd #> (fn [x] => (#fun_args x, #rhs_term x)) |
1377 #-> abstract) |
1395 #-> abstract_over_list) |
1378 |> curry Term.list_comb ctr; |
1396 |> curry Term.list_comb ctr; |
1379 in |
1397 in |
1380 SOME (prems, t) |
1398 SOME (prems, t) |
1381 end; |
1399 end; |
1382 val ctr_conds_argss_opt = map prove_code_ctr ctr_specs; |
1400 val ctr_conds_argss_opt = map prove_code_ctr ctr_specs; |