src/HOL/Tools/BNF/bnf_gfp_rec_sugar.ML
changeset 55343 5ebf832b58a1
parent 55342 1bd9e637ac9f
child 55344 a593712f6878
equal deleted inserted replaced
55342:1bd9e637ac9f 55343:5ebf832b58a1
   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 =