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); |
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; |
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 |