src/HOL/Tools/BNF/bnf_lfp_compat.ML
changeset 58125 a2ba381607fb
parent 58123 62765d39539f
child 58126 3831312eb476
equal deleted inserted replaced
58124:c60617a84c1d 58125:a2ba381607fb
     8     Author:     Stefan Berghofer, TU Muenchen
     8     Author:     Stefan Berghofer, TU Muenchen
     9 *)
     9 *)
    10 
    10 
    11 signature BNF_LFP_COMPAT =
    11 signature BNF_LFP_COMPAT =
    12 sig
    12 sig
    13   datatype nesting_mode = Keep_Nesting | Unfold_Nesting_if_Possible | Always_Unfold_Nesting
    13   datatype nesting_preference = Keep_Nesting | Unfold_Nesting
    14 
    14 
    15   val get_all: theory -> nesting_mode -> Old_Datatype_Aux.info Symtab.table
    15   val get_all: theory -> nesting_preference -> Old_Datatype_Aux.info Symtab.table
    16   val get_info: theory -> nesting_mode -> string -> Old_Datatype_Aux.info option
    16   val get_info: theory -> nesting_preference -> string -> Old_Datatype_Aux.info option
    17   val the_info: theory -> nesting_mode -> string -> Old_Datatype_Aux.info
    17   val the_info: theory -> nesting_preference -> string -> Old_Datatype_Aux.info
    18   val the_spec: theory -> nesting_mode -> string -> (string * sort) list * (string * typ list) list
    18   val the_spec: theory -> nesting_preference -> string ->
    19   val the_descr: theory -> nesting_mode -> string list ->
    19     (string * sort) list * (string * typ list) list
       
    20   val the_descr: theory -> nesting_preference -> string list ->
    20     Old_Datatype_Aux.descr * (string * sort) list * string list * string
    21     Old_Datatype_Aux.descr * (string * sort) list * string list * string
    21     * (string list * string list) * (typ list * typ list)
    22     * (string list * string list) * (typ list * typ list)
    22   val get_constrs: theory -> nesting_mode -> string -> (string * typ) list option
    23   val get_constrs: theory -> nesting_preference -> string -> (string * typ) list option
    23   val interpretation: nesting_mode ->
    24   val interpretation: nesting_preference ->
    24     (Old_Datatype_Aux.config -> string list -> theory -> theory) -> theory -> theory
    25     (Old_Datatype_Aux.config -> string list -> theory -> theory) -> theory -> theory
       
    26   val datatype_compat: string list -> local_theory -> local_theory
       
    27   val datatype_compat_global: string list -> theory -> theory
    25   val datatype_compat_cmd: string list -> local_theory -> local_theory
    28   val datatype_compat_cmd: string list -> local_theory -> local_theory
    26   val add_datatype: nesting_mode -> Old_Datatype_Aux.spec list -> theory -> string list * theory
    29   val add_datatype: nesting_preference -> Old_Datatype_Aux.spec list -> theory ->
       
    30     string list * theory
    27 end;
    31 end;
    28 
    32 
    29 structure BNF_LFP_Compat : BNF_LFP_COMPAT =
    33 structure BNF_LFP_Compat : BNF_LFP_COMPAT =
    30 struct
    34 struct
    31 
    35 
    36 open BNF_FP_N2M_Sugar
    40 open BNF_FP_N2M_Sugar
    37 open BNF_LFP
    41 open BNF_LFP
    38 
    42 
    39 val compatN = "compat_";
    43 val compatN = "compat_";
    40 
    44 
    41 datatype nesting_mode = Keep_Nesting | Unfold_Nesting_if_Possible | Always_Unfold_Nesting;
    45 datatype nesting_preference = Keep_Nesting | Unfold_Nesting;
    42 
    46 
    43 fun reindex_desc desc =
    47 fun reindex_desc desc =
    44   let
    48   let
    45     val kks = map fst desc;
    49     val kks = map fst desc;
    46     val perm_kks = sort int_ord kks;
    50     val perm_kks = sort int_ord kks;
    55     else
    59     else
    56       perm_kks ~~
    60       perm_kks ~~
    57       map (fn (_, (s, Ds, sDss)) => (s, map perm_dtyp Ds, map (apsnd (map perm_dtyp)) sDss)) desc
    61       map (fn (_, (s, Ds, sDss)) => (s, map perm_dtyp Ds, map (apsnd (map perm_dtyp)) sDss)) desc
    58   end;
    62   end;
    59 
    63 
    60 fun mk_infos_of_mutually_recursive_new_datatypes nesting_mode need_co_inducts_recs check_names
    64 fun mk_infos_of_mutually_recursive_new_datatypes nesting_pref need_co_inducts_recs check_names
    61     raw_fpT_names0 lthy =
    65     fpT_names0 lthy =
    62   let
    66   let
    63     val thy = Proof_Context.theory_of lthy;
    67     val thy = Proof_Context.theory_of lthy;
    64 
    68 
    65     fun not_datatype s = error (quote s ^ " is not a new-style datatype");
    69     fun not_datatype s = error (quote s ^ " is not a new-style datatype");
    66     fun not_mutually_recursive ss =
    70     fun not_mutually_recursive ss =
    67       error ("{" ^ commas ss ^ "} is not a complete set of mutually recursive new-style datatypes");
    71       error ("{" ^ commas ss ^ "} is not a complete set of mutually recursive new-style datatypes");
    68 
       
    69     val fpT_names0 =
       
    70       map (fst o dest_Type o Proof_Context.read_type_name {proper = true, strict = false} lthy)
       
    71         raw_fpT_names0;
       
    72 
    72 
    73     fun lfp_sugar_of s =
    73     fun lfp_sugar_of s =
    74       (case fp_sugar_of lthy s of
    74       (case fp_sugar_of lthy s of
    75         SOME (fp_sugar as {fp = Least_FP, ...}) => fp_sugar
    75         SOME (fp_sugar as {fp = Least_FP, ...}) => fp_sugar
    76       | _ => not_datatype s);
    76       | _ => not_datatype s);
    94 
    94 
    95     val fp_ctr_sugars = map (#ctr_sugar o lfp_sugar_of) fpT_names;
    95     val fp_ctr_sugars = map (#ctr_sugar o lfp_sugar_of) fpT_names;
    96     val orig_descr = map3 mk_typ_descr (0 upto nn_fp - 1) fpTs fp_ctr_sugars;
    96     val orig_descr = map3 mk_typ_descr (0 upto nn_fp - 1) fpTs fp_ctr_sugars;
    97     val all_infos = Old_Datatype_Data.get_all thy;
    97     val all_infos = Old_Datatype_Data.get_all thy;
    98     val (orig_descr' :: nested_descrs) =
    98     val (orig_descr' :: nested_descrs) =
    99       if nesting_mode = Keep_Nesting then
    99       if nesting_pref = Keep_Nesting then [orig_descr]
   100         [orig_descr]
   100       else fst (Old_Datatype_Aux.unfold_datatypes lthy orig_descr all_infos orig_descr nn_fp);
   101       else
       
   102         fst (Old_Datatype_Aux.unfold_datatypes lthy orig_descr all_infos orig_descr nn_fp);
       
   103 
   101 
   104     fun cliquify_descr [] = []
   102     fun cliquify_descr [] = []
   105       | cliquify_descr [entry] = [[entry]]
   103       | cliquify_descr [entry] = [[entry]]
   106       | cliquify_descr (full_descr as (_, (T_name1, _, _)) :: _) =
   104       | cliquify_descr (full_descr as (_, (T_name1, _, _)) :: _) =
   107         let
   105         let
   170     val infos = map_index mk_info (take nn_fp fp_sugars);
   168     val infos = map_index mk_info (take nn_fp fp_sugars);
   171   in
   169   in
   172     (nn, b_names, compat_b_names, lfp_sugar_thms, infos, lthy')
   170     (nn, b_names, compat_b_names, lfp_sugar_thms, infos, lthy')
   173   end;
   171   end;
   174 
   172 
   175 fun infos_of_new_datatype_mutual_cluster lthy nesting_mode raw_fpt_names01 =
   173 fun infos_of_new_datatype_mutual_cluster lthy nesting_pref fpT_name =
   176   mk_infos_of_mutually_recursive_new_datatypes nesting_mode false subset [raw_fpt_names01] lthy
   174   let
   177   |> #5;
   175     fun infos_of nesting_pref =
   178 
   176       #5 (mk_infos_of_mutually_recursive_new_datatypes nesting_pref false subset [fpT_name] lthy);
   179 fun get_all thy nesting_mode =
   177   in
       
   178     infos_of nesting_pref
       
   179     handle ERROR _ => if nesting_pref = Unfold_Nesting then infos_of Keep_Nesting else []
       
   180   end;
       
   181 
       
   182 fun get_all thy nesting_pref =
   180   let
   183   let
   181     val lthy = Named_Target.theory_init thy;
   184     val lthy = Named_Target.theory_init thy;
   182     val old_info_tab = Old_Datatype_Data.get_all thy;
   185     val old_info_tab = Old_Datatype_Data.get_all thy;
   183     val new_T_names = BNF_FP_Def_Sugar.fp_sugars_of_global thy
   186     val new_T_names = BNF_FP_Def_Sugar.fp_sugars_of_global thy
   184       |> map_filter (try (fn {T = Type (s, _), fp_res_index = 0, ...} => s));
   187       |> map_filter (try (fn {T = Type (s, _), fp_res_index = 0, ...} => s));
   185     val new_infos = maps (infos_of_new_datatype_mutual_cluster lthy nesting_mode) new_T_names;
   188     val new_infos = maps (infos_of_new_datatype_mutual_cluster lthy nesting_pref) new_T_names;
   186   in
   189   in
   187     fold (if nesting_mode = Keep_Nesting then Symtab.update else Symtab.default) new_infos
   190     fold (if nesting_pref = Keep_Nesting then Symtab.update else Symtab.default) new_infos
   188       old_info_tab
   191       old_info_tab
   189   end;
   192   end;
   190 
   193 
   191 fun get_one get_old get_new thy nesting_mode x =
   194 fun get_one get_old get_new thy nesting_pref x =
   192   let
   195   let
   193     val (get_fst, get_snd) =
   196     val (get_fst, get_snd) =
   194       (get_old thy, get_new thy nesting_mode) |> nesting_mode = Keep_Nesting ? swap
   197       (get_old thy, get_new thy nesting_pref) |> nesting_pref = Keep_Nesting ? swap
   195   in
   198   in
   196     (case get_fst x of NONE => get_snd x | res => res)
   199     (case get_fst x of NONE => get_snd x | res => res)
   197   end;
   200   end;
   198 
   201 
   199 fun get_info_of_new_datatype thy nesting_mode T_name =
   202 fun get_info_of_new_datatype thy nesting_pref T_name =
   200   let val lthy = Named_Target.theory_init thy in
   203   let val lthy = Named_Target.theory_init thy in
   201     AList.lookup (op =) (infos_of_new_datatype_mutual_cluster lthy nesting_mode T_name) T_name
   204     AList.lookup (op =) (infos_of_new_datatype_mutual_cluster lthy nesting_pref T_name) T_name
   202   end;
   205   end;
   203 
   206 
   204 val get_info = get_one Old_Datatype_Data.get_info get_info_of_new_datatype;
   207 val get_info = get_one Old_Datatype_Data.get_info get_info_of_new_datatype;
   205 
   208 
   206 fun the_info thy nesting_mode T_name =
   209 fun the_info thy nesting_pref T_name =
   207   (case get_info thy nesting_mode T_name of
   210   (case get_info thy nesting_pref T_name of
   208     SOME info => info
   211     SOME info => info
   209   | NONE => error ("Unknown datatype " ^ quote T_name));
   212   | NONE => error ("Unknown datatype " ^ quote T_name));
   210 
   213 
   211 fun the_spec thy nesting_mode T_name =
   214 fun the_spec thy nesting_pref T_name =
   212   let
   215   let
   213     val {descr, index, ...} = the_info thy nesting_mode T_name;
   216     val {descr, index, ...} = the_info thy nesting_pref T_name;
   214     val (_, Ds, ctrs0) = the (AList.lookup (op =) descr index);
   217     val (_, Ds, ctrs0) = the (AList.lookup (op =) descr index);
   215     val Ts = map Old_Datatype_Aux.dest_DtTFree Ds;
   218     val Ts = map Old_Datatype_Aux.dest_DtTFree Ds;
   216     val ctrs = map (apsnd (map (Old_Datatype_Aux.typ_of_dtyp descr))) ctrs0;
   219     val ctrs = map (apsnd (map (Old_Datatype_Aux.typ_of_dtyp descr))) ctrs0;
   217   in (Ts, ctrs) end;
   220   in (Ts, ctrs) end;
   218 
   221 
   219 fun the_descr thy nesting_mode (T_names0 as T_name01 :: _) =
   222 fun the_descr thy nesting_pref (T_names0 as T_name01 :: _) =
   220   let
   223   let
   221     fun not_mutually_recursive ss =
   224     fun not_mutually_recursive ss =
   222       error ("{" ^ commas ss ^ "} is not a complete set of mutually recursive datatypes");
   225       error ("{" ^ commas ss ^ "} is not a complete set of mutually recursive datatypes");
   223 
   226 
   224     val info = the_info thy nesting_mode T_name01;
   227     val info = the_info thy nesting_pref T_name01;
   225     val descr = #descr info;
   228     val descr = #descr info;
   226 
   229 
   227     val (_, Ds, _) = the (AList.lookup (op =) descr (#index info));
   230     val (_, Ds, _) = the (AList.lookup (op =) descr (#index info));
   228     val vs = map Old_Datatype_Aux.dest_DtTFree Ds;
   231     val vs = map Old_Datatype_Aux.dest_DtTFree Ds;
   229 
   232 
   246     val prefix = space_implode "_" names;
   249     val prefix = space_implode "_" names;
   247   in
   250   in
   248     (descr, vs, T_names, prefix, (names, auxnames), (Ts, Us))
   251     (descr, vs, T_names, prefix, (names, auxnames), (Ts, Us))
   249   end;
   252   end;
   250 
   253 
   251 fun get_constrs thy nesting_mode T_name =
   254 fun get_constrs thy nesting_pref T_name =
   252   try (the_spec thy nesting_mode) T_name
   255   try (the_spec thy nesting_pref) T_name
   253   |> Option.map (fn (tfrees, ctrs) =>
   256   |> Option.map (fn (tfrees, ctrs) =>
   254     let
   257     let
   255       fun varify_tfree (s, S) = TVar ((s, 0), S);
   258       fun varify_tfree (s, S) = TVar ((s, 0), S);
   256       fun varify_typ (TFree x) = varify_tfree x
   259       fun varify_typ (TFree x) = varify_tfree x
   257         | varify_typ T = T;
   260         | varify_typ T = T;
   261       fun mk_ctr_typ Ts = map (Term.map_atyps varify_typ) Ts ---> dataT;
   264       fun mk_ctr_typ Ts = map (Term.map_atyps varify_typ) Ts ---> dataT;
   262     in
   265     in
   263       map (apsnd mk_ctr_typ) ctrs
   266       map (apsnd mk_ctr_typ) ctrs
   264     end);
   267     end);
   265 
   268 
   266 fun old_interpretation_of nesting_mode f config T_names thy =
   269 fun old_interpretation_of nesting_pref f config T_names thy =
   267   if nesting_mode <> Keep_Nesting orelse exists (is_none o fp_sugar_of_global thy) T_names then
   270   if nesting_pref = Unfold_Nesting orelse exists (is_none o fp_sugar_of_global thy) T_names then
   268     f config T_names thy
   271     f config T_names thy
   269   else
   272   else
   270     thy;
   273     thy;
   271 
   274 
   272 fun new_interpretation_of nesting_mode f fp_sugars thy =
   275 fun new_interpretation_of nesting_pref f fp_sugars thy =
   273   let val T_names = map (fst o dest_Type o #T) fp_sugars in
   276   let val T_names = map (fst o dest_Type o #T) fp_sugars in
   274     if nesting_mode = Keep_Nesting orelse
   277     if nesting_pref = Keep_Nesting orelse
   275         exists (is_none o Old_Datatype_Data.get_info thy) T_names then
   278         exists (is_none o Old_Datatype_Data.get_info thy) T_names then
   276       f Old_Datatype_Aux.default_config T_names thy
   279       f Old_Datatype_Aux.default_config T_names thy
   277     else
   280     else
   278       thy
   281       thy
   279   end;
   282   end;
   280 
   283 
   281 fun interpretation nesting_mode f =
   284 fun interpretation nesting_pref f =
   282   Old_Datatype_Data.interpretation (old_interpretation_of nesting_mode f)
   285   Old_Datatype_Data.interpretation (old_interpretation_of nesting_pref f)
   283   #> fp_sugar_interpretation (new_interpretation_of nesting_mode f);
   286   #> fp_sugar_interpretation (new_interpretation_of nesting_pref f);
   284 
   287 
   285 val code_nitpicksimp_simp_attrs = Code.add_default_eqn_attrib :: @{attributes [nitpick_simp, simp]};
   288 val code_nitpicksimp_simp_attrs = Code.add_default_eqn_attrib :: @{attributes [nitpick_simp, simp]};
   286 
   289 
   287 fun datatype_compat_cmd fpT_names lthy =
   290 fun datatype_compat fpT_names lthy =
   288   let
   291   let
   289     val (nn, b_names, compat_b_names, lfp_sugar_thms, infos, lthy') =
   292     val (nn, b_names, compat_b_names, lfp_sugar_thms, infos, lthy') =
   290       mk_infos_of_mutually_recursive_new_datatypes Unfold_Nesting_if_Possible true eq_set fpT_names
   293       mk_infos_of_mutually_recursive_new_datatypes Unfold_Nesting true eq_set fpT_names lthy;
   291         lthy;
       
   292 
   294 
   293     val all_notes =
   295     val all_notes =
   294       (case lfp_sugar_thms of
   296       (case lfp_sugar_thms of
   295         NONE => []
   297         NONE => []
   296       | SOME ((induct_thms, induct_thm, induct_attrs), (rec_thmss, _)) =>
   298       | SOME ((induct_thms, induct_thm, induct_attrs), (rec_thmss, _)) =>
   326     |> Local_Theory.raw_theory register_interpret
   328     |> Local_Theory.raw_theory register_interpret
   327     |> Local_Theory.notes all_notes
   329     |> Local_Theory.notes all_notes
   328     |> snd
   330     |> snd
   329   end;
   331   end;
   330 
   332 
   331 fun add_datatype nesting_mode old_specs thy =
   333 fun datatype_compat_global fpT_names =
       
   334   Named_Target.theory_init
       
   335   #> datatype_compat fpT_names
       
   336   #> Named_Target.exit;
       
   337 
       
   338 fun datatype_compat_cmd raw_fpT_names lthy =
       
   339   let
       
   340     val fpT_names =
       
   341       map (fst o dest_Type o Proof_Context.read_type_name {proper = true, strict = false} lthy)
       
   342         raw_fpT_names;
       
   343   in
       
   344     datatype_compat fpT_names lthy
       
   345   end;
       
   346 
       
   347 fun add_datatype nesting_pref old_specs thy =
   332   let
   348   let
   333     val fpT_names = map (Sign.full_name thy o #1 o fst) old_specs;
   349     val fpT_names = map (Sign.full_name thy o #1 o fst) old_specs;
   334 
   350 
   335     fun new_type_args_of (s, S) = (SOME Binding.empty, (TFree (s, @{sort type}), S));
   351     fun new_type_args_of (s, S) = (SOME Binding.empty, (TFree (s, @{sort type}), S));
   336     fun new_ctr_spec_of (b, Ts, mx) = (((Binding.empty, b), map (pair Binding.empty) Ts), mx);
   352     fun new_ctr_spec_of (b, Ts, mx) = (((Binding.empty, b), map (pair Binding.empty) Ts), mx);
   343   in
   359   in
   344     (fpT_names,
   360     (fpT_names,
   345      thy
   361      thy
   346      |> Named_Target.theory_init
   362      |> Named_Target.theory_init
   347      |> co_datatypes Least_FP construct_lfp ((false, false), new_specs)
   363      |> co_datatypes Least_FP construct_lfp ((false, false), new_specs)
   348      |> nesting_mode <> Keep_Nesting ? datatype_compat_cmd fpT_names
   364      |> Named_Target.exit
   349      |> Named_Target.exit)
   365      |> nesting_pref = Unfold_Nesting ? perhaps (try (datatype_compat_global fpT_names)))
   350   end;
   366   end;
   351 
   367 
   352 val _ =
   368 val _ =
   353   Outer_Syntax.local_theory @{command_spec "datatype_compat"}
   369   Outer_Syntax.local_theory @{command_spec "datatype_compat"}
   354     "register new-style datatypes as old-style datatypes"
   370     "register new-style datatypes as old-style datatypes"