src/HOL/Tools/typedef_package.ML
changeset 19342 094a1c071c8e
parent 18964 67f572e03236
child 19391 4812d28c90a6
equal deleted inserted replaced
19341:3414c04fbc39 19342:094a1c071c8e
     8 signature TYPEDEF_PACKAGE =
     8 signature TYPEDEF_PACKAGE =
     9 sig
     9 sig
    10   val quiet_mode: bool ref
    10   val quiet_mode: bool ref
    11   val add_typedecls: (bstring * string list * mixfix) list -> theory -> theory
    11   val add_typedecls: (bstring * string list * mixfix) list -> theory -> theory
    12   val add_typedef: bool -> string option -> bstring * string list * mixfix ->
    12   val add_typedef: bool -> string option -> bstring * string list * mixfix ->
    13     string -> (bstring * bstring) option -> tactic -> theory -> theory *
    13     string -> (bstring * bstring) option -> tactic -> theory ->
    14     {type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
    14     {type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
    15       Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
    15       Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
    16       Rep_induct: thm, Abs_induct: thm}
    16       Rep_induct: thm, Abs_induct: thm} * theory
    17   val add_typedef_i: bool -> string option -> bstring * string list * mixfix ->
    17   val add_typedef_i: bool -> string option -> bstring * string list * mixfix ->
    18     term -> (bstring * bstring) option -> tactic -> theory -> theory *
    18     term -> (bstring * bstring) option -> tactic -> theory ->
    19     {type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
    19     {type_definition: thm, set_def: thm option, Rep: thm, Rep_inverse: thm,
    20       Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
    20       Abs_inverse: thm, Rep_inject: thm, Abs_inject: thm, Rep_cases: thm, Abs_cases: thm,
    21       Rep_induct: thm, Abs_induct: thm}
    21       Rep_induct: thm, Abs_induct: thm} * theory
    22   val typedef: (bool * string) * (bstring * string list * mixfix) * string
    22   val typedef: (bool * string) * (bstring * string list * mixfix) * string
    23     * (string * string) option -> theory -> Proof.state
    23     * (string * string) option -> theory -> Proof.state
    24   val typedef_i: (bool * string) * (bstring * string list * mixfix) * term
    24   val typedef_i: (bool * string) * (bstring * string list * mixfix) * term
    25     * (string * string) option -> theory -> Proof.state
    25     * (string * string) option -> theory -> Proof.state
    26   val setup: theory -> theory
    26   val setup: theory -> theory
       
    27   structure TypedefData : THEORY_DATA
    27 end;
    28 end;
    28 
    29 
    29 structure TypedefPackage: TYPEDEF_PACKAGE =
    30 structure TypedefPackage: TYPEDEF_PACKAGE =
    30 struct
    31 struct
    31 
    32 
    72 (* theory data *)
    73 (* theory data *)
    73 
    74 
    74 structure TypedefData = TheoryDataFun
    75 structure TypedefData = TheoryDataFun
    75 (struct
    76 (struct
    76   val name = "HOL/typedef";
    77   val name = "HOL/typedef";
    77   type T = (typ * typ * string * string) Symtab.table;
    78   type T = ((typ * typ * string * string) * (thm option * thm * thm)) Symtab.table;
    78   val empty = Symtab.empty;
    79   val empty = Symtab.empty;
    79   val copy = I;
    80   val copy = I;
    80   val extend = I;
    81   val extend = I;
    81   fun merge _ (tabs: T * T) = Symtab.merge (op =) tabs;
    82   fun merge _ (tabs: T * T) = Symtab.merge (op =) tabs;
    82   fun print _ _ = ();
    83   fun print _ _ = ();
    83 end);
    84 end);
    84 
    85 
    85 fun put_typedef newT oldT Abs_name Rep_name =
    86 fun put_typedef newT oldT Abs_name Rep_name def inject inverse =
    86   TypedefData.map (Symtab.update_new (fst (dest_Type newT), (newT, oldT, Abs_name, Rep_name)));
    87   TypedefData.map (Symtab.update_new (fst (dest_Type newT),
       
    88     ((newT, oldT, Abs_name, Rep_name), (def, inject, inverse))));
    87 
    89 
    88 
    90 
    89 (* prepare_typedef *)
    91 (* prepare_typedef *)
    90 
    92 
    91 fun read_term thy used s =
    93 fun read_term thy used s =
   148         |> PureThy.add_defs_i false [Thm.no_attributes def']
   150         |> PureThy.add_defs_i false [Thm.no_attributes def']
   149         |-> (fn [def'] => pair (SOME def'))
   151         |-> (fn [def'] => pair (SOME def'))
   150       else
   152       else
   151         (NONE, thy);
   153         (NONE, thy);
   152 
   154 
   153     fun typedef_result (context, nonempty) =
   155     fun typedef_result nonempty context =
   154       Context.the_theory context
   156       Context.the_theory context
   155       |> put_typedef newT oldT (full Abs_name) (full Rep_name)
       
   156       |> add_typedecls [(t, vs, mx)]
   157       |> add_typedecls [(t, vs, mx)]
   157       |> Theory.add_consts_i
   158       |> Theory.add_consts_i
   158        ((if def then [(name, setT', NoSyn)] else []) @
   159        ((if def then [(name, setT', NoSyn)] else []) @
   159         [(Rep_name, newT --> oldT, NoSyn),
   160         [(Rep_name, newT --> oldT, NoSyn),
   160          (Abs_name, oldT --> newT, NoSyn)])
   161          (Abs_name, oldT --> newT, NoSyn)])
   163           [apsnd (fn cond_axm => Drule.standard (nonempty RS cond_axm))])]
   164           [apsnd (fn cond_axm => Drule.standard (nonempty RS cond_axm))])]
   164       ||> Theory.add_finals_i false [RepC, AbsC]
   165       ||> Theory.add_finals_i false [RepC, AbsC]
   165       |-> (fn (set_def, [type_definition]) => fn theory' =>
   166       |-> (fn (set_def, [type_definition]) => fn theory' =>
   166         let
   167         let
   167           fun make th = Drule.standard (th OF [type_definition]);
   168           fun make th = Drule.standard (th OF [type_definition]);
       
   169           val abs_inject = make Abs_inject;
       
   170           val abs_inverse = make Abs_inverse;
   168           val ([Rep, Rep_inverse, Abs_inverse, Rep_inject, Abs_inject,
   171           val ([Rep, Rep_inverse, Abs_inverse, Rep_inject, Abs_inject,
   169               Rep_cases, Abs_cases, Rep_induct, Abs_induct], theory'') =
   172               Rep_cases, Abs_cases, Rep_induct, Abs_induct], theory'') =
   170             theory'
   173             theory'
   171             |> Theory.add_path name
   174             |> Theory.add_path name
   172             |> PureThy.add_thms
   175             |> PureThy.add_thms
   173               ([((Rep_name, make Rep), []),
   176               ([((Rep_name, make Rep), []),
   174                 ((Rep_name ^ "_inverse", make Rep_inverse), []),
   177                 ((Rep_name ^ "_inverse", make Rep_inverse), []),
   175                 ((Abs_name ^ "_inverse", make Abs_inverse), []),
   178                 ((Abs_name ^ "_inverse", abs_inverse), []),
   176                 ((Rep_name ^ "_inject", make Rep_inject), []),
   179                 ((Rep_name ^ "_inject", make Rep_inject), []),
   177                 ((Abs_name ^ "_inject", make Abs_inject), []),
   180                 ((Abs_name ^ "_inject", abs_inject), []),
   178                 ((Rep_name ^ "_cases", make Rep_cases),
   181                 ((Rep_name ^ "_cases", make Rep_cases),
   179                   [RuleCases.case_names [Rep_name], InductAttrib.cases_set full_name]),
   182                   [RuleCases.case_names [Rep_name], InductAttrib.cases_set full_name]),
   180                 ((Abs_name ^ "_cases", make Abs_cases),
   183                 ((Abs_name ^ "_cases", make Abs_cases),
   181                   [RuleCases.case_names [Abs_name], InductAttrib.cases_type full_tname]),
   184                   [RuleCases.case_names [Abs_name], InductAttrib.cases_type full_tname]),
   182                 ((Rep_name ^ "_induct", make Rep_induct),
   185                 ((Rep_name ^ "_induct", make Rep_induct),
   183                   [RuleCases.case_names [Rep_name], InductAttrib.induct_set full_name]),
   186                   [RuleCases.case_names [Rep_name], InductAttrib.induct_set full_name]),
   184                 ((Abs_name ^ "_induct", make Abs_induct),
   187                 ((Abs_name ^ "_induct", make Abs_induct),
   185                   [RuleCases.case_names [Abs_name], InductAttrib.induct_type full_tname])])
   188                   [RuleCases.case_names [Abs_name], InductAttrib.induct_type full_tname])])
   186             ||> Theory.parent_path;
   189             ||> Theory.parent_path
       
   190             ||> put_typedef newT oldT (full Abs_name) (full Rep_name)
       
   191                  set_def abs_inject abs_inverse
   187           val result = {type_definition = type_definition, set_def = set_def,
   192           val result = {type_definition = type_definition, set_def = set_def,
   188             Rep = Rep, Rep_inverse = Rep_inverse, Abs_inverse = Abs_inverse,
   193             Rep = Rep, Rep_inverse = Rep_inverse, Abs_inverse = Abs_inverse,
   189             Rep_inject = Rep_inject, Abs_inject = Abs_inject, Rep_cases = Rep_cases,
   194             Rep_inject = Rep_inject, Abs_inject = Abs_inject, Rep_cases = Rep_cases,
   190             Abs_cases = Abs_cases, Rep_induct = Rep_induct, Abs_induct = Abs_induct};
   195             Abs_cases = Abs_cases, Rep_induct = Rep_induct, Abs_induct = Abs_induct};
   191         in ((Context.Theory theory'', type_definition), result) end);
   196         in ((type_definition, result), Context.Theory theory'') end);
   192 
   197 
   193 
   198 
   194     (* errors *)
   199     (* errors *)
   195 
   200 
   196     fun show_names pairs = commas_quote (map fst pairs);
   201     fun show_names pairs = commas_quote (map fst pairs);
   214     val errs = illegal_vars @ dup_lhs_tfrees @ extra_rhs_tfrees @ illegal_frees;
   219     val errs = illegal_vars @ dup_lhs_tfrees @ extra_rhs_tfrees @ illegal_frees;
   215     val _ = if null errs then () else error (cat_lines errs);
   220     val _ = if null errs then () else error (cat_lines errs);
   216 
   221 
   217     (*test theory errors now!*)
   222     (*test theory errors now!*)
   218     val test_thy = Theory.copy thy;
   223     val test_thy = Theory.copy thy;
   219     val _ = (Context.Theory test_thy,
   224     val _ = 
   220       setmp quick_and_dirty true (SkipProof.make_thm test_thy) goal) |> typedef_result;
   225       Context.Theory test_thy
       
   226       |> typedef_result (setmp quick_and_dirty true (SkipProof.make_thm test_thy) goal);
   221 
   227 
   222   in (cset, goal, goal_pat, typedef_result) end
   228   in (cset, goal, goal_pat, typedef_result) end
   223   handle ERROR msg => err_in_typedef msg name;
   229   handle ERROR msg => err_in_typedef msg name;
   224 
   230 
   225 
   231 
   233     val (cset, goal, _, typedef_result) =
   239     val (cset, goal, _, typedef_result) =
   234       prepare_typedef prep_term def name typ set opt_morphs thy;
   240       prepare_typedef prep_term def name typ set opt_morphs thy;
   235     val _ = message ("Proving non-emptiness of set " ^ quote (string_of_cterm cset) ^ " ...");
   241     val _ = message ("Proving non-emptiness of set " ^ quote (string_of_cterm cset) ^ " ...");
   236     val non_empty = Goal.prove thy [] [] goal (K tac) handle ERROR msg =>
   242     val non_empty = Goal.prove thy [] [] goal (K tac) handle ERROR msg =>
   237       cat_error msg ("Failed to prove non-emptiness of " ^ quote (string_of_cterm cset));
   243       cat_error msg ("Failed to prove non-emptiness of " ^ quote (string_of_cterm cset));
   238     val (thy', result) =
   244   in
   239       (Context.Theory thy, non_empty) |> typedef_result |>> (Context.the_theory o fst);
   245     Context.Theory thy
   240   in (thy', result) end;
   246     |> typedef_result non_empty
       
   247     ||> Context.the_theory
       
   248     |-> (fn (_, result) => pair result)
       
   249   end;
   241 
   250 
   242 in
   251 in
   243 
   252 
   244 val add_typedef = gen_typedef read_term;
   253 val add_typedef = gen_typedef read_term;
   245 val add_typedef_i = gen_typedef cert_term;
   254 val add_typedef_i = gen_typedef cert_term;
   253 
   262 
   254 fun gen_typedef prep_term ((def, name), typ, set, opt_morphs) thy =
   263 fun gen_typedef prep_term ((def, name), typ, set, opt_morphs) thy =
   255   let
   264   let
   256     val (_, goal, goal_pat, att_result) =
   265     val (_, goal, goal_pat, att_result) =
   257       prepare_typedef prep_term def name typ set opt_morphs thy;
   266       prepare_typedef prep_term def name typ set opt_morphs thy;
   258     val att = #1 o att_result;
   267     fun att (thy, th) =
       
   268       let val ((th', _), thy') = att_result th thy
       
   269       in (thy', th') end;
   259   in IsarThy.theorem_i PureThy.internalK ("", [att]) (goal, ([goal_pat], [])) thy end;
   270   in IsarThy.theorem_i PureThy.internalK ("", [att]) (goal, ([goal_pat], [])) thy end;
   260 
   271 
   261 in
   272 in
   262 
   273 
   263 val typedef = gen_typedef read_term;
   274 val typedef = gen_typedef read_term;
   281         val id = Codegen.mk_qual_id module (Codegen.get_const_id s gr'')
   292         val id = Codegen.mk_qual_id module (Codegen.get_const_id s gr'')
   282       in SOME (gr'', Codegen.mk_app brack (Pretty.str id) ps) end;
   293       in SOME (gr'', Codegen.mk_app brack (Pretty.str id) ps) end;
   283     fun lookup f T =
   294     fun lookup f T =
   284       (case Symtab.lookup (TypedefData.get thy) (get_name T) of
   295       (case Symtab.lookup (TypedefData.get thy) (get_name T) of
   285         NONE => ""
   296         NONE => ""
   286       | SOME s => f s);
   297       | SOME (s, _) => f s);
   287   in
   298   in
   288     (case strip_comb t of
   299     (case strip_comb t of
   289        (Const (s, Type ("fun", [T, U])), ts) =>
   300        (Const (s, Type ("fun", [T, U])), ts) =>
   290          if lookup #4 T = s andalso
   301          if lookup #4 T = s andalso
   291            is_none (Codegen.get_assoc_type thy (get_name T))
   302            is_none (Codegen.get_assoc_type thy (get_name T))
   302   | mk_tyexpr ps s = Pretty.list "(" (") " ^ s) ps;
   313   | mk_tyexpr ps s = Pretty.list "(" (") " ^ s) ps;
   303 
   314 
   304 fun typedef_tycodegen thy defs gr dep module brack (Type (s, Ts)) =
   315 fun typedef_tycodegen thy defs gr dep module brack (Type (s, Ts)) =
   305       (case Symtab.lookup (TypedefData.get thy) s of
   316       (case Symtab.lookup (TypedefData.get thy) s of
   306          NONE => NONE
   317          NONE => NONE
   307        | SOME (newT as Type (tname, Us), oldT, Abs_name, Rep_name) =>
   318        | SOME ((newT as Type (tname, Us), oldT, Abs_name, Rep_name), _) =>
   308            if is_some (Codegen.get_assoc_type thy tname) then NONE else
   319            if is_some (Codegen.get_assoc_type thy tname) then NONE else
   309            let
   320            let
   310              val module' = Codegen.if_library
   321              val module' = Codegen.if_library
   311                (Codegen.thyname_of_type tname thy) module;
   322                (Codegen.thyname_of_type tname thy) module;
   312              val node_id = tname ^ " (type)";
   323              val node_id = tname ^ " (type)";
   354                in Codegen.map_node node_id (K (NONE, module', s)) gr'' end
   365                in Codegen.map_node node_id (K (NONE, module', s)) gr'' end
   355              | SOME _ => Codegen.add_edge (node_id, dep) gr', tyexpr)
   366              | SOME _ => Codegen.add_edge (node_id, dep) gr', tyexpr)
   356            end)
   367            end)
   357   | typedef_tycodegen thy defs gr dep module brack _ = NONE;
   368   | typedef_tycodegen thy defs gr dep module brack _ = NONE;
   358 
   369 
       
   370 fun typedef_type_extr thy tyco =
       
   371   case Symtab.lookup (TypedefData.get thy) tyco
       
   372    of SOME ((ty_abs, ty_rep, c_abs, c_rep), (SOME def, inject, _)) =>
       
   373         let
       
   374           val exists_thm =
       
   375             UNIV_I
       
   376             |> Drule.instantiate' [SOME (ctyp_of thy ty_rep)] []
       
   377             |> rewrite_rule [symmetric def];
       
   378         in case try (Tactic.rule_by_tactic ((ALLGOALS o resolve_tac) [exists_thm])) inject
       
   379          of SOME eq_thm => SOME (((Term.typ_tfrees o Type.no_tvars) ty_abs, [(c_abs, [ty_rep])]),
       
   380              (ALLGOALS o resolve_tac) [eq_reflection]
       
   381             THEN (ALLGOALS o resolve_tac) [eq_thm])
       
   382           | NONE => NONE
       
   383         end
       
   384     | _ => NONE;
       
   385 
       
   386 fun typedef_fun_extr thy (c, ty) =
       
   387   case (fst o strip_type) ty
       
   388    of Type (tyco, _) :: _ =>
       
   389     (case Symtab.lookup (TypedefData.get thy) tyco
       
   390      of SOME ((ty_abs, ty_rep, c_abs, c_rep), (SOME def, _, inverse)) =>
       
   391           if c = c_rep then
       
   392             let
       
   393               val exists_thm =
       
   394                 UNIV_I
       
   395                 |> Drule.instantiate' [SOME (ctyp_of thy ty_rep)] []
       
   396                 |> rewrite_rule [symmetric def]
       
   397             in case try (Tactic.rule_by_tactic ((ALLGOALS o resolve_tac) [exists_thm])) inverse
       
   398              of SOME eq_thm => SOME [eq_thm]
       
   399               | NONE => NONE
       
   400             end
       
   401           else NONE
       
   402       | _ => NONE)
       
   403     | _ => NONE;
       
   404 
   359 val setup =
   405 val setup =
   360   TypedefData.init #>
   406   TypedefData.init
   361   Codegen.add_codegen "typedef" typedef_codegen #>
   407   #> Codegen.add_codegen "typedef" typedef_codegen
   362   Codegen.add_tycodegen "typedef" typedef_tycodegen;
   408   #> Codegen.add_tycodegen "typedef" typedef_tycodegen
       
   409   #> CodegenTheorems.add_fun_extr (these oo typedef_fun_extr)
       
   410   #> CodegenTheorems.add_datatype_extr typedef_type_extr
   363 
   411 
   364 
   412 
   365 
   413 
   366 (** outer syntax **)
   414 (** outer syntax **)
   367 
   415