82 val selN = "sel"; |
82 val selN = "sel"; |
83 |
83 |
84 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
84 val nitpicksimp_attrs = @{attributes [nitpick_simp]}; |
85 val simp_attrs = @{attributes [simp]}; |
85 val simp_attrs = @{attributes [simp]}; |
86 |
86 |
|
87 fun extra_variable ctxt ts var = |
|
88 error_at ctxt ts ("Extra variable " ^ quote (Syntax.string_of_term ctxt var)); |
87 fun not_codatatype ctxt T = |
89 fun not_codatatype ctxt T = |
88 error ("Not a codatatype: " ^ Syntax.string_of_typ ctxt T); |
90 error ("Not a codatatype: " ^ Syntax.string_of_typ ctxt T); |
89 fun ill_formed_corec_call ctxt t = |
91 fun ill_formed_corec_call ctxt t = |
90 error ("Ill-formed corecursive call " ^ quote (Syntax.string_of_term ctxt t)); |
92 error ("Ill-formed corecursive call " ^ quote (Syntax.string_of_term ctxt t)); |
91 fun invalid_map ctxt t = |
93 fun invalid_map ctxt t = |
581 Sel of coeqn_data_sel; |
583 Sel of coeqn_data_sel; |
582 |
584 |
583 fun is_free_in frees (Free (v, _)) = member (op =) frees v |
585 fun is_free_in frees (Free (v, _)) = member (op =) frees v |
584 | is_free_in _ _ = false; |
586 | is_free_in _ _ = false; |
585 |
587 |
586 fun check_extra_variables ctxt vars names eqn = |
588 fun add_extra_frees ctxt frees names = |
587 let val b = fold_aterms (fn x as Free (v, _) => |
589 fold_aterms (fn x as Free (v, _) => |
588 if (not (member (op =) vars x) andalso |
590 (not (member (op =) frees x) andalso not (member (op =) names v) andalso |
589 not (member (op =) names v) andalso |
591 not (Variable.is_fixed ctxt v) andalso v <> Name.uu_) |
590 v <> Name.uu_ andalso |
592 ? cons x | _ => I); |
591 not (Variable.is_fixed ctxt v)) then cons x else I | _ => I) eqn [] |
593 |
592 in |
594 fun check_extra_frees ctxt frees names t = |
593 null b orelse error_at ctxt [eqn] |
595 let val bads = add_extra_frees ctxt frees names t [] in |
594 ("Extra variable " ^ quote (Syntax.string_of_term ctxt (hd b))) |
596 null bads orelse extra_variable ctxt [t] (hd bads) |
595 end; |
597 end; |
596 |
598 |
597 fun dissect_coeqn_disc ctxt fun_names sequentials |
599 fun dissect_coeqn_disc ctxt fun_names sequentials |
598 (basic_ctr_specss : basic_corec_ctr_spec list list) eqn_pos ctr_rhs_opt code_rhs_opt prems0 |
600 (basic_ctr_specss : basic_corec_ctr_spec list list) eqn_pos ctr_rhs_opt code_rhs_opt prems0 |
599 concl matchedsss = |
601 concl matchedsss = |
663 val user_eqn = |
665 val user_eqn = |
664 (actual_prems, concl) |
666 (actual_prems, concl) |
665 |>> map HOLogic.mk_Trueprop ||> HOLogic.mk_Trueprop o abstract (List.rev fun_args) |
667 |>> map HOLogic.mk_Trueprop ||> HOLogic.mk_Trueprop o abstract (List.rev fun_args) |
666 |> curry Logic.list_all (map dest_Free fun_args) o Logic.list_implies; |
668 |> curry Logic.list_all (map dest_Free fun_args) o Logic.list_implies; |
667 |
669 |
668 val _ = check_extra_variables ctxt fun_args fun_names user_eqn; |
670 val _ = check_extra_frees ctxt fun_args fun_names user_eqn; |
669 in |
671 in |
670 (Disc {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, ctr_no = ctr_no, |
672 (Disc {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, ctr_no = ctr_no, |
671 disc = disc, prems = actual_prems, auto_gen = catch_all, ctr_rhs_opt = ctr_rhs_opt, |
673 disc = disc, prems = actual_prems, auto_gen = catch_all, ctr_rhs_opt = ctr_rhs_opt, |
672 code_rhs_opt = code_rhs_opt, eqn_pos = eqn_pos, user_eqn = user_eqn}, |
674 code_rhs_opt = code_rhs_opt, eqn_pos = eqn_pos, user_eqn = user_eqn}, |
673 matchedsss') |
675 matchedsss') |
694 SOME of_spec => the (find_first (curry (op =) of_spec o #ctr) basic_ctr_specs) |
696 SOME of_spec => the (find_first (curry (op =) of_spec o #ctr) basic_ctr_specs) |
695 | NONE => filter (exists (curry (op =) sel) o #sels) basic_ctr_specs |> the_single |
697 | NONE => filter (exists (curry (op =) sel) o #sels) basic_ctr_specs |> the_single |
696 handle List.Empty => error_at ctxt [eqn] "Ambiguous selector (without \"of\")"); |
698 handle List.Empty => error_at ctxt [eqn] "Ambiguous selector (without \"of\")"); |
697 val user_eqn = drop_all eqn0; |
699 val user_eqn = drop_all eqn0; |
698 |
700 |
699 val _ = check_extra_variables ctxt fun_args fun_names user_eqn; |
701 val _ = check_extra_frees ctxt fun_args fun_names user_eqn; |
700 in |
702 in |
701 Sel {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, sel = sel, |
703 Sel {fun_name = fun_name, fun_T = fun_T, fun_args = fun_args, ctr = ctr, sel = sel, |
702 rhs_term = rhs, ctr_rhs_opt = ctr_rhs_opt, code_rhs_opt = code_rhs_opt, eqn_pos = eqn_pos, |
704 rhs_term = rhs, ctr_rhs_opt = ctr_rhs_opt, code_rhs_opt = code_rhs_opt, eqn_pos = eqn_pos, |
703 user_eqn = user_eqn} |
705 user_eqn = user_eqn} |
704 end; |
706 end; |
707 eqn_pos eqn0 code_rhs_opt prems concl matchedsss = |
709 eqn_pos eqn0 code_rhs_opt prems concl matchedsss = |
708 let |
710 let |
709 val (lhs, rhs) = HOLogic.dest_eq concl; |
711 val (lhs, rhs) = HOLogic.dest_eq concl; |
710 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
712 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
711 |
713 |
712 val _ = check_extra_variables ctxt fun_args fun_names (drop_all eqn0); |
714 val _ = check_extra_frees ctxt fun_args fun_names (drop_all eqn0); |
713 |
715 |
714 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name); |
716 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name); |
715 val (ctr, ctr_args) = strip_comb (unfold_lets_splits rhs); |
717 val (ctr, ctr_args) = strip_comb (unfold_lets_splits rhs); |
716 val {disc, sels, ...} = the (find_first (curry (op =) ctr o #ctr) basic_ctr_specs) |
718 val {disc, sels, ...} = the (find_first (curry (op =) ctr o #ctr) basic_ctr_specs) |
717 handle Option.Option => error_at ctxt [ctr] "Not a constructor"; |
719 handle Option.Option => error_at ctxt [ctr] "Not a constructor"; |
739 fun dissect_coeqn_code ctxt has_call fun_names basic_ctr_specss eqn_pos eqn0 concl matchedsss = |
741 fun dissect_coeqn_code ctxt has_call fun_names basic_ctr_specss eqn_pos eqn0 concl matchedsss = |
740 let |
742 let |
741 val (lhs, (rhs', rhs)) = HOLogic.dest_eq concl ||> `(expand_corec_code_rhs ctxt has_call []); |
743 val (lhs, (rhs', rhs)) = HOLogic.dest_eq concl ||> `(expand_corec_code_rhs ctxt has_call []); |
742 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
744 val (fun_name, fun_args) = strip_comb lhs |>> fst o dest_Free; |
743 |
745 |
744 val _ = check_extra_variables ctxt fun_args fun_names concl; |
746 val _ = check_extra_frees ctxt fun_args fun_names concl; |
745 |
747 |
746 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name); |
748 val basic_ctr_specs = the (AList.lookup (op =) (fun_names ~~ basic_ctr_specss) fun_name); |
747 |
749 |
748 val cond_ctrs = fold_rev_corec_code_rhs ctxt (fn cs => fn ctr => fn _ => |
750 val cond_ctrs = fold_rev_corec_code_rhs ctxt (fn cs => fn ctr => fn _ => |
749 if member (op = o apsnd #ctr) basic_ctr_specs ctr then cons (ctr, cs) |
751 if member (op = o apsnd #ctr) basic_ctr_specs ctr then cons (ctr, cs) |
913 if range_type T = HOLogic.boolT then Abs (Name.uu_, domain_type T, @{term False}) |
915 if range_type T = HOLogic.boolT then Abs (Name.uu_, domain_type T, @{term False}) |
914 else Const (@{const_name undefined}, T)) |
916 else Const (@{const_name undefined}, T)) |
915 |> fold2 (fold o build_corec_arg_disc) ctr_specss disc_eqnss |
917 |> fold2 (fold o build_corec_arg_disc) ctr_specss disc_eqnss |
916 |> fold2 (fold o build_corec_args_sel ctxt has_call) sel_eqnss ctr_specss; |
918 |> fold2 (fold o build_corec_args_sel ctxt has_call) sel_eqnss ctr_specss; |
917 |
919 |
|
920 val bad = fold (add_extra_frees ctxt [] []) corec_args []; |
|
921 val _ = null bad orelse |
|
922 (if exists has_call corec_args then nonprimitive_corec ctxt [] |
|
923 else extra_variable ctxt [] (hd bad)); |
|
924 |
918 fun currys [] t = t |
925 fun currys [] t = t |
919 | currys Ts t = t $ mk_tuple1_balanced (List.rev Ts) (map Bound (length Ts - 1 downto 0)) |
926 | currys Ts t = t $ mk_tuple1_balanced (List.rev Ts) (map Bound (length Ts - 1 downto 0)) |
920 |> fold_rev (Term.abs o pair Name.uu) Ts; |
927 |> fold_rev (Term.abs o pair Name.uu) Ts; |
921 |
928 |
922 val excludess' = |
929 val excludess' = |
1052 |> map (the o #ctr_rhs_opt)) |
1059 |> map (the o #ctr_rhs_opt)) |
1053 "Multiple equations for same constructor" |
1060 "Multiple equations for same constructor" |
1054 else |
1061 else |
1055 error_at lthy |
1062 error_at lthy |
1056 (maps (fn t => filter (curry (op =) (#ctr_no t) o #ctr_no) x) d |> map #user_eqn) |
1063 (maps (fn t => filter (curry (op =) (#ctr_no t) o #ctr_no) x) d |> map #user_eqn) |
1057 "Excess discriminator formula in definition") |
1064 "Extra discriminator formula in definition") |
1058 end); |
1065 end); |
1059 |
1066 |
1060 val sel_eqnss = map_filter (try (fn Sel x => x)) eqns_data |
1067 val sel_eqnss = map_filter (try (fn Sel x => x)) eqns_data |
1061 |> partition_eq (op = o apply2 #fun_name) |
1068 |> partition_eq (op = o apply2 #fun_name) |
1062 |> fst o finds (fn (x, ({fun_name, ...} :: _)) => x = fun_name) fun_names |
1069 |> fst o finds (fn (x, ({fun_name, ...} :: _)) => x = fun_name) fun_names |