src/HOL/Tools/BNF/bnf_gfp_rec_sugar.ML
changeset 60704 fdd965b35bcd
parent 60683 d34e1b0b331a
child 60718 b88a1279c8ea
equal deleted inserted replaced
60703:8963331cc0de 60704:fdd965b35bcd
    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;