generalized datatype code generation code so that it works with old-style and new-style (co)datatypes (as long as they are not local)
authorblanchet
Mon, 02 Dec 2013 20:31:54 +0100
changeset 5598862fb5af93fe2
parent 55987 689398f0953f
child 55989 a21a2223c02b
generalized datatype code generation code so that it works with old-style and new-style (co)datatypes (as long as they are not local)
src/HOL/Ctr_Sugar.thy
src/HOL/Inductive.thy
src/HOL/Tools/Datatype/datatype_codegen.ML
src/HOL/Tools/ctr_sugar.ML
src/HOL/Tools/ctr_sugar_code.ML
     1.1 --- a/src/HOL/Ctr_Sugar.thy	Mon Dec 02 20:31:54 2013 +0100
     1.2 +++ b/src/HOL/Ctr_Sugar.thy	Mon Dec 02 20:31:54 2013 +0100
     1.3 @@ -40,6 +40,7 @@
     1.4  
     1.5  ML_file "Tools/ctr_sugar_util.ML"
     1.6  ML_file "Tools/ctr_sugar_tactics.ML"
     1.7 +ML_file "Tools/ctr_sugar_code.ML"
     1.8  ML_file "Tools/ctr_sugar.ML"
     1.9  
    1.10  end
     2.1 --- a/src/HOL/Inductive.thy	Mon Dec 02 20:31:54 2013 +0100
     2.2 +++ b/src/HOL/Inductive.thy	Mon Dec 02 20:31:54 2013 +0100
     2.3 @@ -274,7 +274,7 @@
     2.4  ML_file "Tools/Datatype/datatype_prop.ML"
     2.5  ML_file "Tools/Datatype/datatype_data.ML" setup Datatype_Data.setup
     2.6  ML_file "Tools/Datatype/rep_datatype.ML"
     2.7 -ML_file "Tools/Datatype/datatype_codegen.ML" setup Datatype_Codegen.setup
     2.8 +ML_file "Tools/Datatype/datatype_codegen.ML"
     2.9  ML_file "Tools/Datatype/primrec.ML"
    2.10  
    2.11  text{* Lambda-abstractions with pattern matching: *}
     3.1 --- a/src/HOL/Tools/Datatype/datatype_codegen.ML	Mon Dec 02 20:31:54 2013 +0100
     3.2 +++ b/src/HOL/Tools/Datatype/datatype_codegen.ML	Mon Dec 02 20:31:54 2013 +0100
     3.3 @@ -6,152 +6,24 @@
     3.4  
     3.5  signature DATATYPE_CODEGEN =
     3.6  sig
     3.7 -  val setup: theory -> theory
     3.8  end;
     3.9  
    3.10  structure Datatype_Codegen : DATATYPE_CODEGEN =
    3.11  struct
    3.12  
    3.13 -(** generic code generator **)
    3.14 +fun add_code_for_datatype fcT_name thy =
    3.15 +  let
    3.16 +    val (As', ctr_specs) = Datatype_Data.the_spec thy fcT_name;
    3.17 +    val {inject = inject_thms, distinct = distinct_thms, case_rewrites = case_thms, ...} =
    3.18 +      Datatype_Data.the_info thy fcT_name;
    3.19  
    3.20 -(* liberal addition of code data for datatypes *)
    3.21 -
    3.22 -fun mk_constr_consts thy vs tyco cos =
    3.23 -  let
    3.24 -    val cs = map (fn (c, tys) => (c, tys ---> Type (tyco, map TFree vs))) cos;
    3.25 -    val cs' = map (fn c_ty as (_, ty) => (Axclass.unoverload_const thy c_ty, ty)) cs;
    3.26 +    val As = map TFree As';
    3.27 +    val fcT = Type (fcT_name, As);
    3.28 +    val ctrs = map (fn (c, arg_Ts) => (c, arg_Ts ---> fcT)) ctr_specs;
    3.29    in
    3.30 -    if is_some (try (Code.constrset_of_consts thy) cs')
    3.31 -    then SOME cs
    3.32 -    else NONE
    3.33 +    Ctr_Sugar_Code.add_ctr_code fcT_name As ctrs inject_thms distinct_thms case_thms thy
    3.34    end;
    3.35  
    3.36 -
    3.37 -(* case certificates *)
    3.38 -
    3.39 -fun mk_case_cert thy tyco =
    3.40 -  let
    3.41 -    val raw_thms = #case_rewrites (Datatype_Data.the_info thy tyco);
    3.42 -    val thms as hd_thm :: _ = raw_thms
    3.43 -      |> Conjunction.intr_balanced
    3.44 -      |> Thm.unvarify_global
    3.45 -      |> Conjunction.elim_balanced (length raw_thms)
    3.46 -      |> map Simpdata.mk_meta_eq
    3.47 -      |> map Drule.zero_var_indexes;
    3.48 -    val params = fold_aterms (fn (Free (v, _)) => insert (op =) v | _ => I) (Thm.prop_of hd_thm) [];
    3.49 -    val rhs = hd_thm
    3.50 -      |> Thm.prop_of
    3.51 -      |> Logic.dest_equals
    3.52 -      |> fst
    3.53 -      |> Term.strip_comb
    3.54 -      |> apsnd (fst o split_last)
    3.55 -      |> list_comb;
    3.56 -    val lhs = Free (singleton (Name.variant_list params) "case", Term.fastype_of rhs);
    3.57 -    val asm = Thm.cterm_of thy (Logic.mk_equals (lhs, rhs));
    3.58 -  in
    3.59 -    thms
    3.60 -    |> Conjunction.intr_balanced
    3.61 -    |> rewrite_rule [Thm.symmetric (Thm.assume asm)]
    3.62 -    |> Thm.implies_intr asm
    3.63 -    |> Thm.generalize ([], params) 0
    3.64 -    |> Axclass.unoverload thy
    3.65 -    |> Thm.varifyT_global
    3.66 -  end;
    3.67 -
    3.68 -
    3.69 -(* equality *)
    3.70 -
    3.71 -fun mk_eq_eqns thy tyco =
    3.72 -  let
    3.73 -    val (vs, cos) = Datatype_Data.the_spec thy tyco;
    3.74 -    val {descr, index, inject = inject_thms, distinct = distinct_thms, ...} =
    3.75 -      Datatype_Data.the_info thy tyco;
    3.76 -    val ty = Type (tyco, map TFree vs);
    3.77 -    fun mk_eq (t1, t2) = Const (@{const_name HOL.equal}, ty --> ty --> HOLogic.boolT) $ t1 $ t2;
    3.78 -    fun true_eq t12 = HOLogic.mk_eq (mk_eq t12, @{term True});
    3.79 -    fun false_eq t12 = HOLogic.mk_eq (mk_eq t12, @{term False});
    3.80 -    val triv_injects =
    3.81 -      map_filter
    3.82 -        (fn (c, []) => SOME (HOLogic.mk_Trueprop (true_eq (Const (c, ty), Const (c, ty))))
    3.83 -          | _ => NONE) cos;
    3.84 -    fun prep_inject (trueprop $ (equiv $ (_ $ t1 $ t2) $ rhs)) =
    3.85 -      trueprop $ (equiv $ mk_eq (t1, t2) $ rhs);
    3.86 -    val injects = map prep_inject (nth (Datatype_Prop.make_injs [descr]) index);
    3.87 -    fun prep_distinct (trueprop $ (not $ (_ $ t1 $ t2))) =
    3.88 -      [trueprop $ false_eq (t1, t2), trueprop $ false_eq (t2, t1)];
    3.89 -    val distincts = maps prep_distinct (nth (Datatype_Prop.make_distincts [descr]) index);
    3.90 -    val refl = HOLogic.mk_Trueprop (true_eq (Free ("x", ty), Free ("x", ty)));
    3.91 -    val simp_ctxt =
    3.92 -      Simplifier.global_context thy HOL_basic_ss
    3.93 -        addsimps (map Simpdata.mk_eq (@{thms equal eq_True} @ inject_thms @ distinct_thms));
    3.94 -    fun prove prop =
    3.95 -      Goal.prove_sorry_global thy [] [] prop (K (ALLGOALS (simp_tac simp_ctxt)))
    3.96 -      |> Simpdata.mk_eq;
    3.97 -  in (map prove (triv_injects @ injects @ distincts), prove refl) end;
    3.98 -
    3.99 -fun add_equality vs tycos thy =
   3.100 -  let
   3.101 -    fun add_def tyco lthy =
   3.102 -      let
   3.103 -        val ty = Type (tyco, map TFree vs);
   3.104 -        fun mk_side const_name =
   3.105 -          Const (const_name, ty --> ty --> HOLogic.boolT) $ Free ("x", ty) $ Free ("y", ty);
   3.106 -        val def =
   3.107 -          HOLogic.mk_Trueprop (HOLogic.mk_eq
   3.108 -            (mk_side @{const_name HOL.equal}, mk_side @{const_name HOL.eq}));
   3.109 -        val def' = Syntax.check_term lthy def;
   3.110 -        val ((_, (_, thm)), lthy') =
   3.111 -          Specification.definition (NONE, (Attrib.empty_binding, def')) lthy;
   3.112 -        val ctxt_thy = Proof_Context.init_global (Proof_Context.theory_of lthy);
   3.113 -        val thm' = singleton (Proof_Context.export lthy' ctxt_thy) thm;
   3.114 -      in (thm', lthy') end;
   3.115 -    fun tac thms = Class.intro_classes_tac [] THEN ALLGOALS (Proof_Context.fact_tac thms);
   3.116 -    fun prefix tyco =
   3.117 -      Binding.qualify true (Long_Name.base_name tyco) o Binding.qualify true "eq" o Binding.name;
   3.118 -    fun add_eq_thms tyco =
   3.119 -      `(fn thy => mk_eq_eqns thy tyco)
   3.120 -      #-> (fn (thms, thm) =>
   3.121 -        Global_Theory.note_thmss Thm.lemmaK
   3.122 -          [((prefix tyco "refl", [Code.add_nbe_default_eqn_attribute]), [([thm], [])]),
   3.123 -            ((prefix tyco "simps", [Code.add_default_eqn_attribute]), [(rev thms, [])])])
   3.124 -      #> snd;
   3.125 -  in
   3.126 -    thy
   3.127 -    |> Class.instantiation (tycos, vs, [HOLogic.class_equal])
   3.128 -    |> fold_map add_def tycos
   3.129 -    |-> (fn def_thms => Class.prove_instantiation_exit_result (map o Morphism.thm)
   3.130 -         (fn _ => fn def_thms => tac def_thms) def_thms)
   3.131 -    |-> (fn def_thms => fold Code.del_eqn def_thms)
   3.132 -    |> fold add_eq_thms tycos
   3.133 -  end;
   3.134 -
   3.135 -
   3.136 -(* register a datatype etc. *)
   3.137 -
   3.138 -fun add_all_code config tycos thy =
   3.139 -  let
   3.140 -    val (vs :: _, coss) = split_list (map (Datatype_Data.the_spec thy) tycos);
   3.141 -    val any_css = map2 (mk_constr_consts thy vs) tycos coss;
   3.142 -    val css = if exists is_none any_css then [] else map_filter I any_css;
   3.143 -    val case_rewrites = maps (#case_rewrites o Datatype_Data.the_info thy) tycos;
   3.144 -    val certs = map (mk_case_cert thy) tycos;
   3.145 -    val tycos_eq =
   3.146 -      filter_out
   3.147 -        (fn tyco => Sorts.has_instance (Sign.classes_of thy) tyco [HOLogic.class_equal]) tycos;
   3.148 -  in
   3.149 -    if null css then thy
   3.150 -    else
   3.151 -      thy
   3.152 -      |> tap (fn _ => Datatype_Aux.message config "Registering datatype for code generator ...")
   3.153 -      |> fold Code.add_datatype css
   3.154 -      |> fold_rev Code.add_default_eqn case_rewrites
   3.155 -      |> fold Code.add_case certs
   3.156 -      |> not (null tycos_eq) ? add_equality vs tycos_eq
   3.157 -   end;
   3.158 -
   3.159 -
   3.160 -(** theory setup **)
   3.161 -
   3.162 -val setup = Datatype_Data.interpretation add_all_code;
   3.163 +val _ = Theory.setup (Datatype_Data.interpretation (K (fold add_code_for_datatype)));
   3.164  
   3.165  end;
     4.1 --- a/src/HOL/Tools/ctr_sugar.ML	Mon Dec 02 20:31:54 2013 +0100
     4.2 +++ b/src/HOL/Tools/ctr_sugar.ML	Mon Dec 02 20:31:54 2013 +0100
     4.3 @@ -66,6 +66,7 @@
     4.4  
     4.5  open Ctr_Sugar_Util
     4.6  open Ctr_Sugar_Tactics
     4.7 +open Ctr_Sugar_Code
     4.8  
     4.9  type ctr_sugar =
    4.10    {ctrs: term list,
    4.11 @@ -926,11 +927,13 @@
    4.12          (ctr_sugar,
    4.13           lthy
    4.14           |> not rep_compat ?
    4.15 -            (Local_Theory.declaration {syntax = false, pervasive = true}
    4.16 -               (fn phi => Case_Translation.register
    4.17 -                  (Morphism.term phi casex) (map (Morphism.term phi) ctrs)))
    4.18 +            Local_Theory.declaration {syntax = false, pervasive = true}
    4.19 +              (fn phi => Case_Translation.register
    4.20 +                 (Morphism.term phi casex) (map (Morphism.term phi) ctrs))
    4.21           |> Local_Theory.notes (anonymous_notes @ notes) |> snd
    4.22 -         |> register_ctr_sugar fcT_name ctr_sugar)
    4.23 +         |> register_ctr_sugar fcT_name ctr_sugar
    4.24 +         |> Local_Theory.background_theory
    4.25 +           (add_ctr_code fcT_name As (map dest_Const ctrs) inject_thms distinct_thms case_thms))
    4.26        end;
    4.27    in
    4.28      (goalss, after_qed, lthy')
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/HOL/Tools/ctr_sugar_code.ML	Mon Dec 02 20:31:54 2013 +0100
     5.3 @@ -0,0 +1,129 @@
     5.4 +(*  Title:      HOL/Tools/ctr_sugar_code.ML
     5.5 +    Author:     Jasmin Blanchette, TU Muenchen
     5.6 +    Author:     Dmitriy Traytel, TU Muenchen
     5.7 +    Author:     Stefan Berghofer, TU Muenchen
     5.8 +    Author:     Florian Haftmann, TU Muenchen
     5.9 +    Copyright   2001-2013
    5.10 +
    5.11 +Code generation for freely generated types.
    5.12 +*)
    5.13 +
    5.14 +signature CTR_SUGAR_CODE =
    5.15 +sig
    5.16 +  val add_ctr_code: string -> typ list -> (string * typ) list -> thm list -> thm list -> thm list ->
    5.17 +    theory -> theory
    5.18 +end;
    5.19 +
    5.20 +structure Ctr_Sugar_Code : CTR_SUGAR_CODE =
    5.21 +struct
    5.22 +
    5.23 +open Ctr_Sugar_Util
    5.24 +
    5.25 +val eqN = "eq"
    5.26 +val reflN = "refl"
    5.27 +val simpsN = "simps"
    5.28 +
    5.29 +fun mk_case_certificate thy raw_thms =
    5.30 +  let
    5.31 +    val thms as thm1 :: _ = raw_thms
    5.32 +      |> Conjunction.intr_balanced
    5.33 +      |> Thm.unvarify_global
    5.34 +      |> Conjunction.elim_balanced (length raw_thms)
    5.35 +      |> map Simpdata.mk_meta_eq
    5.36 +      |> map Drule.zero_var_indexes;
    5.37 +    val params = Term.add_free_names (Thm.prop_of thm1) [];
    5.38 +    val rhs = thm1
    5.39 +      |> Thm.prop_of |> Logic.dest_equals |> fst |> Term.strip_comb
    5.40 +      ||> fst o split_last |> list_comb;
    5.41 +    val lhs = Free (singleton (Name.variant_list params) "case", Term.fastype_of rhs);
    5.42 +    val assum = Thm.cterm_of thy (Logic.mk_equals (lhs, rhs));
    5.43 +  in
    5.44 +    thms
    5.45 +    |> Conjunction.intr_balanced
    5.46 +    |> rewrite_rule [Thm.symmetric (Thm.assume assum)]
    5.47 +    |> Thm.implies_intr assum
    5.48 +    |> Thm.generalize ([], params) 0
    5.49 +    |> Axclass.unoverload thy
    5.50 +    |> Thm.varifyT_global
    5.51 +  end;
    5.52 +
    5.53 +fun mk_free_ctr_equations fcT ctrs inject_thms distinct_thms thy =
    5.54 +  let
    5.55 +    fun mk_fcT_eq (t, u) = Const (@{const_name HOL.equal}, fcT --> fcT --> HOLogic.boolT) $ t $ u;
    5.56 +    fun true_eq tu = HOLogic.mk_eq (mk_fcT_eq tu, @{term True});
    5.57 +    fun false_eq tu = HOLogic.mk_eq (mk_fcT_eq tu, @{term False});
    5.58 +
    5.59 +    val monomorphic_prop_of = prop_of o Thm.unvarify_global o Drule.zero_var_indexes;
    5.60 +
    5.61 +    fun massage_inject (tp $ (eqv $ (_ $ t $ u) $ rhs)) = tp $ (eqv $ mk_fcT_eq (t, u) $ rhs);
    5.62 +    fun massage_distinct (tp $ (_ $ (_ $ t $ u))) = [tp $ false_eq (t, u), tp $ false_eq (u, t)];
    5.63 +
    5.64 +    val triv_inject_goals =
    5.65 +      map_filter (fn c as (_, T) =>
    5.66 +          if T = fcT then SOME (HOLogic.mk_Trueprop (true_eq (Const c, Const c))) else NONE)
    5.67 +        ctrs;
    5.68 +    val inject_goals = map (massage_inject o monomorphic_prop_of) inject_thms;
    5.69 +    val distinct_goals = maps (massage_distinct o monomorphic_prop_of) distinct_thms;
    5.70 +    val refl_goal = HOLogic.mk_Trueprop (true_eq (Free ("x", fcT), Free ("x", fcT)));
    5.71 +
    5.72 +    val simp_ctxt =
    5.73 +      Simplifier.global_context thy HOL_basic_ss
    5.74 +        addsimps (map Simpdata.mk_eq (@{thms equal eq_True} @ inject_thms @ distinct_thms));
    5.75 +
    5.76 +    fun prove goal =
    5.77 +      Goal.prove_sorry_global thy [] [] goal (K (ALLGOALS (simp_tac simp_ctxt)))
    5.78 +      |> Simpdata.mk_eq;
    5.79 +  in
    5.80 +    (map prove (triv_inject_goals @ inject_goals @ distinct_goals), prove refl_goal)
    5.81 +  end;
    5.82 +
    5.83 +fun add_equality fcT fcT_name As ctrs inject_thms distinct_thms =
    5.84 +  let
    5.85 +    fun add_def lthy =
    5.86 +      let
    5.87 +        fun mk_side const_name =
    5.88 +          Const (const_name, fcT --> fcT --> HOLogic.boolT) $ Free ("x", fcT) $ Free ("y", fcT);
    5.89 +        val spec =
    5.90 +          mk_Trueprop_eq (mk_side @{const_name HOL.equal}, mk_side @{const_name HOL.eq})
    5.91 +          |> Syntax.check_term lthy;
    5.92 +        val ((_, (_, raw_def)), lthy') =
    5.93 +          Specification.definition (NONE, (Attrib.empty_binding, spec)) lthy;
    5.94 +        val ctxt_thy = Proof_Context.init_global (Proof_Context.theory_of lthy); (* FIXME? *)
    5.95 +        val def = singleton (Proof_Context.export lthy' ctxt_thy) raw_def;
    5.96 +      in
    5.97 +        (def, lthy')
    5.98 +      end;
    5.99 +
   5.100 +    fun tac thms = Class.intro_classes_tac [] THEN ALLGOALS (Proof_Context.fact_tac thms);
   5.101 +
   5.102 +    val qualify =
   5.103 +      Binding.qualify true (Long_Name.base_name fcT_name) o Binding.qualify true eqN o Binding.name;
   5.104 +  in
   5.105 +    Class.instantiation ([fcT_name], map dest_TFree As, [HOLogic.class_equal])
   5.106 +    #> add_def
   5.107 +    #-> Class.prove_instantiation_exit_result (map o Morphism.thm) (K tac) o single
   5.108 +    #-> fold Code.del_eqn
   5.109 +    #> `(mk_free_ctr_equations fcT ctrs inject_thms distinct_thms)
   5.110 +    #-> (fn (thms, thm) => Global_Theory.note_thmss Thm.lemmaK
   5.111 +      [((qualify reflN, [Code.add_nbe_default_eqn_attribute]), [([thm], [])]),
   5.112 +        ((qualify simpsN, [Code.add_default_eqn_attribute]), [(rev thms, [])])])
   5.113 +    #> snd
   5.114 +  end;
   5.115 +
   5.116 +fun add_ctr_code fcT_name As ctrs inject_thms distinct_thms case_thms thy =
   5.117 +  let
   5.118 +    val fcT = Type (fcT_name, As);
   5.119 +    val unover_ctrs = map (fn ctr as (_, fcT) => (Axclass.unoverload_const thy ctr, fcT)) ctrs;
   5.120 +  in
   5.121 +    if can (Code.constrset_of_consts thy) unover_ctrs then
   5.122 +      thy
   5.123 +      |> Code.add_datatype ctrs
   5.124 +      |> fold_rev Code.add_default_eqn case_thms
   5.125 +      |> Code.add_case (mk_case_certificate thy case_thms)
   5.126 +      |> not (Sorts.has_instance (Sign.classes_of thy) fcT_name [HOLogic.class_equal])
   5.127 +        ? add_equality fcT fcT_name As ctrs inject_thms distinct_thms
   5.128 +    else
   5.129 +      thy
   5.130 +  end;
   5.131 +
   5.132 +end;