147 let |
147 let |
148 val thy = Proof_Context.theory_of ctxt; |
148 val thy = Proof_Context.theory_of ctxt; |
149 |
149 |
150 fun fld conds t = |
150 fun fld conds t = |
151 (case Term.strip_comb t of |
151 (case Term.strip_comb t of |
152 (Const (@{const_name Let}, _), [_, _]) => fld conds (unfold_let t) |
152 (Const (@{const_name Let}, _), [_, _]) => fld conds (unfold_lets_splits t) |
153 | (Const (@{const_name If}, _), [cond, then_branch, else_branch]) => |
153 | (Const (@{const_name If}, _), [cond, then_branch, else_branch]) => |
154 fld (conds @ conjuncts_s cond) then_branch o fld (conds @ s_not_conj [cond]) else_branch |
154 fld (conds @ conjuncts_s cond) then_branch o fld (conds @ s_not_conj [cond]) else_branch |
155 | (Const (c, _), args as _ :: _ :: _) => |
155 | (Const (c, _), args as _ :: _ :: _) => |
156 let val n = num_binder_types (Sign.the_const_type thy c) - 1 in |
156 let val n = num_binder_types (Sign.the_const_type thy c) - 1 in |
157 if n >= 0 andalso n < length args then |
157 if n >= 0 andalso n < length args then |
188 Abs (Name.uu, T, massage_abs (T :: bound_Ts) (m - 1) (incr_boundvars 1 t $ Bound 0)) |
188 Abs (Name.uu, T, massage_abs (T :: bound_Ts) (m - 1) (incr_boundvars 1 t $ Bound 0)) |
189 end |
189 end |
190 and massage_rec bound_Ts t = |
190 and massage_rec bound_Ts t = |
191 let val typof = curry fastype_of1 bound_Ts in |
191 let val typof = curry fastype_of1 bound_Ts in |
192 (case Term.strip_comb t of |
192 (case Term.strip_comb t of |
193 (Const (@{const_name Let}, _), [_, _]) => massage_rec bound_Ts (unfold_let t) |
193 (Const (@{const_name Let}, _), [_, _]) => massage_rec bound_Ts (unfold_lets_splits t) |
194 | (Const (@{const_name If}, _), obj :: (branches as [_, _])) => |
194 | (Const (@{const_name If}, _), obj :: (branches as [_, _])) => |
195 let val branches' = map (massage_rec bound_Ts) branches in |
195 let val branches' = map (massage_rec bound_Ts) branches in |
196 Term.list_comb (If_const (typof (hd branches')) $ tap check_no_call obj, branches') |
196 Term.list_comb (If_const (typof (hd branches')) $ tap check_no_call obj, branches') |
197 end |
197 end |
|
198 | (c as Const (@{const_name prod_case}, _), arg :: args) => |
|
199 massage_rec bound_Ts |
|
200 (unfold_lets_splits (Term.list_comb (c $ Envir.eta_long bound_Ts arg, args))) |
198 | (Const (c, _), args as _ :: _ :: _) => |
201 | (Const (c, _), args as _ :: _ :: _) => |
199 (case try strip_fun_type (Sign.the_const_type thy c) of |
202 (case try strip_fun_type (Sign.the_const_type thy c) of |
200 SOME (gen_branch_Ts, gen_body_fun_T) => |
203 SOME (gen_branch_Ts, gen_body_fun_T) => |
201 let |
204 let |
202 val gen_branch_ms = map num_binder_types gen_branch_Ts; |
205 val gen_branch_ms = map num_binder_types gen_branch_Ts; |
637 eqn_pos eqn0 code_rhs_opt prems concl matchedsss = |
640 eqn_pos eqn0 code_rhs_opt prems concl matchedsss = |
638 let |
641 let |
639 val (lhs, rhs) = HOLogic.dest_eq concl; |
642 val (lhs, rhs) = HOLogic.dest_eq concl; |
640 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
643 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
641 val SOME basic_ctr_specs = AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name; |
644 val SOME basic_ctr_specs = AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name; |
642 val (ctr, ctr_args) = strip_comb (unfold_let rhs); |
645 val (ctr, ctr_args) = strip_comb (unfold_lets_splits rhs); |
643 val {disc, sels, ...} = the (find_first (curry (op =) ctr o #ctr) basic_ctr_specs) |
646 val {disc, sels, ...} = the (find_first (curry (op =) ctr o #ctr) basic_ctr_specs) |
644 handle Option.Option => primcorec_error_eqn "not a constructor" ctr; |
647 handle Option.Option => primcorec_error_eqn "not a constructor" ctr; |
645 |
648 |
646 val disc_concl = betapply (disc, lhs); |
649 val disc_concl = betapply (disc, lhs); |
647 val (eqn_data_disc_opt, matchedsss') = |
650 val (eqn_data_disc_opt, matchedsss') = |
683 val ctr_premss = (case cond_ctrs of [_] => [[]] | _ => map (s_dnf o snd) cond_ctrs); |
686 val ctr_premss = (case cond_ctrs of [_] => [[]] | _ => map (s_dnf o snd) cond_ctrs); |
684 val ctr_concls = cond_ctrs |> map (fn (ctr, _) => |
687 val ctr_concls = cond_ctrs |> map (fn (ctr, _) => |
685 binder_types (fastype_of ctr) |
688 binder_types (fastype_of ctr) |
686 |> map_index (fn (n, T) => massage_corec_code_rhs lthy (fn _ => fn ctr' => fn args => |
689 |> map_index (fn (n, T) => massage_corec_code_rhs lthy (fn _ => fn ctr' => fn args => |
687 if ctr' = ctr then nth args n else Const (@{const_name undefined}, T)) [] rhs') |
690 if ctr' = ctr then nth args n else Const (@{const_name undefined}, T)) [] rhs') |
688 |> curry list_comb ctr |
691 |> curry Term.list_comb ctr |
689 |> curry HOLogic.mk_eq lhs); |
692 |> curry HOLogic.mk_eq lhs); |
690 |
693 |
691 val sequentials = replicate (length fun_names) false; |
694 val sequentials = replicate (length fun_names) false; |
692 in |
695 in |
693 fold_map2 (dissect_coeqn_ctr fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
696 fold_map2 (dissect_coeqn_ctr fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
721 |>> single |
724 |>> single |
722 else if member (op =) sels head then |
725 else if member (op =) sels head then |
723 ([dissect_coeqn_sel fun_names basic_ctr_specss eqn_pos NONE NONE eqn0 of_spec_opt concl], |
726 ([dissect_coeqn_sel fun_names basic_ctr_specss eqn_pos NONE NONE eqn0 of_spec_opt concl], |
724 matchedsss) |
727 matchedsss) |
725 else if is_Free head andalso member (op =) fun_names (fst (dest_Free head)) then |
728 else if is_Free head andalso member (op =) fun_names (fst (dest_Free head)) then |
726 if member (op =) ctrs (head_of (unfold_let (the rhs_opt))) then |
729 if member (op =) ctrs (head_of (unfold_lets_splits (the rhs_opt))) then |
727 dissect_coeqn_ctr fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
730 dissect_coeqn_ctr fun_names sequentials basic_ctr_specss eqn_pos eqn0 |
728 (if null prems then |
731 (if null prems then |
729 SOME (snd (HOLogic.dest_eq (HOLogic.dest_Trueprop (Logic.strip_assums_concl eqn0)))) |
732 SOME (snd (HOLogic.dest_eq (HOLogic.dest_Trueprop (Logic.strip_assums_concl eqn0)))) |
730 else |
733 else |
731 NONE) |
734 NONE) |
780 | rewrite bound_Ts (t as _ $ _) = |
783 | rewrite bound_Ts (t as _ $ _) = |
781 let val (u, vs) = strip_comb t in |
784 let val (u, vs) = strip_comb t in |
782 if is_Free u andalso has_call u then |
785 if is_Free u andalso has_call u then |
783 Inr_const U T $ mk_tuple1 bound_Ts vs |
786 Inr_const U T $ mk_tuple1 bound_Ts vs |
784 else if try (fst o dest_Const) u = SOME @{const_name prod_case} then |
787 else if try (fst o dest_Const) u = SOME @{const_name prod_case} then |
785 map (rewrite bound_Ts) vs |> chop 1 |>> HOLogic.mk_split o the_single |> list_comb |
788 map (rewrite bound_Ts) vs |> chop 1 |
|
789 |>> HOLogic.mk_split o the_single |
|
790 |> Term.list_comb |
786 else |
791 else |
787 list_comb (rewrite bound_Ts u, map (rewrite bound_Ts) vs) |
792 Term.list_comb (rewrite bound_Ts u, map (rewrite bound_Ts) vs) |
788 end |
793 end |
789 | rewrite _ t = |
794 | rewrite _ t = |
790 if is_Free t andalso has_call t then Inr_const U T $ HOLogic.unit else t; |
795 if is_Free t andalso has_call t then Inr_const U T $ HOLogic.unit else t; |
791 in |
796 in |
792 rewrite bound_Ts |
797 rewrite bound_Ts |
852 ((c, c', a orelse a'), (x, s_not (s_conjs y))) |
857 ((c, c', a orelse a'), (x, s_not (s_conjs y))) |
853 ||> apfst (map HOLogic.mk_Trueprop) o apsnd HOLogic.mk_Trueprop |
858 ||> apfst (map HOLogic.mk_Trueprop) o apsnd HOLogic.mk_Trueprop |
854 ||> Logic.list_implies |
859 ||> Logic.list_implies |
855 ||> curry Logic.list_all (map dest_Free fun_args)))); |
860 ||> curry Logic.list_all (map dest_Free fun_args)))); |
856 in |
861 in |
857 map (list_comb o rpair corec_args) corecs |
862 map (Term.list_comb o rpair corec_args) corecs |
858 |> map2 (fn Ts => fn t => if length Ts = 0 then t $ HOLogic.unit else t) arg_Tss |
863 |> map2 (fn Ts => fn t => if length Ts = 0 then t $ HOLogic.unit else t) arg_Tss |
859 |> map2 currys arg_Tss |
864 |> map2 currys arg_Tss |
860 |> Syntax.check_terms lthy |
865 |> Syntax.check_terms lthy |
861 |> map3 (fn b => fn mx => fn t => ((b, mx), ((Binding.conceal (Thm.def_binding b), []), t))) |
866 |> map3 (fn b => fn mx => fn t => ((b, mx), ((Binding.conceal (Thm.def_binding b), []), t))) |
862 bs mxs |
867 bs mxs |
903 K (if has_call rhs_term then fold_rev_let_if_case ctxt (K cons) [] rhs_term [] else []) |
908 K (if has_call rhs_term then fold_rev_let_if_case ctxt (K cons) [] rhs_term [] else []) |
904 |> nth_map sel_no |> AList.map_entry (op =) ctr |
909 |> nth_map sel_no |> AList.map_entry (op =) ctr |
905 end; |
910 end; |
906 |
911 |
907 fun applied_fun_of fun_name fun_T fun_args = |
912 fun applied_fun_of fun_name fun_T fun_args = |
908 list_comb (Free (fun_name, fun_T), map Bound (length fun_args - 1 downto 0)); |
913 Term.list_comb (Free (fun_name, fun_T), map Bound (length fun_args - 1 downto 0)); |
909 |
914 |
910 fun is_trivial_implies thm = |
915 fun is_trivial_implies thm = |
911 uncurry (member (op aconv)) (Logic.strip_horn (Thm.prop_of thm)); |
916 uncurry (member (op aconv)) (Logic.strip_horn (Thm.prop_of thm)); |
912 |
917 |
913 fun add_primcorec_ursive auto opts fixes specs of_specs_opt lthy = |
918 fun add_primcorec_ursive auto opts fixes specs of_specs_opt lthy = |
1162 SOME rhs => rhs |
1167 SOME rhs => rhs |
1163 | NONE => |
1168 | NONE => |
1164 filter (curry (op =) ctr o #ctr) sel_eqns |
1169 filter (curry (op =) ctr o #ctr) sel_eqns |
1165 |> fst o finds (op = o apsnd #sel) sels |
1170 |> fst o finds (op = o apsnd #sel) sels |
1166 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) #-> abstract) |
1171 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) #-> abstract) |
1167 |> curry list_comb ctr) |
1172 |> curry Term.list_comb ctr) |
1168 |> curry mk_Trueprop_eq (applied_fun_of fun_name fun_T fun_args) |
1173 |> curry mk_Trueprop_eq (applied_fun_of fun_name fun_T fun_args) |
1169 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1174 |> curry Logic.list_implies (map HOLogic.mk_Trueprop prems) |
1170 |> curry Logic.list_all (map dest_Free fun_args); |
1175 |> curry Logic.list_all (map dest_Free fun_args); |
1171 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1176 val disc_thm_opt = AList.lookup (op =) disc_alist disc; |
1172 val sel_thms = map snd (filter (member (op =) sels o fst) sel_alist); |
1177 val sel_thms = map snd (filter (member (op =) sels o fst) sel_alist); |
1217 val t = |
1222 val t = |
1218 filter (curry (op =) ctr o #ctr) sel_eqns |
1223 filter (curry (op =) ctr o #ctr) sel_eqns |
1219 |> fst o finds (op = o apsnd #sel) sels |
1224 |> fst o finds (op = o apsnd #sel) sels |
1220 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) |
1225 |> map (snd #> (fn [x] => (List.rev (#fun_args x), #rhs_term x)) |
1221 #-> abstract) |
1226 #-> abstract) |
1222 |> curry list_comb ctr; |
1227 |> curry Term.list_comb ctr; |
1223 in |
1228 in |
1224 SOME (prems, t) |
1229 SOME (prems, t) |
1225 end; |
1230 end; |
1226 val ctr_conds_argss_opt = map prove_code_ctr ctr_specs; |
1231 val ctr_conds_argss_opt = map prove_code_ctr ctr_specs; |
1227 val exhaustive_code = |
1232 val exhaustive_code = |